From 32958e0de9d6fa70b4eabb9309211406305e3a1a Mon Sep 17 00:00:00 2001 From: stv Date: Thu, 15 Jun 2017 14:26:56 +0300 Subject: [PATCH] Improve Action managers for case with actions visibility change --- src/Qtx/Qtx.cxx | 39 ++++++++++++++++++++---------------- src/Qtx/QtxActionMenuMgr.cxx | 33 +++++++++++++++++++++++++----- src/Qtx/QtxActionMenuMgr.h | 1 + src/Qtx/QtxActionMgr.cxx | 29 ++++++++++++++++++++++++++- src/Qtx/QtxActionMgr.h | 2 ++ 5 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/Qtx/Qtx.cxx b/src/Qtx/Qtx.cxx index d596874ce..09e879e34 100755 --- a/src/Qtx/Qtx.cxx +++ b/src/Qtx/Qtx.cxx @@ -277,26 +277,31 @@ void Qtx::simplifySeparators( QWidget* wid, const bool recursive ) if ( items.isEmpty() ) return; - QList toRemove; - for ( int i = 1; i < items.count(); i++ ) + bool action = false; + for ( int i = 0; i < items.count(); i++ ) { - if ( items[i]->isSeparator() && items[i - 1]->isSeparator() ) - toRemove.append( items[i] ); - - if ( recursive && items[i]->menu() ) - simplifySeparators( items[i]->menu(), recursive ); + QAction* a = items[i]; + if ( a->isSeparator() ) { + a->setVisible(action); + action = false; + } + else if ( a->isVisible() ) { + action = true; + if ( recursive && a->menu() ) + simplifySeparators( a->menu(), recursive ); + } } - for ( QList::iterator it = toRemove.begin(); it != toRemove.end(); ++it ) - wid->removeAction( *it ); - - items = wid->actions(); - if ( !items.isEmpty() && items[0]->isSeparator() ) - wid->removeAction( items[0] ); - - items = wid->actions(); - if ( !items.isEmpty() && items[items.count() - 1]->isSeparator() ) - wid->removeAction( items[items.count() - 1] ); + action = false; + for ( int i = items.count() - 1; i > 0; i-- ) { + QAction* a = items[i]; + if ( a->isSeparator() ) { + a->setVisible(action); + action = false; + } + else if ( a->isVisible() ) + action = true; + } } /*! diff --git a/src/Qtx/QtxActionMenuMgr.cxx b/src/Qtx/QtxActionMenuMgr.cxx index a4972a755..54704d0c7 100644 --- a/src/Qtx/QtxActionMenuMgr.cxx +++ b/src/Qtx/QtxActionMenuMgr.cxx @@ -874,8 +874,6 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo if ( !mw ) return; - bool filled = checkWidget( mw ); - // first remove all own actions and collect foreign ones QMap< QAction*, QList > foreign; QAction* a; @@ -966,13 +964,14 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo 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 ) ) + if ( updParent && node->parent ) { updateMenu( node->parent, false ); + } } /*! @@ -1019,7 +1018,12 @@ bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const if ( !wid ) return false; - return !wid->actions().isEmpty(); + bool res = false; + QList lst = wid->actions(); + for ( QList::const_iterator it = lst.begin(); it != lst.end() && !res; ++it ) { + res = !(*it)->isSeparator() && (*it)->isVisible(); + } + return res; } /*! @@ -1200,6 +1204,25 @@ void QtxActionMenuMgr::triggerUpdate( const int id, const bool rec ) QtxActionMgr::triggerUpdate(); } +/*! + \brief Called when action is changed. + + Schedule delayed update for parent menu of changed action. +*/ +void QtxActionMenuMgr::actionChanged( int id ) +{ + NodeList aNodes; + find( id, aNodes ); + + for ( NodeList::iterator it = aNodes.begin(); it != aNodes.end(); ++it ) + { + MenuNode* node = *it; + if ( node->visible ) { + triggerUpdate( node->parent ? node->parent->id : myRoot->id, false ); + } + } +} + /*! \brief Called when delayed content update is performed. diff --git a/src/Qtx/QtxActionMenuMgr.h b/src/Qtx/QtxActionMenuMgr.h index fd99a0d10..dcd3f2967 100644 --- a/src/Qtx/QtxActionMenuMgr.h +++ b/src/Qtx/QtxActionMenuMgr.h @@ -132,6 +132,7 @@ protected: void updateMenu( MenuNode* = 0, const bool = true, const bool = true ); virtual void internalUpdate(); virtual void updateContent(); + virtual void actionChanged( int ); private: bool ownAction( QAction*, MenuNode* ) const; diff --git a/src/Qtx/QtxActionMgr.cxx b/src/Qtx/QtxActionMgr.cxx index 528ae8349..9fb7bb6ad 100644 --- a/src/Qtx/QtxActionMgr.cxx +++ b/src/Qtx/QtxActionMgr.cxx @@ -156,6 +156,8 @@ int QtxActionMgr::registerAction( QAction* a, const int userId ) myActions.insert( theId, a ); + connect( a, SIGNAL( changed() ), this, SLOT( onActionChanged() ) ); + return theId; } @@ -166,8 +168,11 @@ int QtxActionMgr::registerAction( QAction* a, const int userId ) */ void QtxActionMgr::unRegisterAction( const int id ) { - if( contains( id ) ) + if ( contains( id ) ) { + disconnect( myActions[id], SIGNAL( changed() ), + this, SLOT( onActionChanged() ) ); myActions.remove( id ); + } } /*! @@ -419,6 +424,13 @@ void QtxActionMgr::updateContent() { } +/*! + \brief Internal action changing response operation. +*/ +void QtxActionMgr::actionChanged( int ) +{ +} + /*! \brief Called when delayed update is performed (via timer event). @@ -430,6 +442,21 @@ void QtxActionMgr::onUpdateContent() updateContent(); } +/*! + \brief Called when one of the registered actions changed. + + Calls virtual method actionChanged() which can be redefined in the + subclasses to customize reaction on this. +*/ +void QtxActionMgr::onActionChanged() +{ + QAction* a = ::qobject_cast( sender() ); + + int id = actionId( a ); + if ( id != -1 ) + actionChanged( id ); +} + /*! \class QtxActionMgr::Reader \brief Generic actions description files reader class. diff --git a/src/Qtx/QtxActionMgr.h b/src/Qtx/QtxActionMgr.h index a1a0e6635..7cb0a6e96 100644 --- a/src/Qtx/QtxActionMgr.h +++ b/src/Qtx/QtxActionMgr.h @@ -88,8 +88,10 @@ protected: void triggerUpdate(); virtual void updateContent(); + virtual void actionChanged( int ); private slots: + void onActionChanged(); void onUpdateContent(); private: -- 2.39.2