From 336663b75f48d8aedbe4f0a416cfe8c1c00f5281 Mon Sep 17 00:00:00 2001 From: vsr Date: Mon, 30 Jun 2008 11:24:57 +0000 Subject: [PATCH] Fix 0019892 : enable empty menus (for Python modules) --- src/Qtx/QtxActionMenuMgr.cxx | 126 ++++++++++++++++-- src/Qtx/QtxActionMenuMgr.h | 5 + .../SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx | 33 ++++- src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx | 34 +++-- 4 files changed, 166 insertions(+), 32 deletions(-) diff --git a/src/Qtx/QtxActionMenuMgr.cxx b/src/Qtx/QtxActionMenuMgr.cxx index 2540721e3..95d6ab7ca 100644 --- a/src/Qtx/QtxActionMenuMgr.cxx +++ b/src/Qtx/QtxActionMenuMgr.cxx @@ -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 > foreign; + QAction* a; + QAction* preva = 0; + QListIterator 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 >::Iterator formapit; + for( formapit = foreign.begin(); formapit != foreign.end(); ++formapit ) + { + QMutableListIterator foralit( formapit.value() ); + while ( foralit.hasNext() ) + { + a = foralit.next(); + if ( !mw->actions().contains( a ) ) + foralit.remove(); + } + } + QList alist = mw->actions(); + foreach( a, alist ) mw->removeAction( a ); + // collect all registered menus by group id QMap 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 diff --git a/src/Qtx/QtxActionMenuMgr.h b/src/Qtx/QtxActionMenuMgr.h index 1f5079161..6ee27cf61 100644 --- a/src/Qtx/QtxActionMenuMgr.h +++ b/src/Qtx/QtxActionMenuMgr.h @@ -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* ); diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx index 76a461c19..9c7515e7b 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx @@ -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 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() ) { diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx index 02e8e8519..f10acdec6 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx @@ -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 ) ); } -- 2.39.2