]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxStdOperations.cxx
Salome HOME
0e4bacb81a0177bb60245425f2c237429693f070
[modules/gui.git] / src / Qtx / QtxStdOperations.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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/
18 //
19 #include "QtxStdOperations.h"
20
21 #include <math.h>
22 #include <stdlib.h>
23
24 /*!
25    Default constructor
26 */
27 QtxStdOperations::QtxStdOperations()
28 {
29 }
30
31 /*!
32    Destructor
33 */
34 QtxStdOperations::~QtxStdOperations()
35 {
36 }
37
38 /*!
39    Fills list of brackets treated as open (when 'open' is 'true') or close ('open' is 'false')
40 */
41 void QtxStdOperations::bracketsList( QStringList& list, bool open ) const
42 {
43     if( open )
44         list.append( "(" );
45     else
46         list.append( ")" );
47 }
48
49 /*!
50    Fills list with operation names by copying of internal list of operations
51 */
52 void QtxStdOperations::opersList( QStringList& list ) const
53 {
54   list += myOpers;
55 }
56
57 /*!
58    Add operation names from list to internal list of operations
59 */
60 void QtxStdOperations::addOperations( const QStringList& list )
61 {
62     QStringList::const_iterator anIt = list.begin(),
63                                 aLast = list.end();
64     for( ; anIt!=aLast; anIt++ )
65         if( myOpers.contains( *anIt )==0 )
66             myOpers.append( *anIt );
67 }
68
69 /*!
70    Append operation names from 'list' to internal list of operations
71 */
72 void QtxStdOperations::addTypes( const ListOfTypes& list )
73 {
74     ListOfTypes::const_iterator anIt = list.begin(),
75                                 aLast = list.end();
76     for( ; anIt!=aLast; anIt++ )
77         if( myTypes.contains( *anIt )==0 )
78             myTypes.append( *anIt );
79 }
80
81 /*!
82    \return whether values with passed types are valid for arguments of operation
83    \param op - name of operation
84    \param t1 - type of first argument
85    \param t2 - type of second argument
86 */
87 QtxParser::Error QtxStdOperations::isValid( const QString& op,
88                                             const QVariant::Type t1,
89                                             const QVariant::Type t2 ) const
90 {
91     if( ( t1==QVariant::Invalid || myTypes.contains( t1 ) ) &&
92         ( t2==QVariant::Invalid || myTypes.contains( t2 ) ) &&
93         ( t1!=QVariant::Invalid || t2!=QVariant::Invalid ) )
94         if( prior( op, t1!=QVariant::Invalid && t2!=QVariant::Invalid ) > 0 )
95             return QtxParser::OK;
96         else
97             return QtxParser::InvalidOperation;
98     else
99         return QtxParser::OperandsNotMatch;
100 }
101
102
103
104
105
106
107
108
109 /*!
110    Default constructor
111 */
112 QtxArithmetics::QtxArithmetics()
113 : QtxStdOperations()
114 {
115     QStringList aList;
116     aList.append( "+" );
117     aList.append( "-" );
118     aList.append( "*" );
119     aList.append( "/" );
120     aList.append( "=" );
121     aList.append( "<" );
122     aList.append( ">" );
123     aList.append( "<=" );
124     aList.append( ">=" );
125     aList.append( "<>" );
126     aList.append( "!=" ); // same as "<>" - for C++ addicts
127     addOperations( aList );
128
129     ListOfTypes aTypes;
130     aTypes.append( QVariant::Int );
131     aTypes.append( QVariant::UInt );
132     aTypes.append( QVariant::Double );
133     addTypes( aTypes );
134 }
135
136 /*!
137    Destructor
138 */
139 QtxArithmetics::~QtxArithmetics()
140 {
141 }
142
143 /*!
144     Creates numbers by it's string representation [redefined virtual]
145 */
146 bool QtxArithmetics::createValue( const QString& str, QtxValue& v ) const
147 {
148     bool ok = false;
149     v = str.toInt( &ok );
150
151     if( !ok )
152     {
153         v = str.toDouble( &ok );
154         if( !ok )
155             ok = QtxStdOperations::createValue( str, v );
156     }
157     return ok;
158 }
159
160 /*!
161     \return priority of arithmetic operation 'op'.
162     \param isBin indicate whether the operation is binary
163 */
164 int QtxArithmetics::prior( const QString& op, bool isBin ) const
165 {
166     if( isBin )
167         if( op=="<" || op==">" || op=="=" || 
168             op=="<=" || op==">=" || op=="<>" || op=="!=" )
169             return 1;
170         else if( op=="+" || op=="-" )
171             return 2;
172         else if( op=="*" || op=="/" )
173             return 3;
174         else
175             return 0;
176     else if( op=="+" || op=="-" )
177         return 5;
178     else
179         return 0;
180 }
181
182 void set( QVariant& v1, bool v2 )
183 {
184     v1 = QVariant( v2, 0 );
185 }
186
187 /*!
188     Calculates result of operation
189     \return one of error states
190     \param op - name of operation
191     \param v1 - first operation argument (must be used also to store result)
192     \param v2 - second operation argument
193 */
194 QtxParser::Error QtxArithmetics::calculate( const QString& op, 
195                                                 QtxValue& v1, QtxValue& v2 ) const
196 {
197     QtxParser::Error err = QtxParser::OK;
198
199     if( v1.isValid() && v2.isValid() )
200         // binary operations
201         if( ( v1.type()==QVariant::Int || v1.type()==QVariant::UInt ) &&
202             ( v2.type()==QVariant::Int || v2.type()==QVariant::UInt ) )
203         {
204             int _v1 = v1.toInt(),
205                 _v2 = v2.toInt();
206
207             if( op=="+" )
208                 v1 = _v1 + _v2;
209             else if( op=="-" )
210                 v1 = _v1 - _v2;
211             else if( op=="*" )
212                 v1 = _v1 * _v2;
213             else if( op=="/" )
214                 if( _v2!=0 )
215                     if( _v1%_v2==0 )
216                         v1 = _v1 / _v2;
217                     else
218                         v1 = double( _v1 ) / double( _v2 );
219                 else
220                     err = QtxParser::InvalidResult;
221             else if( op=="<" )
222                 set( v1, _v1<_v2 );
223             else if( op==">" )
224                 set( v1, _v1>_v2 );
225             else if( op=="=" )
226                 set( v1, _v1==_v2 );
227             else if( op=="<=" )
228                 set( v1, _v1<=_v2 );
229             else if( op==">=" )
230                 set( v1, _v1>=_v2 );
231             else if( op=="<>" || op=="!=" )
232                 set( v1, _v1!=_v2 );
233         }
234         else if( ( v1.type()==QVariant::Int || v1.type()==QVariant::Double ) &&
235                  ( v2.type()==QVariant::Int || v2.type()==QVariant::Double ) )
236         {
237             double _v1 = v1.toDouble(),
238                    _v2 = v2.toDouble();
239
240             if( op=="+" )
241                 v1 = _v1 + _v2;
242             else if( op=="-" )
243                 v1 = _v1 - _v2;
244             else if( op=="*" )
245                 v1 = _v1 * _v2;
246             else if( op=="/" )
247                 if( _v2!=0 )
248                     v1 = _v1 / _v2;
249                 else
250                     err = QtxParser::InvalidResult;
251             else if( op=="<" )
252                 set( v1, _v1<_v2 );
253             else if( op==">" )
254                 set( v1, _v1>_v2 );
255             else if( op=="=" )
256                 set( v1, _v1==_v2 );
257             else if( op=="<=" )
258                 set( v1, _v1<=_v2 );
259             else if( op==">=" )
260                 set( v1, _v1>=_v2 );
261             else if( op=="<>" || op=="!=" )
262                 set( v1, _v1!=_v2 );
263         }
264     else
265         // prefix operations
266         if( op=="-" )
267             if( v2.type()==QVariant::Int )
268                 v2 = -v2.toInt();
269             else if( v2.type()==QVariant::Double )
270                 v2 = -v2.toDouble();
271
272     return err;
273 }
274
275
276
277
278
279
280
281
282
283
284
285 /*!
286    Default constructor
287 */
288 QtxLogic::QtxLogic()
289 : QtxStdOperations()
290 {
291     QStringList aList;
292     aList.append( "and" );
293     aList.append( "&&" );
294     aList.append( "or" );
295     aList.append( "||" );
296     aList.append( "xor" );
297     aList.append( "not" );
298     aList.append( "!" );
299     aList.append( "imp" );
300     aList.append( "=" );
301     addOperations( aList );
302
303     ListOfTypes aTypes;
304     aTypes.append( QVariant::Bool );
305     aTypes.append( QVariant::Int );
306     aTypes.append( QVariant::UInt );
307     addTypes( aTypes );
308 }
309
310 /*!
311    Destructor
312 */
313 QtxLogic::~QtxLogic()
314 {
315 }
316
317 /*!
318     Creates value 'true' or 'false' it's string representation [redefined virtual]
319 */
320 bool QtxLogic::createValue( const QString& str, QtxValue& v ) const
321 {
322     bool ok = true;
323     if( str.lower()=="true" )
324         v = QtxValue( true, 0 );
325     else if( str.lower()=="false" )
326         v = QtxValue( false, 0 );
327     else
328         ok = QtxStdOperations::createValue( str, v );
329
330     return ok;
331 }
332
333 /*!
334     \return priority of arithmetic operation 'op'.
335     \param isBin indicate whether the operation is binary
336 */
337 int QtxLogic::prior( const QString& op, bool isBin ) const
338 {
339     if( isBin )
340         if( op=="and" || op=="or" || op=="xor" ||
341             op=="&&"  || op=="||" ||
342             op=="imp" )
343             return 1;
344         else if( op=="=" )
345             return 2;
346         else 
347             return 0;
348     else if( op=="not" || op=="!" )
349             return 5;
350          else
351             return 0;
352 }
353
354 bool boolean_value( const QtxValue& v )
355 {
356   if( v.type()==QVariant::Bool )
357     return v.toBool();
358   else if( v.type()==QVariant::Int )
359     return v.toInt()!=0;
360   else if( v.type()==QVariant::UInt )
361     return v.toUInt()!=0;
362   else
363     return false;
364 }
365
366 /*!
367     Calculates result of operation
368     \return one of error states
369     \param op - name of operation
370     \param v1 - first operation argument (must be used also to store result)
371     \param v2 - second operation argument
372 */
373 QtxParser::Error QtxLogic::calculate( const QString& op,
374                                           QtxValue& v1, QtxValue& v2 ) const
375 {
376     QtxParser::Error err = QtxParser::OK;
377     bool val1 = boolean_value( v1 ),
378          val2 = boolean_value( v2 );
379     if( v1.isValid() && v2.isValid() )
380     {
381         if( op=="and" || op=="&&" )
382             set( v1, val1 && val2 );
383         else if( op=="or" || op=="||" )
384             set( v1, val1 || val2 );
385         else if( op=="xor" )
386             set( v1, ( !val1 && val2 ) || ( val1 && !val2 ) );
387         else if( op=="imp" )
388             set( v1, !val1 || val2 );
389         else if( op=="=" )
390             set( v1, val1==val2 );
391     }
392     else
393         if( op=="not" || op=="!" )
394             set( v2, !val2 );
395
396     return err;
397 }
398
399
400
401
402
403
404 /*!
405    Default constructor
406 */
407 QtxFunctions::QtxFunctions()
408 : QtxStdOperations()
409 {
410     QStringList aList;
411     aList.append( "sqrt" );
412     aList.append( "abs" );
413     aList.append( "sin" );
414     aList.append( "cos" );
415     aList.append( "rad2grad" );
416     aList.append( "grad2rad" );
417     addOperations( aList );
418
419     ListOfTypes aTypes;
420     aTypes.append( QVariant::Int );
421     aTypes.append( QVariant::Double );
422     addTypes( aTypes );
423 }
424
425 /*!
426    Destructor
427 */
428 QtxFunctions::~QtxFunctions()
429 {
430 }
431
432 /*!
433     Creates numbers by it's string representation [redefined virtual]
434 */
435 bool QtxFunctions::createValue( const QString& str, QtxValue& v ) const
436 {
437     bool ok = false;
438     v = str.toInt( &ok );
439
440     if( !ok )
441     {
442         v = str.toDouble( &ok );
443         if( !ok )
444             ok = QtxStdOperations::createValue( str, v );
445     }
446     return ok;
447 }
448
449 /*!
450     \return priority of arithmetic operation 'op'.
451     \param isBin indicate whether the operation is binary
452 */
453 int QtxFunctions::prior( const QString& op, bool isBin ) const
454 {
455     if( isBin )
456         return 0;
457     else if( op=="sqrt" || op=="abs" || op=="sin" || op=="cos" ||
458              op=="rad2grad" || op=="grad2rad" )
459         return 1;
460     else
461         return 0;
462 }
463
464 /*!
465     Calculates result of operation
466     \return one of error states
467     \param op - name of operation
468     \param v1 - first operation argument (must be used also to store result)
469     \param v2 - second operation argument
470 */
471 QtxParser::Error QtxFunctions::calculate( const QString& op,
472                                           QtxValue& v1, QtxValue& v2 ) const
473 {
474     QtxParser::Error err = QtxParser::OK;
475     double val = v2.toDouble();
476     if( op=="sqrt" )
477         if( val>=0 )
478             v2 = sqrt( val );
479         else
480             err = QtxParser::InvalidResult;
481     else if( op=="abs" )
482         if( v2.type()==QVariant::Int )
483             v2 = abs( v2.toInt() );
484         else 
485             v2 = fabs( v2.toDouble() );
486     else if( op=="sin" )
487         v2 = sin( val );
488     else if( op=="cos" )
489         v2 = cos( val );
490     else if( op=="grad2rad" )
491         v2 = val * 3.14159256 / 180.0;
492     else if( op=="rad2grad" )
493         v2 = val * 180.0 / 3.14159256;
494
495     return err;
496 }
497
498
499
500
501
502
503
504
505 /*!
506    Default constructor
507 */
508 QtxStrings::QtxStrings()
509 : QtxStdOperations()
510 {
511     QStringList aList;
512     aList.append( "+" );
513     aList.append( "=" );
514     aList.append( "<" );
515     aList.append( ">" );
516     aList.append( "<=" );
517     aList.append( ">=" );
518     aList.append( "<>" );
519     aList.append( "!=" ); // same as "<>" - for C++ addicts
520     aList.append( "length" );
521     aList.append( "lower" );
522     aList.append( "upper" );
523     addOperations( aList );
524
525     ListOfTypes aTypes;
526     aTypes.append( QVariant::Int );
527     aTypes.append( QVariant::Double );
528     aTypes.append( QVariant::String );
529     aTypes.append( QVariant::CString );
530     addTypes( aTypes );
531 }
532
533
534 /*!
535    Destructor
536 */
537 QtxStrings::~QtxStrings()
538 {
539 }
540
541 /*!
542     Creates string QtxValue by it's Qt string representation [redefined virtual]
543 */
544 bool QtxStrings::createValue( const QString& str, QtxValue& v ) const
545 {
546     QChar st = str[0],
547           fin = str[ ( int )( str.length()-1 ) ];
548     if( st=="'" && fin=="'" )
549     {
550         v = str.mid( 1, str.length()-2 );
551         return true;
552     }
553     else
554         return QtxStdOperations::createValue( str, v );
555 }
556
557 /*!
558     \return priority of arithmetic operation 'op'.
559     \param isBin indicate whether the operation is binary
560 */
561 int QtxStrings::prior( const QString& op, bool isBin ) const
562 {
563     if( isBin )
564         if( op=="+" ) 
565             return 2;
566         else if( op=="="  || op=="<"  || op==">"  ||
567                  op=="<=" || op==">=" || op=="<>" || op=="!=" )
568             return 1;
569         else
570             return 0;
571     else
572         if( op=="length" || op=="lower" || op=="upper" )
573             return 5;
574         else
575             return 0;
576 }
577
578 /*!
579     Calculates result of operation
580     \return one of error states
581     \param op - name of operation
582     \param v1 - first operation argument (must be used also to store result)
583     \param v2 - second operation argument
584 */
585 QtxParser::Error QtxStrings::calculate( const QString& op,
586                                             QtxValue& v1, QtxValue& v2 ) const
587 {
588     QtxParser::Error err = QtxParser::OK;
589     if( v1.isValid() && v2.isValid() )
590     {
591         QString _v1 = v1.toString(),
592                 _v2 = v2.toString();
593         if( op=="+" )
594             v1 = _v1 + _v2;
595         else if( op=="=" )
596             set( v1, _v1==_v2 );
597         else if( op=="<" )
598             set( v1, _v1<_v2 );
599         else if( op==">" )
600             set( v1, _v1>_v2 );
601         else if( op=="<>" || op=="!=" )
602             set( v1, _v1!=_v2 );
603         else if( op=="<=" )
604             set( v1, _v1<_v2 || _v1==_v2 );
605         else if( op==">=" )
606             set( v1, _v1>_v2 || _v1==_v2 );
607     }
608     else if( !v1.isValid() && v2.isValid() )
609     {
610         QString val = v2.toString();
611         if( op=="length" )
612             v2 = ( int )val.length();
613         else if( op=="lower" )
614             v2 = val.lower();
615         else if( op=="upper" )
616             v2 = val.upper();
617     }
618
619     return err;
620 }
621
622
623
624
625
626
627 /*!
628    Default constructor
629 */
630 QtxSets::QtxSets()
631 {
632     QStringList aList;
633     aList.append( "{" );
634     aList.append( "}" );
635     aList.append( "=" );
636     aList.append( "<>" );
637     aList.append( "!=" ); // same as "<>" - for C++ addicts
638     aList.append( "+" );
639     aList.append( "-" );
640     aList.append( "*" );
641     aList.append( "in" );
642     aList.append( "count" );
643     addOperations( aList );
644
645     ListOfTypes aTypes;
646     aTypes.append( QVariant::List );
647     addTypes( aTypes );
648 }
649
650 /*!
651    Destructor
652 */
653 QtxSets::~QtxSets()
654 {
655 }
656
657 /*!
658    Fills list of brackets treated as open (when 'open' is 'true') or close ('open' is 'false')
659 */
660 void QtxSets::bracketsList( QStringList& list, bool open ) const
661 {
662     if( open )
663         list.append( "{" );
664     else 
665         list.append( "}" );
666     QtxStdOperations::bracketsList( list, open );
667 }
668
669 /*!
670     Creates set of QtxValues by their string representation [redefined virtual]
671 */
672 bool QtxSets::createValue( const QString& str, QtxValue& val ) const
673 {
674     return QtxStdOperations::createValue( str, val );
675 }
676
677 /*!
678     \return priority of arithmetic operation 'op'.
679     \param isBin indicate whether the operation is binary
680 */
681 int QtxSets::prior( const QString& op, bool isBin ) const
682 {
683     if( isBin )
684         if( op=="=" || op=="<>" || op=="!=" )
685             return 1;
686         else if( op=="+" || op=="-" || op=="*" )
687             return 2;
688         else if( op=="in" )
689             return 3;
690         else
691             return 0;
692
693     else 
694         if( op=="{" || op=="}" )
695             return 5;
696         else if( op=="count" )
697             return 4;
698         else
699             return 0;
700 }
701
702 /*!
703    \return whether values with passed types are valid for arguments of operation
704    \param op - name of operation
705    \param t1 - type of first argument
706    \param t2 - type of second argument
707 */
708 QtxParser::Error QtxSets::isValid( const QString& op,
709                                    const QVariant::Type t1,
710                                    const QVariant::Type t2 ) const
711 {
712     if( op=="{" )
713         return QtxParser::OK;
714     else if( op=="in" )
715         if( t1!=QVariant::Invalid && t2==QVariant::List )
716             return QtxParser::OK;
717         else
718             return QtxParser::OperandsNotMatch;
719     else
720         return QtxStdOperations::isValid( op, t1, t2 );
721 }
722
723 /*!
724    Adds new value 'v' to set 'set' [static]
725 */
726 void QtxSets::add( ValueSet& set, const QtxValue& v )
727 {
728     if( v.isValid() && set.contains( v )==0 )
729         set.append( v );
730 }
731
732 /*!
733    Adds values from set 's2' to set 's1'
734 */
735 void QtxSets::add( ValueSet& s1, const ValueSet& s2 )
736 {
737     ValueSet::const_iterator anIt = s2.begin(),
738                              aLast = s2.end();
739     for( ; anIt!=aLast; anIt++ )
740         add( s1, *anIt );
741 }
742
743 /*!
744    Removes value 'v' from set 'set'
745 */
746 void QtxSets::remove( ValueSet& set, const QtxValue& v )
747 {
748     set.remove( v );
749 }
750
751 /*!
752    Removes values of set 's2' from set 's1'
753 */
754 void QtxSets::remove( ValueSet& s1, const ValueSet& s2 )
755 {
756     ValueSet::const_iterator anIt = s2.begin(),
757                              aLast = s2.end();
758     for( ; anIt!=aLast; anIt++ )
759         s1.remove( *anIt );
760 }
761
762 /*!
763     Calculates result of operation
764     \return one of error states
765     \param op - name of operation
766     \param v1 - first operation argument (must be used also to store result)
767     \param v2 - second operation argument
768 */
769 QtxParser::Error QtxSets::calculate( const QString& op, QtxValue& v1, QtxValue& v2 ) const
770 {
771     QtxParser::Error err = QtxParser::OK;
772
773     if( op!="{" )
774         if( op=="}" )
775         {
776             ValueSet aNewList;
777             add( aNewList, v1.toList() );
778             v1 = aNewList;
779         }
780
781         else if( op=="=" || op=="<>" || op=="!=" || op=="+" || op=="-" || op=="*" )
782         {
783             ValueSet aNewList;
784             add( aNewList, v1.toList() );
785
786             if( op=="=" || op=="<>" || op=="!=" || op=="-" )
787             {
788                 remove( aNewList, v2.toList() );
789
790                 if( op=="=" )
791                     set( v1, aNewList.isEmpty() && v1.toList().count()==v2.toList().count() );
792                 else if( op=="<>" || op=="!=" )
793                     set( v1, !aNewList.isEmpty() || v1.toList().count()!=v2.toList().count() );
794                 else
795                     v1 = aNewList;
796             }
797             else if( op=="+" )
798             {
799                 add( aNewList, v2.toList() );
800                 v1 = aNewList;
801             }
802             else if( op=="*" )
803             {
804                 ValueSet toDelete;
805                 add( toDelete, aNewList );
806                 remove( toDelete, v2.toList() );
807                 remove( aNewList, toDelete );
808                 v1 = aNewList;
809             }
810         }
811         else if( op=="count" )
812             v2 = ( int )v2.toList().count();
813         else if( op=="in" )
814         {
815             if( v1.type()==QVariant::List )
816             {
817                 bool res = true;
818                 ValueSet::const_iterator anIt = v1.toList().begin(),
819                                          aLast = v1.toList().end();
820                 for( ; anIt!=aLast && res; anIt++ )
821                     res = v2.toList().contains( *anIt )>0;
822
823                 set( v1, res );
824             }
825             else
826             {
827               const QValueList< QVariant >& list = v2.toList();
828               v1 = ( bool )( list.find( v1 )!=list.end() );
829             }
830         }
831
832     return err;
833 }