]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxEvalExpr.cxx
Salome HOME
e949c0add57e4ef0d0ef542fdc683a0a5d2e6675
[modules/gui.git] / src / Qtx / QtxEvalExpr.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File:      QtxEvalExpr.cxx
21 // Author:    Alexander SOLOVYOV, Sergey TELKOV
22 //
23 #include "QtxEvalExpr.h"
24
25 #include <QStack>
26
27 #include <math.h>
28
29 /*!
30   \class QtxEvalExpr
31   \brief String expression evaluator.
32 */
33
34 /*!
35   \brief Constructor.
36
37   The evaluator is initalized by standard operations. Use another constructor with parameter
38   \a stdSets = \c false to avoid initialization of evaluator with standard operations.
39
40   \param expr expression to be evaluated
41 */
42 QtxEvalExpr::QtxEvalExpr( const QString& expr )
43 {
44   intialize( true, expr );
45 }
46
47 /*!
48   \brief Constructor.
49   \param stdSets if \c true, the evaluator is initalized by standard operations
50   \param expr expression to be evaluated
51 */
52 QtxEvalExpr::QtxEvalExpr( const bool stdSets, const QString& expr )
53 {
54   intialize( stdSets, expr );
55 }
56
57 /*!
58   \brief Destructor.
59 */
60 QtxEvalExpr::~QtxEvalExpr()
61 {
62   delete myParser;
63 }
64
65 /*!
66   \brief Initialize the evaluator.
67   \param stdSets if \c true, the evaluator is initalized by standard operations
68   \param expr expression to be evaluated
69 */
70 void QtxEvalExpr::intialize( const bool stdSets, const QString& expr )
71 {
72   myParser = new QtxEvalParser();
73   if ( stdSets )
74   {
75     myParser->setAutoDeleteOperationSets( true );
76     myParser->insertOperationSet( new QtxEvalSetLogic() );
77     myParser->insertOperationSet( new QtxEvalSetArithmetic() );
78     myParser->insertOperationSet( new QtxEvalSetString() );
79     myParser->insertOperationSet( new QtxEvalSetMath() );
80     myParser->insertOperationSet( new QtxEvalSetSets() );
81     myParser->insertOperationSet( new QtxEvalSetConst() );
82   }
83   setExpression( expr );
84 }
85
86 /*!
87   \brief Evaluate the expression.
88   \param expr expression to be evaluated
89   \return result of the evaluation
90 */
91 QVariant QtxEvalExpr::calculate( const QString& expr )
92 {
93   if ( !expr.isEmpty() )
94     setExpression( expr );
95   return myParser->calculate();
96 }
97
98 /*!
99   \brief Get the expression.
100   \return expression string
101 */
102 QString QtxEvalExpr::expression() const
103 {
104   return myExpr;
105 }
106
107 /*!
108   \brief Set the expression.
109   \param expr expression string
110 */
111 void QtxEvalExpr::setExpression( const QString& expr )
112 {
113   if ( expr == expression() )
114     return;
115
116   myExpr = expr;
117   myParser->setExpression( myExpr );
118 }
119
120 /*!
121   \brief Get the code of latest parsing error.
122   \return the code of the last error
123 */
124 QtxEvalExpr::Error QtxEvalExpr::error() const
125 {
126   return myParser->error();
127 }
128
129 /*!
130   \brief Get the expression parser.
131   \return expression parser
132 */
133 QtxEvalParser* QtxEvalExpr::parser() const
134 {
135   return myParser;
136 }
137
138 /*!
139   \brief Get current set of operations.
140   \return operations set
141   \sa insertOperationSet(), removeOperationSet(), operationSet()
142 */
143 QList<QtxEvalSet*> QtxEvalExpr::operationSets() const
144 {
145   return myParser->operationSets();
146 }
147
148 /*!
149   \brief Install the operation.
150   \param operation to be added
151   \param idx index in the list at which the operation shoud be inserted
152   \sa operationSets(), removeOperationSet(), operationSet()
153 */
154 void QtxEvalExpr::insertOperationSet( QtxEvalSet* set, const int idx )
155 {
156   myParser->insertOperationSet( set, idx );
157 }
158
159 /*!
160   \brief Remove the operation.
161   \param operation to be removed
162   \sa operationSets(), insertOperationSet(), operationSet()
163 */
164 void QtxEvalExpr::removeOperationSet( QtxEvalSet* set )
165 {
166   myParser->removeOperationSet( set );
167 }
168
169 /*!
170   \brief Get the operation by name.
171   \param name operation name
172   \return operation of 0 if not found
173   \sa operationSets(), insertOperationSet(), removeOperationSet()
174 */
175 QtxEvalSet* QtxEvalExpr::operationSet( const QString& name ) const
176 {
177   return myParser->operationSet( name );
178 }
179
180 /*!
181   \brief Get the 'auto-delete operations' flag value.
182   \return \c true if all operations shoud be automatically deleted when the evaluator is destroyed
183   \sa setAutoDeleteOperationSets()
184 */
185 bool QtxEvalExpr::autoDeleteOperationSets() const
186 {
187   return myParser->autoDeleteOperationSets();
188 }
189
190 /*!
191   \brief Set the 'auto-delete operations' flag value.
192   \param on if \c true, all operations shoud be automatically deleted when the evaluator is destroyed
193   \sa autoDeleteOperationSets()
194 */
195 void QtxEvalExpr::setAutoDeleteOperationSets( const bool on )
196 {
197   myParser->setAutoDeleteOperationSets( on );
198 }
199
200 /*!
201   \class QtxEvalParser
202   \brief Expression parser.
203
204   This class provides the functionality to calculate value of the expression using defined set of operations.
205   Standard operations (arithmetics, logic, strings, etc) are implemented in the corresponding successors of the
206   QtxEvalSet class: QtxEvalSetArithmetic, QtxEvalSetLogic, QtxEvalSetMath, QtxEvalSetString, ...
207
208   The parser allows using parameters with help of methods has(), set(), remove(), value(). It uses
209   postfix representation of expressions and uses class QtxEvalSet in order to make certain operation.
210
211   Every instance of parser contains only one postfix - thus, if the expression is changed, the postfix
212   must be rebuilt. In order to increase performance of frequent calculations for many of expressions it is 
213   recommended to use different instances of the parser for each expression.
214 */
215
216 /*!
217   \brief Constructor.
218 */
219 QtxEvalParser::QtxEvalParser()
220 : myAutoDel( false )
221 {
222   setError( QtxEvalExpr::OK );
223 }
224
225 /*!
226   \brief Destructor.
227 */
228 QtxEvalParser::~QtxEvalParser()
229 {
230   if ( autoDeleteOperationSets() )
231     qDeleteAll( mySets );
232 }
233
234 /*!
235   \brief Get current operations set.
236   \return current operations set
237 */
238 QList<QtxEvalSet*> QtxEvalParser::operationSets() const
239 {
240   return mySets;
241 }
242
243 /*!
244   \brief Get the operations set by \a name.
245   \param name the name of the operation set
246   \return operation set or 0 if not found
247 */
248 QtxEvalSet* QtxEvalParser::operationSet( const QString& name ) const
249 {
250   QtxEvalSet* set = 0;
251   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end() && !set; ++it )
252   {
253     if ( (*it)->name() == name )
254       set = *it;
255   }
256   return set;
257 }
258
259 /*!
260   \brief Install the operations set.
261   \param operations set to be added
262   \param idx index in the list at which the operations set shoud be inserted
263   \sa operationSets(), removeOperationSet(), operationSet()
264 */
265 void QtxEvalParser::insertOperationSet( QtxEvalSet* set, const int idx )
266 {
267   if ( mySets.contains( set ) )
268     return;
269
270   int index = idx < 0 ? mySets.count() : idx;
271   index = qMin( index, mySets.count() );
272   mySets.insert( index, set );
273 }
274
275 /*!
276   \brief Remove the operations set.
277   \param operations set to be removed
278   \sa operationSets(), insertOperationSet(), operationSet()
279 */
280 void QtxEvalParser::removeOperationSet( QtxEvalSet* set )
281 {
282   mySets.removeAll( set );
283 }
284
285 /*!
286   \brief Get the 'auto-delete operations' flag value.
287   \return \c true if all operations shoud be automatically deleted when the parser is destroyed
288   \sa setAutoDeleteOperationSets()
289 */
290 bool QtxEvalParser::autoDeleteOperationSets() const
291 {
292   return myAutoDel;
293 }
294
295 /*!
296   \brief Set the 'auto-delete operations' flag value.
297   \param on if \c true, all operations shoud be automatically deleted when the parser is destroyed
298   \sa autoDeleteOperationSets()
299 */
300 void QtxEvalParser::setAutoDeleteOperationSets( const bool on )
301 {
302   myAutoDel = on;
303 }
304
305 /*!
306   \brief Search elements of the list as substrings starting from \a offset.
307   \param list list of substrings
308   \param str string in which the searching is performed
309   \param offset starting index for search
310   \param matchLen returning matching length of any substring
311   \param listind returning index of the found substring in the \a list
312   \return position of first found substring inside the \a str or -1 if no matches is found
313 */
314 int QtxEvalParser::search( const QStringList& list, const QString& str,
315                            int offset, int& matchLen, int& listind )
316 {
317   int min = -1;
318   QStringList::const_iterator anIt = list.begin(), aLast = list.end();
319   for ( int ind = 0; anIt != aLast; anIt++, ind++ )
320   {
321     int pos = str.indexOf( *anIt, offset );
322     if ( pos >= 0 && ( min < 0 || min > pos ||
323                        ( min == pos && matchLen < (int)(*anIt).length() ) ) )
324     {
325       min = pos;
326       listind = ind;
327       matchLen = (*anIt).length();
328     }
329   }
330   if ( min < 0 )
331     matchLen = 0;
332   return min;
333 }
334
335 /*!
336   \brief Get the substring field from the string \a str.
337   \param str source string
338   \param pos start position of the substring
339   \param len length of the substring
340   \return substring (leading and trailing spaces are truncated)
341 */
342 QString QtxEvalParser::note( const QString& str, int pos, int len )
343 {
344     return str.mid( pos, len ).trimmed();
345 }
346
347 /*!
348   \brief Prepare to the parsing.
349
350   Performs the first step of the parsing:
351   - find tokens
352   - determine tokens types
353   - create unsorted pseudo-postfix (with brackets)
354
355   \param expr string expression
356   \param post postfix to be created
357   \return \c true on success and \c false if error is found
358 */
359 bool QtxEvalParser::prepare( const QString& expr, Postfix& post )
360 {
361   int pos = 0;
362   int len = expr.length();
363   QStack<int> aBracketStack;
364   QStringList anOpers, anOpenBr, aCloseBr;
365   if ( !checkOperations() )
366     return false;
367
368   bracketsList( anOpenBr, true );
369   bracketsList( aCloseBr, false );
370   operationList( anOpers );
371
372   while ( pos < len && error() == QtxEvalExpr::OK )
373   {
374     PostfixItem item;
375     while ( pos < len && expr[pos].isSpace() )
376       pos++;
377     if ( pos >= len )
378       break;
379
380     int mBrLen = 0, mLen = 0, br_ind = -1, op_ind = -1;
381     int oPos = search( anOpenBr, expr, pos, mBrLen, br_ind );
382     int cPos = oPos == pos ? -1 : search( aCloseBr, expr, pos, mBrLen, br_ind );
383     int opPos = search( anOpers, expr, pos, mLen, op_ind );
384
385     if ( expr[pos] == QChar( '\'' ) )
386     {
387       int vpos = pos + 1;
388       while ( vpos < (int)expr.length() && expr[vpos] != QChar( '\'' ) )
389         vpos++;
390
391       mLen = vpos - pos + 1;
392
393       int res = createValue( note( expr, pos, mLen ), item.myValue );
394       item.myType = res ? Value : Param;
395       post.append( item );
396       pos = vpos + 1;
397       continue;
398     }
399
400     if ( oPos == pos )
401     {
402       aBracketStack.push( br_ind );
403       item.myValue = note( expr, pos, mBrLen );
404       item.myType = Open;
405       post.append( item );
406     }
407     else if ( cPos == pos )
408     {
409       if ( aBracketStack.count() == 0 )
410       {
411         setError( QtxEvalExpr::ExcessClose );
412         break;
413       }
414       if ( br_ind != aBracketStack.top() )
415       {
416         setError( QtxEvalExpr::BracketsNotMatch );
417         break;
418       }
419       else
420       {
421         aBracketStack.pop();
422         item.myValue = note( expr, pos, mBrLen );
423         item.myType = Close;
424         post.append( item );
425       }
426     }
427     else
428       mBrLen = 0;
429
430     if ( opPos == pos )
431     {
432       mBrLen = 0;
433       item.myValue = note( expr, pos, mLen );
434       item.myType = Binary;
435
436       if ( oPos == pos )
437         post.insert( post.count() - 1, item );
438       else
439         post.append( item );
440     }
441     else
442     {
443       mLen = 0;
444       if ( oPos != pos && cPos != pos )
445       {
446               int i; 
447         for ( i = pos + 1; i < (int)expr.length(); i++ )
448         {
449           if ( expr[i].isSpace() )
450             break;
451         }
452
453         int vpos = i;
454         if ( oPos >= 0 && oPos < vpos )
455           vpos = oPos;
456         if ( cPos >= 0 && cPos < vpos )
457           vpos = cPos;
458         if ( opPos >= 0 && opPos < vpos )
459           vpos = opPos;
460
461         while( vpos < (int)expr.length() && 
462                ( expr[vpos].isLetter() || expr[vpos].isDigit() || expr[vpos]=='_' ) )
463           vpos++;
464
465         mLen = vpos - pos;
466         bool res = createValue( note( expr, pos, mLen ), item.myValue );
467         item.myType = res ? Value : Param;
468         post.append( item );
469       }
470     }
471
472     pos += mBrLen + mLen;
473   }
474
475   //Bracket checking
476   int brValue = 0;
477   for ( Postfix::iterator anIt = post.begin(); anIt != post.end(); ++anIt )
478   {
479     if ( (*anIt).myType == Open )
480       brValue++;
481     else if ( (*anIt).myType == Close )
482     {
483       if ( brValue > 0 )
484         brValue--;
485       else
486       {
487         setError( QtxEvalExpr::ExcessClose );
488         break;
489       }
490     }
491   }
492
493   if ( brValue > 0 )
494     setError( QtxEvalExpr::CloseExpected );
495
496   return error() == QtxEvalExpr::OK;
497 }
498
499 /*!
500   \brief Analyze the operations used.
501   
502   Second step of the parsing: analyze the types of the operations used in the expression.
503
504   \param post unsorted postfix
505   \return \c true on success and \c false if error is found
506 */
507 bool QtxEvalParser::setOperationTypes( Postfix& post )
508 {
509   if ( !checkOperations() )
510     return false;
511
512   QStringList anOpen, aClose;
513   bracketsList( anOpen, true );
514   bracketsList( aClose, false );
515
516   Postfix::iterator aPrev, aNext;
517   for ( Postfix::iterator anIt = post.begin(); anIt != post.end(); ++anIt )
518   {
519     aPrev = anIt;
520     aPrev--;
521     aNext = anIt;
522     aNext++;
523     if ( (*anIt).myType != Binary )
524       continue;
525
526     if ( ( anIt == post.begin() || (*aPrev).myType == Open ||
527            (*aPrev).myType == Pre || (*aPrev).myType == Binary ) &&  aNext != post.end() &&
528          ( (*aNext).myType == Value || (*aNext).myType == Param ||
529            (*aNext).myType == Open  || (*aNext).myType == Binary ) )
530       (*anIt).myType = Pre;
531     else if ( anIt != post.begin() && ( (*aPrev).myType == Close || (*aPrev).myType == Param ||
532                                         (*aPrev).myType == Value || (*aPrev).myType == Pre ||
533                                         (*aPrev).myType == Post || (*aPrev).myType == Binary ) &&
534               ( aNext == post.end() || (*aNext).myType == Close ) )
535       (*anIt).myType = Post;
536
537     if ( anOpen.contains( (*anIt).myValue.toString() ) )
538       (*anIt).myType = Pre;
539     else if ( aClose.contains( (*anIt).myValue.toString() ) )
540       (*anIt).myType = Post;
541   }
542
543   return error() == QtxEvalExpr::OK;
544 }
545
546 /*!
547   \brief Get the number of the globar brackets pairs.
548
549   For example, the expression '((2+3))' has 2 global brackets pairs.
550
551   \param post postfix to be checked
552   \param f starting position for the search
553   \param l last position for the search
554   \return number of brackets pairs
555 */
556 int QtxEvalParser::globalBrackets( const QtxEvalParser::Postfix& post, int f, int l )
557 {
558   int i;
559   int start_br = 0;
560   int fin_br = 0;
561   int br = 0;
562   int br_num = 0;
563   int min_br_num = (l-f+1)*5;
564     
565   for( i=f; i<=l; i++ )
566     if( post[ i ].myType==QtxEvalParser::Open )
567       start_br++;
568     else
569       break;
570   for( i=l; i>=f; i-- )
571     if( post[ i ].myType==QtxEvalParser::Close )
572       fin_br++;
573     else
574       break;
575
576   br = start_br<fin_br ? start_br : fin_br;
577   for( i=f+br; i<=l-br; i++ )
578   {
579     if( post[i].myType==QtxEvalParser::Open )
580       br_num++;
581     else if( post[i].myType==QtxEvalParser::Close )
582       br_num--;
583     if( br_num<min_br_num )
584       min_br_num = br_num;
585   }
586   
587   return br+min_br_num;
588 }
589
590 /*!
591   \brief Sort the operations in the postfix.
592
593   Third step of parsing: sort the postfix operations in order to convert it to real postfix.
594
595   \param post source postfix
596   \param res returning resulting postfix
597   \param anOpen list of open brackets
598   \param aClose list of close brackets
599   \param f start index of postfix for sorting
600   \param l last index of postfix for sorting
601   \return \c true on success and \c false if error is found
602 */
603 bool QtxEvalParser::sort( const Postfix& post, Postfix& res, const QStringList& anOpen,
604                           const QStringList& aClose, int f, int l )
605 {
606   if ( l < f )
607     return true;
608
609   if ( f < 0 )
610     f = 0;
611
612   if ( l < 0 )
613     l = post.count() - 1;
614
615   int br = globalBrackets( post, f, l );
616   f += br;
617   l -= br;
618
619   if ( f == l && f >= 0 )
620     res.append( post[f] );
621
622   if ( l <= f )
623     return true;
624
625   if ( !checkOperations() )
626     return false;
627
628   int min = -1;
629   QIntList argmin;
630   QList<PostfixItemType> min_types;
631
632   for ( int i = 0, j = f; j <= l; i++, j++ )
633   {
634     const PostfixItem& item = post[j];
635     PostfixItemType tt = item.myType;
636     if ( tt == Binary || tt == Pre || tt == Post )
637     {
638       int cur_pr = priority( item.myValue.toString(), tt == Binary );
639       if ( cur_pr > 0 )
640       {
641         if ( min < 0 || min >= cur_pr )
642         {
643           if ( min == cur_pr )
644           {
645             argmin.append( f + i );
646             min_types.append( tt );
647           }
648           else
649           {
650             min = cur_pr;
651             argmin.clear();
652             argmin.append( f + i );
653             min_types.clear(); min_types.append( tt );
654           }
655         }
656       }
657       else
658       {
659         setError( QtxEvalExpr::InvalidOperation );
660         break;
661       }
662     }
663     else if ( tt == Open )
664     {
665       QString opBr = item.myValue.toString();
666       int ind = anOpen.indexOf( opBr ), brValue = 0;
667       while ( j <= l )
668       {
669         const PostfixItem& anItem = post[j];
670         if ( anItem.myType == Open )
671           brValue++;
672
673         if ( anItem.myType == Close )
674         {
675           brValue--;
676           QString clBr = anItem.myValue.toString();
677           if ( aClose.indexOf( clBr ) == ind && brValue == 0 )
678             break;
679         }
680         i++; j++;
681       }
682
683       if ( brValue > 0 )
684       {
685         setError( QtxEvalExpr::CloseExpected );
686           break;
687       }
688     }
689   }
690
691   if ( error() == QtxEvalExpr::OK )
692   {
693     if ( min >= 0 )
694     {
695       Postfix one;
696       QList<Postfix> parts;
697       QIntList::const_iterator anIt = argmin.begin(), aLast = argmin.end();
698       bool ok = sort( post, one, anOpen, aClose, f, *anIt - 1 );
699       parts.append( one );
700       one.clear();
701       for ( ; anIt != aLast && ok; anIt++ )
702       {
703         QIntList::const_iterator aNext = anIt; aNext++;
704         ok = sort( post, one, anOpen, aClose, *anIt + 1, aNext == aLast ? l : *aNext - 1 );
705         parts.append( one );
706         one.clear();
707       }
708
709       if ( !ok )
710         return false;
711
712       QStack<PostfixItem> aStack;
713       QList<Postfix>::const_iterator aPIt = parts.begin();
714       QList<PostfixItemType>::const_iterator aTIt = min_types.begin();
715       res += (*aPIt);
716       aPIt++;
717       anIt = argmin.begin();
718       for ( ; anIt != aLast; anIt++, aPIt++, aTIt++ )
719       {
720         if ( *aTIt == Pre )
721         {
722           if ( anOpen.contains( post[*anIt].myValue.toString() ) == 0 )
723           {
724             res += (*aPIt);
725             aStack.push( post[ *anIt ] );
726           }
727           else
728           {
729             res.append( post[*anIt] );
730             res += *aPIt;
731           }
732         }
733         else
734         {
735           res += *aPIt;
736           while ( !aStack.isEmpty() )
737           {
738             res.append( aStack.top() );
739             aStack.pop();
740           }
741           res.append( post[*anIt] );
742         }
743       }
744       while ( !aStack.isEmpty() )
745       {
746         res.append( aStack.top() );
747         aStack.pop();
748       }
749     }
750     else
751     { //there are no operations
752       for ( int k = f; k <= l; k++ )
753       {
754         if ( post.at( k ).myType==Value || post.at( k ).myType == Param )
755           res.append( post.at( k ) );
756       }
757     }
758   }
759
760   return error() == QtxEvalExpr::OK;
761 }
762
763 /*!
764   \brief Parse the expression and build the posfix.
765
766   If by parsing error is found, the function returns \c false. In this case the code of the error
767   can be retrieved with error() method.
768
769   \param expr string expression
770   \return \c true on success and \c false if error is found
771 */
772 bool QtxEvalParser::parse( const QString& expr )
773 {
774   myPostfix.clear();
775
776   if ( !checkOperations() )
777     return false;
778
779   Postfix p;
780   QStringList opens, closes;
781
782   setError( QtxEvalExpr::OK );
783   bracketsList( opens, true );
784   bracketsList( closes, false );
785
786   return prepare( expr, p ) && setOperationTypes( p ) && sort( p, myPostfix, opens, closes );
787 }
788
789 /*!
790   \brief Calculate the operation.
791
792   The result of the operation is returned in the parameter \a v1.
793
794   \param op operation name
795   \param v1 first argument (not valid for unary prefix operations)
796   \param v2 second argument (not valid for unary postfix operations)
797   \return \c true on success and \c false if error is found
798 */
799 bool QtxEvalParser::calculate( const QString& op, QVariant& v1, QVariant& v2 )
800 {
801   QtxEvalExpr::Error err = isValid( op, v1.type(), v2.type() );
802   if ( err == QtxEvalExpr::OK )
803     setError( calculation( op, v1, v2 ) );
804   else
805     setError( err );
806
807   return error() == QtxEvalExpr::OK;
808 }
809
810 /*!
811   \brief Calculate the expression without postfix rebuilding.
812   \return QVariant as result (it is invalid if there were errors during calculation)
813 */
814 QVariant QtxEvalParser::calculate()
815 {
816   if ( !checkOperations() )
817     return QVariant();
818
819   setError( QtxEvalExpr::OK );
820
821   QStringList anOpen, aClose;
822   bracketsList( anOpen, true );
823   bracketsList( aClose, false );
824
825   QStack<QVariant> aStack;
826   Postfix::iterator anIt = myPostfix.begin(), aLast = myPostfix.end();
827   for ( ; anIt != aLast && error() == QtxEvalExpr::OK; anIt++ )
828   {
829     QString nn = (*anIt).myValue.toString();
830     if ( (*anIt).myType == Param )
831     {
832       if ( hasParameter( nn ) )
833       {
834         QVariant& v = myParams[nn];
835         if ( v.isValid() )
836           aStack.push( v );
837         else
838           setError( QtxEvalExpr::InvalidToken );
839       }
840       else
841         setError( QtxEvalExpr::InvalidToken );
842     }
843     else if ( (*anIt).myType == Value )
844       aStack.push( (*anIt).myValue );
845     else if ( (*anIt).myType == Pre || (*anIt).myType == Post )
846     {
847       if ( anOpen.contains( nn ) )
848       {
849         QVariant inv;
850         if ( calculate( nn, inv, inv ) )
851           aStack.push( QVariant() );
852       }
853       else if ( aClose.contains( nn ) )
854       {
855         QList<QVariant> set;
856         while ( true )
857         {
858           if ( aStack.isEmpty() )
859           {
860             setError( QtxEvalExpr::StackUnderflow );
861             break;
862           }
863           if ( aStack.top().isValid() )
864           {
865             set.append( aStack.top() );
866             aStack.pop();
867           }
868           else
869           {
870             aStack.pop();
871             break;
872           }
873         }
874
875         QVariant qSet = set, inv;
876         if ( calculate( nn, qSet, inv ) )
877           aStack.push( set );
878       }
879       else if ( aStack.count() >= 1 )
880       {
881         QVariant inv;
882         QVariant* v1 = &aStack.top(), *v2 = &inv; //"post-" case
883         if ( (*anIt).myType == Pre )
884         {
885           v2 = &aStack.top();
886           v1 = &inv;
887         }
888         calculate( nn, *v1, *v2 );
889       }
890       else
891         setError( QtxEvalExpr::StackUnderflow );
892     }
893     else if ( (*anIt).myType == Binary )
894     {
895       if ( aStack.count() >= 2 )
896       {
897         QVariant v2 = aStack.top();
898         aStack.pop();
899         calculate( nn, aStack.top(), v2 );
900       }
901       else
902         setError( QtxEvalExpr::StackUnderflow );
903     }
904   }
905
906   QVariant res;
907   if ( error() == QtxEvalExpr::OK )
908   {
909     int count = aStack.count();
910     if ( count == 0 )
911       setError( QtxEvalExpr::StackUnderflow );
912     else if( count == 1 )
913       res = aStack.top();
914     else
915       setError( QtxEvalExpr::ExcessData );
916   }
917   return res;
918 }
919
920 /*!
921   \brief Change the expression, rebuild the postfix and calculate it.
922   \param expr new expression
923   \return QVariant as result (it is invalid if there were errors during calculation)
924 */
925 QVariant QtxEvalParser::calculate( const QString& expr )
926 {
927   setExpression( expr );
928   return calculate();
929 }
930
931 /*!
932   \brief Change the expression and rebuild the postfix.
933   \param expr new expression
934   \return \c true on success and \c false if error is found
935 */
936 bool QtxEvalParser::setExpression( const QString& expr )
937 {
938   return parse( expr );
939 }
940
941 /*!
942   \brief Check if the parser contains specified parameter.
943   \param name parameter name
944   \return \c true, if the parser contains parameter
945 */
946 bool QtxEvalParser::hasParameter( const QString& name ) const
947 {
948   return myParams.contains( name.trimmed() );
949 }
950
951 /*!
952   \brief Set parameters value.
953   \param name parameter name
954   \param value parameter value
955 */
956 void QtxEvalParser::setParameter( const QString& name, const QVariant& value )
957 {
958   myParams.insert( name.trimmed(), value );
959 }
960
961 /*!
962   \brief Remove parameter.
963   \param name parameter name
964   \return \c true on success
965 */
966 bool QtxEvalParser::removeParameter( const QString& name )
967 {
968   return myParams.remove( name.trimmed() );
969 }
970
971 /*!
972   \brief Get the parameter value.
973   \param name parameter name
974   \return parameter value or invalud QVariant if there is no such parameter
975 */
976 QVariant QtxEvalParser::parameter( const QString& name ) const
977 {
978   QVariant res;
979   if ( myParams.contains( name.trimmed() ) )
980     res = myParams[name.trimmed()].toString();
981   return res;
982 }
983
984 /*!
985   \brief Search first parameter with assigned invalid value.
986   \param name used to retrieve the name of the parameter if it is found
987   \return \c true if parameter is found
988 */
989 bool QtxEvalParser::firstInvalid( QString& name ) const
990 {
991   for ( ParamMap::const_iterator anIt = myParams.begin(); anIt != myParams.end(); anIt++ )
992   {
993     if ( !anIt.value().isValid() )
994     {
995       name = anIt.key();
996       return true;
997     }
998   }
999   return false;
1000 }
1001
1002 /*!
1003   \brief Remove all parameters with assigned invalid values.
1004 */
1005 void QtxEvalParser::removeInvalids()
1006 {
1007   QStringList toDelete;
1008   for ( ParamMap::const_iterator anIt = myParams.begin(); anIt != myParams.end(); anIt++ )
1009   {
1010     if ( !anIt.value().isValid() )
1011       toDelete.append( anIt.key() );
1012   }
1013
1014   for ( QStringList::const_iterator aLIt = toDelete.begin(); aLIt != toDelete.end(); aLIt++ )
1015     myParams.remove( *aLIt );
1016 }
1017
1018 /*!
1019   \brief Get the code of the latest parsing error.
1020   \return last error code
1021 */
1022 QtxEvalExpr::Error QtxEvalParser::error() const
1023 {
1024   return myError;
1025 }
1026
1027 /*!
1028   \brief Set the error vode.
1029   \internal
1030   \param err error code
1031 */
1032 void QtxEvalParser::setError( QtxEvalExpr::Error err )
1033 {
1034   myError = err;
1035 }
1036
1037 /*!
1038   \brief Dump the current postfix contents to the string.
1039   \return string representation of the internal parser postfix
1040 */
1041 QString QtxEvalParser::dump() const
1042 {
1043   return dump( myPostfix );
1044 }
1045
1046 /*!
1047   \brief Dump the postfix contents to the string.
1048   \param post postfix to be dumped
1049   \return string representation of the postfix
1050 */
1051 QString QtxEvalParser::dump( const Postfix& post ) const
1052 {
1053   QString res;
1054
1055   if ( !checkOperations() )
1056     return res;
1057
1058   for ( Postfix::const_iterator anIt = post.begin(); anIt != post.end(); anIt++ )
1059   {
1060     if ( (*anIt).myType == Value && (*anIt).myValue.type() == QVariant::String )
1061       res += "'" + (*anIt).myValue.toString() + "'";
1062     else
1063       res += (*anIt).myValue.toString();
1064     
1065     if ( (*anIt).myType == Pre )
1066       res += "(pre)";
1067     else if ( (*anIt).myType == Post )
1068       res += "(post)";
1069     else if ( (*anIt).myType == Binary )
1070       res += "(bin)";
1071
1072     res += "_";
1073   }
1074
1075   return res;
1076 }
1077
1078 /*!
1079   \brief Get the list of the parameters names.
1080   \return parameters names
1081 */
1082 QStringList QtxEvalParser::parameters() const
1083 {
1084   QStringList lst;
1085   for ( Postfix::const_iterator anIt = myPostfix.begin(); anIt != myPostfix.end(); anIt++ )
1086   {
1087     if ( (*anIt).myType == Param )
1088     {
1089       QString name = (*anIt).myValue.toString();
1090       if ( !lst.contains( name ) )
1091         lst.append( name );
1092     }
1093   }
1094   return lst;
1095 }
1096
1097 /*!
1098   \brief Remove all parameters.
1099 */
1100 void QtxEvalParser::clearParameters()
1101 {
1102   myParams.clear();
1103 }
1104
1105 /*!
1106   \brief Get the string representation for the list of QVariant values.
1107   \param list list to be converted
1108   \return string representation for the list
1109 */
1110 QString QtxEvalParser::toString( const QList<QVariant>& list )
1111 {
1112   QString res = "set : [ ";
1113   for ( QList<QVariant>::const_iterator anIt = list.begin(); anIt != list.end(); anIt++ )
1114     res += (*anIt).toString() + " ";
1115   res += "]";
1116   return res;
1117 }
1118
1119 /*!
1120   \brief Get names of all operations used in the expression.
1121   \param list returning list of the operations names
1122 */
1123 void QtxEvalParser::operationList( QStringList& list ) const
1124 {
1125   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
1126   {
1127     QStringList custom;
1128     QtxEvalSet* set = *it;
1129     set->operationList( custom );
1130     for ( QStringList::const_iterator sIt = custom.begin(); sIt != custom.end(); ++sIt )
1131     {
1132       if ( !list.contains( *sIt ) )
1133         list.append( *sIt );
1134     }
1135   }
1136 }
1137
1138 /*!
1139   \brief Get list of brackets.
1140   \param list returning list of brackets
1141   \param open if \c true, collect opening brackets, or closing brackets otherwise
1142 */
1143 void QtxEvalParser::bracketsList( QStringList& list, bool open ) const
1144 {
1145   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
1146   {
1147     QStringList custom;
1148     QtxEvalSet* set = *it;
1149     set->bracketsList( custom, open );
1150     for ( QStringList::const_iterator sIt = custom.begin(); sIt != custom.end(); ++sIt )
1151     {
1152       if ( !list.contains( *sIt ) )
1153         list.append( *sIt );
1154     }
1155   }
1156 }
1157
1158 /*!
1159   \brief Create value.
1160   \param str parsed string
1161   \param val returning value
1162   \return \c true on success
1163 */
1164 bool QtxEvalParser::createValue( const QString& str, QVariant& val ) const
1165 {
1166   bool ok = false;
1167   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end() && !ok; ++it )
1168     ok = (*it)->createValue( str, val );
1169   return ok;
1170 }
1171
1172 /*!
1173   \brief Get the operation priority level.
1174   \param op operation
1175   \param isBin \c true if the operation is binary and \c false if it is unary
1176   \return operation priority
1177 */
1178 int QtxEvalParser::priority( const QString& op, bool isBin ) const
1179 {
1180   int i = 0;
1181   int priority = 0;
1182   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end() && priority <= 0; ++it, i++ )
1183     priority = (*it)->priority( op, isBin );
1184
1185   return priority > 0 ? priority + i * 50 : 0;
1186 }
1187
1188 /*!
1189   \brief Check operation validity.
1190
1191   If the operation is valid, QtxEvalExpr::OK is returned.
1192
1193   \param op operation
1194   \param t1 first operand type
1195   \param t2 second operand type
1196   \return error code (QtxEvalExpr::Error)
1197 */
1198 QtxEvalExpr::Error QtxEvalParser::isValid( const QString& op,
1199                                            const QVariant::Type t1, const QVariant::Type t2 ) const
1200 {
1201   QtxEvalExpr::Error err = QtxEvalExpr::OK;
1202   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
1203   {
1204     err = (*it)->isValid( op, t1, t2 );
1205     if ( err == QtxEvalExpr::OK )
1206       break;
1207   }
1208   return err;
1209 }
1210
1211 /*!
1212   \brief Perform calculation
1213   
1214   The result of the operation is returned in the parameter \a v1.
1215   If the operation is calculated correctly, the function returns QtxEvalExpr::OK.
1216
1217   \param op operation name
1218   \param v1 first argument (not valid for unary prefix operations)
1219   \param v2 second argument (not valid for unary postfix operations)
1220   \return error code (QtxEvalExpr::Error)
1221 */
1222 QtxEvalExpr::Error QtxEvalParser::calculation( const QString& op, QVariant& v1, QVariant& v2 ) const
1223 {
1224   QVariant nv1, nv2;
1225   for ( SetList::const_iterator it = mySets.begin(); it != mySets.end(); ++it )
1226   {
1227     nv1 = v1;
1228     nv2 = v2;
1229     if ( (*it)->isValid( op, v1.type(), v2.type() ) == QtxEvalExpr::OK )
1230     {
1231       QtxEvalExpr::Error err = (*it)->calculate( op, nv1, nv2 );
1232       if ( err == QtxEvalExpr::OK || err == QtxEvalExpr::InvalidResult )
1233       {
1234         v1 = nv1;
1235         v2 = nv2;
1236         return err;
1237       }
1238     }
1239   }
1240   return QtxEvalExpr::InvalidOperation;
1241 }
1242
1243 /*!
1244   \brief Check current operations set.
1245   \return \c false if current set of operations is empty
1246 */
1247 bool QtxEvalParser::checkOperations() const
1248 {
1249   if ( !mySets.isEmpty() )
1250     return true;
1251
1252   QtxEvalParser* that = (QtxEvalParser*)this;
1253   that->setError( QtxEvalExpr::OperationsNull );
1254   return false;
1255 }
1256
1257 /*!
1258   \class QtxEvalSet
1259   \brief Generic class for all the operations sets used in expressions.
1260 */
1261
1262 /*!
1263   \brief Constructor.
1264 */
1265 QtxEvalSet::QtxEvalSet()
1266 {
1267 }
1268
1269 /*!
1270   \brief Destructor.
1271 */
1272 QtxEvalSet::~QtxEvalSet()
1273 {
1274 }
1275
1276 /*!
1277   \fn void QtxEvalSet::operationList( QStringList& list ) const;
1278   \brief Get the list of possible operations.
1279   \param list returning list of operations supported by the class
1280 */
1281
1282 /*!
1283   \fn void QtxEvalSet::bracketsList( QStringList& list, bool open ) const;
1284   \brief Get list of brackets.
1285   \param list returning list of brackets
1286   \param open if \c true, collect opening brackets, or closing brackets otherwise
1287 */
1288
1289 /*!
1290   \brief Create value from its string representation.
1291
1292   By default, the string value is set, that corresponds to the parameter.
1293   Base implementation always returns \c false (it means that string 
1294   is evaluated to the parameter).
1295   Successor class can re-implement this method to return \c true 
1296   if the argument being parsed can be evaluated as custom value.
1297
1298   \param str string representration of the value
1299   \param val returning value
1300   \return \c true if \a str can be evaluated as custom value and \c false
1301           otherwise (parameter)
1302 */
1303 bool QtxEvalSet::createValue( const QString& str, QVariant& val ) const
1304 {
1305   val = str;
1306   return false;
1307 }
1308
1309 /*!
1310   \fn int QtxEvalSet::priority( const QString& op, bool isBin ) const;
1311   \brief Get the operation priority.
1312
1313   Operation priority counts from 1.
1314   If the operation is impossible, this function should return value <= 0.
1315   
1316   \param op operation
1317   \param isBin \c true if the operation is binary and \c false if it is unary
1318   \return operation priority
1319 */
1320
1321 /*!
1322   \fn QtxEvalExpr::Error QtxEvalSet::isValid( const QString& op, const QVariant::Type t1, 
1323                                               const QVariant::Type t2 ) const;
1324   \brief Check operation validity.
1325
1326   If the operation is valid, QtxEvalExpr::OK is returned.
1327   If types of operands are invalid, the function returns QtxEvalExpr::OperandsNotMatch
1328   or QtxEvalExpr::InvalidOperation.
1329
1330   \param op operation
1331   \param t1 first operand type
1332   \param t2 second operand type
1333   \return error code (QtxEvalExpr::Error)
1334 */
1335
1336 /*!
1337   \fn QtxEvalExpr::Error QtxEvalSet::calculate( const QString& op, QVariant& v1,
1338                                                 QVariant& v2 ) const;
1339   \brief Calculate the operation.
1340
1341   Process binary operation with values \a v1 and \a v2.
1342   For unary operation the \v2 is invalid.
1343   The result of the operation is returned in the parameter \a v1.
1344
1345   \param op operation name
1346   \param v1 first argument (not valid for unary prefix operations)
1347   \param v2 second argument (not valid for unary postfix operations)
1348   \return error code (QtxEvalExpr::Error)
1349 */
1350
1351 /*!
1352   \fn QString QtxEvalSet::name() const;
1353   \brief Get unique operations set name.
1354
1355   Should be redefined in the successor classes.
1356
1357   \return operations set name
1358 */
1359
1360 /*!
1361   \class QtxEvalSetBase
1362   \brief Generic class. Provides functionality for standard operations sets.
1363 */
1364
1365 /*!
1366   \brief Constructor.
1367 */
1368 QtxEvalSetBase::QtxEvalSetBase()
1369 {
1370 }
1371
1372 /*!
1373   \brief Destructor.
1374 */
1375 QtxEvalSetBase::~QtxEvalSetBase()
1376 {
1377 }
1378
1379 /*!
1380   \brief Get list of brackets.
1381   \param list returning list of brackets
1382   \param open if \c true, collect opening brackets, or closing brackets otherwise
1383 */
1384 void QtxEvalSetBase::bracketsList( QStringList& list, bool open ) const
1385 {
1386   list.append( open ? "(" : ")" );
1387 }
1388
1389 /*!
1390   \brief Get the list of possible operations.
1391   \param list returning list of operations supported by the class
1392 */
1393 void QtxEvalSetBase::operationList( QStringList& list ) const
1394 {
1395   list += myOpers;
1396 }
1397
1398 /*!
1399   \brief Add operation names to the internal list of operations.
1400   \param list operations to be added
1401 */
1402 void QtxEvalSetBase::addOperations( const QStringList& list )
1403 {
1404   for ( QStringList::const_iterator anIt = list.begin(); anIt != list.end(); ++anIt )
1405   {
1406     if ( !myOpers.contains( *anIt ) )
1407       myOpers.append( *anIt );
1408   }
1409 }
1410
1411 /*!
1412   \brief Add operand types.
1413   \param list operand types to be added
1414 */
1415 void QtxEvalSetBase::addTypes( const ListOfTypes& list )
1416 {
1417   for ( ListOfTypes::const_iterator anIt = list.begin(); anIt != list.end(); ++anIt )
1418   {
1419     if ( !myTypes.contains( *anIt ) )
1420       myTypes.append( *anIt );
1421   }
1422 }
1423
1424 /*!
1425   \brief Check operation validity.
1426
1427   If the operation is valid, QtxEvalExpr::OK is returned.
1428   If types of operands are invalid, the function returns QtxEvalExpr::OperandsNotMatch
1429   or QtxEvalExpr::InvalidOperation.
1430
1431   \param op operation
1432   \param t1 first operand type
1433   \param t2 second operand type
1434   \return error code (QtxEvalExpr::Error)
1435 */
1436 QtxEvalExpr::Error QtxEvalSetBase::isValid( const QString& op,
1437                                             const QVariant::Type t1, const QVariant::Type t2 ) const
1438 {
1439   if ( ( t1 == QVariant::Invalid || myTypes.contains( t1 ) ) &&
1440        ( t2 == QVariant::Invalid || myTypes.contains( t2 ) ) &&
1441        ( t1 != QVariant::Invalid || t2 != QVariant::Invalid ) )
1442   {
1443     if ( priority( op, t1 != QVariant::Invalid && t2 != QVariant::Invalid ) > 0 )
1444       return QtxEvalExpr::OK;
1445     else
1446       return QtxEvalExpr::InvalidOperation;
1447   }
1448   else
1449     return QtxEvalExpr::OperandsNotMatch;
1450 }
1451
1452 /*!
1453   \class QtxEvalSetArithmetic
1454   \brief Provides set of arithmetical operations for the parser.
1455 */
1456
1457 /*!
1458   \brief Constructor.
1459 */
1460 QtxEvalSetArithmetic::QtxEvalSetArithmetic()
1461 : QtxEvalSetBase()
1462 {
1463   addOperations( QString( "+;-;*;/;=;<;>;<=;>=;<>;!=" ).split( ";" ) );
1464
1465   ListOfTypes aTypes;
1466   aTypes.append( QVariant::Int );
1467   aTypes.append( QVariant::UInt );
1468   aTypes.append( QVariant::Double );
1469   addTypes( aTypes );
1470 }
1471
1472 /*!
1473   \brief Destructor.
1474 */
1475 QtxEvalSetArithmetic::~QtxEvalSetArithmetic()
1476 {
1477 }
1478
1479 /*!
1480   \brief Get operations set name.
1481   \return operations set name
1482 */
1483 QString QtxEvalSetArithmetic::Name()
1484 {
1485   return "Arithmetic";
1486 }
1487
1488 /*!
1489   \brief Get operations set name.
1490   \return operations set name
1491 */
1492 QString QtxEvalSetArithmetic::name() const
1493 {
1494   return Name();
1495 }
1496
1497 /*!
1498   \brief Create value from its string representation.
1499
1500   Creates numbers from string representation.
1501
1502   \param str string representration of the value
1503   \param val returning value
1504   \return \c true if \a str can be evaluated as custom value and \c false
1505           otherwise (parameter)
1506 */
1507 bool QtxEvalSetArithmetic::createValue( const QString& str, QVariant& val ) const
1508 {
1509   bool ok = false;
1510   val = str.toInt( &ok );
1511
1512   if ( !ok )
1513   {
1514     val = str.toDouble( &ok );
1515     if ( !ok )
1516       ok = QtxEvalSetBase::createValue( str, val );
1517   }
1518   return ok;
1519 }
1520
1521 /*!
1522   \brief Get the operation priority.
1523
1524   Operation priority counts from 1.
1525   If the operation is impossible, this function returns value <= 0.
1526   
1527   \param op operation
1528   \param isBin \c true if the operation is binary and \c false if it is unary
1529   \return operation priority
1530 */
1531 int QtxEvalSetArithmetic::priority( const QString& op, bool isBin ) const
1532 {
1533   if ( isBin )
1534   {
1535     if ( op == "<" || op == ">" || op == "=" ||
1536          op == "<=" || op == ">=" || op == "<>" || op == "!=" )
1537       return 1;
1538     else if ( op == "+" || op == "-" )
1539       return 2;
1540     else if( op == "*" || op == "/" )
1541       return 3;
1542     else
1543       return 0;
1544   }
1545   else if ( op == "+" || op == "-" )
1546     return 5;
1547   else
1548     return 0;
1549 }
1550
1551 /*!
1552   \brief Calculate the operation.
1553
1554   Process binary operation with values \a v1 and \a v2.
1555   For unary operation the \v2 is invalid.
1556   The result of the operation is returned in the parameter \a v1.
1557
1558   \param op operation name
1559   \param v1 first argument (not valid for unary prefix operations)
1560   \param v2 second argument (not valid for unary postfix operations)
1561   \return error code (QtxEvalExpr::Error)
1562 */
1563 QtxEvalExpr::Error QtxEvalSetArithmetic::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
1564 {
1565   QtxEvalExpr::Error err = QtxEvalExpr::OK;
1566
1567   if ( v1.isValid() && v2.isValid() )
1568   {
1569     // binary operations
1570     if ( ( v1.type() == QVariant::Int || v1.type() == QVariant::UInt ) &&
1571          ( v2.type() == QVariant::Int || v2.type() == QVariant::UInt ) )
1572     {
1573       int _v1 = v1.toInt();
1574       int _v2 = v2.toInt();
1575
1576       if ( op == "+" )
1577         v1 = _v1 + _v2;
1578       else if ( op == "-" )
1579         v1 = _v1 - _v2;
1580       else if ( op == "*" )
1581         v1 = _v1 * _v2;
1582       else if ( op == "/" )
1583       {
1584         if ( _v2 != 0 )
1585         {
1586           if ( _v1 % _v2 == 0 )
1587             v1 = _v1 / _v2;
1588           else
1589             v1 = double( _v1 ) / double( _v2 );
1590         }
1591         else
1592           err = QtxEvalExpr::InvalidResult;
1593       }
1594       else if ( op == "<" )
1595         v1 = _v1 < _v2;
1596       else if ( op == ">" )
1597         v1 = _v1 > _v2;
1598       else if ( op == "=" )
1599         v1 = _v1 == _v2;
1600       else if ( op == "<=" )
1601         v1 = _v1 <= _v2;
1602       else if ( op == ">=" )
1603         v1 = _v1 >= _v2;
1604       else if ( op == "<>" || op == "!=" )
1605         v1 = _v1 != _v2;
1606     }
1607     else if ( ( v1.type() == QVariant::Int || v1.type() == QVariant::Double ) &&
1608               ( v2.type() == QVariant::Int || v2.type() == QVariant::Double ) )
1609     {
1610       double _v1 = v1.toDouble();
1611       double _v2 = v2.toDouble();
1612
1613       if ( op == "+" )
1614         v1 = _v1 + _v2;
1615       else if ( op == "-" )
1616         v1 = _v1 - _v2;
1617       else if ( op == "*" )
1618           v1 = _v1 * _v2;
1619       else if ( op == "/" )
1620       {
1621         if ( _v2 != 0 )
1622           v1 = _v1 / _v2;
1623         else
1624           err = QtxEvalExpr::InvalidResult;
1625       }
1626       else if ( op == "<" )
1627         v1 = _v1 < _v2;
1628       else if ( op == ">" )
1629         v1 = _v1 > _v2;
1630       else if ( op == "=" )
1631         v1 = _v1 == _v2;
1632       else if ( op == "<=" )
1633         v1 = _v1 <= _v2;
1634       else if ( op == ">=" )
1635         v1 = _v1 >= _v2;
1636       else if ( op == "<>" || op == "!=" )
1637         v1 = _v1 != _v2;
1638     }
1639     else // prefix operations
1640     {
1641       if ( op == "-" )
1642       {
1643         if ( v2.type() == QVariant::Int )
1644           v2 = -v2.toInt();
1645         else if ( v2.type() == QVariant::Double )
1646           v2 = -v2.toDouble();
1647       }
1648     }
1649   }
1650
1651   return err;
1652 }
1653
1654 /*!
1655   \class QtxEvalSetLogic
1656   \brief Provides set of logical operations for the parser.
1657 */
1658
1659 /*!
1660   \brief Constructor.
1661 */
1662 QtxEvalSetLogic::QtxEvalSetLogic()
1663 : QtxEvalSetBase()
1664 {
1665   addOperations( QString( "and;&&;or;||;xor;not;!;imp;=" ).split( ";" ) );
1666
1667   ListOfTypes aTypes;
1668   aTypes.append( QVariant::Bool );
1669   aTypes.append( QVariant::Int );
1670   aTypes.append( QVariant::UInt );
1671   addTypes( aTypes );
1672 }
1673
1674 /*!
1675   \brief Destructor.
1676 */
1677 QtxEvalSetLogic::~QtxEvalSetLogic()
1678 {
1679 }
1680
1681 /*!
1682   \brief Get operations set name.
1683   \return operations set name
1684 */
1685 QString QtxEvalSetLogic::Name()
1686 {
1687   return "Logic";
1688 }
1689
1690 /*!
1691   \brief Get operations set name.
1692   \return operations set name
1693 */
1694 QString QtxEvalSetLogic::name() const
1695 {
1696   return Name();
1697 }
1698
1699 /*!
1700   \brief Create value from its string representation.
1701
1702   Create \c true or \c false value from string representation.
1703
1704   \param str string representration of the value
1705   \param val returning value
1706   \return \c true if \a str can be evaluated as custom value and \c false
1707           otherwise (parameter)
1708 */
1709 bool QtxEvalSetLogic::createValue( const QString& str, QVariant& val ) const
1710 {
1711   bool ok = true;
1712   QString valStr = str.toLower();
1713   if ( valStr == "true" || valStr == "yes" )
1714     val = QVariant( true );
1715   else if ( valStr == "false" || valStr == "no" )
1716     val = QVariant( false );
1717   else
1718     ok = QtxEvalSetBase::createValue( str, val );
1719
1720   return ok;
1721 }
1722
1723 /*!
1724   \brief Get the operation priority.
1725
1726   Operation priority counts from 1.
1727   If the operation is impossible, this function returns value <= 0.
1728   
1729   \param op operation
1730   \param isBin \c true if the operation is binary and \c false if it is unary
1731   \return operation priority
1732 */
1733 int QtxEvalSetLogic::priority( const QString& op, bool isBin ) const
1734 {
1735   if ( isBin )
1736   {
1737     if ( op == "and" || op == "or" || op == "xor" || op == "&&" || op == "||" || op == "imp" )
1738       return 1;
1739     else if ( op == "=" )
1740       return 2;
1741     else 
1742       return 0;
1743   }
1744   else if ( op == "not" || op == "!" )
1745     return 5;
1746   else
1747     return 0;
1748 }
1749
1750 /*!
1751   \brief Calculate the operation.
1752
1753   Process binary operation with values \a v1 and \a v2.
1754   For unary operation the \v2 is invalid.
1755   The result of the operation is returned in the parameter \a v1.
1756
1757   \param op operation name
1758   \param v1 first argument (not valid for unary prefix operations)
1759   \param v2 second argument (not valid for unary postfix operations)
1760   \return error code (QtxEvalExpr::Error)
1761 */
1762 QtxEvalExpr::Error QtxEvalSetLogic::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
1763 {
1764   QtxEvalExpr::Error err = QtxEvalExpr::OK;
1765   int val1 = intValue( v1 );
1766   int val2 = intValue( v2 );
1767   if ( v1.isValid() && v2.isValid() )
1768   {
1769     if ( op == "and" || op == "&&" )
1770       v1 = val1 && val2;
1771     else if ( op == "or" || op == "||" )
1772       v1 = val1 || val2;
1773     else if ( op == "xor" )
1774       v1 = ( !val1 && val2 ) || ( val1 && !val2 );
1775     else if ( op == "imp" )
1776       v1 = !val1 || val2;
1777     else if ( op == "=" )
1778       v1 = val1 == val2;
1779   }
1780   else if ( op == "not" || op == "!" )
1781     v2 = !val2;
1782
1783   return err;
1784 }
1785
1786 /*!
1787   \brief Convert value to the integer.
1788
1789   Note: the value is converted to the integer (not boolean) in order
1790   to compare integer numbers correctly.
1791
1792   \param v value being converted
1793   \return converted value
1794 */
1795 int QtxEvalSetLogic::intValue( const QVariant& v ) const
1796 {
1797   int res = 0;
1798   switch ( v.type() )
1799   {
1800   case QVariant::Bool:
1801     res = v.toBool() ? 1 : 0;
1802     break;
1803   case QVariant::Int:
1804   case QVariant::UInt:
1805     res = v.toInt();
1806     break;
1807   default:
1808     break;
1809   }
1810   return res;
1811 }
1812
1813 /*!
1814   \class QtxEvalSetMath
1815   \brief Provides a set of more complex operations (mathematical functions)
1816          for the parser (sqrt, sin, cos, etc).
1817 */
1818
1819 /*!
1820   \brief Constructor.
1821 */
1822 QtxEvalSetMath::QtxEvalSetMath()
1823 : QtxEvalSetBase()
1824 {
1825   addOperations( QString( "sqrt;abs;sin;cos;rad2grad;grad2rad" ).split( ";" ) );
1826
1827   ListOfTypes aTypes;
1828   aTypes.append( QVariant::Int );
1829   aTypes.append( QVariant::Double );
1830   addTypes( aTypes );
1831 }
1832
1833 /*!
1834   \brief Destructor.
1835 */
1836 QtxEvalSetMath::~QtxEvalSetMath()
1837 {
1838 }
1839
1840 /*!
1841   \brief Get operations set name.
1842   \return operations set name
1843 */
1844 QString QtxEvalSetMath::Name()
1845 {
1846   return "Math";
1847 }
1848
1849 /*!
1850   \brief Get operations set name.
1851   \return operations set name
1852 */
1853 QString QtxEvalSetMath::name() const
1854 {
1855   return Name();
1856 }
1857
1858 /*!
1859   \brief Create value from its string representation.
1860
1861   Creates numbers from string representation.
1862
1863   \param str string representration of the value
1864   \param val returning value
1865   \return \c true if \a str can be evaluated as custom value and \c false
1866           otherwise (parameter)
1867 */
1868 bool QtxEvalSetMath::createValue( const QString& str, QVariant& val ) const
1869 {
1870   bool ok = false;
1871   val = str.toInt( &ok );
1872
1873   if ( !ok )
1874   {
1875     val = str.toDouble( &ok );
1876     if ( !ok )
1877       ok = QtxEvalSetBase::createValue( str, val );
1878   }
1879   return ok;
1880 }
1881
1882 /*!
1883   \brief Get the operation priority.
1884
1885   Operation priority counts from 1.
1886   If the operation is impossible, this function returns value <= 0.
1887   
1888   \param op operation
1889   \param isBin \c true if the operation is binary and \c false if it is unary
1890   \return operation priority
1891 */
1892 int QtxEvalSetMath::priority( const QString& op, bool isBin ) const
1893 {
1894   if ( isBin )
1895     return 0;
1896   else if ( op == "sqrt" || op == "abs" || op == "sin" ||
1897             op == "cos" || op == "rad2grad" || op == "grad2rad" )
1898     return 1;
1899   else
1900     return 0;
1901 }
1902
1903 /*!
1904   \brief Calculate the operation.
1905
1906   Process binary operation with values \a v1 and \a v2.
1907   For unary operation the \v2 is invalid.
1908   The result of the operation is returned in the parameter \a v1.
1909
1910   \param op operation name
1911   \param v1 first argument (not valid for unary prefix operations)
1912   \param v2 second argument (not valid for unary postfix operations)
1913   \return error code (QtxEvalExpr::Error)
1914 */
1915 QtxEvalExpr::Error QtxEvalSetMath::calculate( const QString& op, QVariant& /*v1*/, QVariant& v2 ) const
1916 {
1917   QtxEvalExpr::Error err = QtxEvalExpr::OK;
1918   double val = v2.toDouble();
1919   if ( op == "sqrt" )
1920   {
1921     if ( val >= 0 )
1922       v2 = sqrt( val );
1923     else
1924       err = QtxEvalExpr::InvalidResult;
1925   }
1926   else if ( op == "abs" )
1927   {
1928     if ( v2.type() == QVariant::Int )
1929       v2 = abs( v2.toInt() );
1930     else 
1931       v2 = fabs( v2.toDouble() );
1932   }
1933   else if ( op == "sin" )
1934     v2 = sin( val );
1935   else if ( op == "cos" )
1936     v2 = cos( val );
1937   else if ( op == "grad2rad" )
1938     v2 = val * 3.14159256 / 180.0;
1939   else if ( op == "rad2grad" )
1940     v2 = val * 180.0 / 3.14159256;
1941
1942   return err;
1943 }
1944
1945 /*!
1946   \class QtxEvalSetString
1947   \brief Provides set of string operations for the parser.
1948 */
1949
1950 /*!
1951   \brief Constructor.
1952 */
1953 QtxEvalSetString::QtxEvalSetString()
1954 : QtxEvalSetBase()
1955 {
1956   addOperations( QString( "+;=;<;>;<=;>=;<>;!=;length;lower;upper" ).split( ";" ) );
1957
1958   ListOfTypes aTypes;
1959   aTypes.append( QVariant::Int );
1960   aTypes.append( QVariant::Double );
1961   aTypes.append( QVariant::String );
1962   addTypes( aTypes );
1963 }
1964
1965 /*!
1966   \brief Destructor.
1967 */
1968 QtxEvalSetString::~QtxEvalSetString()
1969 {
1970 }
1971
1972 /*!
1973   \brief Get operations set name.
1974   \return operations set name
1975 */
1976 QString QtxEvalSetString::Name()
1977 {
1978   return "String";
1979 }
1980
1981 /*!
1982   \brief Get operations set name.
1983   \return operations set name
1984 */
1985 QString QtxEvalSetString::name() const
1986 {
1987   return Name();
1988 }
1989
1990 /*!
1991   \brief Create value from its string representation.
1992
1993   Creates string value from Qt string representation.
1994
1995   \param str string representration of the value
1996   \param val returning value
1997   \return \c true if \a str can be evaluated as custom value and \c false
1998           otherwise (parameter)
1999 */
2000 bool QtxEvalSetString::createValue( const QString& str, QVariant& val ) const
2001 {
2002   bool ok = false;
2003   if ( str.length() > 1 && str[0] == '\'' && str[str.length() - 1] == '\'' )
2004   {
2005     val = str.mid( 1, str.length() - 2 );
2006     ok = true;
2007   }
2008   else
2009     ok = QtxEvalSetBase::createValue( str, val );
2010   return ok;
2011 }
2012
2013 /*!
2014   \brief Get the operation priority.
2015
2016   Operation priority counts from 1.
2017   If the operation is impossible, this function returns value <= 0.
2018   
2019   \param op operation
2020   \param isBin \c true if the operation is binary and \c false if it is unary
2021   \return operation priority
2022 */
2023 int QtxEvalSetString::priority( const QString& op, bool isBin ) const
2024 {
2025   if ( isBin )
2026   {
2027     if ( op == "+" ) 
2028       return 2;
2029     else if ( op == "=" || op == "<" || op == ">" ||
2030               op == "<=" || op == ">=" || op == "<>" || op == "!=" )
2031       return 1;
2032     else
2033       return 0;
2034   }
2035   else if ( op == "length" || op == "lower" || op=="upper" )
2036     return 5;
2037   else
2038     return 0;
2039 }
2040
2041 /*!
2042   \brief Calculate the operation.
2043
2044   Process binary operation with values \a v1 and \a v2.
2045   For unary operation the \v2 is invalid.
2046   The result of the operation is returned in the parameter \a v1.
2047
2048   \param op operation name
2049   \param v1 first argument (not valid for unary prefix operations)
2050   \param v2 second argument (not valid for unary postfix operations)
2051   \return error code (QtxEvalExpr::Error)
2052 */
2053 QtxEvalExpr::Error QtxEvalSetString::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
2054 {
2055   QtxEvalExpr::Error err = QtxEvalExpr::OK;
2056   if ( v1.isValid() && v2.isValid() )
2057   {
2058     QString _v1 = v1.toString();
2059     QString _v2 = v2.toString();
2060     if ( op == "+" )
2061       v1 = _v1 + _v2;
2062     else if ( op == "=" )
2063       v1 = _v1 ==_v2;
2064     else if ( op == "<" )
2065       v1 = _v1 < _v2;
2066     else if ( op == ">" )
2067       v1 = _v1 > _v2;
2068     else if ( op == "<>" || op == "!=" )
2069       v1 = _v1 != _v2;
2070     else if ( op == "<=" )
2071       v1 = _v1 < _v2 || _v1 == _v2;
2072     else if ( op == ">=" )
2073       v1 = _v1 > _v2 || _v1 == _v2;
2074   }
2075   else if ( !v1.isValid() && v2.isValid() )
2076   {
2077     QString val = v2.toString();
2078     if ( op == "length" )
2079       v2 = (int)val.length();
2080     else if ( op == "lower" )
2081       v2 = val.toLower();
2082     else if ( op == "upper" )
2083       v2 = val.toUpper();
2084   }
2085   return err;
2086 }
2087
2088 /*!
2089   \class QtxEvalSetSets
2090   \brief Provides set of operations with sequences for the parser.
2091 */
2092
2093 /*!
2094   \brief Constructor.
2095 */
2096 QtxEvalSetSets::QtxEvalSetSets()
2097 : QtxEvalSetBase()
2098 {
2099   addOperations( QString( "{;};=;<>;!=;+;-;*;in;count" ).split( ";" ) );
2100
2101   ListOfTypes aTypes;
2102   aTypes.append( QVariant::List );
2103   addTypes( aTypes );
2104 }
2105
2106 /*!
2107   \brief Destructor.
2108 */
2109 QtxEvalSetSets::~QtxEvalSetSets()
2110 {
2111 }
2112
2113 /*!
2114   \brief Get operations set name.
2115   \return operations set name
2116 */
2117 QString QtxEvalSetSets::Name()
2118 {
2119   return "Sets";
2120 }
2121
2122 /*!
2123   \brief Get operations set name.
2124   \return operations set name
2125 */
2126 QString QtxEvalSetSets::name() const
2127 {
2128   return Name();
2129 }
2130
2131 /*!
2132   \brief Get list of brackets.
2133   \param list returning list of brackets
2134   \param open if \c true, collect opening brackets, or closing brackets otherwise
2135 */
2136 void QtxEvalSetSets::bracketsList( QStringList& list, bool open ) const
2137 {
2138   list.append( open ? "{" : "}" );
2139   QtxEvalSetBase::bracketsList( list, open );
2140 }
2141
2142 /*!
2143   \brief Get the operation priority.
2144
2145   Operation priority counts from 1.
2146   If the operation is impossible, this function returns value <= 0.
2147   
2148   \param op operation
2149   \param isBin \c true if the operation is binary and \c false if it is unary
2150   \return operation priority
2151 */
2152 int QtxEvalSetSets::priority( const QString& op, bool isBin ) const
2153 {
2154   if ( isBin )
2155   {
2156     if ( op == "=" || op == "<>" || op == "!=" )
2157       return 1;
2158     else if ( op == "+" || op == "-" || op == "*" )
2159       return 2;
2160     else if ( op == "in" )
2161       return 3;
2162     else
2163       return 0;
2164   }
2165   else if ( op == "{" || op == "}" )
2166     return 5;
2167   else if ( op == "count" )
2168     return 4;
2169   else
2170     return 0;
2171 }
2172
2173 /*!
2174   \brief Check operation validity.
2175
2176   If the operation is valid, QtxEvalExpr::OK is returned.
2177   If types of operands are invalid, the function returns QtxEvalExpr::OperandsNotMatch
2178   or QtxEvalExpr::InvalidOperation.
2179
2180   \param op operation
2181   \param t1 first operand type
2182   \param t2 second operand type
2183   \return error code (QtxEvalExpr::Error)
2184 */
2185 QtxEvalExpr::Error QtxEvalSetSets::isValid( const QString& op,
2186                                             const QVariant::Type t1, const QVariant::Type t2 ) const
2187 {
2188   if ( op == "{" )
2189     return QtxEvalExpr::OK;
2190
2191   if ( op != "in" )
2192     return QtxEvalSetBase::isValid( op, t1, t2 );
2193
2194   if ( t1 != QVariant::Invalid && t2 == QVariant::List )
2195     return QtxEvalExpr::OK;
2196   else
2197     return QtxEvalExpr::OperandsNotMatch;
2198 }
2199
2200 /*!
2201   \brief Add new value \a v to the sequence \a set.
2202   \param set sequence
2203   \param v value to be added
2204 */
2205 void QtxEvalSetSets::add( ValueSet& set, const QVariant& v )
2206 {
2207   if ( v.isValid() && !set.contains( v ) )
2208     set.append( v );
2209 }
2210
2211 /*!
2212   \brief Add all values from sequence \a s2 to the sequence \a s1.
2213   \param s1 destination sequence
2214   \param s2 source sequence
2215 */
2216 void QtxEvalSetSets::add( ValueSet& s1, const ValueSet& s2 )
2217 {
2218   for ( ValueSet::const_iterator anIt = s2.begin(); anIt != s2.end(); ++anIt )
2219     add( s1, *anIt );
2220 }
2221
2222 /*!
2223   \brief Remove value \a v from sequence \a set.
2224   \param set sequence
2225   \param v value to be removed
2226 */
2227 void QtxEvalSetSets::remove( ValueSet& set, const QVariant& v )
2228 {
2229   set.removeAll( v );
2230 }
2231
2232 /*!
2233   \brief Remove all values listed in the sequence \a s2 from the sequence \a s1.
2234   \param s1 sequence from which items are removed
2235   \param s2 sequence which items are removed
2236 */
2237 void QtxEvalSetSets::remove( ValueSet& s1, const ValueSet& s2 )
2238 {
2239   for ( ValueSet::const_iterator anIt = s2.begin(); anIt != s2.end(); ++anIt )
2240     s1.removeAll( *anIt );
2241 }
2242
2243 /*!
2244   \brief Calculate the operation.
2245
2246   Process binary operation with values \a v1 and \a v2.
2247   For unary operation the \v2 is invalid.
2248   The result of the operation is returned in the parameter \a v1.
2249
2250   \param op operation name
2251   \param v1 first argument (not valid for unary prefix operations)
2252   \param v2 second argument (not valid for unary postfix operations)
2253   \return error code (QtxEvalExpr::Error)
2254 */
2255 QtxEvalExpr::Error QtxEvalSetSets::calculate( const QString& op, QVariant& v1, QVariant& v2 ) const
2256 {
2257   QtxEvalExpr::Error err = QtxEvalExpr::OK;
2258
2259   if ( op != "{" )
2260   {
2261     if ( op == "}" )
2262     {
2263       ValueSet aNewList;
2264       add( aNewList, v1.toList() );
2265       v1 = aNewList;
2266     }
2267     else if ( op == "=" || op == "<>" || op == "!=" || op == "+" || op == "-" || op == "*" )
2268     {
2269       ValueSet aNewList;
2270       add( aNewList, v1.toList() );
2271       if ( op == "=" || op == "<>" || op == "!=" || op == "-" )
2272       {
2273         remove( aNewList, v2.toList() );
2274         if ( op == "=" )
2275           v1 = aNewList.isEmpty() && v1.toList().count() == v2.toList().count();
2276         else if ( op == "<>" || op == "!=" )
2277           v1 = !aNewList.isEmpty() || v1.toList().count() != v2.toList().count();
2278         else
2279           v1 = aNewList;
2280       }
2281       else if ( op == "+" )
2282       {
2283         add( aNewList, v2.toList() );
2284         v1 = aNewList;
2285       }
2286       else if ( op == "*" )
2287       {
2288         ValueSet toDelete;
2289         add( toDelete, aNewList );
2290         remove( toDelete, v2.toList() );
2291         remove( aNewList, toDelete );
2292         v1 = aNewList;
2293       }
2294     }
2295     else if ( op== "count" )
2296       v2 = (int)v2.toList().count();
2297     else if ( op == "in" )
2298     {
2299       if ( v1.type() == QVariant::List )
2300       {
2301         bool res = true;
2302         ValueSet lst1 = v1.toList();
2303         ValueSet lst2 = v2.toList();
2304         for ( ValueSet::const_iterator anIt = lst1.begin(); anIt != lst1.end() && res; ++anIt )
2305           res = lst2.contains( *anIt );
2306
2307         v1 = res;
2308       }
2309       else
2310               v1 = QVariant( v2.toList().contains( v1 ) );
2311     }
2312   }
2313   return err;
2314 }
2315
2316 /*!
2317   \class QtxEvalSetConst
2318   \brief Provides different standard constants.
2319 */
2320 QtxEvalSetConst::QtxEvalSetConst()
2321 : QtxEvalSet()
2322 {
2323 }
2324
2325 /*!
2326   \brief Destructor.
2327 */
2328 QtxEvalSetConst::~QtxEvalSetConst()
2329 {
2330 }
2331
2332 /*!
2333   \brief Get operations set name.
2334   \return operations set name
2335 */
2336 QString QtxEvalSetConst::Name()
2337 {
2338   return "Const";
2339 }
2340
2341 /*!
2342   \brief Get operations set name.
2343   \return operations set name
2344 */
2345 QString QtxEvalSetConst::name() const
2346 {
2347   return Name();
2348 }
2349
2350 /*!
2351   \brief Create value from its string representation.
2352
2353   Convert constant name to its value.
2354
2355   \param str string representration of the constant
2356   \param val returning value
2357   \return \c true if \a str can be evaluated as custom value and \c false
2358           otherwise (parameter)
2359 */
2360 bool QtxEvalSetConst::createValue( const QString& str, QVariant& val ) const
2361 {
2362   bool ok = true;
2363   if ( str == "pi" )            // PI number
2364     val = QVariant( 3.141593 );
2365   else if ( str == "exp" )      // Exponent value (e)
2366     val = QVariant( 2.718282 );
2367   else if ( str == "g" )        // Free fall acceleration (g)
2368     val = QVariant( 9.80665 );
2369   else
2370     ok = false;
2371
2372   return ok;
2373 }
2374
2375 /*!
2376   \brief Get the list of possible operations.
2377   \param list returning list of operations supported by the class (not used)
2378 */
2379 void QtxEvalSetConst::operationList( QStringList& /*list*/ ) const
2380 {
2381 }
2382
2383 /*!
2384   \brief Get list of brackets.
2385   \param list returning list of brackets (not used)
2386   \param open if \c true, collect opening brackets, or closing brackets otherwise (not used)
2387 */
2388 void QtxEvalSetConst::bracketsList( QStringList& /*list*/, bool /*open*/ ) const
2389 {
2390 }
2391
2392 /*!
2393   \brief Get the operation priority.
2394
2395   Operation priority counts from 1.
2396   If the operation is impossible, this function returns value <= 0.
2397   
2398   \param op operation (not used)
2399   \param isBin \c true if the operation is binary and \c false if it is unary (not used)
2400   \return operation priority
2401 */
2402 int QtxEvalSetConst::priority( const QString& /*op*/, bool /*isBin*/ ) const
2403 {
2404   return 0;
2405 }
2406
2407 /*!
2408   \brief Check operation validity.
2409
2410   Always returns QtxEvalExpr::InvalidOperation.
2411
2412   \param op operation (not used)
2413   \param t1 first operand type (not used)
2414   \param t2 second operand type (not used)
2415   \return error code (QtxEvalExpr::Error)
2416 */
2417 QtxEvalExpr::Error QtxEvalSetConst::isValid( const QString&       /*op*/, 
2418                                              const QVariant::Type /*t1*/,
2419                                              const QVariant::Type /*t2*/ ) const
2420 {
2421   return QtxEvalExpr::InvalidOperation;
2422 }
2423
2424 /*!
2425   \brief Calculate the operation.
2426
2427   Always returns QtxEvalExpr::InvalidOperation.
2428
2429   \param op operation name (not used)
2430   \param v1 first argument (not valid for unary prefix operations) (not used)
2431   \param v2 second argument (not valid for unary postfix operations) (not used)
2432   \return error code (QtxEvalExpr::Error)
2433 */
2434 QtxEvalExpr::Error QtxEvalSetConst::calculate( const QString&, QVariant&, QVariant& ) const
2435 {
2436   return QtxEvalExpr::InvalidOperation;
2437 }