Back to index

salome-gui  6.5.0
QtxActionMenuMgr.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:      QtxActionMenuMgr.cxx
00024 // Author:    Alexander SOLOVYOV, Sergey TELKOV
00025 //
00026 #include "QtxActionMenuMgr.h"
00027 
00028 #include "QtxAction.h"
00029 
00030 #include <QMenu>
00031 #include <QMenuBar>
00032 #include <QWidget>
00033 #include <QMainWindow>
00034 
00041 class QtxActionMenuMgr::MenuNode
00042 {
00043 public:
00044   MenuNode();
00045   MenuNode( MenuNode*, const int, const int, const int );
00046   ~MenuNode();
00047   
00048   MenuNode* parent;       
00049   int       id;           
00050   int       idx;          
00051   int       group;        
00052   bool      visible;      
00053   int       emptyEnabled; 
00054   NodeList  children;     
00055 };
00056 
00061 QtxActionMenuMgr::MenuNode::MenuNode()
00062   : parent( 0 ), id( -1 ), idx( -1 ), group( -1 ), visible( true ), emptyEnabled( 0 )
00063 {
00064 }
00065 
00074 QtxActionMenuMgr::MenuNode::MenuNode( MenuNode* p,
00075                                       const int _id,
00076                                       const int _idx,
00077                                       const int _group )
00078 : parent( p ), id( _id ), idx( _idx ), group( _group ), visible( true ), emptyEnabled( 0 )
00079 {
00080   if ( p )
00081     p->children.append( this );
00082 }
00083 
00088 QtxActionMenuMgr::MenuNode::~MenuNode()
00089 {
00090   for ( NodeList::iterator it = children.begin(); it != children.end(); ++it )
00091     delete *it;
00092 }
00093 
00115 QtxActionMenuMgr::QtxActionMenuMgr( QMainWindow* p )
00116 : QtxActionMgr( p ), 
00117   myRoot( new MenuNode() ),
00118   myMenu( p ? p->menuBar() : 0 )
00119 {
00120   if ( myMenu ) {
00121     connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00122   }
00123 }
00124 
00130 QtxActionMenuMgr::QtxActionMenuMgr( QWidget* mw, QObject* p )
00131 : QtxActionMgr( p ), 
00132   myRoot( new MenuNode() ),
00133   myMenu( mw )
00134 {
00135   if ( myMenu ) {
00136     connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00137   }
00138 }
00139 
00143 QtxActionMenuMgr::~QtxActionMenuMgr()
00144 {
00145   for ( MenuMap::Iterator itr = myMenus.begin(); itr != myMenus.end(); ++itr )
00146   {
00147     QPointer<QAction> a = itr.value();
00148     delete a->menu();
00149     delete a;
00150   }
00151 
00152   delete myRoot;
00153 }
00154 
00163 bool QtxActionMenuMgr::isVisible( const int actId, const int place ) const
00164 {
00165   MenuNode* node = find( actId, place );
00166   return node && node->visible;
00167 }
00168 
00176 void QtxActionMenuMgr::setVisible( const int actId, const int place, const bool v )
00177 {
00178   MenuNode* node = find( actId, place );
00179   if ( node )
00180     node->visible = v;
00181 }
00182 
00197 int QtxActionMenuMgr::insert( const int id, const QString& menus, const int group, const int idx )
00198 {
00199   return insert( id, menus.split( "|", QString::SkipEmptyParts ), group, idx );
00200 }
00201 
00216 int QtxActionMenuMgr::insert( QAction* a, const QString& menus, const int group, const int idx )
00217 {
00218   return insert( a, menus.split( "|", QString::SkipEmptyParts ), group, idx );
00219 }
00220 
00236 int QtxActionMenuMgr::insert( const int id, const QStringList& menus, const int group, const int idx )
00237 {
00238   int pId = createMenu( menus, -1 );
00239   if ( pId == -1 )
00240     return -1;
00241 
00242   return insert( id, pId, group, idx );
00243 }
00244 
00260 int QtxActionMenuMgr::insert( QAction* a, const QStringList& menus, const int group, const int idx )
00261 {
00262   int pId = createMenu( menus, -1 );
00263   if ( pId == -1 )
00264     return -1;
00265 
00266   return insert( a, pId, group, idx );
00267 }
00268 
00277 int QtxActionMenuMgr::insert( const int id, const int pId, const int group, const int idx )
00278 {
00279   if ( id == -1 )
00280     return -1;
00281 
00282   MenuNode* pNode = pId == -1 ? myRoot : find( pId );
00283   if ( !pNode )
00284     return -1;
00285 
00286   MenuNode* node = new MenuNode( pNode, id, idx, group );
00287 
00288   triggerUpdate( pNode->id, false );
00289 
00290   return node->id;
00291 }
00292 
00301 int QtxActionMenuMgr::insert( QAction* a, const int pId, const int group, const int idx )
00302 {
00303   return insert( registerAction( a ), pId, group, idx );
00304 }
00305 
00315 int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int id, const int idx )
00316 {
00317   MenuNode* pNode = pId == -1 ? myRoot : find( pId );
00318   if ( !pNode )
00319     return -1;
00320 
00321   MenuNode* eNode = id == -1 ? 0 : find( id );
00322 
00323   int fid = -1;
00324   for ( NodeList::iterator it = pNode->children.begin(); it != pNode->children.end() && fid == -1; ++it )
00325   {
00326     if ( myMenus.contains( (*it)->id ) &&
00327          clearTitle( myMenus[(*it)->id]->text() ) == clearTitle( title ) )
00328       fid = (*it)->id;
00329   }
00330 
00331   if ( fid != -1 )
00332     return fid;
00333 
00334   int gid = (id == -1 || eNode ) ? generateId() : id;
00335 
00336   QMenu* menu = new QMenu( 0 );
00337   QAction* ma = menu->menuAction();
00338   ma->setText( title );
00339 
00340   connect( ma->menu(), SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
00341   connect( ma->menu(), SIGNAL( aboutToHide() ), this, SLOT( onAboutToHide() ) );
00342 
00343   MenuNode* node = new MenuNode( pNode, myMenus.insert( gid, ma ).key(), idx, group );
00344 
00345   triggerUpdate( pNode->id, false );
00346 
00347   return node->id;
00348 }
00349 
00365 int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int id, const int idx )
00366 {
00367   return insert( title, menus.split( "|", QString::SkipEmptyParts ), group, id, idx );
00368 }
00369 
00386 int QtxActionMenuMgr::insert( const QString& title, const QStringList& menus, const int group, const int id, const int idx )
00387 {
00388   int pId = createMenu( menus, -1 );
00389   return insert( title, pId, group, id, idx );
00390 }
00391 
00400 int QtxActionMenuMgr::append( const QString& title, const int pId, const int group, const int id )
00401 {
00402   return insert( title, pId, group, id );
00403 }
00404 
00412 int QtxActionMenuMgr::append( const int id, const int pId, const int group )
00413 {
00414   return insert( id, pId, group );
00415 }
00416 
00424 int QtxActionMenuMgr::append( QAction* a, const int pId, const int group )
00425 {
00426   return insert( a, pId, group );
00427 }
00428 
00437 int QtxActionMenuMgr::prepend( const QString& title, const int pId, const int group, const int id )
00438 {
00439   return insert( title, pId, group, id, 0 );
00440 }
00441 
00449 int QtxActionMenuMgr::prepend( const int id, const int pId, const int group )
00450 {
00451   return insert( id, pId, group, 0 );
00452 }
00453 
00461 int QtxActionMenuMgr::prepend( QAction* a, const int pId, const int group )
00462 {
00463   return insert( a, pId, group, 0 );
00464 }
00465 
00470 void QtxActionMenuMgr::remove( const int id )
00471 {
00472   removeMenu( id, 0 );
00473   update();
00474 }
00475 
00482 void QtxActionMenuMgr::remove( const int id, const int pId, const int group )
00483 {
00484   MenuNode* pNode = pId == -1 ? myRoot : find( pId );
00485   if ( !pNode )
00486     return;
00487 
00488   NodeList delNodes;
00489   for ( NodeList::iterator it = pNode->children.begin(); it != pNode->children.end(); ++it )
00490   {
00491     if ( (*it)->id == id && ( (*it)->group == group || group == -1 ) )
00492       delNodes.append( *it );
00493   }
00494 
00495   QWidget* mW = menuWidget( pNode );
00496   for ( NodeList::iterator itr = delNodes.begin(); itr != delNodes.end(); ++itr )
00497   {
00498     int id = (*itr)->id;
00499     if( mW && menuAction( id ) )
00500     {
00501       mW->removeAction( menuAction( id ) );
00502       myMenus.remove( id );
00503     }
00504     else if( mW && itemAction( id ) )
00505       mW->removeAction( itemAction( id ) );
00506     pNode->children.removeAll( *itr );
00507   }
00508 
00509   triggerUpdate( pNode->id, false );
00510 }
00511 
00517 void QtxActionMenuMgr::show( const int id )
00518 {
00519   setShown( id, true );
00520 }
00521 
00527 void QtxActionMenuMgr::hide( const int id )
00528 {
00529   setShown( id, false );
00530 }
00531 
00538 bool QtxActionMenuMgr::isShown( const int id ) const
00539 {
00540   bool res = false;
00541   MenuNode* node = find( id );
00542   if ( node )
00543     res = node->visible;
00544   return res;
00545 }
00546 
00553 void QtxActionMenuMgr::setShown( const int id, const bool on )
00554 {
00555   NodeList aNodes;
00556   find( id, aNodes );
00557 
00558   for ( NodeList::iterator it = aNodes.begin(); it != aNodes.end(); ++it )
00559   {
00560     if ( (*it)->visible != on )
00561     {
00562       (*it)->visible = on;
00563       triggerUpdate( (*it)->parent ? (*it)->parent->id : myRoot->id, false );
00564     }
00565   }
00566 }
00567 
00573 void QtxActionMenuMgr::change( const int id, const QString& title )
00574 {
00575   QAction* a = menuAction( id );
00576   if ( a )
00577     a->setText( title );
00578 }
00579 
00585 void QtxActionMenuMgr::onAboutToShow()
00586 {
00587   QMenu* m = ::qobject_cast<QMenu*>( sender() );
00588   if ( m )
00589     emit menuAboutToShow( m );
00590 }
00591 
00597 void QtxActionMenuMgr::onAboutToHide()
00598 {
00599   QMenu* m = ::qobject_cast<QMenu*>( sender() );
00600   if ( m )
00601     emit menuAboutToHide( m );
00602 }
00603 
00611 void QtxActionMenuMgr::onDestroyed( QObject* obj )
00612 {
00613   if ( myMenu == obj )
00614     myMenu = 0;
00615 }
00616 
00617 
00634 QWidget* QtxActionMenuMgr::menuWidget() const
00635 {
00636   return myMenu;
00637 }
00638 
00643 void QtxActionMenuMgr::setMenuWidget( QWidget* mw )
00644 {
00645   if ( myMenu == mw )
00646     return;
00647 
00648   if ( myMenu )
00649     disconnect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00650 
00651   myMenu = mw;
00652 
00653   if ( myMenu )
00654     connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
00655 
00656   triggerUpdate( -1, true );
00657 }
00658 
00666 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, const int pId, const bool rec ) const
00667 {
00668   return find( id, find( pId ), rec );
00669 }
00670 
00678 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* startNode, const bool rec ) const
00679 {
00680   MenuNode* node = 0;
00681   MenuNode* start = startNode ? startNode : myRoot;
00682   for ( NodeList::iterator it = start->children.begin(); it != start->children.end() && !node; ++it )
00683   {
00684     if ( (*it)->id == id )
00685       node = *it;
00686     else if ( rec )
00687       node = find( id, *it, rec );
00688   }
00689   return node;
00690 }
00691 
00699 bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode ) const
00700 {
00701   MenuNode* start = startNode ? startNode : myRoot;
00702   for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
00703   {
00704     MenuNode* node = *it;
00705     if ( node->id == id )
00706       lst.prepend( node );
00707 
00708     find( id, lst, node );
00709   }
00710   return !lst.isEmpty();
00711 }
00712 
00720 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, const int pId, const bool rec ) const
00721 {
00722   return find( title, find( pId ), rec );
00723 }
00724 
00732 bool QtxActionMenuMgr::find( const QString& title, NodeList& lst, MenuNode* startNode ) const
00733 {
00734   MenuNode* start = startNode ? startNode : myRoot;
00735   for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
00736   {
00737     QAction* a = itemAction( (*it)->id );
00738     if ( !a )
00739       a = menuAction( (*it)->id );
00740     if ( a && clearTitle( a->text() ) == clearTitle( title ) )
00741       lst.prepend( *it );
00742 
00743     find( title, lst, *it );
00744   }
00745   return !lst.isEmpty();
00746 }
00747 
00755 QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, MenuNode* startNode, const bool rec ) const
00756 {
00757   MenuNode* node = 0;
00758   MenuNode* start = startNode ? startNode : myRoot;
00759   for ( NodeList::iterator it = start->children.begin(); it != start->children.end() && !node; ++it )
00760   {
00761     QAction* a = itemAction( (*it)->id );
00762     if ( !a )
00763       a = menuAction( (*it)->id );
00764     if ( a && clearTitle( a->text() ) == clearTitle( title ) )
00765       node = *it;
00766     if ( !node && rec )
00767       node = find( title, *it, rec );
00768   }
00769   return node;
00770 }
00771 
00778 int QtxActionMenuMgr::findId( const int id, const int pid ) const
00779 {
00780   MenuNode* start = pid != -1 ? find( pid ) : myRoot;
00781   if ( start )
00782   {
00783     for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
00784     {
00785       if ( (*it)->id == id )
00786         return id;
00787     }
00788   }
00789   return -1;
00790 }
00791 
00797 void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode )
00798 {
00799   MenuNode* start = startNode ? startNode : myRoot;
00800   for ( NodeList::iterator it = start->children.begin(); it != start->children.end(); ++it )
00801   {
00802     if ( (*it)->id == id )
00803       start->children.removeAll( *it );
00804     else
00805       removeMenu( id, *it );
00806   }
00807 }
00808 
00814 QAction* QtxActionMenuMgr::itemAction( const int id ) const
00815 {
00816   return action( id );
00817 }
00818 
00824 QAction* QtxActionMenuMgr::menuAction( const int id ) const
00825 {
00826   QAction* a = 0;
00827 
00828   if ( myMenus.contains( id ) )
00829     a = myMenus[id];
00830 
00831   return a;
00832 }
00833 
00839 int QtxActionMenuMgr::menuActionId( QAction* a ) const
00840 {
00841   int id = -1;
00842   for ( MenuMap::ConstIterator itr = myMenus.begin(); itr != myMenus.end() && id == -1; ++itr )
00843   {
00844     if ( itr.value() == a )
00845       id = itr.key();
00846   }
00847   return id;
00848 }
00849 
00861 void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bool updParent )
00862 {
00863   if ( !isUpdatesEnabled() )
00864     return;
00865 
00866   MenuNode* node = startNode ? startNode : myRoot;
00867 
00868   QWidget* mw = menuWidget( node );
00869   if ( !mw )
00870     return;
00871 
00872   bool filled = checkWidget( mw );
00873 
00874   // first remove all own actions and collect foreign ones
00875   QMap< QAction*, QList<QAction*> > foreign;
00876   QAction* a;
00877   QAction* preva = 0;
00878   QListIterator<QAction*> ait( mw->actions() ); ait.toBack();
00879   while ( ait.hasPrevious() )
00880   {
00881     a = ait.previous();
00882     if ( ownAction( a, node ) )
00883     {
00884       preva = a;
00885       mw->removeAction( a );     // remove own actions
00886     }
00887     else
00888     {
00889       foreign[preva].prepend(a); // do not yet remove foreign actions
00890     }
00891   }
00892   // now only foreign actions should stay in the menu, thus remove them also
00893   QMap< QAction*, QList<QAction*> >::Iterator formapit;
00894   for( formapit = foreign.begin(); formapit != foreign.end(); ++formapit )
00895   {
00896     QMutableListIterator<QAction*> foralit( formapit.value() );
00897     while ( foralit.hasNext() )
00898     {
00899       a = foralit.next();
00900       if ( !mw->actions().contains( a ) )
00901         foralit.remove();
00902     }
00903   }
00904   QList<QAction*> alist = mw->actions();
00905   foreach( a, alist ) mw->removeAction( a );
00906 
00907   // collect all registered menus by group id
00908   QMap<int, NodeList> idMap;
00909   for ( NodeList::iterator it2 = node->children.begin(); it2 != node->children.end(); ++it2 )
00910   {
00911     NodeList& lst = idMap[(*it2)->group];
00912     int idx = (*it2)->idx;
00913     if ( idx < 0 || idx >= (int)lst.count() )
00914       lst.append( *it2 );
00915     else
00916       lst.insert( idx, *it2 );
00917   }
00918 
00919   QIntList groups = idMap.keys();
00920   qSort( groups );
00921 
00922   groups.removeAll( -1 );
00923   groups.append( -1 );
00924 
00925   // rebuild menu: 1. add all registered actions
00926   for ( QIntList::const_iterator gIt = groups.begin(); gIt != groups.end(); ++gIt )
00927   {
00928     if ( !idMap.contains( *gIt ) )
00929       continue;
00930 
00931     const NodeList& lst = idMap[*gIt];
00932     for ( NodeList::const_iterator iter = lst.begin(); iter != lst.end(); ++iter )
00933     {
00934       MenuNode* node = *iter;
00935       if ( !node ) continue;
00936 
00937       if ( rec )
00938         updateMenu( node, rec, false );
00939 
00940       MenuNode* par = node->parent;
00941       if ( !isVisible( node->id, par ? par->id : -1 ) )
00942         continue;
00943 
00944       bool isMenu = false;
00945       QAction* a = itemAction( node->id );
00946       if ( !a )
00947       {
00948         isMenu = true;
00949         a = menuAction( node->id );
00950       }
00951       if ( !a ) continue;
00952 
00953       if ( !isMenu || !a->menu()->isEmpty() || node->emptyEnabled > 0 )
00954         mw->addAction( a );
00955     }
00956   }
00957 
00958   // rebuild menu: 2. insert back all foreign actions
00959   for( formapit = foreign.begin(); formapit != foreign.end(); ++formapit ) {
00960     preva = formapit.key();
00961     foreach( a, formapit.value() )
00962       mw->insertAction( preva, a );
00963   }
00964   
00965   // remove extra separators
00966   simplifySeparators( mw );
00967 
00968   // update parent menu if necessary
00969   if ( updParent && node->parent && filled != checkWidget( mw ) )
00970     updateMenu( node->parent, false );
00971 }
00972 
00978 void QtxActionMenuMgr::internalUpdate()
00979 {
00980   if ( !isUpdatesEnabled() )
00981     return;
00982 
00983   updateMenu();
00984   myUpdateIds.clear();
00985 }
00986 
00994 bool QtxActionMenuMgr::ownAction( QAction* a, MenuNode* node ) const
00995 {
00996   for ( NodeList::const_iterator iter = node->children.begin(); iter != node->children.end(); ++iter )
00997   {
00998     QAction* mya = itemAction( (*iter)->id );
00999     if ( !mya )
01000       mya = menuAction( (*iter)->id );
01001     if ( mya && mya == a )
01002       return true;
01003   }
01004   return false;
01005 }
01006 
01012 bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const
01013 {
01014   if ( !wid )
01015     return false;
01016 
01017   return !wid->actions().isEmpty();
01018 }
01019 
01026 QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node ) const
01027 {
01028   if ( !node || node == myRoot )
01029      return myMenu;
01030 
01031   if ( !myMenus.contains( node->id ) || !myMenus[node->id] )
01032     return 0;
01033 
01034   return myMenus[node->id]->menu();
01035 }
01036 
01041 void QtxActionMenuMgr::simplifySeparators( QWidget* wid )
01042 {
01043   Qtx::simplifySeparators( wid, false );
01044 }
01045 
01051 QString QtxActionMenuMgr::clearTitle( const QString& txt ) const
01052 {
01053   QString res = txt;
01054 
01055   for ( int i = 0; i < (int)res.length(); i++ )
01056   {
01057     if ( res.at( i ) == '&' )
01058       res.remove( i--, 1 );
01059   }
01060 
01061   return res;
01062 }
01063 
01070 int QtxActionMenuMgr::createMenu( const QStringList& lst, const int pId )
01071 {
01072   if ( lst.isEmpty() )
01073     return -1;
01074 
01075   QStringList sl( lst );
01076 
01077   QString title = sl.last().trimmed();
01078   sl.removeLast();
01079 
01080   int parentId = sl.isEmpty() ? pId : createMenu( sl, pId );
01081 
01082   return insert( title, parentId, -1 );
01083 }
01084 
01091 bool QtxActionMenuMgr::load( const QString& fname, QtxActionMgr::Reader& r )
01092 {
01093   MenuCreator cr( &r, this );
01094   return r.read( fname, cr );
01095 }
01096 
01103 bool QtxActionMenuMgr::containsMenu( const QString& title, const int pid, const bool rec ) const
01104 {
01105   return (bool)find( title, pid, rec );
01106 }
01107 
01114 bool QtxActionMenuMgr::containsMenu( const int id, const int pid, const bool rec ) const
01115 {
01116   return (bool)find( id, pid, rec );
01117 }
01118 
01124 QMenu* QtxActionMenuMgr::findMenu( const int id ) const
01125 {
01126   QMenu* m = 0;
01127   QAction* a = menuAction( id );
01128   if ( a )
01129     m = a->menu();
01130   return m;
01131 }
01132 
01140 QMenu* QtxActionMenuMgr::findMenu( const QString& title, const int pid, const bool rec ) const
01141 {
01142   QMenu* m = 0;
01143   MenuNode* node = find( title, pid, rec );
01144   if ( node )
01145   {
01146     QAction* a = menuAction( node->id );
01147     if ( a )
01148       m = a->menu();
01149   }
01150   return m;
01151 }
01152 
01158 bool QtxActionMenuMgr::isEmptyEnabled( const int id ) const
01159 {
01160   MenuNode* node = find( id );
01161   if ( node && menuAction( id ) )
01162     return node->emptyEnabled > 0;
01163   
01164   return false;
01165 }
01166 
01172 void QtxActionMenuMgr::setEmptyEnabled( const int id, const bool enable )
01173 {
01174   MenuNode* node = find( id );
01175   if ( node && menuAction( id ) ) {
01176     int old = node->emptyEnabled;
01177     node->emptyEnabled += enable ? 1 : -1;
01178     if ( ( old <= 0 && enable ) || ( old > 0 && !enable ) ) // update menu only if enabled state has been changed
01179       updateMenu( node, true, true );
01180   }
01181 }
01182 
01188 void QtxActionMenuMgr::triggerUpdate( const int id, const bool rec )
01189 {
01190   bool isRec = rec;
01191   if ( myUpdateIds.contains( id ) )
01192     isRec = isRec || myUpdateIds[ id ];
01193   myUpdateIds.insert( id, isRec );
01194 
01195   QtxActionMgr::triggerUpdate();
01196 }
01197 
01203 void QtxActionMenuMgr::updateContent()
01204 {
01205   // Warning: For correct updating it is necessary to update the most enclosed submenu in first turn
01206   //          because not updated empty submenu will be skipped. Now the submenus are iterated in
01207   //          ascending order according to their identifiers. For a submenus with automatically generated 
01208   //          identifiers this will work correctly since the uppermost submenus have the biggest number
01209   //          (identifiers are generated by decrementing 1 starting from -1). In general, if any submenu
01210   //          have positive identifiers this method might not work correctly. In this case it would be
01211   //          necessary to improve this method and to add preliminary sorting a submenus by depth of an 
01212   //          enclosure.
01213   for ( QMap<int, bool>::const_iterator it = myUpdateIds.constBegin(); it != myUpdateIds.constEnd(); ++it )
01214   {
01215     MenuNode* node = it.key() == -1 ? myRoot : find( it.key() );
01216     if ( node )
01217       updateMenu( node, it.value() );
01218   }
01219   myUpdateIds.clear();
01220 }
01221 
01235 QtxActionMenuMgr::MenuCreator::MenuCreator( QtxActionMgr::Reader* r, QtxActionMenuMgr* mgr )
01236 : QtxActionMgr::Creator( r ),
01237   myMgr( mgr )
01238 {
01239 }
01240 
01244 QtxActionMenuMgr::MenuCreator::~MenuCreator()
01245 {
01246 }
01247 
01256 int QtxActionMenuMgr::MenuCreator::append( const QString& tag, const bool subMenu,
01257                                            const ItemAttributes& attr, const int pId )
01258 {
01259   if( !myMgr || !reader() )
01260     return -1;
01261 
01262   QString label   = reader()->option( "label",     "label"     ),
01263           id      = reader()->option( "id",        "id"        ),
01264           pos     = reader()->option( "pos",       "pos"       ),
01265           group   = reader()->option( "group",     "group"     ),
01266           tooltip = reader()->option( "tooltip",   "tooltip"   ),
01267           sep     = reader()->option( "separator", "separator" ),
01268           accel   = reader()->option( "accel",     "accel"     ),
01269           icon    = reader()->option( "icon",      "icon"      ),
01270           toggle  = reader()->option( "toggle",    "toggle"    );
01271 
01272   int res = -1, actId = intValue( attr, id, -1 );
01273 
01274   if( subMenu )
01275     res = myMgr->insert( strValue( attr, label ), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
01276   else if( tag==sep )
01277     res = myMgr->insert( separator(), pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
01278   else
01279   {
01280     QIcon set;
01281     QPixmap pix;
01282     QString name = strValue( attr, icon );
01283     if( !name.isEmpty() && loadPixmap( name, pix ) )
01284       set = QIcon( pix );
01285 
01286     QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set,
01287                                        strValue( attr, label ),
01288                                        QKeySequence( strValue( attr, accel ) ),
01289                                        myMgr );
01290     newAct->setToolTip( strValue( attr, tooltip ) );
01291     QString toggleact = strValue( attr, toggle );
01292     newAct->setCheckable( !toggleact.isEmpty() );
01293     newAct->setChecked( toggleact.toLower() == "true" );
01294 
01295     connect( newAct );
01296     int aid = myMgr->registerAction( newAct, actId );
01297     res = myMgr->insert( aid, pId, intValue( attr, group, 0 ), intValue( attr, pos, -1 ) );
01298   }
01299 
01300   return res;
01301 }