From 570a2056bde893f0f8569e8262684576c644365f Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 9 Mar 2006 13:41:03 +0000 Subject: [PATCH] MERGE from BR_vsr_menu branch: support dynamic menus in SALOME GUI --- src/CAM/CAM_Module.cxx | 44 +- src/CAM/CAM_Module.h | 10 +- src/LightApp/LightApp_Application.cxx | 2 +- src/LightApp/LightApp_Application.h | 2 + src/Qtx/QtxActionMenuMgr.cxx | 210 ++++-- src/Qtx/QtxActionMenuMgr.h | 27 +- src/Qtx/QtxActionToolMgr.cxx | 14 + src/Qtx/QtxActionToolMgr.h | 2 + .../SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx | 606 +++++++++++++----- .../SALOME_PYQT_GUI/SALOME_PYQT_Module.h | 66 +- src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx | 67 +- src/SALOME_PYQT/SalomePyQt/SalomePyQt.h | 9 +- src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip | 11 +- src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip | 16 +- src/STD/STD_Application.cxx | 36 +- src/STD/STD_Application.h | 16 +- src/STD/STD_MDIDesktop.cxx | 2 +- src/STD/STD_MDIDesktop.h | 1 + src/STD/STD_TabDesktop.cxx | 2 +- src/STD/STD_TabDesktop.h | 1 + src/SUIT/SUIT_Application.cxx | 81 ++- src/SUIT/SUIT_Application.h | 3 +- src/SalomeApp/SalomeApp_Application.cxx | 2 +- src/SalomeApp/SalomeApp_Application.h | 1 + 24 files changed, 895 insertions(+), 336 deletions(-) diff --git a/src/CAM/CAM_Module.cxx b/src/CAM/CAM_Module.cxx index 885f6e05d..264054bdf 100755 --- a/src/CAM/CAM_Module.cxx +++ b/src/CAM/CAM_Module.cxx @@ -299,12 +299,13 @@ int CAM_Module::createTool( const int id, const QString& tBar, const int idx ) *\retval Return -1 if something wrong. */ int CAM_Module::createMenu( const QString& subMenu, const int menu, - const int id, const int group, const int index ) + const int id, const int group, const int index, + const bool enableEmpty ) { if ( !menuMgr() ) return -1; - return menuMgr()->insert( subMenu, menu, group, index ); + return menuMgr()->insert( subMenu, menu, group, id, index, enableEmpty ); } /*! Create menu. @@ -318,12 +319,13 @@ int CAM_Module::createMenu( const QString& subMenu, const int menu, *\retval Return -1 if something wrong. */ int CAM_Module::createMenu( const QString& subMenu, const QString& menu, - const int id, const int group, const int index ) + const int id, const int group, const int index, + const bool enableEmpty ) { if ( !menuMgr() ) return -1; - return menuMgr()->insert( subMenu, menu, group, index ); + return menuMgr()->insert( subMenu, menu, group, id, index, enableEmpty ); } @@ -572,6 +574,40 @@ int CAM_Module::registerAction( const int id, QAction* a ) return ident; } +/*! Unregister an action. + * \param id - id for action. + * \retval true if succeded, false if action is used + */ +bool CAM_Module::unregisterAction( const int id ) +{ + return unregisterAction( action( id ) ); +} + +/*! Unregister an action. + * \param a - action + * \retval true if succeded, false if action is used + */ +bool CAM_Module::unregisterAction( QAction* a ) +{ + if ( !a ) + return false; + if ( menuMgr() ) { + int id = menuMgr()->actionId( a ); + if ( id != -1 && menuMgr()->containsMenu( id, -1 ) ) + return false; + } + if ( toolMgr() ) { + int id = toolMgr()->actionId( a ); + if ( id != -1 && toolMgr()->containsAction( id ) ) + return false; + } + if ( menuMgr() ) + menuMgr()->unRegisterAction( menuMgr()->actionId( a ) ); + if ( toolMgr() ) + toolMgr()->unRegisterAction( toolMgr()->actionId( a ) ); + return true; +} + /*! Return qt action manager separator.*/ QAction* CAM_Module::separator() { diff --git a/src/CAM/CAM_Module.h b/src/CAM/CAM_Module.h index 7b525996c..8896eb23b 100755 --- a/src/CAM/CAM_Module.h +++ b/src/CAM/CAM_Module.h @@ -65,14 +65,14 @@ public: /** @name Set Menu Shown*/ //@{ - void setMenuShown( const bool ); + virtual void setMenuShown( const bool ); void setMenuShown( QAction*, const bool ); void setMenuShown( const int, const bool ); //@} /** @name Set Tool Shown*/ //@{ - void setToolShown( const bool ); + virtual void setToolShown( const bool ); void setToolShown( QAction*, const bool ); void setToolShown( const int, const bool ); //@} @@ -106,8 +106,8 @@ protected: /** @name Create menu methods.*/ //@{ - int createMenu( const QString&, const int, const int = -1, const int = -1, const int = -1 ); - int createMenu( const QString&, const QString&, const int = -1, const int = -1, const int = -1 ); + int createMenu( const QString&, const int, const int = -1, const int = -1, const int = -1, const bool = false ); + int createMenu( const QString&, const QString&, const int = -1, const int = -1, const int = -1, const bool = false ); int createMenu( const int, const int, const int = -1, const int = -1 ); int createMenu( const int, const QString&, const int = -1, const int = -1 ); int createMenu( QAction*, const int, const int = -1, const int = -1, const int = -1 ); @@ -123,6 +123,8 @@ protected: //@} int registerAction( const int, QAction* ); + bool unregisterAction( const int ); + bool unregisterAction( QAction* ); QAction* createAction( const int, const QString&, const QIconSet&, const QString&, const QString&, const int, QObject* = 0, const bool = false, QObject* = 0, const char* = 0 ); diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx index d3706badb..7a055b9a4 100644 --- a/src/LightApp/LightApp_Application.cxx +++ b/src/LightApp/LightApp_Application.cxx @@ -495,7 +495,7 @@ void LightApp_Application::createActions() SUIT_Tools::simplifySeparators( modTBar ); // New window - int windowMenu = createMenu( tr( "MEN_DESK_WINDOW" ), -1, 100 ); + int windowMenu = createMenu( tr( "MEN_DESK_WINDOW" ), -1, MenuWindowId, 100 ); int newWinMenu = createMenu( tr( "MEN_DESK_NEWWINDOW" ), windowMenu, -1, 0 ); createMenu( separator(), windowMenu, -1, 1 ); diff --git a/src/LightApp/LightApp_Application.h b/src/LightApp/LightApp_Application.h index 3fbd81dcd..bfcf376d6 100644 --- a/src/LightApp/LightApp_Application.h +++ b/src/LightApp/LightApp_Application.h @@ -52,6 +52,8 @@ public: WT_User } WindowTypes; + enum { MenuWindowId = 6 }; + enum { RenameId = CAM_Application::UserID, #ifndef DISABLE_GLVIEWER diff --git a/src/Qtx/QtxActionMenuMgr.cxx b/src/Qtx/QtxActionMenuMgr.cxx index 7782a7b57..2d09b2d09 100644 --- a/src/Qtx/QtxActionMenuMgr.cxx +++ b/src/Qtx/QtxActionMenuMgr.cxx @@ -40,7 +40,7 @@ class QtxActionMenuMgr::MenuAction : public QtxAction { public: - MenuAction( const QString&, const QString&, QObject* ); + MenuAction( const QString&, const QString&, QObject*, const bool = false ); virtual ~MenuAction(); virtual bool addTo( QWidget* ); @@ -52,12 +52,17 @@ public: private: int myId; QPopupMenu* myPopup; + bool myEmptyEnabled; }; -QtxActionMenuMgr::MenuAction::MenuAction( const QString& text, const QString& menuText, QObject* parent ) +QtxActionMenuMgr::MenuAction::MenuAction( const QString& text, + const QString& menuText, + QObject* parent, + const bool allowEmpty ) : QtxAction( text, menuText, 0, parent ), -myId( -1 ), -myPopup( 0 ) + myId( -1 ), + myPopup( 0 ), + myEmptyEnabled( allowEmpty ) { myPopup = new QPopupMenu(); } @@ -75,6 +80,12 @@ bool QtxActionMenuMgr::MenuAction::addTo( QWidget* w ) if ( !w->inherits( "QPopupMenu" ) && !w->inherits( "QMenuBar" ) ) return false; + if ( !myPopup ) + return false; + + if ( !myEmptyEnabled && !myPopup->count() ) + return false; + if ( w->inherits( "QPopupMenu" ) && QAction::addTo( w ) ) { QPopupMenu* pm = (QPopupMenu*)w; @@ -126,8 +137,11 @@ myMenu( p ? p->menuBar() : 0 ) myRoot.id = -1; myRoot.group = -1; - if ( myMenu ) + if ( myMenu ) { connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); + if ( myMenu->inherits( "QMenuBar" ) ) + connect( myMenu, SIGNAL( highlighted( int ) ), this, SLOT( onHighlighted( int ) ) ); + } } QtxActionMenuMgr::QtxActionMenuMgr( QWidget* mw, QObject* p ) @@ -209,12 +223,10 @@ int QtxActionMenuMgr::insert( const int id, const int pId, const int group, cons MenuNode* node = new MenuNode( pNode ); node->id = id; + node->idx = idx; node->group = group; - if ( idx < 0 || idx >= (int)pNode->children.count() ) - pNode->children.append( node ); - else - pNode->children.insert( idx, node ); + pNode->children.append( node ); updateMenu( pNode, false ); @@ -226,53 +238,54 @@ int QtxActionMenuMgr::insert( QAction* a, const int pId, const int group, const return insert( registerAction( a ), pId, group, idx ); } -int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int idx ) +int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int id, const int idx, const bool allowEmpty ) { MenuNode* pNode = pId == -1 ? &myRoot : find( pId ); if ( !pNode ) return -1; - int id = -1; - for ( NodeListIterator it( pNode->children ); it.current() && id == -1; ++it ) + MenuNode* eNode = id == -1 ? 0 : find( id ); + + int fid = -1; + for ( NodeListIterator it( pNode->children ); it.current() && fid == -1; ++it ) { if ( myMenus.contains( it.current()->id ) && clearTitle( myMenus[it.current()->id]->menuText() ) == clearTitle( title ) ) - id = it.current()->id; + fid = it.current()->id; } - if ( id != -1 ) - return id; + if ( fid != -1 ) + return fid; - MenuAction* ma = new MenuAction( clearTitle( title ), title, this ); + MenuAction* ma = new MenuAction( clearTitle( title ), title, this, allowEmpty ); + connect( ma->popup(), SIGNAL( highlighted( int ) ), this, SLOT( onHighlighted( int ) ) ); MenuNode* node = new MenuNode( pNode ); node->group = group; - node->id = myMenus.insert( generateId(), ma ).key(); + node->idx = idx; + node->id = myMenus.insert( (id == -1 || eNode ) ? generateId() : id, ma ).key(); - if ( idx < 0 || idx >= (int)pNode->children.count() ) - pNode->children.append( node ); - else - pNode->children.insert( idx, node ); + pNode->children.append( node ); updateMenu( pNode, false ); return node->id; } -int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int idx ) +int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int id, const int idx, const bool allowEmpty ) { - return insert( title, QStringList::split( "|", menus ), group, idx ); + return insert( title, QStringList::split( "|", menus ), group, id, idx, allowEmpty ); } -int QtxActionMenuMgr::insert( const QString& title, const QStringList& menus, const int group, const int idx ) +int QtxActionMenuMgr::insert( const QString& title, const QStringList& menus, const int group, const int id, const int idx, const bool allowEmpty ) { int pId = createMenu( menus, -1 ); - return insert( title, pId, group, idx ); + return insert( title, pId, group, id, idx, allowEmpty ); } -int QtxActionMenuMgr::append( const QString& title, const int pId, const int group ) +int QtxActionMenuMgr::append( const QString& title, const int pId, const int group, const int id, const bool allowEmpty ) { - return insert( title, pId, group ); + return insert( title, pId, group, id, allowEmpty ); } int QtxActionMenuMgr::append( const int id, const int pId, const int group ) @@ -285,9 +298,9 @@ int QtxActionMenuMgr::append( QAction* a, const int pId, const int group ) return insert( a, pId, group ); } -int QtxActionMenuMgr::prepend( const QString& title, const int pId, const int group ) +int QtxActionMenuMgr::prepend( const QString& title, const int pId, const int group, const int id, const bool allowEmpty ) { - return insert( title, pId, group, 0 ); + return insert( title, pId, group, id, 0, allowEmpty ); } int QtxActionMenuMgr::prepend( const int id, const int pId, const int group ) @@ -308,7 +321,7 @@ void QtxActionMenuMgr::remove( const int id ) void QtxActionMenuMgr::remove( const int id, const int pId, const int group ) { - MenuNode* pNode = find( pId ); + MenuNode* pNode = pId == -1 ? &myRoot : find( pId ); if ( !pNode ) return; @@ -369,6 +382,30 @@ void QtxActionMenuMgr::onDestroyed( QObject* obj ) myMenu = 0; } +void QtxActionMenuMgr::onHighlighted( int id ) +{ + const QObject* snd = sender(); + int pid = 0, realId; + if ( myMenu && snd == myMenu ) + pid = -1; + else { + for ( MenuMap::Iterator itr = myMenus.begin(); itr != myMenus.end(); ++itr ) { + if ( itr.data()->popup() && itr.data()->popup() == snd ) + pid = itr.key(); + } + } + if ( pid ) { + realId = findId( id, pid ); + if ( realId != -1 ) { + bool updatesEnabled = isUpdatesEnabled(); + setUpdatesEnabled( false ); + emit menuHighlighted( pid, realId ); + setUpdatesEnabled( updatesEnabled ); + updateMenu( find( realId ) ); + } + } +} + void QtxActionMenuMgr::setWidget( QWidget* mw ) { if ( myMenu == mw ) @@ -383,12 +420,12 @@ void QtxActionMenuMgr::setWidget( QWidget* mw ) connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); } -QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int actId, const int pId ) const +QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int actId, const int pId, const bool rec ) const { - return find( actId, find( pId ) ); + return find( actId, find( pId ), rec ); } -QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* startNode ) const +QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* startNode, const bool rec ) const { MenuNode* node = 0; MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot; @@ -396,8 +433,8 @@ QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* star { if ( it.current()->id == id ) node = it.current(); - else - node = find( id, it.current() ); + else if ( rec ) + node = find( id, it.current(), rec ); } return node; } @@ -415,6 +452,55 @@ bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode ) return !lst.isEmpty(); } +QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, const int pId, const bool rec ) const +{ + return find( title, find( pId ), rec ); +} + +bool QtxActionMenuMgr::find( const QString& title, NodeList& lst, MenuNode* startNode ) const +{ + MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot; + for ( NodeListIterator it( start->children ); it.current(); ++it ) + { + QAction* a = itemAction( it.current()->id ); + if ( !a ) + a = menuAction( it.current()->id ); + if ( a && clearTitle( a->menuText() ) == clearTitle( title ) ) + lst.prepend( it.current() ); + + find( title, lst, it.current() ); + } + return !lst.isEmpty(); +} + +QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, MenuNode* startNode, const bool rec ) const +{ + MenuNode* node = 0; + MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot; + for ( NodeListIterator it( start->children ); it.current() && !node; ++it ) + { + QAction* a = itemAction( it.current()->id ); + if ( !a ) + a = menuAction( it.current()->id ); + if ( a && clearTitle( a->menuText() ) == clearTitle( title ) ) + node = it.current(); + if ( !node && rec ) + node = find( title, it.current(), rec ); + } + return node; +} + +int QtxActionMenuMgr::findId( const int id, const int pid ) const +{ + MenuNode* start = pid != -1 ? find( pid ) : (MenuNode*)&myRoot; + if ( start ) { + for ( NodeListIterator it( start->children ); it.current(); ++it ) { + if ( it.current()->id == id ) return id; + } + } + return -1; +} + void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode ) { MenuNode* start = startNode ? startNode : &myRoot; @@ -465,23 +551,20 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo a->removeFrom( mw ); } - if ( node != &myRoot ) - { - if ( mw->inherits( "QMenuBar" ) ) - ((QMenuBar*)mw)->clear(); - else if ( mw->inherits( "QPopupMenu" ) ) - ((QPopupMenu*)mw)->clear(); - } + if ( mw->inherits( "QMenuBar" ) ) + ((QMenuBar*)mw)->clear(); + else if ( mw->inherits( "QPopupMenu" ) ) + ((QPopupMenu*)mw)->clear(); QMap idMap; for ( NodeListIterator it2( node->children ); it2.current(); ++it2 ) { - MenuNode* par = it2.current()->parent; - if ( isVisible( it2.current()->id, par ? par->id : -1 ) ) - { - NodeList& lst = idMap[it2.current()->group]; + NodeList& lst = idMap[it2.current()->group]; + int idx = it2.current()->idx; + if ( idx < 0 || idx >= lst.count() ) lst.append( it2.current() ); - } + else + lst.insert( idx, it2.current() ); } QIntList groups = idMap.keys(); @@ -498,17 +581,27 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo const NodeList& lst = idMap[*gIt]; for ( NodeListIterator iter( lst ); iter.current(); ++iter ) { + MenuNode* par = iter.current()->parent; + if ( !isVisible( iter.current()->id, par ? par->id : -1 ) ) + continue; + if ( rec ) updateMenu( iter.current(), rec, false ); QAction* a = itemAction( iter.current()->id ); - if ( a ) - a->addTo( mw ); - else - { - MenuAction* ma = menuAction( iter.current()->id ); - if ( ma && ma->popup() && ma->popup()->count() ) - ma->addTo( mw ); + if ( !a ) + a = menuAction( iter.current()->id ); + if ( a ) { + QMenuData* md = dynamic_cast( mw ); + int cnt = 0; + if ( md ) cnt = md->count(); + a->addTo( mw ); + if ( md && md->count() - cnt == 1 ) { //&& iter.current()->id > 0 + int lid = md->idAt( cnt ); + QMenuItem* mi = md->findItem( lid ); + if ( mi && !mi->isSeparator() ) + md->setId( cnt, iter.current()->id ); + } } } } @@ -590,6 +683,15 @@ bool QtxActionMenuMgr::load( const QString& fname, QtxActionMgr::Reader& r ) return r.read( fname, cr ); } +bool QtxActionMenuMgr::containsMenu( const QString& title, const int pid ) const +{ + return (bool)find( title, pid, false ); +} + +bool QtxActionMenuMgr::containsMenu( const int id, const int pid ) const +{ + return (bool)find( id, pid, false ); +} /*! Class: QtxActionMenuMgr::MenuCreator diff --git a/src/Qtx/QtxActionMenuMgr.h b/src/Qtx/QtxActionMenuMgr.h index 89b81aa89..f06ff9d3b 100644 --- a/src/Qtx/QtxActionMenuMgr.h +++ b/src/Qtx/QtxActionMenuMgr.h @@ -51,6 +51,7 @@ class QTX_EXPORT QtxActionMenuMgr : public QtxActionMgr MenuNode( MenuNode* p ) : parent( p ), visible( true ) { children.setAutoDelete( true ); }; int id; + int idx; int group; MenuNode* parent; bool visible; @@ -79,17 +80,17 @@ public: virtual int insert( const int, const int, const int, const int = -1 ); int insert( QAction*, const int, const int, const int = -1 ); - int insert( const QString&, const QString&, const int, const int = -1 ); - int insert( const QString&, const QStringList&, const int, const int = -1 ); - virtual int insert( const QString&, const int, const int, const int = -1 ); + int insert( const QString&, const QString&, const int, const int = -1, const int = -1, const bool = false ); + int insert( const QString&, const QStringList&, const int, const int = -1, const int = -1, const bool = false ); + virtual int insert( const QString&, const int, const int, const int = -1, const int = -1, const bool = false ); int append( const int, const int, const int ); int append( QAction*, const int, const int ); - int append( const QString&, const int, const int ); + int append( const QString&, const int, const int, const int = -1, const bool = false ); int prepend( const int, const int, const int ); int prepend( QAction*, const int, const int ); - int prepend( const QString&, const int, const int ); + int prepend( const QString&, const int, const int, const int = -1, const bool = false ); void remove( const int ); void remove( const int, const int, const int = -1 ); @@ -102,14 +103,26 @@ public: virtual bool load( const QString&, QtxActionMgr::Reader& ); + bool containsMenu( const QString&, const int ) const; + bool containsMenu( const int, const int ) const; + + private slots: void onDestroyed( QObject* ); + void onHighlighted( int ); + +signals: + void menuHighlighted( int, int ); protected: void setWidget( QWidget* ); - MenuNode* find( const int, const int ) const; - MenuNode* find( const int, MenuNode* = 0 ) const; + MenuNode* find( const int, const int, const bool = true ) const; + MenuNode* find( const int, MenuNode* = 0, const bool = true ) const; bool find( const int, NodeList&, MenuNode* = 0 ) const; + MenuNode* find( const QString&, const int, const bool = true ) const; + MenuNode* find( const QString&, MenuNode* = 0, const bool = true ) const; + bool find( const QString&, NodeList&, MenuNode* = 0 ) const; + int findId( const int, const int = -1 ) const; void removeMenu( const int, MenuNode* ); diff --git a/src/Qtx/QtxActionToolMgr.cxx b/src/Qtx/QtxActionToolMgr.cxx index f797306f0..b9ff56c8f 100644 --- a/src/Qtx/QtxActionToolMgr.cxx +++ b/src/Qtx/QtxActionToolMgr.cxx @@ -227,6 +227,20 @@ bool QtxActionToolMgr::hasToolBar( const QString& tname ) const return find( tname ) != -1; } +bool QtxActionToolMgr::containsAction( const int id, const int tid ) const +{ + for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end(); ++it ) + { + if ( tid == -1 || it.key() == tid ) { + const NodeList& list = it.data().nodes; + for ( NodeList::const_iterator nit = list.begin(); nit != list.end(); ++nit ) + if ( (*nit).id == id ) + return true; + } + } + return false; +} + void QtxActionToolMgr::onToolBarDestroyed() { myToolBars.remove( find( (QToolBar*)sender() ) ); diff --git a/src/Qtx/QtxActionToolMgr.h b/src/Qtx/QtxActionToolMgr.h index 31c02209d..48a722785 100644 --- a/src/Qtx/QtxActionToolMgr.h +++ b/src/Qtx/QtxActionToolMgr.h @@ -95,6 +95,8 @@ public: bool hasToolBar( const int ) const; bool hasToolBar( const QString& ) const; + bool containsAction( const int, const int = -1 ) const; + virtual bool load( const QString&, QtxActionMgr::Reader& ); protected slots: 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 3cb6cbbda..1f1a3a5e2 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx @@ -1,17 +1,17 @@ // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D -// +// // 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 +// 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 +// +// 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/ @@ -35,6 +35,8 @@ #include "SalomeApp_Study.h" #include "QtxWorkstack.h" +#include "QtxActionMenuMgr.h" +#include "QtxActionToolMgr.h" #include #include @@ -59,15 +61,19 @@ using namespace std; /////////////////////////////////////////////////////////////////////////////// // Default name of the module, replaced at the moment of module creation -#define __DEFAULT_NAME__ "SALOME_PYQT_Module" +const char* __DEFAULT_NAME__ = "SALOME_PYQT_Module"; /////////////////////////////////////////////////////////////////////////////// -// If __CALL_OLD_METHODS__ macro is not defined the invoking of obsolete Python +// Default menu group number +const int __DEFAULT_GROUP__ = 40; + +/////////////////////////////////////////////////////////////////////////////// +// If __CALL_OLD_METHODS__ macro is not defined the invoking of obsolete Python // module's methods like setSetting(), definePopup(), etc. is blocked. // This macro is defined by default (in Makefile) #ifdef __CALL_OLD_METHODS__ const bool IsCallOldMethods = true; -#else +#else const bool IsCallOldMethods = false; #endif @@ -88,17 +94,17 @@ class SALOME_PYQT_XmlHandler public: SALOME_PYQT_XmlHandler( SALOME_PYQT_Module* module, const QString& fileName ); void createActions(); - void createPopup ( QPopupMenu* menu, - const QString& context, - const QString& parent, + void createPopup ( QPopupMenu* menu, + const QString& context, + const QString& parent, const QString& object ); protected: void createToolBar ( QDomNode& parentNode ); - void createMenu ( QDomNode& parentNode, + void createMenu ( QDomNode& parentNode, const int parentMenuId = -1 ); - void insertPopupItems( QDomNode& parentNode, + void insertPopupItems( QDomNode& parentNode, QPopupMenu* menu ); private: @@ -130,7 +136,7 @@ extern "C" { if ( !alreadyInitialized ) { // call only once (see above) ! PyEval_RestoreThread( KERNEL_PYTHON::_gtstate ); - initSalomePyQtGUI(); + initSalomePyQtGUI(); PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate ); alreadyInitialized = !alreadyInitialized; } @@ -138,7 +144,7 @@ extern "C" { } } -/*! +/*! * Static variables definition */ SALOME_PYQT_Module::InterpMap SALOME_PYQT_Module::myInterpMap; @@ -148,9 +154,9 @@ SALOME_PYQT_Module* SALOME_PYQT_Module::myInitModule = 0; * Little trick : provide an access to being activated Python module from outside; * needed by the SalomePyQt library :( */ -SALOME_PYQT_Module* SALOME_PYQT_Module::getInitModule() -{ - return myInitModule; +SALOME_PYQT_Module* SALOME_PYQT_Module::getInitModule() +{ + return myInitModule; } /*! @@ -159,9 +165,6 @@ SALOME_PYQT_Module* SALOME_PYQT_Module::getInitModule() SALOME_PYQT_Module::SALOME_PYQT_Module() : SalomeApp_Module( __DEFAULT_NAME__ ), myModule( 0 ), myXmlHandler ( 0 ) { - myMenuActionList.setAutoDelete( false ); - myPopupActionList.setAutoDelete( false ); - myToolbarActionList.setAutoDelete( false ); } /*! @@ -169,9 +172,6 @@ SALOME_PYQT_Module::SALOME_PYQT_Module() : */ SALOME_PYQT_Module::~SALOME_PYQT_Module() { - myMenuActionList.clear(); - myPopupActionList.clear(); - myToolbarActionList.clear(); if ( myXmlHandler ) delete myXmlHandler; } @@ -182,7 +182,7 @@ SALOME_PYQT_Module::~SALOME_PYQT_Module() * * This method is used for creation of the menus, toolbars and other staff. * There are two ways: - * - for obsolete modules this method first tries to read _.xml + * - for obsolete modules this method first tries to read _.xml * resource file which contains a menu, toolbars and popup menus description. * - new modules can create menus by by calling the corresponding methods of SalomePyQt * Python API in the Python module's initialize() method which is called from here. @@ -200,7 +200,7 @@ void SALOME_PYQT_Module::initialize( CAM_Application* app ) QString aName = name( "" ); QString aFileName = aName + "_" + aLang + ".xml"; aFileName = aResMgr->path( "resources", aName, aFileName ); - + // parse XML file if it is found and create actions if ( !myXmlHandler && !aFileName.isEmpty() ) { myXmlHandler = new SALOME_PYQT_XmlHandler( this, aFileName ); @@ -213,11 +213,11 @@ void SALOME_PYQT_Module::initialize( CAM_Application* app ) { public: InitializeReq( CAM_Application* _app, - SALOME_PYQT_Module* _obj ) + SALOME_PYQT_Module* _obj ) : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) myApp( _app ), myObj( _obj ) {} - + protected: virtual void execute() { @@ -242,7 +242,7 @@ bool SALOME_PYQT_Module::activateModule( SUIT_Study* theStudy ) MESSAGE( "SALOME_PYQT_Module::activateModule" ); bool res = SalomeApp_Module::activateModule( theStudy ); - + if ( !res ) return res; @@ -250,12 +250,12 @@ bool SALOME_PYQT_Module::activateModule( SUIT_Study* theStudy ) class ActivateReq : public PyInterp_Request { public: - ActivateReq( SUIT_Study* _study, - SALOME_PYQT_Module* _obj ) + ActivateReq( SUIT_Study* _study, + SALOME_PYQT_Module* _obj ) : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) myStudy ( _study ), myObj ( _obj ) {} - + protected: virtual void execute() { @@ -274,6 +274,10 @@ bool SALOME_PYQT_Module::activateModule( SUIT_Study* theStudy ) setMenuShown( true ); setToolShown( true ); + if ( menuMgr() ) + connect( menuMgr(), SIGNAL( menuHighlighted( int, int ) ), + this, SLOT( onMenuHighlighted( int, int ) ) ); + return true; } @@ -285,6 +289,10 @@ bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* theStudy ) { MESSAGE( "SALOME_PYQT_Module::deactivateModule" ); + if ( menuMgr() ) + disconnect( menuMgr(), SIGNAL( menuHighlighted( int, int ) ), + this, SLOT( onMenuHighlighted( int, int ) ) ); + bool res = SalomeApp_Module::deactivateModule( theStudy ); // deactivate menus, toolbars, etc @@ -295,13 +303,13 @@ bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* theStudy ) class DeactivateReq : public PyInterp_LockRequest { public: - DeactivateReq( PyInterp_base* _py_interp, - SUIT_Study* _study, - SALOME_PYQT_Module* _obj ) + DeactivateReq( PyInterp_base* _py_interp, + SUIT_Study* _study, + SALOME_PYQT_Module* _obj ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myStudy ( _study ), myObj ( _obj ) {} - + protected: virtual void execute() { @@ -338,13 +346,13 @@ void SALOME_PYQT_Module::onGUIEvent() class GUIEvent : public PyInterp_LockRequest { public: - GUIEvent( PyInterp_base* _py_interp, + GUIEvent( PyInterp_base* _py_interp, SALOME_PYQT_Module* _obj, - int _id ) + int _id ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myId ( _id ), myObj ( _obj ) {} - + protected: virtual void execute() { @@ -363,19 +371,19 @@ void SALOME_PYQT_Module::onGUIEvent() /*! * Processes GUI action (from context popup menu, only for XML-based actions!) */ -void SALOME_PYQT_Module::onGUIEvent( int id ) +void SALOME_PYQT_Module::onGUIEvent( int id ) { // perform synchronous request to Python event dispatcher class GUIEvent : public PyInterp_LockRequest { public: - GUIEvent( PyInterp_base* _py_interp, + GUIEvent( PyInterp_base* _py_interp, SALOME_PYQT_Module* _obj, - int _id ) + int _id ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myId ( _id ), myObj ( _obj ) {} - + protected: virtual void execute() { @@ -391,7 +399,43 @@ void SALOME_PYQT_Module::onGUIEvent( int id ) PyInterp_Dispatcher::Get()->Exec( new GUIEvent( myInterp, this, id ) ); } -/*! +/*! + * Menu highlight processing + */ +void SALOME_PYQT_Module::onMenuHighlighted( int menu, int submenu ) +{ + if ( !action( menu ) && registered( menu, submenu ) ) { + // perform synchronous request to Python event dispatcher + class MenuHighlightEvent : public PyInterp_LockRequest + { + public: + MenuHighlightEvent( PyInterp_base* _py_interp, + SALOME_PYQT_Module* _obj, + int _menu, + int _submenu ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myMenu ( _menu ), + mySubMenu( _submenu ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->menuHighlight( myMenu, mySubMenu ); + } + + private: + int myMenu; + int mySubMenu; + SALOME_PYQT_Module* myObj; + }; + + // Posting the request + PyInterp_Dispatcher::Get()->Exec( new MenuHighlightEvent( myInterp, this, menu, submenu ) ); + } +} + +/*! Context popup menu request. Called when user activates popup menu in some window (view, object browser, etc). */ @@ -402,15 +446,15 @@ void SALOME_PYQT_Module::contextMenuPopup( const QString& theContext, QPopupMenu class PopupMenuEvent : public PyInterp_LockRequest { public: - PopupMenuEvent( PyInterp_base* _py_interp, + PopupMenuEvent( PyInterp_base* _py_interp, SALOME_PYQT_Module* _obj, - const QString& _context, - QPopupMenu* _popup ) + const QString& _context, + QPopupMenu* _popup ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) - myContext( _context ), + myContext( _context ), myPopup ( _popup ), myObj ( _obj ) {} - + protected: virtual void execute() { @@ -431,13 +475,13 @@ void SALOME_PYQT_Module::contextMenuPopup( const QString& theContext, QPopupMenu /*! * Defines the dockable window associated with the module. - * To fill the list of windows the correspondind Python module's windows() + * To fill the list of windows the correspondind Python module's windows() * method is called from SALOME_PYQT_Module::init() method. * By default, ObjectBrowser, PythonConsole and LogWindow are provided. */ void SALOME_PYQT_Module::windows( QMap& mappa ) const { - // First clear the output parameters + // First clear the output parameters QMap::ConstIterator it; for ( it = myWindowsMap.begin(); it != myWindowsMap.end(); ++it ) { mappa[ it.key() ] = it.data(); @@ -446,7 +490,7 @@ void SALOME_PYQT_Module::windows( QMap& mappa ) const /*! * Defines the compatible views which should be opened on module activation. - * To fill the list of views the correspondind Python module's views() + * To fill the list of views the correspondind Python module's views() * method is called from SALOME_PYQT_Module::init() method. * By default, the list is empty. */ @@ -483,14 +527,14 @@ void SALOME_PYQT_Module::init( CAM_Application* app ) // initialize Python subinterpreter (on per study) and put it in variable initInterp( aStudyId ); - if ( !myInterp ) - return; // Error + if ( !myInterp ) + return; // Error // import Python GUI module importModule(); if ( !myModule ) - return; // Error - + return; // Error + myInitModule = this; if ( IsCallOldMethods ) { // __CALL_OLD_METHODS__ @@ -509,7 +553,7 @@ void SALOME_PYQT_Module::init( CAM_Application* app ) PyErr_Print(); } } - + // get the windows list from the Python module by calling windows() method // ... first put default values myWindowsMap.insert( SalomeApp_Application::WT_ObjectBrowser, Qt::DockLeft ); @@ -569,7 +613,7 @@ void SALOME_PYQT_Module::init( CAM_Application* app ) } /*! - * Performs internal activation: + * Performs internal activation: * - initializes/gets the Python interpreter (one per study) * - imports the Python GUI module * - calls Python module's setSettings() method (obsolete function, used for compatibility with old code) @@ -583,14 +627,14 @@ void SALOME_PYQT_Module::activate( SUIT_Study* theStudy ) // initialize Python subinterpreter (on per study) and put it in variable initInterp( aStudyId ); - if ( !myInterp ) - return; // Error + if ( !myInterp ) + return; // Error // import Python GUI module importModule(); if ( !myModule ) - return; // Error - + return; // Error + // get python lock PyLockWrapper aLock = myInterp->GetLockWrapper(); @@ -614,7 +658,7 @@ void SALOME_PYQT_Module::activate( SUIT_Study* theStudy ) } /*! - * Performs internal deactivation: + * Performs internal deactivation: * - calls Python module's deactivate() method */ void SALOME_PYQT_Module::deactivate( SUIT_Study* theStudy ) @@ -647,14 +691,14 @@ void SALOME_PYQT_Module::studyChanged( SUIT_Study* theStudy ) // initialize Python subinterpreter (on per study) and put it in variable initInterp( aStudyId ); - if ( !myInterp ) - return; // Error + if ( !myInterp ) + return; // Error // import Python GUI module importModule(); if ( !myModule ) - return; // Error - + return; // Error + // get python lock PyLockWrapper aLock = myInterp->GetLockWrapper(); @@ -692,7 +736,7 @@ QString SALOME_PYQT_Module::engineIOR() const return QString( "" ); } -/*! +/*! * Called when study desktop is activated. * Used for notifying about changing of the active study. */ @@ -702,12 +746,12 @@ void SALOME_PYQT_Module::studyActivated() class StudyChangedReq : public PyInterp_Request { public: - StudyChangedReq( SUIT_Study* _study, - SALOME_PYQT_Module* _obj ) + StudyChangedReq( SUIT_Study* _study, + SALOME_PYQT_Module* _obj ) : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) myStudy ( _study ), myObj ( _obj ) {} - + protected: virtual void execute() { @@ -739,17 +783,17 @@ void SALOME_PYQT_Module::contextMenu( const QString& theContext, QPopupMenu* the // import first if ( !myInterp || !myModule ) return; - + QString aContext( theContext ), aObject( "" ), aParent( "" ); - + if ( IsCallOldMethods && PyObject_HasAttrString(myModule , "definePopup") ) { //__CALL_OLD_METHODS__ // call definePopup() Python module's function // this is obsolete function, used only for compatibility reasons - PyObjWrapper res(PyObject_CallMethod( myModule, - "definePopup", + PyObjWrapper res(PyObject_CallMethod( myModule, + "definePopup", "sss", - aContext.latin1(), - aObject.latin1(), + aContext.latin1(), + aObject.latin1(), aParent.latin1() ) ); if( !res ) { PyErr_Print(); @@ -773,7 +817,7 @@ void SALOME_PYQT_Module::contextMenu( const QString& theContext, QPopupMenu* the PyObjWrapper sipPopup( sipBuildResult( 0, "M", thePopupMenu, sipClass_QPopupMenu ) ); // then call Python module's createPopupMenu() method (for new modules) - if ( PyObject_HasAttrString(myModule , "createPopupMenu") ) { + if ( PyObject_HasAttrString(myModule , "createPopupMenu") ) { PyObjWrapper res1( PyObject_CallMethod( myModule, "createPopupMenu", "Os", @@ -791,8 +835,8 @@ void SALOME_PYQT_Module::contextMenu( const QString& theContext, QPopupMenu* the "customPopup", "Osss", sipPopup.get(), - aContext.latin1(), - aObject.latin1(), + aContext.latin1(), + aObject.latin1(), aParent.latin1() ) ); if( !res2 ) { PyErr_Print(); @@ -803,15 +847,15 @@ void SALOME_PYQT_Module::contextMenu( const QString& theContext, QPopupMenu* the /*! * Processes GUI event * - calls Python module's OnGUIEvent() method - */ + */ void SALOME_PYQT_Module::guiEvent( const int theId ) { // Python interpreter should be initialized and Python module should be // import first if ( !myInterp || !myModule ) return; - - if ( PyObject_HasAttrString(myModule , "OnGUIEvent") ) { + + if ( PyObject_HasAttrString(myModule , "OnGUIEvent") ) { PyObjWrapper res( PyObject_CallMethod( myModule, "OnGUIEvent", "i", theId ) ); if( !res ) { PyErr_Print(); @@ -819,6 +863,25 @@ void SALOME_PYQT_Module::guiEvent( const int theId ) } } +/*! + * Menu highlight processing + * - calls Python module's menuActivated(int,int) method + */ +void SALOME_PYQT_Module::menuHighlight( const int menu, const int submenu ) +{ + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + if ( PyObject_HasAttrString(myModule , "menuHighlight") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, "menuHighlight", "ii", menu, submenu ) ); + if( !res ) { + PyErr_Print(); + } + } +} + /*! * Initialises python subinterpreter (one per study) */ @@ -838,13 +901,13 @@ void SALOME_PYQT_Module::initInterp( int theStudyId ) } // not found - create a new one! /////////////////////////////////////////////////////////////////// - // Attention: the creation of Python interpretor must be protected + // Attention: the creation of Python interpretor must be protected // by a C++ Lock because of C threads /////////////////////////////////////////////////////////////////// myInterp = new SALOME_PYQT_PyInterp(); myInterp->initialize(); myInterpMap[ theStudyId ] = myInterp; - + // import 'salome' module and call 'salome_init' method; // do it only once on interpreter creation // ... first get python lock @@ -913,7 +976,7 @@ void SALOME_PYQT_Module::setWorkSpace() // Error! PyErr_Print(); return; - } + } if ( IsCallOldMethods ) { //__CALL_OLD_METHODS__ // ... then get workspace object @@ -930,7 +993,7 @@ void SALOME_PYQT_Module::setWorkSpace() } PyObjWrapper pyws( sipBuildResult( 0, "M", aWorkspace, sipClass_QWidget ) ); // ... and finally call Python module's setWorkspace() method (obsolete) - if ( PyObject_HasAttrString(myModule , "setWorkSpace") ) { + if ( PyObject_HasAttrString(myModule , "setWorkSpace") ) { PyObjWrapper res( PyObject_CallMethod( myModule, "setWorkSpace", "O", pyws.get() ) ); if( !res ) { PyErr_Print(); @@ -940,28 +1003,19 @@ void SALOME_PYQT_Module::setWorkSpace() } /*! - * Adds an action into private action list [internal usage] + * Returns default menu group */ -void SALOME_PYQT_Module::addAction( const PyQtGUIAction type, QAction* action ) +int SALOME_PYQT_Module::defaultMenuGroup() { - switch ( type ) { - case PYQT_ACTION_MENU: - myMenuActionList.append( action ); - break; - case PYQT_ACTION_TOOLBAL: - myToolbarActionList.append( action ); - break; - case PYQT_ACTION_POPUP: - myPopupActionList.append( action ); - break; - } + return __DEFAULT_GROUP__; } - /*! - * The next methods just call the parent implementation. + * The next methods call the parent implementation. * This is done to open protected methods from CAM_Module class. -*/ + * Also these methods are used to register created from outside menus + * in order to enable dynamic menus handling. + */ int SALOME_PYQT_Module::createTool( const QString& name ) { return SalomeApp_Module::createTool( name ); @@ -982,29 +1036,63 @@ int SALOME_PYQT_Module::createTool( QAction* a, const QString& tBar, const int i { return SalomeApp_Module::createTool( a, tBar, id, idx ); } -int SALOME_PYQT_Module::createMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) +int SALOME_PYQT_Module::createMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx, const bool constantMenu ) { - return SalomeApp_Module::createMenu( subMenu, menu, id, group, idx ); + bool exists = hasMenu( subMenu, menu ); + int regId = SalomeApp_Module::createMenu( subMenu, menu, id, group, idx, true ); + if ( !exists ) + registerMenu( regId, menu, constantMenu ); + return regId; } -int SALOME_PYQT_Module::createMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx ) +int SALOME_PYQT_Module::createMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx, const bool constantMenu ) { - return SalomeApp_Module::createMenu( subMenu, menu, id, group, idx ); + QStringList menus = QStringList::split( "|", menu, false ); + int pid = -1; + for (int i = 0; i < menus.count(); i++ ) { + pid = createMenu( menus[i], pid, -1, -1, -1, constantMenu ); + if ( pid == -1 ) break; + } + if ( pid != -1 ) + pid = createMenu( subMenu, pid, id, group, idx, constantMenu ); + return pid; } -int SALOME_PYQT_Module::createMenu( const int id, const int menu, const int group, const int idx ) +int SALOME_PYQT_Module::createMenu( const int id, const int menu, const int group, const int idx, const bool constantMenu ) { - return SalomeApp_Module::createMenu( id, menu, group, idx ); + int regId = SalomeApp_Module::createMenu( id, menu, group, idx ); + if ( regId != -1 ) + registerMenu( regId, menu, constantMenu ); + return regId; } -int SALOME_PYQT_Module::createMenu( const int id, const QString& menu, const int group, const int idx ) +int SALOME_PYQT_Module::createMenu( const int id, const QString& menu, const int group, const int idx, const bool constantMenu ) { - return SalomeApp_Module::createMenu( id, menu, group, idx ); + QStringList menus = QStringList::split( "|", menu, false ); + int pid = -1; + for (int i = 0; i < menus.count(); i++ ) { + pid = createMenu( menus[i], pid, -1, -1, -1, constantMenu ); + if ( pid == -1 ) break; + } + if ( pid != -1 ) + pid = createMenu( id, pid, group, idx, constantMenu ); + return pid; } -int SALOME_PYQT_Module::createMenu( QAction* a, const int menu, const int id, const int group, const int idx ) +int SALOME_PYQT_Module::createMenu( QAction* a, const int menu, const int id, const int group, const int idx, const bool constantMenu ) { - return SalomeApp_Module::createMenu( a, menu, id, group, idx ); + int regId = SalomeApp_Module::createMenu( a, menu, id, group, idx ); + if ( regId != -1 ) + registerMenu( regId, menu, constantMenu ); + return regId; } -int SALOME_PYQT_Module::createMenu( QAction* a, const QString& menu, const int id, const int group, const int idx ) +int SALOME_PYQT_Module::createMenu( QAction* a, const QString& menu, const int id, const int group, const int idx, const bool constantMenu ) { - return SalomeApp_Module::createMenu( a, menu, id, group, idx ); + QStringList menus = QStringList::split( "|", menu, false ); + int pid = -1; + for (int i = 0; i < menus.count(); i++ ) { + pid = createMenu( menus[i], pid, -1, -1, -1, constantMenu ); + if ( pid == -1 ) break; + } + if ( pid != -1 ) + pid = createMenu( a, pid, id, group, idx, constantMenu ); + return pid; } QAction* SALOME_PYQT_Module::createSeparator() { @@ -1012,27 +1100,13 @@ QAction* SALOME_PYQT_Module::createSeparator() } QAction* SALOME_PYQT_Module::action( const int id ) const { - QAction* a = SalomeApp_Module::action( id ); - if ( !a ) // try own action map for menu items - a = SalomeApp_Module::action( id + PYQT_ACTION_MENU ); - if ( !a ) // try own action map for toolbar items - a = SalomeApp_Module::action( id + PYQT_ACTION_TOOLBAL ); - if ( !a ) // try own action map for popup items - a = SalomeApp_Module::action( id + PYQT_ACTION_POPUP ); - return a; + return SalomeApp_Module::action( id ); } int SALOME_PYQT_Module::actionId( const QAction* a ) const { - int id = SalomeApp_Module::actionId( a ); - if ( myMenuActionList.contains( a ) ) // check own action map for menu items - id -= PYQT_ACTION_MENU; - if ( myToolbarActionList.contains( a ) ) // check own action map for toolbar items - id -= PYQT_ACTION_TOOLBAL; - if ( myPopupActionList.contains( a ) ) // check own action map for popup items - id -= PYQT_ACTION_POPUP; - return id; + return SalomeApp_Module::actionId( a ); } -QAction* SALOME_PYQT_Module::createAction( const int id, const QString& text, const QString& icon, +QAction* SALOME_PYQT_Module::createAction( const int id, const QString& text, const QString& icon, const QString& menu, const QString& tip, const int key, const bool toggle ) { @@ -1042,9 +1116,201 @@ QAction* SALOME_PYQT_Module::createAction( const int id, const QString& text, co if ( !pixmap.isNull() ) anIcon = QIconSet( pixmap ); } - return SalomeApp_Module::createAction( id, text, anIcon, menu, tip, key, getApp()->desktop(), toggle, this, SLOT( onGUIEvent() ) ); + QAction* a = action( id ); + if ( a ) { + if ( a->text().isEmpty() && !text.isEmpty() ) a->setText( text ); + if ( a->menuText().isEmpty() && !menu.isEmpty() ) a->setMenuText( menu ); + if ( a->iconSet().isNull() && !anIcon.isNull() ) a->setIconSet( anIcon ); + if ( a->statusTip().isEmpty() && !tip.isNull() ) a->setStatusTip( tip ); + if ( a->accel().isEmpty() && key ) a->setAccel( key ); + if ( a->isToggleAction() != toggle ) a->setToggleAction( toggle ); + disconnect( a, SIGNAL( activated() ), this, SLOT( onGUIEvent() ) ); + connect( a, SIGNAL( activated() ), this, SLOT( onGUIEvent() ) ); + } + else { + a = SalomeApp_Module::createAction( id, text, anIcon, menu, tip, key, getApp()->desktop(), toggle, this, SLOT( onGUIEvent() ) ); + } + return a; } +/*! + * Returns TRUE if menu already exists + */ +bool SALOME_PYQT_Module::hasMenu( const QString& subMenu, const int menu ) +{ + return menuMgr() && menuMgr()->containsMenu( subMenu, menu ); +} + +/*! + * Register the menu + */ +void SALOME_PYQT_Module::registerMenu( const int id, const int menu, const bool constantMenu ) +{ + QAction* a = action( id ); + QAction* s = separator(); + if ( a && a == s ) + return; + if ( !registered( id, menu ) ) + myMenus[menu].append( MenuId( id, constantMenu ) ); +} + +/*! + * Unregister the menu + */ +void SALOME_PYQT_Module::unregisterMenu( const int id, const int menu ) +{ + if ( myMenus.find( menu ) != myMenus.end() ) { + MenuIdList::iterator lit; + for ( lit = myMenus[menu].begin(); lit != myMenus[menu].end(); ++lit ) { + if ( (*lit).id == id ) { + myMenus[menu].remove( lit ); + return; + } + } + } +} + +/*! + * Returns TRUE if the menu is registered + */ +bool SALOME_PYQT_Module::registered( const int id, const int menu ) +{ + MenuMap::iterator mit; + for ( mit = myMenus.begin(); mit != myMenus.end(); ++mit ) { + MenuIdList::iterator lit; + for ( lit = mit.data().begin(); lit != mit.data().end(); ++lit ) { + if ( (*lit).id == id && ( menu == 0 || mit.key() == menu ) ) + return true; + } + } + return false; +} + +/*! + * Returns TRUE if the menu is constant (not removed by clearMenu()). + * This concerns the menus which are created from XML files. + */ +bool SALOME_PYQT_Module::isConstantMenu( const int id, const int menu ) +{ + if ( myMenus.find( menu ) != myMenus.end() ) { + MenuIdList& l = myMenus[ menu ]; + MenuIdList::iterator lit; + for ( lit = l.begin(); lit != l.end(); ++lit ) { + if ( (*lit).id == id && (*lit).constantMenu ) + return true; + } + } + return false; +} + +/*! + * Displays/hides the module's menus. + */ +void SALOME_PYQT_Module::setMenuShown( const bool show ) +{ + QtxActionMenuMgr* mMgr = menuMgr(); + if ( !mMgr ) + return; + + bool upd = mMgr->isUpdatesEnabled(); + mMgr->setUpdatesEnabled( false ); + + SalomeApp_Module::setMenuShown( show ); + + for ( MenuMap::iterator mit = myMenus.begin(); mit != myMenus.end(); ++mit ) { + MenuIdList::iterator lit; + for ( lit = mit.data().begin(); lit != mit.data().end(); ++lit ) + if ( !action( (*lit).id ) ) + mMgr->setShown( (*lit).id, show ); + } + + mMgr->setUpdatesEnabled( upd ); + if ( upd ) + mMgr->update(); +} + +/*! + * Displays/hides the module's toolbars. + */ +void SALOME_PYQT_Module::setToolShown( const bool show ) +{ + SalomeApp_Module::setToolShown( show ); +} + +/*! + * Clears the given menu. + * If = 0 : clear all items in the menu + * If = 0 : clear all menus recursively starting from top-level. + * If = 0 : also unregister all removed actions (not delete!). + */ +bool SALOME_PYQT_Module::clearMenu( const int id, const int menu, const bool removeActions ) +{ + QAction* a = action( id ); + QAction* s = separator(); + typedef QValueList IntList; + if ( a && a != s ) { + // action + IntList menus; + if ( menu != 0 ) { + if ( registered( id, menu ) ) menus.append( menu ); + } + else { + MenuMap::iterator mit; + for ( mit = myMenus.begin(); mit != myMenus.end(); ++mit ) + if ( registered( id, mit.key() ) ) menus.append( mit.key() ); + } + for ( int i = 0; i < menus.count(); i++ ) { + if ( !isConstantMenu( id, menus[i] ) ) { + menuMgr()->remove( menuMgr()->actionId( a ), menus[ i ] ); + unregisterMenu( id, menus[i] ); + } + } + if ( !registered( id ) && removeActions ) + unregisterAction( id ); + } + else { + // menu + if ( id == 0 ) { + if ( menu == 0 ) { + // clear all menus recursively starting from top-level (main menu) + IntList l = myMenus.keys(); + IntList::iterator lit; + for ( lit = l.begin(); lit != l.end(); ++lit ) + clearMenu( 0, *lit, removeActions ); + } + else { + if ( myMenus.find( menu ) != myMenus.end() ) { + // remove all items in the parent menu + IntList l; + MenuIdList::iterator lit; + for ( lit = myMenus[menu].begin(); lit != myMenus[menu].end(); ++lit ) + l.append( (*lit).id ); + for ( int i = 0; i < l.count(); i++ ) + clearMenu( l[i], menu, removeActions ); + if ( myMenus[menu].empty() ) + myMenus.remove( menu ); + } + } + } + else { + MenuMap::iterator mit; + for ( mit = myMenus.begin(); mit != myMenus.end(); ++mit ) { + MenuIdList::iterator lit; + for ( lit = mit.data().begin(); lit != mit.data().end(); ++lit ) { + if ( (*lit).id == id && ( menu == 0 || mit.key() == menu ) ) { + clearMenu( 0, id, removeActions ); // first remove all sub-menus + if ( !isConstantMenu( id, mit.key() ) ) { + menuMgr()->remove( id, mit.key() ); + mit.data().remove( lit ); + break; + } + } + } + } + } + } + return false; +} //============================================================================= // SALOME_PYQT_XmlHandler class implementation @@ -1053,7 +1319,7 @@ QAction* SALOME_PYQT_Module::createAction( const int id, const QString& text, co // gets an tag name for the dom element [ static ] // returns an empty string if the element does not have tag name static QString tagName( const QDomElement& element ) { - return element.tagName().stripWhiteSpace(); + return element.tagName().stripWhiteSpace(); } // gets an attribute by it's name for the dom element [ static ] @@ -1070,15 +1336,15 @@ static bool checkBool( const QString& value ) { // checks the given value for the integer value [ static ] // returns -1 if item is empty or presents and invalid number -static int checkInt( const QString& value ) +static int checkInt( const QString& value, const int def = -1 ) { - return value.isEmpty() ? -1 : value.toInt(); + return value.isEmpty() ? def : value.toInt(); } /*! * Constructor */ -SALOME_PYQT_XmlHandler::SALOME_PYQT_XmlHandler( SALOME_PYQT_Module* module, const QString& fileName ) +SALOME_PYQT_XmlHandler::SALOME_PYQT_XmlHandler( SALOME_PYQT_Module* module, const QString& fileName ) : myModule( module ) { QFile aFile( fileName ); @@ -1092,7 +1358,7 @@ SALOME_PYQT_XmlHandler::SALOME_PYQT_XmlHandler( SALOME_PYQT_Module* module, cons } /*! - Called by SALOME_PYQT_Module::initialize() in order to create actions + Called by SALOME_PYQT_Module::initialize() in order to create actions (menus, toolbars, popup menus) */ void SALOME_PYQT_XmlHandler::createActions() @@ -1118,9 +1384,9 @@ void SALOME_PYQT_XmlHandler::createActions() /*! * Creates popup menu */ -void SALOME_PYQT_XmlHandler::createPopup( QPopupMenu* menu, - const QString& context, - const QString& parent, +void SALOME_PYQT_XmlHandler::createPopup( QPopupMenu* menu, + const QString& context, + const QString& parent, const QString& object ) { // get document element @@ -1151,22 +1417,25 @@ void SALOME_PYQT_XmlHandler::createMenu( QDomNode& parentNode, const int parentM { if ( !myModule ) return; - + if ( parentNode.isNull() ) return; - QDomElement parentElement = parentNode.toElement(); + QDomElement parentElement = parentNode.toElement(); if ( !parentElement.isNull() ) { QString plabel = attribute( parentElement, "label-id" ); int pid = checkInt( attribute( parentElement, "item-id" ) ); int ppos = checkInt( attribute( parentElement, "pos-id" ) ); + int group = checkInt( attribute( parentElement, "group-id" ), + myModule->defaultMenuGroup() ); if ( !plabel.isEmpty() ) { // create menu int menuId = myModule->createMenu( plabel, // label parentMenuId, // parent menu ID, should be -1 for main menu pid, // ID - 80, // group ID - ppos ); // position + group, // group ID + ppos, // position + true ); // create constant menu (not removed by clearMenu()) QDomNode node = parentNode.firstChild(); while ( !node.isNull() ) { if ( node.isElement() ) { @@ -1175,6 +1444,8 @@ void SALOME_PYQT_XmlHandler::createMenu( QDomNode& parentNode, const int parentM if ( aTagName == "popup-item" ) { int id = checkInt( attribute( elem, "item-id" ) ); int pos = checkInt( attribute( elem, "pos-id" ) ); + int group = checkInt( attribute( elem, "group-id" ), + myModule->defaultMenuGroup() ); QString label = attribute( elem, "label-id" ); QString icon = attribute( elem, "icon-id" ); QString tooltip = attribute( elem, "tooltip-id" ); @@ -1184,9 +1455,7 @@ void SALOME_PYQT_XmlHandler::createMenu( QDomNode& parentNode, const int parentM // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created - if ( id != -1 && !myModule->action( SALOME_PYQT_Module::PYQT_ACTION_MENU + id ) ) { - // little trick to have several actions with same ID for menus and toolbars - id = SALOME_PYQT_Module::PYQT_ACTION_MENU + id; + if ( id != -1 ) { // create menu action QAction* action = myModule->createAction( id, // ID tooltip, // tooltip @@ -1195,8 +1464,12 @@ void SALOME_PYQT_XmlHandler::createMenu( QDomNode& parentNode, const int parentM tooltip, // status-bar text QKeySequence( accel ), // keyboard accelerator toggle ); // toogled action - myModule->addAction( SALOME_PYQT_Module::PYQT_ACTION_MENU, action ); - myModule->createMenu( action, menuId, -1, 80, pos ); + myModule->createMenu( action, // action + menuId, // parent menu ID + id, // ID (same as for createAction()) + group, // group ID + pos, // position + true ); // create constant menu (not removed by clearMenu()) } } else if ( aTagName == "submenu" ) { @@ -1205,9 +1478,17 @@ void SALOME_PYQT_XmlHandler::createMenu( QDomNode& parentNode, const int parentM } else if ( aTagName == "separator" ) { // create menu separator - int pos = checkInt( attribute( elem, "pos-id" ) ); + int id = checkInt( attribute( elem, "item-id" ) ); // separator can have ID + int pos = checkInt( attribute( elem, "pos-id" ) ); + int group = checkInt( attribute( elem, "group-id" ), + myModule->defaultMenuGroup() ); QAction* action = myModule->createSeparator(); - myModule->createMenu( action, menuId, -1, 80, pos ); + myModule->createMenu( action, // separator action + menuId, // parent menu ID + id, // ID + group, // group ID + pos, // position + true ); // create constant menu (not removed by clearMenu()) } } node = node.nextSibling(); @@ -1223,11 +1504,11 @@ void SALOME_PYQT_XmlHandler::createToolBar( QDomNode& parentNode ) { if ( !myModule ) return; - + if ( parentNode.isNull() ) return; - QDomElement parentElement = parentNode.toElement(); + QDomElement parentElement = parentNode.toElement(); if ( !parentElement.isNull() ) { QString aLabel = attribute( parentElement, "label-id" ); if ( !aLabel.isEmpty() ) { @@ -1250,9 +1531,7 @@ void SALOME_PYQT_XmlHandler::createToolBar( QDomNode& parentNode ) // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created - if ( id != -1 && !myModule->action( SALOME_PYQT_Module::PYQT_ACTION_TOOLBAL + id ) ) { - // little trick to have several actions with same ID for menus and toolbars - id = SALOME_PYQT_Module::PYQT_ACTION_TOOLBAL + id; + if ( id != -1 ) { // create toolbar action QAction* action = myModule->createAction( id, // ID tooltip, // tooltip @@ -1261,7 +1540,6 @@ void SALOME_PYQT_XmlHandler::createToolBar( QDomNode& parentNode ) tooltip, // status-bar text QKeySequence( accel ), // keyboard accelerator toggle ); // toogled action - myModule->addAction( SALOME_PYQT_Module::PYQT_ACTION_TOOLBAL, action ); myModule->createTool( action, tbId, -1, pos ); } } @@ -1275,14 +1553,14 @@ void SALOME_PYQT_XmlHandler::createToolBar( QDomNode& parentNode ) node = node.nextSibling(); } } - } + } } void SALOME_PYQT_XmlHandler::insertPopupItems( QDomNode& parentNode, QPopupMenu* menu ) { if ( !myModule ) return; - + if ( parentNode.isNull() ) return; @@ -1309,7 +1587,7 @@ void SALOME_PYQT_XmlHandler::insertPopupItems( QDomNode& parentNode, QPopupMenu* if ( !pixmap.isNull() ) anIcon = QIconSet( pixmap ); } - + // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created if ( id != -1 ) { diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.h b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.h index 2582ee59e..57fa50cce 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.h +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.h @@ -60,20 +60,22 @@ private: SALOME_PYQT_PyInterp* myInterp; /* Python GUI module loaded */ PyObjWrapper myModule; - /* Pytho GUI being initialized (not zero only during the initialization)*/ - static SALOME_PYQT_Module* myInitModule; - - typedef QPtrList ActionList; - - /* own actions list */ - ActionList myMenuActionList; - ActionList myPopupActionList; - ActionList myToolbarActionList; + /* Python GUI being initialized (not zero only during the initialization)*/ + static SALOME_PYQT_Module* myInitModule; + + /* own menus list */ + struct MenuId + { + int id; + bool constantMenu; + MenuId() : id( -1 ), constantMenu( false ) {} + MenuId( const int _id, const bool _constantMenu ) + : id( _id ), constantMenu( _constantMenu ) {} + }; + typedef QValueList MenuIdList; + typedef QMap MenuMap; + MenuMap myMenus; - enum PyQtGUIAction { PYQT_ACTION_MENU = 10000000, - PYQT_ACTION_TOOLBAL = 20000000, - PYQT_ACTION_POPUP = 30000000 }; - /* XML resource file parser */ SALOME_PYQT_XmlHandler* myXmlHandler; /* windows map*/ @@ -121,6 +123,9 @@ public: /* called when study desktop is activated */ virtual void studyActivated(); + /* returns default menu group */ + static int defaultMenuGroup(); + /* working with toolbars : open protected methods */ int createTool( const QString& ); int createTool( const int, const int, const int = -1 ); @@ -129,12 +134,15 @@ public: int createTool( QAction*, const QString&, const int = -1, const int = -1 ); /* working with menus : open protected methods */ - int createMenu( const QString&, const int, const int = -1, const int = -1, const int = -1 ); - int createMenu( const QString&, const QString&, const int = -1, const int = -1, const int = -1 ); - int createMenu( const int, const int, const int = -1, const int = -1 ); - int createMenu( const int, const QString&, const int = -1, const int = -1 ); - int createMenu( QAction*, const int, const int = -1, const int = -1, const int = -1 ); - int createMenu( QAction*, const QString&, const int = -1, const int = -1, const int = -1 ); + int createMenu( const QString&, const int, const int = -1, const int = -1, const int = -1, const bool = false ); + int createMenu( const QString&, const QString&, const int = -1, const int = -1, const int = -1, const bool = false ); + int createMenu( const int, const int, const int = -1, const int = -1, const bool = false ); + int createMenu( const int, const QString&, const int = -1, const int = -1, const bool = false ); + int createMenu( QAction*, const int, const int = -1, const int = -1, const int = -1, const bool = false ); + int createMenu( QAction*, const QString&, const int = -1, const int = -1, const int = -1, const bool = false ); + + /* clear given menu */ + bool clearMenu( const int = 0, const int = 0, const bool = true ); /* create separator : open protected method */ QAction* createSeparator(); @@ -145,6 +153,10 @@ public: QAction* createAction( const int, const QString&, const QString&, const QString&, const QString&, const int, const bool = false ); + /* Show/hide menus/toolbars */ + void setMenuShown( const bool ); + void setToolShown( const bool ); + public slots: /* activation */ virtual bool activateModule( SUIT_Study* ); @@ -160,6 +172,17 @@ public slots: void onGUIEvent(); void onGUIEvent( int ); +protected: + /* Menu processing */ + bool hasMenu( const QString&, const int ); + void registerMenu( const int, const int, const bool = false ); + void unregisterMenu( const int, const int ); + bool registered( const int, const int = 0 ); + bool isConstantMenu( const int, const int ); + +protected slots: + void onMenuHighlighted( int, int ); + private: /* internal initizalition */ void init ( CAM_Application* ); @@ -173,9 +196,8 @@ private: void contextMenu( const QString&, QPopupMenu* ); /* GUI event processing */ void guiEvent( const int ); - - /* add action to the private action map */ - void addAction ( const PyQtGUIAction, QAction* ); + /* Menu highlight processing */ + void menuHighlight( const int, const int ); /* initialize a Python subinterpreter */ void initInterp ( int ); diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx index d7b887fe6..67f222687 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx @@ -939,6 +939,24 @@ bool SalomePyQt::dumpView( const QString& filename ) return ProcessEvent( new TDumpViewEvent( filename ) ); } +/*! + SalomePyQt::defaultMenuGroup + Returns default menu group +*/ +class TDefMenuGroupEvent: public SALOME_Event { +public: + typedef int TResult; + TResult myResult; + TDefMenuGroupEvent() : myResult( -1 ) {} + virtual void Execute() { + myResult = SALOME_PYQT_Module::defaultMenuGroup(); + } +}; +int SalomePyQt::defaultMenuGroup() +{ + return ProcessEvent( new TDefMenuGroupEvent() ); +} + /*! SalomePyQt::createTool These methods allow operating with the toolbars: @@ -1045,10 +1063,10 @@ int SalomePyQt::createTool( QtxAction* a, const QString& tBar, const int id, con class CrMenu { public: - CrMenu( const QString& subMenu, const int menu, const int group, const int idx ) - : myCase( 0 ), mySubMenuName( subMenu ), myMenuId( menu ), myGroup( group ), myIndex( idx ) {} - CrMenu( const QString& subMenu, const QString& menu, const int group, const int idx ) - : myCase( 1 ), mySubMenuName( subMenu ), myMenuName( menu ), myGroup( group ), myIndex( idx ) {} + CrMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) + : myCase( 0 ), mySubMenuName( subMenu ), myMenuId( menu ), myId( id ), myGroup( group ), myIndex( idx ) {} + CrMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx ) + : myCase( 1 ), mySubMenuName( subMenu ), myMenuName( menu ), myId( id ), myGroup( group ), myIndex( idx ) {} CrMenu( const int id, const int menu, const int group, const int idx ) : myCase( 2 ), myId( id ), myMenuId( menu ), myGroup( group ), myIndex( idx ) {} CrMenu( const int id, const QString& menu, const int group, const int idx ) @@ -1063,9 +1081,9 @@ public: if ( module ) { switch ( myCase ) { case 0: - return module->createMenu( mySubMenuName, myMenuId, -1, myGroup, myIndex ); + return module->createMenu( mySubMenuName, myMenuId, myId, myGroup, myIndex ); case 1: - return module->createMenu( mySubMenuName, myMenuName, -1, myGroup, myIndex ); + return module->createMenu( mySubMenuName, myMenuName, myId, myGroup, myIndex ); case 2: return module->createMenu( myId, myMenuId, myGroup, myIndex ); case 3: @@ -1104,14 +1122,14 @@ public: } } }; -int SalomePyQt::createMenu( const QString& subMenu, const int menu, const int group, const int idx ) +int SalomePyQt::createMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) { - return ProcessEvent( new TCreateMenuEvent( CrMenu( subMenu, menu, group, idx ) ) ); + return ProcessEvent( new TCreateMenuEvent( CrMenu( subMenu, menu, id, group, idx ) ) ); } -int SalomePyQt::createMenu( const QString& subMenu, const QString& menu, const int group, const int idx ) +int SalomePyQt::createMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx ) { - return ProcessEvent( new TCreateMenuEvent( CrMenu( subMenu, menu, group, idx ) ) ); + return ProcessEvent( new TCreateMenuEvent( CrMenu( subMenu, menu, id, group, idx ) ) ); } int SalomePyQt::createMenu( const int id, const int menu, const int group, const int idx ) @@ -1253,3 +1271,32 @@ int SalomePyQt::actionId( const QtxAction* a ) { return ProcessEvent( new TActionIdEvent( a ) ); } + +/*! + SalomePyQt::clearMenu + Clears given menu (recursively if necessary) +*/ +class TClearMenuEvent: public SALOME_Event { +public: + typedef bool TResult; + TResult myResult; + int myId; + int myMenu; + bool myRemoveActions; + TClearMenuEvent( const int id, const int menu, const bool removeActions ) + : myResult( false ), myId( id ), myMenu( menu ), myRemoveActions( removeActions ) {} + virtual void Execute() { + if ( SalomeApp_Application* anApp = getApplication() ) { + SALOME_PYQT_Module* module = SALOME_PYQT_Module::getInitModule(); + if ( !module ) + module = dynamic_cast( anApp->activeModule() ); + if ( module ) + myResult = module->clearMenu( myId, myMenu, myRemoveActions ); + } + } +}; +bool SalomePyQt::clearMenu( const int id, const int menu, const bool removeActions ) +{ + return ProcessEvent( new TClearMenuEvent( id, menu, removeActions ) ); +} + diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h index 51f245f23..a3022cb2a 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h @@ -102,6 +102,8 @@ public: static bool dumpView( const QString& ); + static int defaultMenuGroup(); + static int createTool( const QString& ); static int createTool( const int, const int, const int = -1 ); static int createTool( const int, const QString&, const int = -1 ); @@ -109,9 +111,9 @@ public: static int createTool( QtxAction*, const QString&, const int = -1, const int = -1 ); static int createMenu( const QString&, const int = -1, - const int = -1, const int = -1 ); + const int = -1, const int = -1, const int = -1 ); static int createMenu( const QString&, const QString& = QString::null, - const int = -1, const int = -1 ); + const int = -1, const int = -1, const int = -1 ); static int createMenu( const int, const int = -1, const int = -1, const int = -1 ); static int createMenu( const int, const QString& = QString::null, @@ -130,6 +132,9 @@ public: static QtxAction* action( const int ); static int actionId( const QtxAction* ); + static bool clearMenu( const int = 0, const int = 0, + const bool = true ); + static void addSetting ( const QString&, const QString&, const double ); static void addSetting ( const QString&, const QString&, const int ); static void addSetting ( const QString&, const QString&, const QString& ); diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip index 3824647dd..813a9d710 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip @@ -81,6 +81,8 @@ public: static bool dumpView( const QString& ); + static int defaultMenuGroup(); + static int createTool( const QString& ); static int createTool( const int, const int, int = -1 ); static int createTool( const int, const QString&, int = -1 ); @@ -88,9 +90,9 @@ public: static int createTool( QtxAction*, const QString&, int = -1, int = -1 ); static int createMenu( const QString&, const int, - int = -1, int = -1 ); + int = -1, int = -1, int = -1 ); static int createMenu( const QString&, const QString&, - int = -1, int = -1 ); + int = -1, int = -1, int = -1 ); static int createMenu( const int, const int, int = -1, int = -1 ); static int createMenu( const int, const QString&, @@ -109,13 +111,16 @@ public: static QtxAction* action( const int ); static int actionId( const QtxAction* ); + static bool clearMenu( int = 0, int = 0, + bool = true ); + static void addSetting ( const QString&, const QString&, const double ); static void addSetting ( const QString&, const QString&, const int /Constrained/ ); static void addSetting ( const QString&, const QString&, const QString& ); static void addSetting ( const QString&, const QString&, const QColor& ); static int integerSetting( const QString&, const QString&, int = 0 ); static double doubleSetting ( const QString&, const QString&, int = 0 ); - static bool boolSetting ( const QString&, const QString&, bool = 0 ); + static bool boolSetting ( const QString&, const QString&, bool = false ); static QString stringSetting ( const QString&, const QString&, const QString& = QString("") ); static QColor colorSetting ( const QString&, const QString&, const QColor& = QColor() ); static void removeSetting ( const QString&, const QString& ); diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip index f306399b1..c7371eb24 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_v4.sip @@ -74,13 +74,15 @@ public: static void updateObjBrowser( const int = 0, bool = true ); static QString getFileName ( QWidget*, const QString&, const QStringList&, const QString&, bool ) /ReleaseGIL/ ; - static QStringList getOpenFileNames ( QWidget*, const QString&, const QStringList&, const QString& ); - static QString getExistingDirectory( QWidget*, const QString&, const QString& ); + static QStringList getOpenFileNames ( QWidget*, const QString&, const QStringList&, const QString& ) /ReleaseGIL/ ; + static QString getExistingDirectory( QWidget*, const QString&, const QString& ) /ReleaseGIL/ ; static void helpContext( const QString&, const QString& ); static bool dumpView( const QString& ); + static int defaultMenuGroup(); + static int createTool( const QString& ); static int createTool( const int, const int, const int = -1 ); static int createTool( const int, const QString&, const int = -1 ); @@ -88,9 +90,9 @@ public: static int createTool( QtxAction*, const QString&, const int = -1, const int = -1 ); static int createMenu( const QString&, const int, - const int = -1, const int = -1 ); + const int = -1, const int = -1, const int = -1 ); static int createMenu( const QString&, const QString&, - const int = -1, const int = -1 ); + const int = -1, const int = -1, const int = -1 ); static int createMenu( const int, const int, const int = -1, const int = -1 ); static int createMenu( const int, const QString&, @@ -99,7 +101,6 @@ public: const int = -1, const int = -1 ); static int createMenu( QtxAction*, const QString&, const int = -1, const int = -1, const int = -1 ); - static QtxAction* createSeparator(); static QtxAction* createAction( const int, const QString&, @@ -109,13 +110,16 @@ public: static QtxAction* action( const int ); static int actionId( const QtxAction* ); + static bool clearMenu( const int = 0, const int = 0, + const bool = true ); + static void addSetting ( const QString&, const QString&, const double ); static void addSetting ( const QString&, const QString&, const int /Constrained/ ); static void addSetting ( const QString&, const QString&, const QString& ); static void addSetting ( const QString&, const QString&, const QColor& ); static int integerSetting( const QString&, const QString&, const int = 0 ); static double doubleSetting ( const QString&, const QString&, const int = 0 ); - static bool boolSetting ( const QString&, const QString&, const bool = 0 ); + static bool boolSetting ( const QString&, const QString&, const bool = false ); static QString stringSetting ( const QString&, const QString&, const QString& = QString("") ); static QColor colorSetting ( const QString&, const QString&, const QColor& = QColor() ); static void removeSetting ( const QString&, const QString& ); diff --git a/src/STD/STD_Application.cxx b/src/STD/STD_Application.cxx index a3ab1739e..68b7b1a06 100755 --- a/src/STD/STD_Application.cxx +++ b/src/STD/STD_Application.cxx @@ -199,32 +199,32 @@ void STD_Application::createActions() // Create menus - int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1, -1, 0 ); - int editMenu = createMenu( tr( "MEN_DESK_EDIT" ), -1, -1, 10 ); - int viewMenu = createMenu( tr( "MEN_DESK_VIEW" ), -1, -1, 10 ); - int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 ); + int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1, MenuFileId, 0 ); + int editMenu = createMenu( tr( "MEN_DESK_EDIT" ), -1, MenuEditId, 10 ); + int viewMenu = createMenu( tr( "MEN_DESK_VIEW" ), -1, MenuViewId, 10 ); + int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, MenuHelpId, 1000 ); // Create menu items - createMenu( FileNewId, fileMenu, 0 ); - createMenu( FileOpenId, fileMenu, 0 ); - createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load" - createMenu( FileCloseId, fileMenu, 0 ); - createMenu( separator(), fileMenu, -1, 0 ); - createMenu( FileSaveId, fileMenu, 0 ); + createMenu( FileNewId, fileMenu, 0 ); + createMenu( FileOpenId, fileMenu, 0 ); + createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load" + createMenu( FileCloseId, fileMenu, 0 ); + createMenu( separator(), fileMenu, -1, 0 ); + createMenu( FileSaveId, fileMenu, 0 ); createMenu( FileSaveAsId, fileMenu, 0 ); - createMenu( separator(), fileMenu, -1, 0 ); + createMenu( separator(), fileMenu, -1, 0 ); - createMenu( separator(), fileMenu ); - createMenu( FileExitId, fileMenu ); + createMenu( separator(), fileMenu ); + createMenu( FileExitId, fileMenu ); - createMenu( EditCopyId, editMenu ); + createMenu( EditCopyId, editMenu ); createMenu( EditPasteId, editMenu ); createMenu( separator(), editMenu ); - createMenu( ViewWindowsId, viewMenu ); + createMenu( ViewWindowsId, viewMenu ); createMenu( ViewStatusBarId, viewMenu ); - createMenu( separator(), viewMenu ); + createMenu( separator(), viewMenu ); createMenu( HelpAboutId, helpMenu ); createMenu( separator(), helpMenu ); @@ -547,8 +547,8 @@ void STD_Application::setEditEnabled( bool theEnable ) for ( int i = EditCopyId; i <= EditPasteId; i++ ) { - mMgr->setShown( i, myEditEnabled ); - tMgr->setShown( i, myEditEnabled ); + mMgr->setShown( mMgr->actionId(action(i)), myEditEnabled ); + tMgr->setShown( tMgr->actionId(action(i)), myEditEnabled ); } } diff --git a/src/STD/STD_Application.h b/src/STD/STD_Application.h index c8e3b4ad5..cd63268bd 100755 --- a/src/STD/STD_Application.h +++ b/src/STD/STD_Application.h @@ -120,9 +120,19 @@ private slots: virtual void onViewManagerActivated( SUIT_ViewManager* ); protected: - enum { FileNewId, FileOpenId, FileCloseId, FileSaveId, FileSaveAsId, - FileExitId, EditCutId, EditCopyId, EditPasteId, ViewStatusBarId, - NewWindowId, HelpAboutId, ViewWindowsId, FileLoadId, UserID }; + enum { MenuFileId = 1, + MenuViewId = 2, + MenuEditId = 3, + MenuHelpId = 7 + }; + + enum { FileNewId, FileOpenId, FileLoadId, FileCloseId, + FileSaveId, FileSaveAsId, FileExitId, + ViewStatusBarId, ViewWindowsId, NewWindowId, + EditCutId, EditCopyId, EditPasteId, + HelpAboutId, + UserID + }; protected: virtual void createActions(); diff --git a/src/STD/STD_MDIDesktop.cxx b/src/STD/STD_MDIDesktop.cxx index aec25bb59..214e8a767 100755 --- a/src/STD/STD_MDIDesktop.cxx +++ b/src/STD/STD_MDIDesktop.cxx @@ -183,7 +183,7 @@ void STD_MDIDesktop::createActions() if ( !mMgr ) return; - int winMenuId = mMgr->insert( tr( "MEN_DESK_WINDOW" ), -1, 100 ); + int winMenuId = mMgr->insert( tr( "MEN_DESK_WINDOW" ), -1, 100, MenuWindowId ); mMgr->insert( myWorkspaceAction, winMenuId, -1 ); mMgr->insert( QtxActionMenuMgr::separator(), winMenuId, -1 ); } diff --git a/src/STD/STD_MDIDesktop.h b/src/STD/STD_MDIDesktop.h index 25ec9cb08..e61f5c3d5 100755 --- a/src/STD/STD_MDIDesktop.h +++ b/src/STD/STD_MDIDesktop.h @@ -37,6 +37,7 @@ class STD_EXPORT STD_MDIDesktop: public SUIT_Desktop Q_OBJECT public: + enum { MenuWindowId = 6 }; enum { Cascade, Tile, HTile, VTile }; public: diff --git a/src/STD/STD_TabDesktop.cxx b/src/STD/STD_TabDesktop.cxx index 24dfd5ccf..5fdfce584 100644 --- a/src/STD/STD_TabDesktop.cxx +++ b/src/STD/STD_TabDesktop.cxx @@ -177,7 +177,7 @@ void STD_TabDesktop::createActions() if ( !mMgr ) return; - int winMenuId = mMgr->insert( tr( "MEN_DESK_WINDOW" ), -1, 100 ); + int winMenuId = mMgr->insert( tr( "MEN_DESK_WINDOW" ), -1, 100, MenuWindowId ); mMgr->insert( myWorkstackAction, winMenuId, -1 ); mMgr->insert( QtxActionMenuMgr::separator(), winMenuId, -1 ); } diff --git a/src/STD/STD_TabDesktop.h b/src/STD/STD_TabDesktop.h index f3b1d1282..c91b6e08e 100644 --- a/src/STD/STD_TabDesktop.h +++ b/src/STD/STD_TabDesktop.h @@ -38,6 +38,7 @@ class STD_EXPORT STD_TabDesktop: public SUIT_Desktop Q_OBJECT public: + enum { MenuWindowId = 6 }; enum { VSplit, HSplit }; public: diff --git a/src/SUIT/SUIT_Application.cxx b/src/SUIT/SUIT_Application.cxx index f187bfabd..bf0daebe6 100755 --- a/src/SUIT/SUIT_Application.cxx +++ b/src/SUIT/SUIT_Application.cxx @@ -186,8 +186,9 @@ int SUIT_Application::createTool( QAction* a, const int tBar, const int id, cons if ( !desktop() || !desktop()->toolMgr() ) return -1; - int regId = desktop()->toolMgr()->registerAction( a, id ); - return desktop()->toolMgr()->insert( regId, tBar, idx ); + int regId = registerAction( id, a ); + int intId = desktop()->toolMgr()->insert( a, tBar, idx ); + return intId != -1 ? regId : -1; } int SUIT_Application::createTool( QAction* a, const QString& tBar, const int id, const int idx ) @@ -195,7 +196,9 @@ int SUIT_Application::createTool( QAction* a, const QString& tBar, const int id, if ( !desktop() || !desktop()->toolMgr() ) return -1; - return desktop()->toolMgr()->insert( a, tBar, idx ); + int regId = registerAction( id, a ); + int intId = desktop()->toolMgr()->insert( a, tBar, idx ); + return intId != -1 ? regId : -1; } int SUIT_Application::createTool( const int id, const int tBar, const int idx ) @@ -203,7 +206,8 @@ int SUIT_Application::createTool( const int id, const int tBar, const int idx ) if ( !desktop() || !desktop()->toolMgr() ) return -1; - return desktop()->toolMgr()->insert( id, tBar, idx ); + int intId = desktop()->toolMgr()->insert( action( id ), tBar, idx ); + return intId != -1 ? id : -1; } int SUIT_Application::createTool( const int id, const QString& tBar, const int idx ) @@ -211,7 +215,8 @@ int SUIT_Application::createTool( const int id, const QString& tBar, const int i if ( !desktop() || !desktop()->toolMgr() ) return -1; - return desktop()->toolMgr()->insert( id, tBar, idx ); + int intId = desktop()->toolMgr()->insert( action( id ), tBar, idx ); + return intId != -1 ? id : -1; } int SUIT_Application::createMenu( const QString& subMenu, const int menu, @@ -220,7 +225,7 @@ int SUIT_Application::createMenu( const QString& subMenu, const int menu, if ( !desktop() || !desktop()->menuMgr() ) return -1; - return desktop()->menuMgr()->insert( subMenu, menu, group, index ); + return desktop()->menuMgr()->insert( subMenu, menu, group, id, index ); } int SUIT_Application::createMenu( const QString& subMenu, const QString& menu, @@ -229,7 +234,7 @@ int SUIT_Application::createMenu( const QString& subMenu, const QString& menu, if ( !desktop() || !desktop()->menuMgr() ) return -1; - return desktop()->menuMgr()->insert( subMenu, menu, group, index ); + return desktop()->menuMgr()->insert( subMenu, menu, group, id, index ); } int SUIT_Application::createMenu( QAction* a, const int menu, const int id, const int group, const int index ) @@ -237,8 +242,9 @@ int SUIT_Application::createMenu( QAction* a, const int menu, const int id, cons if ( !a || !desktop() || !desktop()->menuMgr() ) return -1; - int regId = desktop()->menuMgr()->registerAction( a, id ); - return desktop()->menuMgr()->insert( regId, menu, group, index ); + int regId = registerAction( id, a ); + int intId = desktop()->menuMgr()->insert( a, menu, group, index ); + return intId != -1 ? regId : -1; } int SUIT_Application::createMenu( QAction* a, const QString& menu, const int id, const int group, const int index ) @@ -246,8 +252,9 @@ int SUIT_Application::createMenu( QAction* a, const QString& menu, const int id, if ( !a || !desktop() || !desktop()->menuMgr() ) return -1; - int regId = desktop()->menuMgr()->registerAction( a, id ); - return desktop()->menuMgr()->insert( regId, menu, group, index ); + int regId = registerAction( id, a ); + int intId = desktop()->menuMgr()->insert( a, menu, group, index ); + return intId != -1 ? regId : -1; } int SUIT_Application::createMenu( const int id, const int menu, const int group, const int index ) @@ -255,7 +262,8 @@ int SUIT_Application::createMenu( const int id, const int menu, const int group, if ( !desktop() || !desktop()->menuMgr() ) return -1; - return desktop()->menuMgr()->insert( id, menu, group, index ); + int intId = desktop()->menuMgr()->insert( action( id ), menu, group, index ); + return intId != -1 ? id : -1; } int SUIT_Application::createMenu( const int id, const QString& menu, const int group, const int index ) @@ -263,7 +271,8 @@ int SUIT_Application::createMenu( const int id, const QString& menu, const int g if ( !desktop() || !desktop()->menuMgr() ) return -1; - return desktop()->menuMgr()->insert( id, menu, group, index ); + int intId = desktop()->menuMgr()->insert( action( id ), menu, group, index ); + return intId != -1 ? id : -1; } void SUIT_Application::setMenuShown( QAction* a, const bool on ) @@ -302,31 +311,21 @@ void SUIT_Application::setActionShown( const int id, const bool on ) QAction* SUIT_Application::action( const int id ) const { - SUIT_Application* that = (SUIT_Application*)this; - SUIT_Desktop* desk = that->desktop(); - if ( !desk ) - return 0; - QAction* a = 0; - if ( desk->menuMgr() ) - a = desk->menuMgr()->action( id ); - if ( !a && desk->toolMgr() ) - a = desk->toolMgr()->action( id ); + if ( myActionMap.contains( id ) ) + a = myActionMap[id]; return a; } int SUIT_Application::actionId( const QAction* a ) const { - SUIT_Application* that = (SUIT_Application*)this; - SUIT_Desktop* desk = that->desktop(); - if ( !desk ) - return 0; - int id = -1; - if ( desk->menuMgr() ) - id = desk->menuMgr()->actionId( a ); - if ( id == -1 && desk->toolMgr() ) - id = desk->toolMgr()->actionId( a ); + for ( QMap::ConstIterator it = myActionMap.begin(); + it != myActionMap.end() && id == -1; + ++it ) { + if ( it.data() == a ) + id = it.key(); + } return id; } @@ -345,13 +344,27 @@ QAction* SUIT_Application::createAction( const int id, const QString& text, cons return a; } -void SUIT_Application::registerAction( const int id, QAction* a ) +int SUIT_Application::registerAction( const int id, QAction* a ) { + int ident = actionId( a ); + if ( ident != -1 ) + return ident; + + static int generatedId = -1; + ident = id == -1 ? --generatedId : id; + + if ( action( ident ) ) + qWarning( "Action registration id is already in use: %d", ident ); + + myActionMap.insert( ident, a ); + if ( desktop() && desktop()->menuMgr() ) - desktop()->menuMgr()->registerAction( a, id ); + desktop()->menuMgr()->registerAction( a ); if ( desktop() && desktop()->toolMgr() ) - desktop()->toolMgr()->registerAction( a, id ); + desktop()->toolMgr()->registerAction( a ); + + return ident; } QAction* SUIT_Application::separator() diff --git a/src/SUIT/SUIT_Application.h b/src/SUIT/SUIT_Application.h index b630177e6..5bab83a14 100755 --- a/src/SUIT/SUIT_Application.h +++ b/src/SUIT/SUIT_Application.h @@ -146,7 +146,7 @@ protected: static QAction* separator(); QAction* action( const int ) const; int actionId( const QAction* ) const; - void registerAction( const int, QAction* ); + int registerAction( const int, QAction* ); QAction* createAction( const int, const QString&, const QIconSet&, const QString&, const QString&, const int, QObject* = 0, const bool = false, QObject* = 0, const char* = 0 ); @@ -157,6 +157,7 @@ protected slots: private: SUIT_Study* myStudy; SUIT_Desktop* myDesktop; + QMap myActionMap; QLabel* myStatusLabel; }; diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index 76cabcd3f..a3ab2a9a1 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -145,7 +145,7 @@ void SalomeApp_Application::createActions() createMenu( PropertiesId, fileMenu, 10, -1 ); createMenu( separator(), fileMenu, -1, 15, -1 ); - int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, -1, 50 ); + int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 ); createMenu( CatalogGenId, toolsMenu, 10, -1 ); createMenu( RegDisplayId, toolsMenu, 10, -1 ); createMenu( separator(), toolsMenu, -1, 15, -1 ); diff --git a/src/SalomeApp/SalomeApp_Application.h b/src/SalomeApp/SalomeApp_Application.h index 1ea58679e..2d324973b 100644 --- a/src/SalomeApp/SalomeApp_Application.h +++ b/src/SalomeApp/SalomeApp_Application.h @@ -45,6 +45,7 @@ class SALOMEAPP_EXPORT SalomeApp_Application : public LightApp_Application Q_OBJECT public: + enum { MenuToolsId = 5 }; enum { DumpStudyId = LightApp_Application::UserID, LoadScriptId, PropertiesId, CatalogGenId, RegDisplayId, SaveGUIStateId, UserID }; -- 2.39.2