28#include <tqvaluevector.h>
32#include <kstandarddirs.h>
33#include <kstaticdeleter.h>
35#include "kspread_factory.h"
40class Function::Private
45 int paramMin, paramMax;
50class FunctionRepository::Private
53 TQDict<Function> functions;
54 TQDict<FunctionDescription> funcs;
62Function::Function(
const TQString& name, FunctionPtr ptr )
67 d->acceptArray =
false;
78TQString Function::name()
const
83void Function::setParamCount (
int min,
int max)
86 d->paramMax = (max == 0) ? min : max;
89bool Function::paramCountOkay (
int count)
92 if (count < d->paramMin)
return false;
94 if (d->paramMax == -1)
return true;
96 if (count > d->paramMax)
return false;
101void Function::setAcceptArray (
bool accept) {
102 d->acceptArray = accept;
105bool Function::needsExtra () {
108void Function::setNeedsExtra (
bool extra) {
112Value Function::exec (valVector args,
ValueCalc *calc, FuncExtra *extra)
115 if (!paramCountOkay (args.count()))
119 bool mustExpandArray =
false;
121 for (
unsigned int i = 0; i < args.count(); ++i) {
122 if (args[i].isArray())
123 mustExpandArray =
true;
130 if (mustExpandArray) {
134 for (
unsigned int i = 0; i < args.count(); ++i) {
135 int x = (args[i].type() == Value::Array) ? args[i].rows() : 1;
136 if (x > rows) rows = x;
137 x = (args[i].type() == Value::Array) ? args[i].columns() : 1;
138 if (x > cols) cols = x;
141 Value res (cols, rows);
143 for (
int row = 0; row < rows; ++row)
144 for (
int col = 0; col < cols; ++col) {
146 valVector vals (args.count());
147 for (
unsigned int i = 0; i < args.count(); ++i) {
148 int r = args[i].rows();
149 int c = args[i].columns();
150 vals[i] = args[i].isArray() ?
151 args[i].element (col % c, row % r): args[i];
155 res.setElement (col, row, exec (vals, calc, extra));
161 return (*d->ptr) (args, calc, extra);
166void RegisterConversionFunctions();
167void RegisterDatabaseFunctions();
168void RegisterDateTimeFunctions();
169void RegisterEngineeringFunctions();
170void RegisterFinancialFunctions();
171void RegisterInformationFunctions();
172void RegisterLogicFunctions();
173void RegisterMathFunctions();
174void RegisterReferenceFunctions();
175void RegisterStatisticalFunctions();
176void RegisterTextFunctions();
177void RegisterTrigFunctions();
180static KStaticDeleter<FunctionRepository> fr_sd;
181FunctionRepository* FunctionRepository::s_self = 0;
183FunctionRepository* FunctionRepository::self()
187 kdDebug() <<
"Creating function repository" << endl;
189 fr_sd.setObject( s_self,
new FunctionRepository() );
191 kdDebug() <<
"Registering functions" << endl;
194 RegisterConversionFunctions();
195 RegisterDatabaseFunctions();
196 RegisterDateTimeFunctions();
197 RegisterEngineeringFunctions();
198 RegisterFinancialFunctions();
199 RegisterInformationFunctions();
200 RegisterLogicFunctions();
201 RegisterMathFunctions();
202 RegisterReferenceFunctions();
203 RegisterStatisticalFunctions();
204 RegisterTextFunctions();
205 RegisterTrigFunctions();
207 kdDebug() <<
"Functions registered, loading descriptions" << endl;
210 TQStringList files = Factory::global()->dirs()->findAllResources
211 (
"extensions",
"*.xml",
true);
214 for( TQStringList::Iterator it = files.begin(); it != files.end(); ++it )
215 s_self->loadFile (*it);
217 kdDebug() <<
"All ok, repository ready" << endl;
223FunctionRepository::FunctionRepository()
227 d->functions.setAutoDelete(
true );
228 d->funcs.setAutoDelete(
true );
231FunctionRepository::~FunctionRepository()
237void FunctionRepository::add( Function* function )
239 if( !function )
return;
240 d->functions.insert( function->name().upper(), function );
243Function *FunctionRepository::function (
const TQString& name)
245 return d->functions.find (name.upper());
248FunctionDescription *FunctionRepository::functionInfo (
const TQString& name)
250 return d->funcs.find (name.upper());
254TQStringList FunctionRepository::functionNames(
const TQString& group )
258 TQDictIterator<FunctionDescription> it (d->funcs);
259 for(; it.current(); ++it) {
260 if (group.isNull() || (it.current()->group() == group))
261 lst.append (it.current()->name());
268void FunctionRepository::loadFile (
const TQString& filename)
270 TQFile file (filename);
271 if (!file.open (IO_ReadOnly))
275 doc.setContent( &file );
280 TQDomNode n = doc.documentElement().firstChild();
281 for (; !n.isNull(); n = n.nextSibling())
285 TQDomElement e = n.toElement();
286 if (e.tagName() ==
"Group")
288 group = i18n (e.namedItem (
"GroupName").toElement().text().utf8());
289 m_groups.append( group );
292 TQDomNode n2 = e.firstChild();
293 for (; !n2.isNull(); n2 = n2.nextSibling())
297 TQDomElement e2 = n2.toElement();
298 if (e2.tagName() ==
"Function")
300 FunctionDescription* desc =
new FunctionDescription( e2 );
301 desc->setGroup (group);
302 if (d->functions.find (desc->name()))
303 d->funcs.insert (desc->name(), desc);
313static ParameterType toType(
const TQString& type )
315 if ( type ==
"Boolean" )
316 return KSpread_Boolean;
319 if ( type ==
"String" )
320 return KSpread_String;
324 return KSpread_Float;
327static TQString toString (ParameterType type,
bool range =
false)
335 return i18n(
"Whole number (like 1, 132, 2344)");
336 case KSpread_Boolean:
337 return i18n(
"A truth value (TRUE or FALSE)" );
339 return i18n(
"A floating point value (like 1.3, 0.343, 253 )" );
341 return i18n(
"Any kind of value");
348 return i18n(
"A range of strings");
350 return i18n(
"A range of whole numbers (like 1, 132, 2344)");
351 case KSpread_Boolean:
352 return i18n(
"A range of truth values (TRUE or FALSE)" );
354 return i18n(
"A range of floating point values (like 1.3, 0.343, 253 )" );
356 return i18n(
"A range of any kind of values");
363FunctionParameter::FunctionParameter()
365 m_type = KSpread_Float;
369FunctionParameter::FunctionParameter (
const FunctionParameter& param)
371 m_help = param.m_help;
372 m_type = param.m_type;
373 m_range = param.m_range;
376FunctionParameter::FunctionParameter (
const TQDomElement& element)
378 m_type = KSpread_Float;
381 TQDomNode n = element.firstChild();
382 for( ; !n.isNull(); n = n.nextSibling() )
385 TQDomElement e = n.toElement();
386 if ( e.tagName() ==
"Comment" )
387 m_help = i18n( e.text().utf8() );
388 else if ( e.tagName() ==
"Type" )
390 m_type = toType( e.text() );
391 if ( e.hasAttribute(
"range" ))
393 if (e.attribute(
"range").lower() ==
"true")
400FunctionDescription::FunctionDescription()
402 m_type = KSpread_Float;
405FunctionDescription::FunctionDescription (
const TQDomElement& element)
407 TQDomNode n = element.firstChild();
408 for( ; !n.isNull(); n = n.nextSibling() )
412 TQDomElement e = n.toElement();
413 if ( e.tagName() ==
"Name" )
415 else if ( e.tagName() ==
"Type" )
416 m_type = toType( e.text() );
417 else if ( e.tagName() ==
"Parameter" )
418 m_params.append (FunctionParameter (e));
419 else if ( e.tagName() ==
"Help" )
421 TQDomNode n2 = e.firstChild();
422 for( ; !n2.isNull(); n2 = n2.nextSibling() )
426 TQDomElement e2 = n2.toElement();
427 if ( e2.tagName() ==
"Text" )
428 m_help.append ( i18n( e2.text().utf8() ) );
429 else if ( e2.tagName() ==
"Syntax" )
430 m_syntax.append( i18n( e2.text().utf8() ) );
431 else if ( e2.tagName() ==
"Example" )
432 m_examples.append( i18n( e2.text().utf8() ) );
433 else if ( e2.tagName() ==
"Related" )
434 m_related.append( i18n( e2.text().utf8() ) );
440FunctionDescription::FunctionDescription(
const FunctionDescription& desc )
442 m_examples = desc.m_examples;
443 m_related = desc.m_related;
444 m_syntax = desc.m_syntax;
445 m_help = desc.m_help;
446 m_name = desc.m_name;
447 m_type = desc.m_type;
450TQString FunctionDescription::toTQML()
const
452 TQString text(
"<qt><h1>" );
456 if( !m_help.isEmpty() )
459 TQStringList::ConstIterator it = m_help.begin();
460 for( ; it != m_help.end(); ++it )
468 text += i18n(
"<p><b>Return type: </b>");
469 text += toString( type() );
472 if ( !m_syntax.isEmpty() )
474 text += i18n(
"<h2>Syntax</h2><ul>");
475 TQStringList::ConstIterator it = m_syntax.begin();
476 for( ; it != m_syntax.end(); ++it )
484 if ( !m_params.isEmpty() )
486 text += i18n(
"<h2>Parameters</h2><ul>");
487 TQValueList<FunctionParameter>::ConstIterator it = m_params.begin();
488 for( ; it != m_params.end(); ++it )
490 text += i18n(
"<li><b>Comment:</b> ");
491 text += (*it).helpText();
492 text += i18n(
"<br><b>Type:</b> ");
493 text += toString( (*it).type(), (*it).hasRange() );
498 if ( !m_examples.isEmpty() )
500 text += i18n(
"<h2>Examples</h2><ul>");
501 TQStringList::ConstIterator it = m_examples.begin();
502 for( ; it != m_examples.end(); ++it )
510 if ( !m_related.isEmpty() )
512 text += i18n(
"<h2>Related Functions</h2><ul>");
513 TQStringList::ConstIterator it = m_related.begin();
514 for( ; it != m_related.end(); ++it )
517 text +=
"<a href=\"" + *it +
"\">";
The ValueCalc class is used to perform all sorts of calculations.
Provides a wrapper for cell value.
static const Value & errorVALUE()
Returns constant reference to #VALUE! error.