]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Fix 0019892 : enable empty menus (for Python modules)
authorvsr <vsr@opencascade.com>
Mon, 30 Jun 2008 11:24:57 +0000 (11:24 +0000)
committervsr <vsr@opencascade.com>
Mon, 30 Jun 2008 11:24:57 +0000 (11:24 +0000)
src/Qtx/QtxActionMenuMgr.cxx
src/Qtx/QtxActionMenuMgr.h
src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx
src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx

index 2540721e3102dfc6c1b8dad297de8851170a13bb..95d6ab7ca0b5273c34fd0743adafa382ec7dbd77 100644 (file)
@@ -46,6 +46,7 @@ public:
   int       idx;          //!< menu node index 
   int       group;        //!< menu group ID
   bool      visible;      //!< visibility status
+  int       emptyEnabled; //!< enable empty menu flag
   NodeList  children;     //!< children menu nodes list
 };
 
@@ -54,7 +55,7 @@ public:
   \internal
 */
 QtxActionMenuMgr::MenuNode::MenuNode()
-: parent( 0 ), id( -1 ), idx( -1 ), group( -1 ), visible( true )
+  : parent( 0 ), id( -1 ), idx( -1 ), group( -1 ), visible( true ), emptyEnabled( 0 )
 {
 }
 
@@ -70,7 +71,7 @@ QtxActionMenuMgr::MenuNode::MenuNode( MenuNode* p,
                                      const int _id,
                                      const int _idx,
                                      const int _group )
-: parent( p ), id( _id ), idx( _idx ), group( _group ), visible( true )
+: parent( p ), id( _id ), idx( _idx ), group( _group ), visible( true ), emptyEnabled( 0 )
 {
   if ( p )
     p->children.append( this );
@@ -853,17 +854,40 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo
 
   bool filled = checkWidget( mw );
 
-  for ( NodeList::iterator it1 = node->children.begin(); it1 != node->children.end(); ++it1 )
+  // first remove all own actions and collect foreign ones
+  QMap< QAction*, QList<QAction*> > foreign;
+  QAction* a;
+  QAction* preva = 0;
+  QListIterator<QAction*> ait( mw->actions() ); ait.toBack();
+  while ( ait.hasPrevious() )
   {
-    QAction* a = itemAction( (*it1)->id );
-    if ( !a )
-      a = menuAction( (*it1)->id );
-
-    mw->removeAction( a );
-//    if ( a )
-//      a->removeFrom( mw );
+    a = ait.previous();
+    if ( ownAction( a, node ) )
+    {
+      preva = a;
+      mw->removeAction( a );     // remove own actions
+    }
+    else
+    {
+      foreign[preva].prepend(a); // do not yet remove foreign actions
+    }
   }
+  // now only foreign actions should stay in the menu, thus remove them also
+  QMap< QAction*, QList<QAction*> >::Iterator formapit;
+  for( formapit = foreign.begin(); formapit != foreign.end(); ++formapit )
+  {
+    QMutableListIterator<QAction*> foralit( formapit.value() );
+    while ( foralit.hasNext() )
+    {
+      a = foralit.next();
+      if ( !mw->actions().contains( a ) )
+       foralit.remove();
+    }
+  }
+  QList<QAction*> alist = mw->actions();
+  foreach( a, alist ) mw->removeAction( a );
 
+  // collect all registered menus by group id
   QMap<int, NodeList> idMap;
   for ( NodeList::iterator it2 = node->children.begin(); it2 != node->children.end(); ++it2 )
   {
@@ -881,6 +905,7 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo
   groups.removeAll( -1 );
   groups.append( -1 );
 
+  // rebuild menu: 1. add all registered actions
   for ( QIntList::const_iterator gIt = groups.begin(); gIt != groups.end(); ++gIt )
   {
     if ( !idMap.contains( *gIt ) )
@@ -890,6 +915,7 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo
     for ( NodeList::const_iterator iter = lst.begin(); iter != lst.end(); ++iter )
     {
       MenuNode* node = *iter;
+      if ( !node ) continue;
 
       if ( rec )
         updateMenu( node, rec, false );
@@ -905,14 +931,24 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo
         isMenu = true;
         a = menuAction( node->id );
       }
+      if ( !a ) continue;
 
-      if ( !isMenu || !a->menu()->isEmpty() )
+      if ( !isMenu || !a->menu()->isEmpty() || node->emptyEnabled > 0 )
         mw->addAction( a );
     }
   }
 
+  // rebuild menu: 2. insert back all foreign actions
+  for( formapit = foreign.begin(); formapit != foreign.end(); ++formapit ) {
+    preva = formapit.key();
+    foreach( a, formapit.value() )
+      mw->insertAction( preva, a );
+  }
+  
+  // remove extra separators
   simplifySeparators( mw );
 
+  // update parent menu if necessary
   if ( updParent && node->parent && filled != checkWidget( mw ) )
     updateMenu( node->parent, false );
 }
@@ -931,6 +967,24 @@ void QtxActionMenuMgr::internalUpdate()
   myUpdateIds.clear();
 }
 
+/*!
+  \brief Check if action belongs to the menu manager
+  \internal
+  \param a action being checked
+  \param node parent menu node
+  \return \c true if action belongs to the menu \a node
+*/
+bool QtxActionMenuMgr::ownAction( QAction* a, MenuNode* node ) const
+{
+  for ( NodeList::const_iterator iter = node->children.begin(); iter != node->children.end(); ++iter )
+  {
+    QAction* mya = itemAction( (*iter)->id );
+    if ( !mya ) mya = menuAction( (*iter)->id );
+    if ( mya && mya == a ) return true;
+  }
+  return false;
+}
+
 /*!
   \brief Check if menu widget has any actions.
   \param wid widget to be checked
@@ -1057,6 +1111,56 @@ QMenu* QtxActionMenuMgr::findMenu( const int id ) const
   return m;
 }
 
+/*!
+  \brief Get menu by the title.
+  \param title menu text
+  \param pid parent menu item ID (to start search)
+  \param rec if \c true, perform recursive update
+  \return menu pointer or 0 if menu is not found
+*/
+QMenu* QtxActionMenuMgr::findMenu( const QString& title, const int pid, const bool rec ) const
+{
+  QMenu* m = 0;
+  MenuNode* node = find( title, pid, rec );
+  if ( node )
+  {
+    QAction* a = menuAction( node->id );
+    if ( a )
+      m = a->menu();
+  }
+  return m;
+}
+
+/*!
+  \brief Check if empty menu is enabled
+  \param id menu item ID
+  \return \c true if empty menu is enabled
+*/
+bool QtxActionMenuMgr::isEmptyEnabled( const int id ) const
+{
+  MenuNode* node = find( id );
+  if ( node && menuAction( id ) )
+    return node->emptyEnabled > 0;
+  
+  return false;
+}
+
+/*!
+  \brief Enable/disable empty menu
+  \param id menu item ID
+  \param enable if \c true, empty menu will be enabled, otherwise empty menu will be disabled
+*/
+void QtxActionMenuMgr::setEmptyEnabled( const int id, const bool enable )
+{
+  MenuNode* node = find( id );
+  if ( node && menuAction( id ) ) {
+    int old = node->emptyEnabled;
+    node->emptyEnabled += enable ? 1 : -1;
+    if ( old <= 0 && enable || old > 0 && !enable ) // update menu only if enabled state has been changed
+      updateMenu( node, true, true );
+  }
+}
+
 /*!
   \brief Perform delayed menu update.
   \param id menu item ID
index 1f5079161267a45e48ce81e42099ec2cb4359d4f..6ee27cf6100cb579579537728edaa09517ed3f75 100644 (file)
@@ -94,6 +94,10 @@ public:
   bool         containsMenu( const int, const int, const bool = false ) const;
 
   QMenu*       findMenu( const int ) const;
+  QMenu*       findMenu( const QString&, const int, const bool = false ) const;
+
+  bool         isEmptyEnabled( const int ) const;
+  void         setEmptyEnabled( const int, const bool );
 
 private slots:
   void         onAboutToShow();
@@ -126,6 +130,7 @@ protected:
   virtual void updateContent();
 
 private:
+  bool         ownAction( QAction*, MenuNode* ) const;
   bool         checkWidget( QWidget* ) const;
   QWidget*     menuWidget( MenuNode* ) const;
   void         simplifySeparators( QWidget* );
index 76a461c1912a5303d5763adf1299200af1ca7015..9c7515e7b174992866185b768c1dd47d68a0426b 100644 (file)
@@ -112,6 +112,7 @@ public:
                      const QString& context,
                      const QString& parent,
                      const QString& object );
+  void activateMenus( bool );
 
 protected:
   void createToolBar   ( QDomNode&   parentNode );
@@ -125,7 +126,7 @@ protected:
 private:
   SALOME_PYQT_Module* myModule;
   QDomDocument        myDoc;
-  QStringList         myMenuItems;
+  QList<int>          myMenuItems;
 };
 
 //
@@ -376,6 +377,7 @@ bool SALOME_PYQT_Module::activateModule( SUIT_Study* theStudy )
     return false;
 
   // activate menus, toolbars, etc
+  if ( myXmlHandler ) myXmlHandler->activateMenus( true );
   setMenuShown( true );
   setToolShown( true );
 
@@ -429,10 +431,6 @@ bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* theStudy )
   disconnect( getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ),
              this,     SLOT(   preferenceChanged( const QString&, const QString&, const QString& ) ) );
 
-  // deactivate menus, toolbars, etc
-  setMenuShown( false );
-  setToolShown( false );
-
   // perform internal deactivation
   // DeactivateReq: request class for internal deactivate() operation
   class DeactivateReq : public PyInterp_LockRequest
@@ -459,6 +457,11 @@ bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* theStudy )
   // post request
   PyInterp_Dispatcher::Get()->Exec( new DeactivateReq( myInterp, theStudy, this ) );
 
+  // deactivate menus, toolbars, etc
+  if ( myXmlHandler ) myXmlHandler->activateMenus( false );
+  setMenuShown( false );
+  setToolShown( false );
+
   // call base implementation
   return SalomeApp_Module::deactivateModule( theStudy );
 }
@@ -930,7 +933,7 @@ void SALOME_PYQT_Module::activate( SUIT_Study* theStudy )
       // detect return status
       myLastActivateStatus = PyObject_IsTrue( res1 );
     }
-  }
+  } 
 }
 
 /*!
@@ -1849,6 +1852,21 @@ void SALOME_PYQT_Module::XmlHandler::createPopup( QMenu*         menu,
   }
 }
 
+/*!
+  \brief Activate menus
+  \internal
+  \param enable if \c true menus are activated, otherwise menus are deactivated
+*/
+void SALOME_PYQT_Module::XmlHandler::activateMenus( bool enable )
+{
+  if ( !myModule )
+    return;
+
+  QtxActionMenuMgr* mgr = myModule->menuMgr();
+  int id;
+  foreach( id, myMenuItems ) mgr->setEmptyEnabled( id, enable );
+}
+
 /*!
   \brief Create main menu item and insert actions to it.
   \internal
@@ -1862,7 +1880,7 @@ void SALOME_PYQT_Module::XmlHandler::createMenu( QDomNode& parentNode,
 {
   if ( !myModule || parentNode.isNull() )
     return;
-
+  
   QDomElement parentElement = parentNode.toElement();
   if ( !parentElement.isNull() ) {
     QString plabel = attribute( parentElement, "label-id" );
@@ -1879,6 +1897,7 @@ void SALOME_PYQT_Module::XmlHandler::createMenu( QDomNode& parentNode,
                                     pid,            // ID
                                     group,          // group ID
                                     ppos );         // position
+      myMenuItems.append( menuId );
       QDomNode node = parentNode.firstChild();
       while ( !node.isNull() ) {
        if ( node.isElement() ) {
index 02e8e85194bd75494e9247692c1437980b4b9982..f10acdec6c225260451001bd49c159f37401902f 100644 (file)
@@ -317,34 +317,40 @@ public:
     SalomeApp_Application* anApp = getApplication();
     if ( anApp && !myMenuName.isEmpty() ) {
       QtxActionMenuMgr* mgr = anApp->desktop()->menuMgr();
-      SALOME_PYQT_Module* module = getActiveModule();
-      int id = -1;
-      if ( module )
-       id = module->createMenu( myMenuName, -1, -1, -1, -1 );
-      else
-       id = mgr->insert( myMenuName, -1, -1, -1, -1 );
-      myResult = mgr->findMenu( id );
+      myResult = mgr->findMenu( myMenuName, -1, false ); // search only top menu
     }
   }
 };
+
+static QString getMenuName( const QString& menuId )
+{
+  QStringList contexts;
+  contexts << "SalomeApp_Application" << "LightApp_Application" << "STD_TabDesktop" <<
+    "STD_MDIDesktop" << "STD_Application" << "SUIT_Application" << "";
+  QString menuName = menuId;
+  for ( int i = 0; i < contexts.count() && menuName == menuId; i++ )
+    menuName = QApplication::translate( contexts[i].toLatin1().data(), menuId.toLatin1().data() );
+  return menuName;
+}
+
 QMenu* SalomePyQt::getPopupMenu( const MenuName menu )
 {
   QString menuName;
   switch( menu ) {
   case File:
-    menuName = QApplication::translate( "", "MEN_DESK_FILE" );        break;
+    menuName = getMenuName( "MEN_DESK_FILE" );        break;
   case View:
-    menuName = QApplication::translate( "", "MEN_DESK_VIEW" );        break;
+    menuName = getMenuName( "MEN_DESK_VIEW" );        break;
   case Edit:
-    menuName = QApplication::translate( "", "MEN_DESK_EDIT" );        break;
+    menuName = getMenuName( "MEN_DESK_EDIT" );        break;
   case Preferences:
-    menuName = QApplication::translate( "", "MEN_DESK_PREFERENCES" ); break;
+    menuName = getMenuName( "MEN_DESK_PREFERENCES" ); break;
   case Tools:
-    menuName = QApplication::translate( "", "MEN_DESK_TOOLS" );       break;
+    menuName = getMenuName( "MEN_DESK_TOOLS" );       break;
   case Window:
-    menuName = QApplication::translate( "", "MEN_DESK_WINDOW" );      break;
+    menuName = getMenuName( "MEN_DESK_WINDOW" );      break;
   case Help:
-    menuName = QApplication::translate( "", "MEN_DESK_HELP" );        break;
+    menuName = getMenuName( "MEN_DESK_HELP" );        break;
   }
   return ProcessEvent( new TGetPopupMenuEvent( menuName ) );
 }