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