Back to index

salome-gui  6.5.0
QtxPopupMgr.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File:      QtxPopupMgr.cxx
00024 // Author:    Alexander SOLOVYOV, Sergey TELKOV
00025 //
00026 #include "QtxPopupMgr.h"
00027 #include "QtxAction.h"
00028 #include "QtxEvalExpr.h"
00029 #include <QMenu>
00030 
00037 bool operator<( const QVariant& v1, const QVariant& v2 )
00038 {
00039   QVariant::Type t1 = v1.type(), t2 = v2.type();
00040   if ( t1 == t2 )
00041   {
00042     switch( t1 )
00043     {
00044     case QVariant::Int:
00045       return v1.toInt() < v2.toInt();
00046     case QVariant::Double:
00047       return v1.toDouble() < v2.toDouble();
00048     case QVariant::String:
00049       return v1.toString() < v2.toString();
00050     case QVariant::StringList:
00051     case QVariant::List:
00052     {
00053       const QList<QVariant>& aList1 = v1.toList(), aList2 = v2.toList();
00054       QList<QVariant>::const_iterator anIt1 = aList1.begin(), aLast1 = aList1.end(),
00055         anIt2 = aList2.begin(), aLast2 = aList2.end();
00056       for ( ; anIt1 != aLast1 && anIt2 != aLast2;  anIt1++, anIt2++ )
00057       {
00058         if ( (*anIt1) != (*anIt2) )
00059           return (*anIt1)<(*anIt2);
00060       }
00061       return anIt1 == aLast1 && anIt2 != aLast2;
00062     }
00063     default:
00064       return v1.toString() < v2.toString();
00065     }
00066   }
00067   return t1 < t2;
00068 }
00069 
00079 class QtxPopupMgr::PopupCreator : public QtxActionMgr::Creator
00080 {
00081 public:
00082   PopupCreator( QtxActionMgr::Reader*, QtxPopupMgr* );
00083   virtual ~PopupCreator();
00084 
00085   virtual int     append( const QString&, const bool,
00086                           const ItemAttributes&, const int );
00087 
00088   virtual QString rule( const ItemAttributes&, 
00089                         const QtxPopupMgr::RuleType = VisibleRule ) const;
00090 
00091 private:
00092   QtxPopupMgr*    myMgr;
00093 };
00094 
00100 QtxPopupMgr::PopupCreator::PopupCreator( QtxActionMgr::Reader* r,
00101                                          QtxPopupMgr* mgr )
00102 : QtxActionMgr::Creator( r ),
00103   myMgr( mgr )
00104 {
00105 }
00106 
00110 QtxPopupMgr::PopupCreator::~PopupCreator()
00111 {
00112 }
00113 
00122 int QtxPopupMgr::PopupCreator::append( const QString& tag, const bool subMenu,
00123                                        const ItemAttributes& attr, const int pId )
00124 {
00125   if ( !myMgr || !reader() )
00126     return -1;
00127 
00128   QString label   = reader()->option( "label",     "label"     ),
00129           id      = reader()->option( "id",        "id"        ),
00130           pos     = reader()->option( "pos",       "pos"       ),
00131           group   = reader()->option( "group",     "group"     ),
00132           tooltip = reader()->option( "tooltip",   "tooltip"   ),
00133           sep     = reader()->option( "separator", "separator" ),
00134           accel   = reader()->option( "accel",     "accel"     ),
00135           icon    = reader()->option( "icon",      "icon"      ),
00136           toggle  = reader()->option( "toggle",    "toggle"    );
00137 
00138   QtxActionMenuMgr* mgr = myMgr;
00139 
00140   int res = -1, actId = intValue( attr, id, -1 );;
00141   if ( subMenu )
00142     res = mgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
00143   else if ( tag == sep )
00144     res = mgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
00145   else
00146   {
00147     QIcon set;
00148     QPixmap pix;
00149     QString name = strValue( attr, icon );
00150     if( !name.isEmpty() )
00151     {
00152       if ( loadPixmap( name, pix ) )
00153         set = QIcon( pix );
00154     }
00155 
00156     QString actLabel = strValue( attr, label );
00157     QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, actLabel,
00158                                        QKeySequence( strValue( attr, accel ) ),
00159                                        myMgr );
00160     newAct->setToolTip( strValue( attr, tooltip ) );
00161     QString toggleact = strValue( attr, toggle );
00162     bool isToggle = !toggleact.isEmpty();
00163     newAct->setCheckable( isToggle );
00164     newAct->setChecked( toggleact.toLower() == "true" );
00165         
00166     connect( newAct );
00167     int aid = mgr->registerAction( newAct, actId ); 
00168     QString arule = rule( attr, QtxPopupMgr::VisibleRule );
00169     if ( !arule.isEmpty() )
00170       myMgr->setRule( newAct, arule, QtxPopupMgr::VisibleRule );
00171     arule = rule( attr, QtxPopupMgr::EnableRule );
00172     if ( !arule.isEmpty() )
00173       myMgr->setRule( newAct, arule, QtxPopupMgr::EnableRule );
00174     arule = rule( attr, QtxPopupMgr::ToggleRule );
00175     if ( isToggle && !arule.isEmpty() )
00176       myMgr->setRule( newAct, arule, QtxPopupMgr::ToggleRule );
00177     res = mgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
00178   }
00179 
00180   return res;
00181 }
00182 
00192 QString QtxPopupMgr::PopupCreator::rule( const ItemAttributes& /*attr*/, 
00193                                          const QtxPopupMgr::RuleType /*ruleType*/ ) const
00194 {
00195   return QString();
00196 }
00197 
00225 QtxPopupMgr::QtxPopupMgr( QObject* parent )
00226 : QtxActionMenuMgr( 0, parent ),
00227   mySelection( 0 )
00228 {
00229 }
00230 
00236 QtxPopupMgr::QtxPopupMgr( QMenu* popup, QObject* parent )
00237 : QtxActionMenuMgr( popup, parent ),
00238   mySelection( 0 )
00239 {
00240 }
00241 
00245 QtxPopupMgr::~QtxPopupMgr()
00246 {
00247 }
00248 
00253 QMenu* QtxPopupMgr::menu() const
00254 {
00255   return ::qobject_cast<QMenu*>( menuWidget() );
00256 }
00257 
00262 void QtxPopupMgr::setMenu( QMenu* menu )
00263 {
00264   setMenuWidget( menu );
00265 }
00266 
00271 QtxPopupSelection* QtxPopupMgr::selection() const
00272 {
00273   return mySelection;
00274 }
00275 
00280 void QtxPopupMgr::setSelection( QtxPopupSelection* sel )
00281 {
00282   if ( mySelection == sel )
00283     return;
00284 
00285   delete mySelection;
00286 
00287   mySelection = sel;
00288 
00289   if ( mySelection ) {
00290     mySelection->setParent( this );
00291     mySelection->setPopupMgr( this );
00292   }
00293 
00294   connect( mySelection, SIGNAL( destroyed( QObject* ) ), 
00295            this,        SLOT( onSelectionDestroyed( QObject* ) ) );
00296 
00297   QtxActionMgr::triggerUpdate();
00298 }
00299 
00314 int QtxPopupMgr::registerAction( QAction* act, const int id, const QString& rule, const QtxPopupMgr::RuleType ruleType )
00315 {
00316   int _id = QtxActionMenuMgr::registerAction( act, id );
00317   setRule( act, rule, ruleType );
00318   return _id;
00319 }
00320 
00325 void QtxPopupMgr::unRegisterAction( const int id )
00326 {
00327   QAction* a = action( id );
00328   if ( myRules.contains( a ) )
00329   {
00330     for ( ExprMap::iterator it = myRules[a].begin(); it != myRules[a].end(); ++it )
00331       delete it.value();
00332   }
00333   myRules.remove( a );
00334 
00335   remove( id );
00336 
00337   QtxActionMenuMgr::unRegisterAction( id );
00338 }
00339 
00348 int QtxPopupMgr::insertAction( const int id, const int pId, const QString& rule, const RuleType ruleType )
00349 {
00350   int res = QtxActionMenuMgr::insert( id, pId, -1 );
00351   setRule( action( id ), rule, ruleType );
00352   return res;
00353 }
00354 
00363 int QtxPopupMgr::insertAction( QAction* a, const int pId, const QString& rule, const RuleType ruleType )
00364 {
00365   int res = QtxActionMenuMgr::insert( a, pId, -1 );
00366   setRule( a, rule, ruleType );
00367   return res;
00368 }
00369 
00375 bool QtxPopupMgr::hasRule( QAction* a, const RuleType t ) const
00376 {
00377   return a ? expression( a, t, false ) : false;
00378 }
00379 
00385 bool QtxPopupMgr::hasRule( const int id, const RuleType t ) const
00386 {
00387   return hasRule( action( id ), t );
00388 }
00389 
00396 QString QtxPopupMgr::rule( QAction* a, const RuleType ruleType ) const
00397 {
00398   QString rule;
00399   QtxEvalExpr* expr = expression( a, ruleType );
00400   if ( expr )
00401     rule = expr->expression();
00402   return rule;
00403 }
00404 
00411 QString QtxPopupMgr::rule( const int id, const RuleType ruleType ) const
00412 {
00413   return rule( action( id ), ruleType );
00414 }
00415 
00423 void QtxPopupMgr::setRule( QAction* a, const QString& rule, const RuleType ruleType )
00424 {
00425   if ( !a )
00426     return;
00427 
00428   QtxEvalExpr* expr = expression( a, ruleType, true );
00429 
00430   expr->setExpression( rule );
00431 }
00432 
00440 void QtxPopupMgr::setRule( const int id, const QString& rule, const RuleType ruleType )
00441 {
00442   setRule( action( id ), rule, ruleType );
00443 }
00444 
00450 bool QtxPopupMgr::result( QtxEvalParser* p ) const
00451 {
00452   bool res = false;
00453   if ( p )
00454   {
00455     QVariant vv = p->calculate();
00456     res = p->error() == QtxEvalExpr::OK &&
00457           ( ( vv.type() == QVariant::Int && vv.toInt() != 0 ) ||
00458             ( vv.type() == QVariant::Bool && vv.toBool() ) );
00459   }
00460   return res;
00461 }
00462 
00473 void QtxPopupMgr::setParameters( QtxEvalParser* p, QStringList& specific ) const
00474 {
00475   if ( !p || !mySelection )
00476     return;
00477 
00478   QStringList params = p->parameters();
00479   for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it )
00480   {
00481     QVariant v = parameter( *it );
00482     if ( v.isValid() )
00483       p->setParameter( *it, v );
00484     else
00485       specific.append( *it );
00486   }
00487 }
00488 
00495 bool QtxPopupMgr::isSatisfied( QAction* act, const RuleType ruleType ) const
00496 {
00497   if ( !act )
00498     return false;
00499 
00500   QtxEvalExpr* exp = expression( act, ruleType );
00501   if ( !exp )
00502     return true;
00503 
00504   bool res = false;
00505 
00506   QtxEvalParser* p = exp->parser();
00507 
00508   QStringList specific;
00509   p->clearParameters();
00510   setParameters( p, specific );
00511 
00512   QMap<QList<QVariant>, int> aCorteges;
00513   if ( !specific.isEmpty() )
00514   {
00515     if ( mySelection )
00516     {
00517       res = false;
00518       for ( int i = 0; i < mySelection->count() && !res; i++ )
00519       {
00520         QList<QVariant> c;
00521         for ( QStringList::const_iterator anIt1 = specific.begin(); anIt1 != specific.end(); ++anIt1 )
00522           c.append( parameter( *anIt1, i ) );
00523         aCorteges.insert( c, 0 );
00524       }
00525       for ( QMap<QList<QVariant>, int>::const_iterator anIt = aCorteges.begin(); anIt  != aCorteges.end(); ++anIt )
00526       {
00527         const QList<QVariant>& aCortege = anIt.key();
00528         QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end();
00529         QList<QVariant>::const_iterator anIt2 = aCortege.begin();
00530         for ( ; anIt1 != aLast1; anIt1++, anIt2++ )
00531           p->setParameter( *anIt1, *anIt2 );
00532         res = res || result( p );
00533       }
00534     }
00535     else
00536       res = false;
00537   }
00538   else
00539     res = result( p );
00540 
00541   return res;
00542 }
00543 
00550 bool QtxPopupMgr::isVisible( const int id, const int place ) const
00551 {
00552   return QtxActionMenuMgr::isVisible( id, place ) && ( !hasRule( id ) || isSatisfied( action( id ) ) );
00553 }
00554 
00559 void QtxPopupMgr::internalUpdate()
00560 {
00561   myCache.clear();
00562 
00563   for ( RuleMap::iterator it = myRules.begin(); it != myRules.end(); ++it )
00564   {
00565     ExprMap& map = it.value();
00566     if ( it.key()->isCheckable() && map.contains( ToggleRule ) &&
00567          !map[ToggleRule]->expression().isEmpty() )
00568       it.key()->setChecked( isSatisfied( it.key(), ToggleRule ) );
00569   }
00570 
00571   QtxActionMenuMgr::internalUpdate();
00572 
00573   myCache.clear();
00574 }
00575 
00579 void QtxPopupMgr::updateMenu()
00580 {
00581   internalUpdate();
00582 }
00583 
00591 QtxEvalExpr* QtxPopupMgr::expression( QAction* a, const RuleType ruleType, const bool create ) const
00592 {
00593   QtxEvalExpr* res = 0;
00594 
00595   QtxPopupMgr* that = (QtxPopupMgr*)this;
00596   RuleMap& ruleMap = that->myRules;
00597   if ( !ruleMap.contains( a ) && create )
00598     ruleMap.insert( a, ExprMap() );
00599 
00600   if ( ruleMap.contains( a ) )
00601   {
00602     ExprMap& exprMap = ruleMap[a];
00603     if ( exprMap.contains( ruleType ) )
00604       res = exprMap[ruleType];
00605     else if ( create )
00606       exprMap.insert( ruleType, res = new QtxEvalExpr() );
00607   }
00608 
00609   return res;
00610 }
00611 
00618 bool QtxPopupMgr::load( const QString& fname, QtxActionMgr::Reader& r )
00619 {
00620   PopupCreator cr( &r, this );
00621   return r.read( fname, cr );
00622 }
00623 
00624 /*
00625   \brief Get the specified parameter value.
00626   \param name parameter name
00627   \param idx additional index used when used parameters with same names 
00628   \return parameter value
00629   \sa selection()
00630 */
00631 QVariant QtxPopupMgr::parameter( const QString& name, const int idx ) const
00632 {
00633   QVariant val;
00634   QString cacheName = name + ( idx >= 0 ? QString( "_%1" ).arg( idx ) : QString() );
00635   if ( myCache.contains( cacheName ) )
00636     val = myCache[cacheName];
00637   else
00638   {
00639     if ( selection() )
00640       val = idx < 0 ? selection()->parameter( name ) : 
00641                       selection()->parameter( idx, name );
00642     if ( val.isValid() )
00643     {
00644       QtxPopupMgr* that = (QtxPopupMgr*)this;
00645       that->myCache.insert( cacheName, val );
00646     }
00647   }
00648   return val;
00649 }
00650 
00659 void QtxPopupMgr::onSelectionDestroyed( QObject* o )
00660 {
00661   if ( o == mySelection )
00662     mySelection = 0;
00663 }
00664 
00681 QtxPopupSelection::QtxPopupSelection()
00682   : QObject( 0 ),
00683     myPopupMgr( 0 )
00684 {
00685 }
00686 
00690 QtxPopupSelection::~QtxPopupSelection()
00691 {
00692 }
00693 
00699 QString QtxPopupSelection::option( const QString& optName ) const
00700 {
00701   QString opt;
00702   if ( myOptions.contains( optName ) )
00703     opt = myOptions[optName];
00704   return opt;
00705 }
00706 
00712 void QtxPopupSelection::setOption( const QString& optName, const QString& opt )
00713 {
00714   myOptions.insert( optName, opt );
00715 }
00716 
00717 QtxPopupMgr* QtxPopupSelection::popupMgr() const
00718 {
00719   return myPopupMgr;
00720 }
00721 
00722 void QtxPopupSelection::setPopupMgr( QtxPopupMgr* pm )
00723 {
00724   myPopupMgr = pm;
00725 }
00726 
00732 QVariant QtxPopupSelection::parameter( const QString& str ) const
00733 {
00734   if ( str == selCountParam() )
00735     return count();
00736   else if ( str.startsWith( equalityParam() ) )
00737   {
00738     QtxEvalSetSets::ValueSet set;
00739     QString par = str.mid( equalityParam().length() );
00740 
00741     QtxPopupMgr* pMgr = popupMgr();
00742     for ( int i = 0; i < (int)count(); i++ )
00743     {
00744       QVariant v = pMgr ? pMgr->parameter( par, i ) : parameter( i, par );
00745       if ( v.isValid() )
00746         QtxEvalSetSets::add( set, v );
00747       else
00748         return QVariant();
00749     }
00750     return set;
00751   }
00752   else
00753     return QVariant();
00754 }
00755 
00760 QString QtxPopupSelection::equalityParam() const
00761 {
00762   QString str = option( "equality" );
00763   if ( str.isEmpty() )
00764     str = "$";
00765   return str;
00766 }
00767 
00772 QString QtxPopupSelection::selCountParam() const
00773 {
00774   QString str = option( "selcount" );
00775   if ( str.isEmpty() )
00776     str = "selcount";
00777   return str;
00778 }
00779