-// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-//
+// Copyright (C) 2007-2023 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.salome-platform.org/
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
+// File: QtxPopupMgr.cxx
+// Author: Alexander SOLOVYOV, Sergey TELKOV
+//
#include "QtxPopupMgr.h"
-#include "QtxListOfOperations.h"
-#include "QtxStdOperations.h"
#include "QtxAction.h"
+#include "QtxEvalExpr.h"
+#include <QList>
+#include <QMenu>
+#include <QVariant>
-#include <qpopupmenu.h>
-#include <qdatetime.h>
-
-
-/*!
- \return value of global parameter (depending on whole selection, but not dependending on one object of selection)
- \param str - name of parameter
-
- By default, it returns count of selected objects ("selcount") and list of parameters ("$<name>")
-*/
-QtxValue QtxPopupMgr::Selection::globalParam( const QString& str ) const
+bool operator<( const QList<QVariant>& v1, const QList<QVariant>& v2 )
{
- if( str==selCountParam() )
- return count();
-
- else if( str[0]==equality() )
+ QList<QVariant>::const_iterator anIt1 = v1.begin(), aLast1 = v1.end(),
+ anIt2 = v2.begin(), aLast2 = v2.end();
+ for ( ; anIt1 != aLast1 && anIt2 != aLast2; anIt1++, anIt2++ )
{
- QtxSets::ValueSet set;
- QString par = str.mid( 1 );
-
- for( int i=0, n=count(); i<n; i++ )
- {
- QtxValue v = param( i, par );
- if( v.isValid() )
- QtxSets::add( set, v );
- else
- return QtxValue();
- }
- return set;
+ if ( (*anIt1) != (*anIt2) )
+ return (*anIt1) < (*anIt2);
}
-
- else
- return QtxValue();
+ return anIt1 == aLast1 && anIt2 != aLast2;
}
/*!
- \return symbole to detect name of parameter list
+ \class QtxPopupMgr::PopupCreator
+ \internal
+ \brief Popup menu actions creator.
+
+ Used by Reader to create actions by reading descriptions from the file
+ and fill in the action manager with the actions.
*/
-QChar QtxPopupMgr::Selection::equality() const
+
+class QtxPopupMgr::PopupCreator : public QtxActionMgr::Creator
{
- return defEquality();
-}
+public:
+ PopupCreator( QtxActionMgr::Reader*, QtxPopupMgr* );
+ virtual ~PopupCreator();
+
+ virtual int append( const QString&, const bool,
+ const ItemAttributes&, const int );
+
+ virtual QString rule( const ItemAttributes&,
+ const QtxPopupMgr::RuleType = VisibleRule ) const;
+
+private:
+ QtxPopupMgr* myMgr;
+};
/*!
- \return name of parameter for count of selected objects
+ \brief Constructor.
+ \param r menu action reader
+ \param mgr popup menu manager
*/
-QString QtxPopupMgr::Selection::selCountParam() const
+QtxPopupMgr::PopupCreator::PopupCreator( QtxActionMgr::Reader* r,
+ QtxPopupMgr* mgr )
+: QtxActionMgr::Creator( r ),
+ myMgr( mgr )
{
- return defSelCountParam();
}
/*!
- \return default symbole to detect name of parameter list
+ \brief Destructor.
*/
-QChar QtxPopupMgr::Selection::defEquality()
+QtxPopupMgr::PopupCreator::~PopupCreator()
{
- return '$';
}
/*!
- \return default name of parameter for count of selected objects
+ \brief Create and append new action to the action manager.
+ \param tag item tag name
+ \param subMenu \c true if this item is submenu
+ \param attr attributes map
+ \param pId parent action ID
+ \return menu action ID
*/
-QString QtxPopupMgr::Selection::defSelCountParam()
+int QtxPopupMgr::PopupCreator::append( const QString& tag, const bool subMenu,
+ const ItemAttributes& attr, const int pId )
{
- return "selcount";
-}
-
+ if ( !myMgr || !reader() )
+ return -1;
+ QString label = reader()->option( "label", "label" ),
+ id = reader()->option( "id", "id" ),
+ pos = reader()->option( "pos", "pos" ),
+ group = reader()->option( "group", "group" ),
+ tooltip = reader()->option( "tooltip", "tooltip" ),
+ sep = reader()->option( "separator", "separator" ),
+ accel = reader()->option( "accel", "accel" ),
+ icon = reader()->option( "icon", "icon" ),
+ toggle = reader()->option( "toggle", "toggle" );
-/*!
- \class QtxCacheSelection
+ QtxActionMenuMgr* mgr = myMgr;
- Special selection class, that caches parameter values.
- Every parameter during popup building is calculated only one time,
- although it may be included to many rules. After calculation
- it is stored in internal map
-*/
+ int res = -1, actId = intValue( attr, id, -1 );;
+ if ( subMenu )
+ res = mgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+ else if ( tag == sep )
+ res = mgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+ else
+ {
+ QIcon set;
+ QPixmap pix;
+ QString name = strValue( attr, icon );
+ if( !name.isEmpty() )
+ {
+ if ( loadPixmap( name, pix ) )
+ set = QIcon( pix );
+ }
-class QtxCacheSelection : public QtxPopupMgr::Selection
-{
-public:
- QtxCacheSelection( QtxPopupMgr::Selection* );
- virtual ~QtxCacheSelection();
+ QString actLabel = strValue( attr, label );
+ QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, actLabel,
+ QKeySequence( strValue( attr, accel ) ),
+ myMgr );
+ newAct->setToolTip( strValue( attr, tooltip ) );
+ QString toggleact = strValue( attr, toggle );
+ bool isToggle = !toggleact.isEmpty();
+ newAct->setCheckable( isToggle );
+ newAct->setChecked( toggleact.toLower() == "true" );
+
+ connect( newAct );
+ int aid = mgr->registerAction( newAct, actId );
+ QString arule = rule( attr, QtxPopupMgr::VisibleRule );
+ if ( !arule.isEmpty() )
+ myMgr->setRule( newAct, arule, QtxPopupMgr::VisibleRule );
+ arule = rule( attr, QtxPopupMgr::EnableRule );
+ if ( !arule.isEmpty() )
+ myMgr->setRule( newAct, arule, QtxPopupMgr::EnableRule );
+ arule = rule( attr, QtxPopupMgr::ToggleRule );
+ if ( isToggle && !arule.isEmpty() )
+ myMgr->setRule( newAct, arule, QtxPopupMgr::ToggleRule );
+ res = mgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+ }
- virtual int count() const;
- virtual QtxValue param( const int, const QString& ) const;
- virtual QtxValue globalParam( const QString& ) const;
+ return res;
+}
-private:
- typedef QMap< QString, QtxValue > CacheMap;
+/*!
+ \brief Get the rule for the menu item.
- QtxPopupMgr::Selection* mySel;
- CacheMap myParamCache;
-};
+ Default implementation returns empty rule.
-/*!
- Constructor
- \param sel - base selection used for parameter calculation
+ \param attr attributes map
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return rule for the menu item corresponding to the rule type
*/
-QtxCacheSelection::QtxCacheSelection( QtxPopupMgr::Selection* sel )
-: mySel( sel )
+QString QtxPopupMgr::PopupCreator::rule( const ItemAttributes& /*attr*/,
+ const QtxPopupMgr::RuleType /*ruleType*/ ) const
{
+ return QString();
}
/*!
- Destructor
-*/
-QtxCacheSelection::~QtxCacheSelection()
-{
-}
+ \class QtxPopupMgr
+ \brief Popup menu manager.
-/*!
- \return count of selected objects
+ Menu manager allows using of set of action for automatic generating of
+ application context popup menu by reuquest and dynamic update of its
+ contents.
+
+ Use insert() methods to add menu items to the popup menu.
+
+ The visibility, enable and toggle state of the menu item is controlled
+ by the syntaxic rules, which can be set with setRule() methods.
+ The rules are parsed automatically with help of QtxEvalParser class.
+
+ QtxPopupSelection class is used as back-end for getting value of each
+ parameter found in the rule by the expression parser.
+ Use setSelection() and selection() to set/get the selection instance
+ for the popup menu manager.
+
+ Popup menu manager automatically optimizes the menu by removing
+ extra separators, hiding empty popup submenus etc.
*/
-int QtxCacheSelection::count() const
-{
- return mySel ? mySel->count() : 0;
-}
/*!
- Calculates and caches parameters.
- Already calculated parameters are returned without calculation
- \return parameter value
- \param i - index of selected object
- \param name - name of parameter
+ \brief Constructor.
+ \param object parent object
*/
-QtxValue QtxCacheSelection::param( const int i, const QString& name ) const
+QtxPopupMgr::QtxPopupMgr( QObject* parent )
+: QtxActionMenuMgr( 0, parent ),
+ mySelection( 0 )
{
- QString param_name = name + "#####" + QString::number( i );
- if( myParamCache.contains( param_name ) )
- return myParamCache[ param_name ];
- else
- {
- QtxValue v;
- if( mySel )
- v = mySel->param( i, name );
- if( v.isValid() )
- ( ( CacheMap& )myParamCache ).insert( param_name, v );
- return v;
- }
}
/*!
- Calculates and caches global parameters.
- Already calculated parameters are returned without calculation
- \return parameter value
- \param name - name of parameter
+ \brief Constructor.
+ \param popup popup menu
+ \param object parent object
*/
-QtxValue QtxCacheSelection::globalParam( const QString& name ) const
+QtxPopupMgr::QtxPopupMgr( QMenu* popup, QObject* parent )
+: QtxActionMenuMgr( popup, parent ),
+ mySelection( 0 )
{
- if( myParamCache.contains( name ) )
- return myParamCache[ name ];
- else
- {
- QtxValue v;
- if( mySel )
- v = mySel->globalParam( name );
- if( v.isValid() )
- ( ( CacheMap& )myParamCache ).insert( name, v );
- return v;
- }
}
-
-
-
/*!
- Constructor
- \param mgr - popup manager
+ \brief Destructor.
*/
-QtxPopupMgr::Operations::Operations( QtxPopupMgr* mgr )
-: QtxStrings(),
- myPopupMgr( mgr )
+QtxPopupMgr::~QtxPopupMgr()
{
- QStringList aList;
- aList.append( "every" );
- aList.append( "any" );
- aList.append( "onlyone" );
- addOperations( aList );
-
- myParser = new QtxParser( mgr->myOperations );
}
/*!
- Destructor
- Deletes internal parser
+ \brief Get popup menu.
+ \return popup menu
*/
-QtxPopupMgr::Operations::~Operations()
+QMenu* QtxPopupMgr::menu() const
{
- delete myParser;
+ return ::qobject_cast<QMenu*>( menuWidget() );
}
/*!
- \return priority of popup operation 'op'.
- \param isBin indicate whether the operation is binary
+ \brief Get popup menu.
+ \param menu popup menu
*/
-int QtxPopupMgr::Operations::prior( const QString& op, bool isBin ) const
+void QtxPopupMgr::setMenu( QMenu* menu )
{
- if( !isBin && ( op=="every" || op=="any" || op=="onlyone" ) )
- return 1;
- else
- return QtxStrings::prior( op, isBin );
-
+ setMenuWidget( menu );
}
/*!
- Calculates result of operation
- \return one of error states
- \param op - name of operation
- \param v1 - first operation argument (must be used also to store result)
- \param v2 - second operation argument
+ \brief Get selection.
+ \return current selection object
*/
-QtxParser::Error QtxPopupMgr::Operations::calculate
- ( const QString& op, QtxValue& v1, QtxValue& v2 ) const
+QtxPopupSelection* QtxPopupMgr::selection() const
{
- int ind = -1;
- if( op=="every" )
- ind = 0;
- else if( op=="any" )
- ind = 1;
- else if( op=="onlyone" )
- ind = 2;
-
- if( ind>=0 && ind<=2 )
- {
- QString val_name = op + "(" + v2.toString() + ")";
- QtxParser::Error err = QtxParser::OK;
-
- if( !myValues.contains( val_name ) )
- {
- myParser->setExpr( v2.toString() );
- QStringList params, specific;
- myParser->paramsList( params );
-
- myParser->clear();
- myPopupMgr->setParams( myParser, specific );
-
- QtxPopupMgr::Selection* sel = myPopupMgr->myCurrentSelection;
-
- int global_result = 0;
- if( sel )
- for( int i=0, n=sel->count(); i<n; i++ )
- {
- QStringList::const_iterator anIt = specific.begin(),
- aLast = specific.end();
- for( ; anIt!=aLast; anIt++ )
- {
- QtxValue v = sel->param( i, *anIt );
- if( v.isValid() )
- myParser->set( *anIt, v );
- else
- return QtxParser::InvalidToken;
- }
-
- QtxValue res = myParser->calculate();
- err = myParser->lastError();
- if( err==QtxParser::OK )
- if( res.type()==QVariant::Bool )
- {
- if( res.toBool() )
- global_result++;
- if( ind==2 && global_result>1 )
- break;
- }
- else
- return QtxParser::InvalidResult;
- else
- return err;
- }
-
- QtxValue& vv = ( QtxValue& )myValues[ val_name ];
- vv = ( ind==0 && global_result==sel->count() ) ||
- ( ind==1 ) ||
- ( ind==2 && global_result==1 );
- }
-
- v2 = myValues[ val_name ];
-
- return err;
- }
- else
- return QtxStrings::calculate( op, v1, v2 );
+ return mySelection;
}
/*!
- Clears internal map of values
+ \brief Set selection.
+ \param sel new selection object
*/
-void QtxPopupMgr::Operations::clear()
+void QtxPopupMgr::setSelection( QtxPopupSelection* sel )
{
- myValues.clear();
-}
+ if ( mySelection == sel )
+ return;
+ delete mySelection;
+ mySelection = sel;
+ if ( mySelection ) {
+ mySelection->setParent( this );
+ mySelection->setPopupMgr( this );
+ }
+ connect( mySelection, SIGNAL( destroyed( QObject* ) ),
+ this, SLOT( onSelectionDestroyed( QObject* ) ) );
+ QtxActionMgr::triggerUpdate();
+}
+/*!
+ \brief Register an action and return its identifier.
+ If \a id is less than 0, the identifier for the action is generated automatically.
+ If action with given \a id is already registered, it will be re-registered.
+ If required \a id is already in use, new identifier is generatied; in this case
+ returning value will different from required one.
-/*!
- Constructor
+ \param act action to be registered
+ \param id action ID
+ \param rule syntax rule
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return action ID (the same as \a id or generated one)
*/
-QtxPopupMgr::QtxPopupMgr( QPopupMenu* popup, QObject* parent )
-: QtxActionMenuMgr( popup, parent ),
- myCurrentSelection( 0 )
+int QtxPopupMgr::registerAction( QAction* act, const int id, const QString& rule, const QtxPopupMgr::RuleType ruleType )
{
- createOperations();
+ int _id = QtxActionMenuMgr::registerAction( act, id );
+ setRule( act, rule, ruleType );
+ return _id;
}
/*!
- Destructor
+ \brief Unregister action from internal map.
+ \param id action ID
*/
-QtxPopupMgr::~QtxPopupMgr()
+void QtxPopupMgr::unRegisterAction( const int id )
{
+ QAction* a = action( id );
+ if ( myRules.contains( a ) )
+ {
+ for ( ExprMap::iterator it = myRules[a].begin(); it != myRules[a].end(); ++it )
+ delete it.value();
+ }
+ myRules.remove( a );
+
+ remove( id );
+
+ QtxActionMenuMgr::unRegisterAction( id );
}
/*!
- Creates popup operations instance
+ \brief Insert action to the popup menu manager.
+ \param id action ID
+ \param pId parent menu action ID
+ \param rule syntax rule
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return action ID
*/
-void QtxPopupMgr::createOperations()
+int QtxPopupMgr::insertAction( const int id, const int pId, const QString& rule, const RuleType ruleType )
{
- myOperations = new QtxListOfOperations;
- myOperations->prepend( "logic", new QtxLogic(), 0 );
- myOperations->prepend( "arithm", new QtxArithmetics(), 50 );
- myOperations->append( "strings", new QtxStrings(), 100 );
- myOperations->append( "sets", new QtxSets(), 150 );
- myOperations->append( "custom", new Operations( this ), 200 );
+ int res = QtxActionMenuMgr::insert( id, pId, -1 );
+ setRule( action( id ), rule, ruleType );
+ return res;
}
/*!
- Additional version of registerAction
- \param act - action to be registered
- \param visible - rule for visibility state
- \param toggle - rule for toggle on state
- \param id - proposed id (if it is less than 0, then id will be generated automatically)
+ \brief Insert action to the popup menu manager.
+ \param a action
+ \param pId parent menu action ID
+ \param rule syntax rule
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return action ID
*/
-int QtxPopupMgr::registerAction( QAction* act,
- const QString& visible,
- const QString& toggle,
- const int id )
+int QtxPopupMgr::insertAction( QAction* a, const int pId, const QString& rule, const RuleType ruleType )
{
- int _id = QtxActionMenuMgr::registerAction( act, id );
- setRule( _id, visible, true );
- setRule( _id, toggle, false );
- return _id;
+ int res = QtxActionMenuMgr::insert( a, pId, -1 );
+ setRule( a, rule, ruleType );
+ return res;
}
/*!
- Removes action from internal map
- \param id - action id
+ \return true if action has rule of given type
+ \param a - action
+ \param t - rule type
*/
-void QtxPopupMgr::unRegisterAction( const int id )
+bool QtxPopupMgr::hasRule( QAction* a, const RuleType t ) const
{
- QAction* act = action( id );
-
- myVisibility.remove( act );
- myToggle.remove( act );
-
- remove( id );
- //QtxActionMenuMgr::unRegisterAction( id );
+ return a ? expression( a, t, false )!=0 : false;
}
/*!
- \return true if manager has rule for action
- \param act - action
- \param visibility - if it is true, then rule for "visibility" is checked, otherwise - for "toggle"
+ \return true if action with given id has rule of given type
+ \param id - action id
+ \param t - rule type
*/
-bool QtxPopupMgr::hasRule( QAction* act, bool visibility ) const
+bool QtxPopupMgr::hasRule( const int id, const RuleType t ) const
{
- return map( visibility ).contains( act );
+ return hasRule( action( id ), t );
}
/*!
- \return true if manager has rule for action
- \param id - action id
- \param visibility - if it is true, then rule for "visibility" is checked, otherwise - for "toggle"
+ \brief Get rule of type \a type for the action \a a.
+ \param a action
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return rule of required type
*/
-bool QtxPopupMgr::hasRule( const int id, bool visibility ) const
+QString QtxPopupMgr::rule( QAction* a, const RuleType ruleType ) const
{
- return hasRule( action( id ), visibility );
+ QString rule;
+ QtxEvalExpr* expr = expression( a, ruleType );
+ if ( expr )
+ rule = expr->expression();
+ return rule;
}
/*!
- Sets new rule for action
- \param act - action
- \param rule - string expression of rule
- \param visibility - if it is true, then rule for "visibility" will be set, otherwise - for "toggle"
+ \brief Get rule of type \a type for the action \a id.
+ \param id action ID
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return rule of required type
*/
-void QtxPopupMgr::setRule( QAction* act, const QString& rule, bool visibility )
+QString QtxPopupMgr::rule( const int id, const RuleType ruleType ) const
{
- if( !act || rule.isEmpty() )
- return;
-
- if( !hasRule( act, visibility ) )
- {
- QtxParser* p = new QtxParser( myOperations, rule );
- if( p->lastError()==QtxParser::OK )
- map( visibility ).insert( act, p );
- else
- delete p;
- }
- else
- {
- QtxParser* p = map( visibility )[ act ];
- p->setExpr( rule );
- if( p->lastError()!=QtxParser::OK )
- p->setExpr( QString() );
- }
+ return rule( action( id ), ruleType );
}
/*!
- Sets new rule for action
- \param id - action id
- \param rule - string expression of rule
- \param visibility - if it is true, then rule for "visibility" will be set, otherwise - for "toggle"
+ \brief Set rule of type \a type for the action \a a.
+ \param a action
+ \param rule rule
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return rule of required type
*/
-void QtxPopupMgr::setRule( const int id, const QString& rule, bool visibility )
+void QtxPopupMgr::setRule( QAction* a, const QString& rule, const RuleType ruleType )
{
- setRule( action( id ), rule, visibility );
+ if ( !a )
+ return;
+
+ QtxEvalExpr* expr = expression( a, ruleType, true );
+
+ expr->setExpression( rule );
}
/*!
- \return true if parser has finished work without errors
- \param p - parser
+ \brief Set rule of type \a type for the action \a id.
+ \param id action ID
+ \param rule rule
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return rule of required type
*/
-bool result( QtxParser* p )
+void QtxPopupMgr::setRule( const int id, const QString& rule, const RuleType ruleType )
{
- bool res = false;
- if( p )
- {
- QtxValue vv = p->calculate();
- res = p->lastError()==QtxParser::OK &&
- ( ( vv.type()==QVariant::Int && vv.toInt()!=0 ) ||
- ( vv.type()==QVariant::Bool && vv.toBool() ) );
- }
- return res;
+ setRule( action( id ), rule, ruleType );
}
/*!
- Fills parser parameters with help of Selection::globalParam() method
- \param p - parser
- \param specific - list will be filled with names of parameters depending on selection objects (not global)
+ \brief Calculate an expression.
+ \param p expression parser
+ \return \c true if parser has finished work without errors
*/
-void QtxPopupMgr::setParams( QtxParser* p, QStringList& specific ) const
+bool QtxPopupMgr::result( QtxEvalParser* p ) const
{
- if( !p || !myCurrentSelection )
- return;
-
- QStringList params;
-
- p->paramsList( params );
- QStringList::const_iterator anIt = params.begin(),
- aLast = params.end();
- for( ; anIt!=aLast; anIt++ )
- {
- QtxValue v = myCurrentSelection->globalParam( *anIt );
- if( v.isValid() )
- p->set( *anIt, v );
- else
- specific.append( *anIt );
- }
+ bool res = false;
+ if ( p )
+ {
+ QVariant vv = p->calculate();
+ res = p->error() == QtxEvalExpr::OK &&
+ ( ( vv.type() == QVariant::Int && vv.toInt() != 0 ) ||
+ ( vv.type() == QVariant::Bool && vv.toBool() ) );
+ }
+ return res;
}
/*!
- \return true if 'v1'<'v2'
- This function can work with many types of values
+ \brief Fill the parser with parameters of the expression.
+
+ The values of the parameters are given from the selection object
+ (QtxPopupSelection).
+
+ \param p expression parser
+ \param returning list of parameters names which are not retrieved from the selection
+ \sa selection()
*/
-bool operator<( const QtxValue& v1, const QtxValue& v2 )
+void QtxPopupMgr::setParameters( QtxEvalParser* p, QStringList& specific ) const
{
- QVariant::Type t1 = v1.type(), t2 = v2.type();
- if( t1==t2 )
- {
- switch( t1 )
- {
- case QVariant::Int:
- return v1.toInt() < v2.toInt();
-
- case QVariant::Double:
- return v1.toDouble() < v2.toDouble();
-
- case QVariant::CString:
- case QVariant::String:
- return v1.toString() < v2.toString();
-
- case QVariant::StringList:
- case QVariant::List:
- {
- const QValueList<QtxValue>& aList1 = v1.toList(), aList2 = v2.toList();
- QValueList<QtxValue>::const_iterator
- anIt1 = aList1.begin(), aLast1 = aList1.end(),
- anIt2 = aList2.begin(), aLast2 = aList2.end();
- for( ; anIt1!=aLast1 && anIt2!=aLast2; anIt1++, anIt2++ )
- if( (*anIt1)!=(*anIt2) )
- return (*anIt1)<(*anIt2);
-
- return anIt1==aLast1 && anIt2!=aLast2;
- }
+ if ( !p || !mySelection )
+ return;
- default:
- return v1.toString()<v2.toString();
- }
+ QStringList params = p->parameters();
+ for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it )
+ {
+ QVariant v = parameter( *it );
+ if ( v.isValid() )
+ p->setParameter( *it, v );
+ else
+ specific.append( *it );
}
- else
- return t1<t2;
}
/*!
- \return true if rule of action is satisfied on current selection
- \param act - action
- \param visibility - what rule is checked: for visibility(true) or for toggle(false)
+ \brief Check the rule for the action.
+ \param act action
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \return \c true if current selection satisfies the action rule
*/
-bool QtxPopupMgr::isSatisfied( QAction* act, bool visibility ) const
+bool QtxPopupMgr::isSatisfied( QAction* act, const RuleType ruleType ) const
{
- QString menu = act->menuText();
+ if ( !act )
+ return false;
- bool res = false;
- if( !act )
- return res;
+ QtxEvalExpr* exp = expression( act, ruleType );
+ if ( !exp )
+ return true;
- if( hasRule( act, visibility ) )
- {
- QtxParser* p = map( visibility )[ act ];
- QStringList specific;
- p->clear();
- ( ( Operations* )myOperations->operations( "custom" ) )->clear();
+ bool res = false;
- setParams( p, specific );
+ QtxEvalParser* p = exp->parser();
- QMap<QValueList<QtxValue>,int> aCorteges;
- QValueList<QtxValue> c;
+ QStringList specific;
+ p->clearParameters();
+ setParameters( p, specific );
- if( specific.count()>0 )
- if( myCurrentSelection )
+ QMap<QList<QVariant>, int> aCorteges;
+ if ( !specific.isEmpty() )
+ {
+ if ( mySelection )
+ {
+ res = false;
+ for ( int i = 0; i < mySelection->count() && !res; i++ )
{
- res = false;
-
- for( int i=0, n=myCurrentSelection->count(); i<n && !res; i++ )
- {
- QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end();
- c.clear();
- for( ; anIt1!=aLast1; anIt1++ )
- c.append( myCurrentSelection->param( i, *anIt1 ) );
- aCorteges.insert( c, 0 );
- }
-
- //qDebug( QString( "%1 corteges" ).arg( aCorteges.count() ) );
- QMap<QValueList<QtxValue>,int>::const_iterator anIt = aCorteges.begin(), aLast = aCorteges.end();
- for( ; anIt!=aLast; anIt++ )
- {
- QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end();
- const QValueList<QtxValue>& aCortege = anIt.key();
- QValueList<QtxValue>::const_iterator anIt2 = aCortege.begin();
- for( ; anIt1!=aLast1; anIt1++, anIt2++ )
- p->set( *anIt1, *anIt2 );
- res = res || result( p );
- }
-
- /*
- for( int i=0, n=myCurrentSelection->count(); i<n && !res; i++ )
- {
- QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end();
- for( ; anIt1!=aLast1; anIt1++ )
- p->set( *anIt1, myCurrentSelection->param( i, *anIt1 ) );
- res = res || result( p );
- }*/
+ QList<QVariant> c;
+ for ( QStringList::const_iterator anIt1 = specific.begin(); anIt1 != specific.end(); ++anIt1 )
+ c.append( parameter( *anIt1, i ) );
+ aCorteges.insert( c, 0 );
}
- else
- res = false;
+ for ( QMap<QList<QVariant>, int>::const_iterator anIt = aCorteges.begin(); anIt != aCorteges.end(); ++anIt )
+ {
+ const QList<QVariant>& aCortege = anIt.key();
+ QStringList::const_iterator anIt1 = specific.begin(), aLast1 = specific.end();
+ QList<QVariant>::const_iterator anIt2 = aCortege.begin();
+ for ( ; anIt1 != aLast1; anIt1++, anIt2++ )
+ p->setParameter( *anIt1, *anIt2 );
+ res = res || result( p );
+ }
+ }
else
- res = result( p );
+ res = false;
}
+ else
+ res = result( p );
return res;
}
/*!
- \return true if item corresponding to action is visible
- \param actId - action id
- \param place - index of place
+ \brief Check if the menu item is visible.
+ \param id action ID
+ \param place some parent action ID
+ \return \c true if the action is visible
*/
-bool QtxPopupMgr::isVisible( const int actId, const int place ) const
+bool QtxPopupMgr::isVisible( const int id, const int place ) const
{
- bool res = QtxActionMenuMgr::isVisible( actId, place );
- QAction* act = action( actId );
- if( hasRule( act, true ) )
- res = res && isSatisfied( act, true );
- return res;
+ return QtxActionMenuMgr::isVisible( id, place ) && ( !hasRule( id ) || isSatisfied( action( id ) ) );
}
/*!
- Updates popup according to selection
- \param p - popup menu
- \param sel - selection
+ \brief Perform internal update of the popup menu according
+ to the current selection.
*/
-void QtxPopupMgr::updatePopup( QPopupMenu* p, Selection* sel )
+void QtxPopupMgr::internalUpdate()
{
- QTime t1 = QTime::currentTime();
+ myCache.clear();
- if( !p || !sel )
- return;
+ for ( RuleMap::iterator it = myRules.begin(); it != myRules.end(); ++it )
+ {
+ ExprMap& map = it.value();
+ if ( it.key()->isCheckable() && map.contains( ToggleRule ) &&
+ !map[ToggleRule]->expression().isEmpty() )
+ it.key()->setChecked( isSatisfied( it.key(), ToggleRule ) );
+ }
- myCurrentSelection = new QtxCacheSelection( sel );
- RulesMap::iterator anIt = myToggle.begin(),
- aLast = myToggle.end();
- for( ; anIt!=aLast; anIt++ )
- if( anIt.key()->isToggleAction() && hasRule( anIt.key(), false ) )
- anIt.key()->setOn( isSatisfied( anIt.key(), false ) );
+ QtxActionMenuMgr::internalUpdate();
- setWidget( ( QWidget* )p );
- updateMenu();
- QTime t2 = QTime::currentTime();
- qDebug( QString( "update popup time = %1 msecs" ).arg( t1.msecsTo( t2 ) ) );
- qDebug( QString( "number of objects = %1" ).arg( myCurrentSelection->count() ) );
+ myCache.clear();
+}
- delete myCurrentSelection;
+/*!
+ \brief Update popup according to the current selection.
+*/
+void QtxPopupMgr::updateMenu()
+{
+ internalUpdate();
}
/*!
- \return reference to map of rules
- \param visibility - type of map: visibility of toggle
+ \brief Get an syntax expression for the action according to the specified rule type.
+ \param a action
+ \param ruleType rule type (QtxPopupMgr::RuleType)
+ \param create if \c true an expression does not exist, create it
+ \return syntax expression
*/
-QtxPopupMgr::RulesMap& QtxPopupMgr::map( bool visibility ) const
+QtxEvalExpr* QtxPopupMgr::expression( QAction* a, const RuleType ruleType, const bool create ) const
{
- return ( RulesMap& )( visibility ? myVisibility : myToggle );
+ QtxEvalExpr* res = 0;
+
+ QtxPopupMgr* that = (QtxPopupMgr*)this;
+ RuleMap& ruleMap = that->myRules;
+ if ( !ruleMap.contains( a ) && create )
+ ruleMap.insert( a, ExprMap() );
+
+ if ( ruleMap.contains( a ) )
+ {
+ ExprMap& exprMap = ruleMap[a];
+ if ( exprMap.contains( ruleType ) )
+ res = exprMap[ruleType];
+ else if ( create )
+ exprMap.insert( ruleType, res = new QtxEvalExpr() );
+ }
+
+ return res;
}
/*!
- Loads actions description from file
- \param fname - name of file
- \param r - reader of file
- \return true on success
+ \brief Load actions description from the file.
+ \param fname file name
+ \param r action reader
+ \return \c true on success and \c false on error
*/
bool QtxPopupMgr::load( const QString& fname, QtxActionMgr::Reader& r )
{
return r.read( fname, cr );
}
+/*
+ \brief Get the specified parameter value.
+ \param name parameter name
+ \param idx additional index used when used parameters with same names
+ \return parameter value
+ \sa selection()
+*/
+QVariant QtxPopupMgr::parameter( const QString& name, const int idx ) const
+{
+ QVariant val;
+ QString cacheName = name + ( idx >= 0 ? QString( "_%1" ).arg( idx ) : QString() );
+ if ( myCache.contains( cacheName ) )
+ val = myCache[cacheName];
+ else
+ {
+ if ( selection() )
+ val = idx < 0 ? selection()->parameter( name ) :
+ selection()->parameter( idx, name );
+ if ( val.isValid() )
+ {
+ QtxPopupMgr* that = (QtxPopupMgr*)this;
+ that->myCache.insert( cacheName, val );
+ }
+ }
+ return val;
+}
+/*!
+ \brief Called when selection is destroyed.
+
+ Prevents crashes when the selection object is destroyed outside the
+ popup manager.
+ \param o selection object being destroyed
+*/
+void QtxPopupMgr::onSelectionDestroyed( QObject* o )
+{
+ if ( o == mySelection )
+ mySelection = 0;
+}
/*!
- Constructor
- \param r - menu reader
- \param mgr - menu manager
+ \class QtxPopupSelection
+ \brief This class is a part of the popup menu management system.
+
+ The QtxPopupSelection class is used as back-end for getting value
+ of each parameter found in the rule by the expression parser.
+
+ For example, it can be used for the analyzing of the currently
+ selected objects and defining the values of the parameters used
+ in the rules syntax expression. Rules, in their turn, define
+ each action state - visibility, enabled and toggled state.
*/
-QtxPopupMgr::PopupCreator::PopupCreator( QtxActionMgr::Reader* r,
- QtxPopupMgr* mgr )
-: QtxActionMgr::Creator( r ),
- myMgr( mgr )
+
+/*!
+ \brief Constructor.
+*/
+QtxPopupSelection::QtxPopupSelection()
+ : QObject( 0 ),
+ myPopupMgr( 0 )
{
}
/*!
- Destructor
-*/QtxPopupMgr::PopupCreator::~PopupCreator()
+ \brief Destructor.
+*/
+QtxPopupSelection::~QtxPopupSelection()
{
}
+/*!
+ \brief Get an option value.
+ \param optName option name
+ \return option value or empty string if option is not found
+*/
+QString QtxPopupSelection::option( const QString& optName ) const
+{
+ QString opt;
+ if ( myOptions.contains( optName ) )
+ opt = myOptions[optName];
+ return opt;
+}
/*!
- Appends new menu items
- \param tag - tag of item
- \param subMenu - it has submenu
- \param attr - list of attributes
- \param pId - id of action corresponding to parent item
+ \brief Set an option value.
+ \param optName option name
+ \param opt option value
*/
-int QtxPopupMgr::PopupCreator::append( const QString& tag, const bool subMenu,
- const ItemAttributes& attr, const int pId )
+void QtxPopupSelection::setOption( const QString& optName, const QString& opt )
{
- if( !myMgr || !reader() )
- return -1;
+ myOptions.insert( optName, opt );
+}
- QString label = reader()->option( "label", "label" ),
- id = reader()->option( "id", "id" ),
- pos = reader()->option( "pos", "pos" ),
- group = reader()->option( "group", "group" ),
- tooltip = reader()->option( "tooltip", "tooltip" ),
- sep = reader()->option( "separator", "separator" ),
- accel = reader()->option( "accel", "accel" ),
- icon = reader()->option( "icon", "icon" ),
- toggle = reader()->option( "toggle", "toggle" );
+QtxPopupMgr* QtxPopupSelection::popupMgr() const
+{
+ return myPopupMgr;
+}
- int res = -1, actId = intValue( attr, id, -1 );;
- if( subMenu )
- res = myMgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
- else if( tag==sep )
- res = myMgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
- else //if( !myMgr->contains( actId ) )
+void QtxPopupSelection::setPopupMgr( QtxPopupMgr* pm )
+{
+ myPopupMgr = pm;
+}
+
+/*!
+ \brief Get the parameter value.
+ \param str parameter name
+ \return parameter value
+*/
+QVariant QtxPopupSelection::parameter( const QString& str ) const
+{
+ if ( str == selCountParam() )
+ return count();
+ else if ( str.startsWith( equalityParam() ) )
{
- QPixmap pix; QIconSet set;
- QString name = strValue( attr, icon );
- if( !name.isEmpty() )
+ QtxEvalSetSets::ValueSet set;
+ QString par = str.mid( equalityParam().length() );
+
+ QtxPopupMgr* pMgr = popupMgr();
+ for ( int i = 0; i < (int)count(); i++ )
{
- if( loadPixmap( name, pix ) )
- set = QIconSet( pix );
+ QVariant v = pMgr ? pMgr->parameter( par, i ) : parameter( i, par );
+ if ( v.isValid() )
+ QtxEvalSetSets::add( set, v );
+ else
+ return QVariant();
}
-
- QString actLabel = strValue( attr, label );
- QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, actLabel,
- QKeySequence( strValue( attr, accel ) ),
- myMgr );
- newAct->setToolTip( strValue( attr, tooltip ) );
- QString toggleact = strValue( attr, toggle );
- bool isToggle = !toggleact.isEmpty();
- newAct->setToggleAction( isToggle );
- newAct->setOn( toggleact.lower()=="true" );
-
- connect( newAct );
- int aid = myMgr->registerAction( newAct, visibleRule( attr ),
- isToggle ? toggleRule( attr ) : QString::null,
- actId );
- res = myMgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
+ return set;
}
-
- return res;
+ else
+ return QVariant();
}
/*!
- \return visibility rule by attributes
- Default implementation is empty
+ \brief Get symbol which detects the name of the parameter list.
+ \return equality symbol (by default, "$")
*/
-QString QtxPopupMgr::PopupCreator::visibleRule( const ItemAttributes& ) const
+QString QtxPopupSelection::equalityParam() const
{
- return QString::null;
+ QString str = option( "equality" );
+ if ( str.isEmpty() )
+ str = "$";
+ return str;
}
/*!
- \return toggle rule by attributes
- Default implementation is empty
+ \brief Get name of the parameter, specifing number of selected objects
+ \return parameter name (by default, "selcount")
*/
-QString QtxPopupMgr::PopupCreator::toggleRule( const ItemAttributes& ) const
+QString QtxPopupSelection::selCountParam() const
{
- return QString::null;
+ QString str = option( "selcount" );
+ if ( str.isEmpty() )
+ str = "selcount";
+ return str;
}
+
+/*!
+ \fn int QtxPopupSelection::count() const;
+ \brief Get number of the selected objects.
+ \return nb of selected objects
+*/
+
+/*!
+ \fn QVariant QtxPopupSelection::parameter( const int idx, const QString& name ) const;
+ \brief Get value of the parameter which is of list type
+ \param idx parameter index
+ \param name parameter name
+ \return parameter value
+*/