From 6c9ce755c005690dc421ef945f703e51d779af84 Mon Sep 17 00:00:00 2001 From: stv Date: Tue, 14 Nov 2006 13:38:15 +0000 Subject: [PATCH] no message --- src/Qtx/Qtx.cxx | 73 +++- src/Qtx/Qtx.h | 20 +- src/Qtx/QtxAction.cxx | 214 +++++++++-- src/Qtx/QtxAction.h | 20 +- src/Qtx/QtxActionMenuMgr.cxx | 717 ++++++++++++++++++++++++++++++----- src/Qtx/QtxActionMenuMgr.h | 54 ++- src/Qtx/QtxActionMgr.cxx | 206 +++++++++- src/Qtx/QtxActionMgr.h | 32 +- src/Qtx/QtxActionToolMgr.cxx | 242 +++++++++++- src/Qtx/QtxActionToolMgr.h | 25 +- src/Qtx/QtxLogoMgr.cxx | 2 +- src/Qtx/QtxResourceMgr.cxx | 2 +- 12 files changed, 1439 insertions(+), 168 deletions(-) diff --git a/src/Qtx/Qtx.cxx b/src/Qtx/Qtx.cxx index 8201c34d2..6795c5277 100755 --- a/src/Qtx/Qtx.cxx +++ b/src/Qtx/Qtx.cxx @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: Qtx.cxx // Author: Sergey TELKOV @@ -182,24 +182,34 @@ void Qtx::simplifySeparators( QToolBar* toolbar ) QObjectList delList; bool isPrevSep = true; + QObject* lastVis = 0; // last visible for ( QObjectListIt it( *objList ); it.current(); ++it ) { - bool isSep = it.current()->isA( "QToolBarSeparator" ); + QObject* obj = it.current(); + /*/ + if ( !obj || !obj->isWidgetType() || !((QWidget*)obj)->isVisibleTo( toolbar ) ) + continue; + bool isSep = obj->isA( "QToolBarSeparator" ); + */ + if ( !obj || !obj->isWidgetType() ) + continue; + bool isSep = obj->isA( "QToolBarSeparator" ); + if ( !isSep && !((QWidget*)obj)->isVisibleTo( toolbar ) ) + continue; if ( isPrevSep && isSep ) - delList.append( it.current() ); + delList.append( obj ); + else + { isPrevSep = isSep; + lastVis = obj; + } } + // remove last visible separator + if ( lastVis && lastVis->isA( "QToolBarSeparator" ) ) + delList.append( lastVis ); for ( QObjectListIt itr( delList ); itr.current(); ++itr ) delete itr.current(); - - if ( toolbar->children() && !toolbar->children()->isEmpty() && - toolbar->children()->getFirst()->isA( "QToolBarSeparator" ) ) - delete toolbar->children()->getFirst(); - - if ( toolbar->children() && !toolbar->children()->isEmpty() && - toolbar->children()->getLast()->isA( "QToolBarSeparator" ) ) - delete toolbar->children()->getLast(); } /*! @@ -563,11 +573,11 @@ int Qtx::rgbSet( const int r, const int g, const int b ) Name: rgbSet [static public] Desc: Unpack the specified integer RGB set into the color. */ -void Qtx::rgbSet( const int rgb, QColor& c ) +QColor Qtx::rgbSet( const int rgb ) { int r, g, b; rgbSet( rgb, r, g, b ); - c = QColor( r, g, b ); + return QColor( r, g, b ); } /*! @@ -660,6 +670,36 @@ QPixmap Qtx::grayscale( const QPixmap& pix ) return res; } +/*! + Name: transparentImage [static public] + Desc: Create transparent image with specified width \aw, height \ah and color depth \ad. +*/ +QImage Qtx::transparentImage( const int w, const int h, const int d ) +{ + QImage img; + if ( img.create( w, h, d < 0 ? /*QPixmap::defaultDepth()*/32 : d ) ) + { + img.setAlphaBuffer( true ); + for ( int i = 0; i < img.height(); i++ ) + for ( int j = 0; j < img.width(); j++ ) + img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) ); + } + return img; +} + +/*! + Name: transparentPixmap [static public] + Desc: Create transparent pixmap with specified width \aw, height \ah and color depth \ad. +*/ +QPixmap Qtx::transparentPixmap( const int w, const int h, const int d ) +{ + QPixmap pix; + QImage img = transparentImage( w, h, d ); + if ( !img.isNull() ) + pix.convertFromImage( img ); + return pix; +} + /*! Name: composite [static public] Desc: Create composite pixmap. Pixmap 'pix' draws over pixmap 'dest' with coordinates @@ -675,12 +715,7 @@ QPixmap Qtx::composite( const QPixmap& pix, const int x, const int y, const QPix int height = QMAX( pix.height() + y, dest.height() ); QPixmap res( width, height ); - - QImage img( width, height, 32 ); - img.setAlphaBuffer( true ); - for ( int i = 0; i < img.height(); i++ ) - for ( int j = 0; j < img.width(); j++ ) - img.setPixel( j, i, qRgba( 0, 0, 0, 0 ) ); + QImage img = transparentImage( width, height, 32 ); QPainter p; p.begin( &res ); diff --git a/src/Qtx/Qtx.h b/src/Qtx/Qtx.h index 864441bed..1818cf0fc 100755 --- a/src/Qtx/Qtx.h +++ b/src/Qtx/Qtx.h @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: Qtx.h // Author: Sergey TELKOV @@ -46,7 +46,6 @@ #define INCLUDE_MENUITEM_DEF #endif -#include #include #ifndef QT_VERSION @@ -69,7 +68,11 @@ #endif #endif -class QImage; +#include +#include +#include +#include + class QObject; class QString; class QWidget; @@ -89,6 +92,10 @@ typedef QValueList QIntList; typedef QValueList QShortList; typedef QValueList QDoubleList; +/*! + \class Qtx + \brief Set of auxiliary static methods +*/ class QTX_EXPORT Qtx : public Qt { public: @@ -125,7 +132,7 @@ public: static int rgbSet( const QColor& ); static int rgbSet( const int, const int, const int ); - static void rgbSet( const int, QColor& ); + static QColor rgbSet( const int ); static void rgbSet( const int, int&, int&, int& ); static QColor scaleColor( const int, const int, const int ); @@ -133,8 +140,9 @@ public: static QImage grayscale( const QImage& ); static QPixmap grayscale( const QPixmap& ); - static QPixmap composite( const QPixmap&, const int, const int, - const QPixmap& = QPixmap() ); + static QImage transparentImage( const int, const int, const int = -1 ); + static QPixmap transparentPixmap( const int, const int, const int = -1 ); + static QPixmap composite( const QPixmap&, const int, const int, const QPixmap& = QPixmap() ); }; #endif diff --git a/src/Qtx/QtxAction.cxx b/src/Qtx/QtxAction.cxx index 9fafdb7ac..0dfba4cda 100755 --- a/src/Qtx/QtxAction.cxx +++ b/src/Qtx/QtxAction.cxx @@ -14,13 +14,14 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxAction.cxx // Author: Sergey TELKOV #include "QtxAction.h" +#include #include /*! @@ -81,7 +82,41 @@ QtxAction::~QtxAction() bool QtxAction::addTo( QWidget* w ) { - return QAction::addTo( w ); + if ( !w->inherits( "QMenuBar" ) ) + return QAction::addTo( w ); + + // --- Add action to the QMenuBar --- + // n.b. currently for the actions inserted to the menu bar + // the following properties are not supported: + // * tooltips + // * what's this info + // * toggle mode + QMenuBar* mb = (QMenuBar*)w; + if ( myMenuIds.contains( w ) ) + return false; // already added + + QMenuData* mData = mb; + int idx = mData->count(); + while ( idx > 0 ) + { + QMenuData* md = 0; + QMenuItem* mItem = mb->findItem( mb->idAt( idx - 1 ), &md ); + if ( md == mData && mItem && mItem->isSeparator() && mItem->widget() && qstrcmp( mItem->widget()->name(), "qt_maxtools" ) ) + idx--; + else + break; + } + + if ( name() == "qt_separator_action" ) // separator + myMenuIds.insert( w, mb->insertSeparator( idx ) ); + else if ( iconSet().isNull() ) // has no icon + myMenuIds.insert( w, mb->insertItem( menuText(), this, SIGNAL( activated() ), accel(), -1, idx ) ); + else // has icon + myMenuIds.insert( w, mb->insertItem( iconSet(), menuText(), this, SIGNAL( activated() ), accel(), -1, idx ) ); + + mb->setItemEnabled( myMenuIds[w], isEnabled() ); + mb->setItemVisible( myMenuIds[w], isVisible() ); + return true; } /*! @@ -91,30 +126,33 @@ bool QtxAction::addTo( QWidget* w ) successfully and false otherwise. */ -bool QtxAction::addTo( QWidget* w, int index ) +bool QtxAction::addTo( QWidget* w, const int index ) { if ( !addTo( w ) ) return false; if ( w->inherits( "QPopupMenu" ) ) { + // --- Add action to the QPopupMenu --- QPopupMenu* popup = (QPopupMenu*)w; - if ( index < (int)popup->count() - 1 ) + if ( index >= 0 && index < (int)popup->count() - 1 ) { int id = popup->idAt( popup->count() - 1 ); if ( id != -1 ) { QMenuItem* item = popup->findItem( id ); - if ( item && item->isSeparator() ) - { + if ( item && item->isSeparator() ) + { popup->removeItem( id ); popup->insertSeparator( index ); } - else - { + else + { QPopupMenu* p = item ? item->popup() : 0; int accel = popup->accel( id ); bool isOn = popup->isItemEnabled( id ); + bool isVisible = popup->isItemVisible( id ); + bool isChecked = popup->isItemChecked( id ); QString text = popup->text( id ); QIconSet icon; if ( popup->iconSet( id ) ) @@ -122,65 +160,183 @@ bool QtxAction::addTo( QWidget* w, int index ) popup->removeItem( id ); int pos; if ( icon.isNull() ) - if ( p ) + { + if ( p ) pos = popup->indexOf( popup->insertItem( text, p, id, index ) ); else pos = popup->indexOf( popup->insertItem( text, id, index ) ); + } else + { if ( p ) pos = popup->indexOf( popup->insertItem( icon, text, p, id, index ) ); else pos = popup->indexOf( popup->insertItem( icon, text, p, id, index ) ); + } popup->setId( pos, id ); popup->setAccel( accel, id ); popup->setItemEnabled( id, isOn ); + popup->setItemVisible( id, isVisible ); + popup->setItemChecked( id, isChecked ); + if ( !whatsThis().isEmpty() ) + popup->setWhatsThis( id, whatsThis() ); if ( !p ) popup->connectItem( id, this, SLOT( internalActivation() ) ); } } } } - + else if ( w->inherits( "QMenuBar" ) ) + { + // --- Add action to the QMenuBar --- + QMenuBar* mb = (QMenuBar*)w; + if ( index >= 0 && index < (int)mb->count() - 1 ) + { + int id = mb->idAt( mb->count() - 1 ); + if ( id != -1 ) + { + QMenuItem* item = mb->findItem( id ); + if ( item && item->isSeparator() ) + { + mb->removeItem( id ); + mb->insertSeparator( index ); + } + else + { + QPopupMenu* p = item ? item->popup() : 0; + int accel = mb->accel( id ); + bool isOn = mb->isItemEnabled( id ); + bool isVisible = mb->isItemVisible( id ); + QString text = mb->text( id ); + QIconSet icon; + if ( mb->iconSet( id ) ) + icon = *mb->iconSet( id ); + mb->removeItem( id ); + int pos; + if ( icon.isNull() ) + { + if ( p ) + pos = mb->indexOf( mb->insertItem( text, p, id, index ) ); + else + pos = mb->indexOf( mb->insertItem( text, id, index ) ); + } + else + { + if ( p ) + pos = mb->indexOf( mb->insertItem( icon, text, p, id, index ) ); + else + pos = mb->indexOf( mb->insertItem( icon, text, p, id, index ) ); + } + mb->setId( pos, id ); + mb->setAccel( accel, id ); + mb->setItemEnabled( id, isOn ); + mb->setItemVisible( id, isVisible ); + if ( !p ) + mb->connectItem( id, this, SIGNAL( activated() ) ); + } + } + } + } return true; } +/*! + Name: removeFrom [virtual public] + Desc: Removes this action from widget. Returns true if the action was removed + successfully and false otherwise. +*/ + +bool QtxAction::removeFrom( QWidget* w ) +{ + bool res = false; + // check if widget is QMenuBar + if ( w->inherits( "QMenuBar" ) ) + { + QMenuBar* mb = (QMenuBar*)w; + if ( myMenuIds.find( w ) != myMenuIds.end() ) + { + mb->removeItem( myMenuIds[ w ] ); + myMenuIds.remove( w ); + res = true; + } + } + else + res = QAction::removeFrom( w ); + return res; +} + /*! Name: setPopup [virtual public] Desc: Set or unset the sub popup menu for item with specified id in the given popup. */ -void QtxAction::setPopup( QPopupMenu* popup, const int id, QPopupMenu* subPopup ) const +void QtxAction::setPopup( QWidget* w, const int id, QPopupMenu* subPopup ) const { - if ( !popup ) + if ( !w ) return; + QMenuData* pmd = 0; + + if ( w->inherits( "QPopupMenu" ) ) + pmd = ::qt_cast( w ); + else if ( w->inherits( "QMenuBar" ) ) + pmd = ::qt_cast( w ); + + if ( !pmd ) + return; // bad widget + QMenuData* md = 0; - const QMenuData* pmd = popup; - QMenuItem* item = popup->findItem( id, &md ); + QMenuItem* item = pmd->findItem( id, &md ); if ( !item || md != pmd ) - return; + return; // item is not found QPopupMenu* oldPopup = item->popup(); if ( oldPopup == subPopup ) - return; + return; // popup is not changed - int accel = popup->accel( id ); - bool isOn = popup->isItemEnabled( id ); - QString text = popup->text( id ); + // get properties + int accel = pmd->accel( id ); + bool isOn = pmd->isItemEnabled( id ); + bool isVisible = pmd->isItemVisible( id ); + int pos = pmd->indexOf( id ); + QString text = pmd->text( id ); QIconSet icon; - if ( popup->iconSet( id ) ) - icon = *popup->iconSet( id ); - popup->removeItem( id ); + if ( pmd->iconSet( id ) ) + icon = *pmd->iconSet( id ); - int pos; - if ( icon.isNull() ) - pos = popup->indexOf( subPopup ? popup->insertItem( text, subPopup ) : popup->insertItem( text ) ); + // remove previous item + pmd->removeItem( id ); + + // add new item + if ( w->inherits( "QPopupMenu" ) ) + { + // --- QPopupMenu --- + QPopupMenu* popup = (QPopupMenu*)w; + if ( icon.isNull() ) + pos = popup->indexOf( subPopup ? popup->insertItem( text, subPopup, id, pos ) : + popup->insertItem( text, id, pos ) ); + else + pos = popup->indexOf( subPopup ? popup->insertItem( icon, text, subPopup, id, pos ) : + popup->insertItem( icon, text, id, pos ) ); + } else - pos = popup->indexOf( subPopup ? popup->insertItem( icon, text, subPopup ) : popup->insertItem( icon, text ) ); + { + // --- QMenuBar --- + QMenuBar* mb = (QMenuBar*)w; + if ( icon.isNull() ) + pos = mb->indexOf( subPopup ? mb->insertItem( text, subPopup, id, pos ) : + mb->insertItem( text, id, pos ) ); + else + pos = mb->indexOf( subPopup ? mb->insertItem( icon, text, subPopup, id, pos ) : + mb->insertItem( icon, text, id, pos ) ); + } - popup->setId( pos, id ); - popup->setAccel( accel, id ); - popup->setItemEnabled( id, isOn ); + // restore properties + pmd->setId( pos, id ); // for sure (if id < 0) + pmd->setAccel( accel, id ); + pmd->setItemEnabled( id, isOn ); + pmd->setItemVisible( id, isVisible ); + // delete old popup delete oldPopup; } diff --git a/src/Qtx/QtxAction.h b/src/Qtx/QtxAction.h index ffffcc4d8..d60568bf6 100755 --- a/src/Qtx/QtxAction.h +++ b/src/Qtx/QtxAction.h @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxAction.hxx // Author: Sergey TELKOV @@ -24,8 +24,13 @@ #include "Qtx.h" +#include #include +#ifdef WIN32 +#pragma warning ( disable:4251 ) +#endif + class QTX_EXPORT QtxAction : public QAction { Q_OBJECT @@ -37,10 +42,19 @@ public: virtual ~QtxAction(); virtual bool addTo( QWidget* ); - virtual bool addTo( QWidget*, int ); + virtual bool addTo( QWidget*, const int ); + + virtual bool removeFrom( QWidget* ); protected: - void setPopup( QPopupMenu*, const int, QPopupMenu* ) const; + void setPopup( QWidget*, const int, QPopupMenu* ) const; + +private: + QMap myMenuIds; }; +#ifdef WIN32 +#pragma warning ( default:4251 ) +#endif + #endif diff --git a/src/Qtx/QtxActionMenuMgr.cxx b/src/Qtx/QtxActionMenuMgr.cxx index 7782a7b57..aa49bd8bd 100644 --- a/src/Qtx/QtxActionMenuMgr.cxx +++ b/src/Qtx/QtxActionMenuMgr.cxx @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxActionMenuMgr.cxx // Author: Alexander SOLOVYEV, Sergey TELKOV @@ -31,6 +31,71 @@ #include #include #include +#include + +// VSR: Uncomment this #define in order to allow dynamic menus support +// (emit signals when popup menu is pre-activated) +// Currently this support is disabled. +//#define ENABLE_DYNAMIC_MENU + +/*! + Service functions + Level: Internal +*/ +namespace { + QValueList prepareIds( const QWidget* w ) + { + QValueList l; + const QMenuData* md = 0; + if ( w->inherits( "QMenuBar" ) ) + md = ::qt_cast( w ); + else if ( w->inherits( "QPopupMenu" ) ) + md = ::qt_cast( w ); + if ( md ) { + for ( uint i = 0; i < md->count(); i++ ) + l.append( md->idAt( i ) ); + } + return l; + } + + int getNewId( const QWidget* w, const QValueList& l, bool retId = true ) + { + const QMenuData* md = 0; + if ( w->inherits( "QMenuBar" ) ) + md = ::qt_cast( w ); + else if ( w->inherits( "QPopupMenu" ) ) + md = ::qt_cast( w ); + if ( md ) + { + for ( uint i = 0, j = 0; i < md->count() && j < l.count(); i++, j++ ) + if ( md->idAt( i ) != l[ j ] ) + return retId ? md->idAt( i ) : i; + if ( md->count() > l.count() ) + return retId ? md->idAt( md->count()-1 ) : md->count() - 1; + } + return -1; + } + + void dumpMenu( QWidget* w, bool before ) + { + if ( !w ) + return; + + QMenuData* md = 0; + if ( w->inherits( "QMenuBar" ) ) + md = ::qt_cast( w ); + else if ( w->inherits( "QPopupMenu" ) ) + md = ::qt_cast( w ); + + if ( !md ) + return; + + printf( ">>> start dump menu (%s) >>>\n", before ? "before" : "after" ); + for ( uint i = 0; i < md->count(); i++ ) + printf( "%d: %d: %s\n", i, md->idAt( i ), md->text( md->idAt( i ) ).latin1() ); + printf( "<<< end dump menu (%s) <<<\n", before ? "before" : "after" ); + } +}; /*! Class: QtxActionMenuMgr::MenuAction @@ -40,7 +105,7 @@ class QtxActionMenuMgr::MenuAction : public QtxAction { public: - MenuAction( const QString&, const QString&, QObject* ); + MenuAction( const QString&, const QString&, QObject*, const int = -1, const bool = false ); virtual ~MenuAction(); virtual bool addTo( QWidget* ); @@ -52,41 +117,82 @@ public: private: int myId; QPopupMenu* myPopup; + bool myEmptyEnabled; + QMap myIds; }; -QtxActionMenuMgr::MenuAction::MenuAction( const QString& text, const QString& menuText, QObject* parent ) +/*! + Constructor for menu action + \param text - description text + \param menutext - menu text + \param parent - parent object + \param id - integer identificator of action + \param allowEmpty - if it is true, it makes possible to add this action with empty popup to menu +*/ + +QtxActionMenuMgr::MenuAction::MenuAction( const QString& text, const QString& menuText, + QObject* parent, const int id, const bool allowEmpty ) : QtxAction( text, menuText, 0, parent ), -myId( -1 ), -myPopup( 0 ) +myId( id ), +myPopup( 0 ), +myEmptyEnabled( allowEmpty ) { myPopup = new QPopupMenu(); } +/*! + Destructor: deletes internal popup +*/ QtxActionMenuMgr::MenuAction::~MenuAction() { delete myPopup; } +/*! + Adds action to widget, for example, to popup menu or menu bar +*/ bool QtxActionMenuMgr::MenuAction::addTo( QWidget* w ) { - if ( myId != -1 || !w ) - return false; + if ( !w ) + return false; // bad widget if ( !w->inherits( "QPopupMenu" ) && !w->inherits( "QMenuBar" ) ) - return false; + return false; // not allowed widget type + + if ( myIds.find( w ) != myIds.end() ) + return false; // already added + + if ( !myPopup ) + return false; // bad own popup menu + + if ( !myEmptyEnabled && !myPopup->count() ) + return false; // not allowed empty menu - if ( w->inherits( "QPopupMenu" ) && QAction::addTo( w ) ) + if ( w->inherits( "QPopupMenu" ) ) { - QPopupMenu* pm = (QPopupMenu*)w; - myId = pm->idAt( pm->count() - 1 ); - setPopup( pm, myId, myPopup ); + QValueList l = prepareIds( w ); + int idx; + if ( QtxAction::addTo( w ) && ( idx = getNewId( w, l, false ) ) != -1 ) + { + QPopupMenu* pm = (QPopupMenu*)w; + myIds[ w ] = pm->idAt( idx ); + if ( myId != -1 ) + pm->setId( idx, myId ); + setPopup( pm, myId != -1 ? myId : myIds[ w ], myPopup ); + } } else if ( w->inherits( "QMenuBar" ) ) { - QMenuBar* mb = (QMenuBar*)w; - myId = iconSet().isNull() ? mb->insertItem( menuText(), myPopup ) : - mb->insertItem( iconSet(), menuText(), myPopup ); - mb->setItemEnabled( myId, isEnabled() ); + QValueList l = prepareIds( w ); + int idx; + if ( QtxAction::addTo( w ) && ( idx = getNewId( w, l, false ) ) != -1 ) + { + QMenuBar* mb = (QMenuBar*)w; + myIds[ w ] = mb->idAt( idx ); + if ( myId != -1 ) + mb->setId( idx, myId ); + setPopup( mb, myId != -1 ? myId : myIds[ w ], myPopup ); + } } else return false; @@ -94,20 +200,50 @@ bool QtxActionMenuMgr::MenuAction::addTo( QWidget* w ) return true; } +/*! + Removes action from widget, for example, from popup menu or menu bar +*/ bool QtxActionMenuMgr::MenuAction::removeFrom( QWidget* w ) { - if ( w->inherits( "QPopupMenu" ) && QAction::removeFrom( w ) ) - myId = -1; + if ( !w ) + return false; // bad widget + + if ( !w->inherits( "QPopupMenu" ) && !w->inherits( "QMenuBar" ) ) + return false; // not allowed widget type + + if ( myIds.find( w ) == myIds.end() ) + return false; // not yet added + + if ( w->inherits( "QPopupMenu" ) ) + { + if ( myId != -1 ) + { + QPopupMenu* pm = (QPopupMenu*)w; + int idx = pm->indexOf( myId ); + if ( idx != -1 ) + pm->setId( idx, myIds[ w ] ); + } + myIds.remove( w ); + return QtxAction::removeFrom( w );; + } else if ( w->inherits( "QMenuBar" ) ) { - QMenuBar* mb = (QMenuBar*)w; - mb->removeItem( myId ); - myId = -1; + if ( myId != -1 ) + { + QMenuBar* mb = (QMenuBar*)w; + int idx = mb->indexOf( myId ); + if ( idx != -1 ) + mb->setId( idx, myIds[ w ] ); + } + myIds.remove( w ); + return QtxAction::removeFrom( w ); } - - return myId == -1; + return false; } +/*! + \return internal popup of action +*/ QPopupMenu* QtxActionMenuMgr::MenuAction::popup() const { return myPopup; @@ -117,8 +253,6 @@ QPopupMenu* QtxActionMenuMgr::MenuAction::popup() const Class: QtxActionMenuMgr Level: Public */ - - QtxActionMenuMgr::QtxActionMenuMgr( QMainWindow* p ) : QtxActionMgr( p ), myMenu( p ? p->menuBar() : 0 ) @@ -126,10 +260,18 @@ myMenu( p ? p->menuBar() : 0 ) myRoot.id = -1; myRoot.group = -1; - if ( myMenu ) + if ( myMenu ) { connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); +#ifdef ENABLE_DYNAMIC_MENU + if ( myMenu->inherits( "QMenuBar" ) ) + connect( myMenu, SIGNAL( highlighted( int ) ), this, SLOT( onHighlighted( int ) ) ); +#endif + } } +/*! + Constructor +*/ QtxActionMenuMgr::QtxActionMenuMgr( QWidget* mw, QObject* p ) : QtxActionMgr( p ), myMenu( mw ) @@ -141,6 +283,9 @@ myMenu( mw ) connect( myMenu, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) ); } +/*! + Destructor +*/ QtxActionMenuMgr::~QtxActionMenuMgr() { for ( NodeListIterator it( myRoot.children ); it.current() && myMenu; ++it ) @@ -157,12 +302,23 @@ QtxActionMenuMgr::~QtxActionMenuMgr() delete itr.data(); } +/*! + \return whether menu item corresponding to action is visible + \param actId - identificator of action + \param place - identificator of some parent action +*/ bool QtxActionMenuMgr::isVisible( const int actId, const int place ) const { MenuNode* node = find( actId, place ); return node && node->visible; } +/*! + Sets visible state of action + \param actId - identificator of action + \param place - identificator of some parent action + \param v - visibility state +*/ void QtxActionMenuMgr::setVisible( const int actId, const int place, const bool v ) { MenuNode* node = find( actId, place ); @@ -170,16 +326,40 @@ void QtxActionMenuMgr::setVisible( const int actId, const int place, const bool node->visible = v; } +/*! + Insert action as children menu item + \param id - identificator of action + \param menus - few names of parent menu items, separated by '|'. It means sequence of menu items, + for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created. + \param group - group identificator + \param idx - index inside Qt menu +*/ int QtxActionMenuMgr::insert( const int id, const QString& menus, const int group, const int idx ) { return insert( id, QStringList::split( "|", menus ), group, idx ); } +/*! + Insert action as children menu item + \param a - action + \param menus - few names of parent menu items, separated by '|'. It means sequence of menu items, + for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created. + \param group - group identificator + \param idx - index inside Qt menu +*/ int QtxActionMenuMgr::insert( QAction* a, const QString& menus, const int group, const int idx ) { return insert( a, QStringList::split( "|", menus ), group, idx ); } +/*! + Insert action as children menu item + \param id - identificator of action + \param menus - list of names of parent menu items, separated by |. It means sequence of menu items, + for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created. + \param group - group identificator + \param idx - index inside Qt menu +*/ int QtxActionMenuMgr::insert( const int id, const QStringList& menus, const int group, const int idx ) { int pId = createMenu( menus, -1 ); @@ -189,6 +369,14 @@ int QtxActionMenuMgr::insert( const int id, const QStringList& menus, const int return insert( id, pId, group, idx ); } +/*! + Insert action as children menu item + \param a - action + \param menus - list of names of parent menu items. It means sequence of menu items, + for example "File|Edit" means File->Edit submenu. If submenu doesn't exist, it will be created. + \param group - group identificator + \param idx - index inside Qt menu +*/ int QtxActionMenuMgr::insert( QAction* a, const QStringList& menus, const int group, const int idx ) { int pId = createMenu( menus, -1 ); @@ -198,6 +386,13 @@ int QtxActionMenuMgr::insert( QAction* a, const QStringList& menus, const int gr return insert( a, pId, group, idx ); } +/*! + Insert action as children menu item + \param id - identificator of action + \param pId - identificator of action corresponding to parent menu item + \param group - group identificator + \param idx - index inside Qt menu +*/ int QtxActionMenuMgr::insert( const int id, const int pId, const int group, const int idx ) { if ( id == -1 ) @@ -209,106 +404,203 @@ 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 ); - updateMenu( pNode, false ); + triggerUpdate( pNode->id, false ); + return node->id; } +/*! + Insert action as children menu item + \param a - action + \param pId - identificator of action corresponding to parent menu item + \param group - group identificator + \param idx - index inside Qt menu +*/ int QtxActionMenuMgr::insert( QAction* a, const int pId, const int group, const int idx ) { return insert( registerAction( a ), pId, group, idx ); } -int QtxActionMenuMgr::insert( const QString& title, const int pId, const int group, const int idx ) +/*! + Create and insert action as children menu item + \return identificator of inserted action + \param title - menu text of action + \param pId - identificator of action corresponding to parent menu item + \param group - group identificator + \param id - identificator of new action + \param idx - index inside Qt menu + \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu +*/ +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 ); + int gid = (id == -1 || eNode ) ? generateId() : id; + + MenuAction* ma = new MenuAction( clearTitle( title ), title, this, gid, allowEmpty ); +#ifdef ENABLE_DYNAMIC_MENU + connect( ma->popup(), SIGNAL( highlighted( int ) ), this, SLOT( onHighlighted( int ) ) ); +#endif MenuNode* node = new MenuNode( pNode ); node->group = group; - node->id = myMenus.insert( generateId(), ma ).key(); + node->idx = idx; + node->id = myMenus.insert( gid, ma ).key(); - if ( idx < 0 || idx >= (int)pNode->children.count() ) pNode->children.append( node ); - else - pNode->children.insert( idx, node ); - updateMenu( pNode, false ); + triggerUpdate( pNode->id, false ); return node->id; } -int QtxActionMenuMgr::insert( const QString& title, const QString& menus, const int group, const int idx ) +/*! + Create and insert action as children menu item + \return identificator of inserted action + \param title - menu text of action + \param menus - string list of parents' menu texts, separated by | + \param group - group identificator + \param id - identificator of new action + \param idx - index inside Qt menu + \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu +*/ +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 ) +/*! + Create and insert action as children menu item + \return identificator of inserted action + \param title - menu text of action + \param menus - list of parents menu items + \param group - group identificator + \param id - identificator of new action + \param idx - index inside Qt menu + \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu +*/ +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 ) +/*! + Create and append action as last children + \return identificator of inserted action + \param title - menu text of action + \param pId - id of action corresponding to parent menu item + \param group - group identificator + \param id - identificator of new action + \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu +*/ +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 ); } +/*! + Create and append action as last children + \return identificator of inserted action + \param id - identificator of existing action + \param pId - id of action corresponding to parent menu item + \param group - group identificator +*/ int QtxActionMenuMgr::append( const int id, const int pId, const int group ) { return insert( id, pId, group ); } +/*! + Create and append action as last children + \return identificator of inserted action + \param a - action + \param pId - id of action corresponding to parent menu item + \param group - group identificator +*/ 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 ) +/*! + Create and insert action as first children + \return identificator of inserted action + \param title - menu text of action + \param pId - id of action corresponding to parent menu item + \param group - group identificator + \param id - identificator of new action + \param allowEmpty - indicates, that it is possible to add this action with empty popup menu to other menu +*/ +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 ); } +/*! + Create and insert action as last children + \return identificator of inserted action + \param id - identificator of existing action + \param pId - id of action corresponding to parent menu item + \param group - group identificator +*/ int QtxActionMenuMgr::prepend( const int id, const int pId, const int group ) { return insert( id, pId, group, 0 ); } +/*! + Create and insert action as last children + \return identificator of inserted action + \param a - action + \param pId - id of action corresponding to parent menu item + \param group - group identificator +*/ int QtxActionMenuMgr::prepend( QAction* a, const int pId, const int group ) { return insert( a, pId, group, 0 ); } +/*! + Removes menu item corresponding to action + \param id - identificator of action +*/ void QtxActionMenuMgr::remove( const int id ) { removeMenu( id, 0 ); update(); } +/*! + Removes menu item + \param id - identificator of action + \param pId - identificator of action corresponding to parent menu item + \param group - group identificator +*/ 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; @@ -322,19 +614,31 @@ void QtxActionMenuMgr::remove( const int id, const int pId, const int group ) for ( NodeListIterator itr( delNodes ); itr.current(); ++itr ) pNode->children.remove( itr.current() ); - updateMenu( pNode, false ); + triggerUpdate( pNode->id, false ); } +/*! + Shows menu item corresponding to action + \param id - identificator of action +*/ void QtxActionMenuMgr::show( const int id ) { setShown( id, true ); } +/*! + Hides menu item corresponding to action + \param id - identificator of action +*/ void QtxActionMenuMgr::hide( const int id ) { setShown( id, false ); } +/*! + \return shown status of menu item corresponding to action + \param id - identificator of action +*/ bool QtxActionMenuMgr::isShown( const int id ) const { bool res = false; @@ -344,31 +648,66 @@ bool QtxActionMenuMgr::isShown( const int id ) const return res; } +/*! + Sets shown status of menu item corresponding to action + \param id - identificator of action + \param on - new shown status +*/ void QtxActionMenuMgr::setShown( const int id, const bool on ) { NodeList aNodes; find( id, aNodes ); - QMap updMap; for ( NodeListIterator it( aNodes ); it.current(); ++it ) { if ( it.current()->visible != on ) { it.current()->visible = on; - updMap.insert( it.current()->parent, 0 ); + triggerUpdate( it.current()->parent ? it.current()->parent->id : myRoot.id, false ); } } - - for ( QMap::ConstIterator itr = updMap.begin(); itr != updMap.end(); ++itr ) - updateMenu( itr.key(), false ); } +/*! + SLOT: called when corresponding menu is destroyed, clears internal pointer to menu +*/ void QtxActionMenuMgr::onDestroyed( QObject* obj ) { if ( myMenu == obj ) myMenu = 0; } +/*! + SLOT: called when menu item is highlighted +*/ +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 ); + triggerUpdate( realId ); + } + } +} + +/*! + Assignes new menu with manager + \param mw - new menu +*/ void QtxActionMenuMgr::setWidget( QWidget* mw ) { if ( myMenu == mw ) @@ -383,12 +722,24 @@ 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 +/*! + \return menu node by it's place description + \param actId - identificator of action + \param pId - identificator of action corresponding to start menu item + \param rec - recursive search +*/ +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 +/*! + \return menu node by it's place description + \param actId - identificator of action + \param startNode - start menu item + \param rec - recursive search +*/ +QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const int id, MenuNode* startNode, const bool rec ) const { MenuNode* node = 0; MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot; @@ -396,12 +747,19 @@ 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; } +/*! + Finds menu node + \return true if at least one node is found + \param id - identificator of action + \param lst - list to be filled with found nodes + \param startNode - start menu item +*/ bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode ) const { MenuNode* start = startNode ? startNode : (MenuNode*)&myRoot; @@ -415,6 +773,87 @@ bool QtxActionMenuMgr::find( const int id, NodeList& lst, MenuNode* startNode ) return !lst.isEmpty(); } +/*! + Finds menu node + \return menu node + \param title - menu text of searched node + \param pId - id of action corresponding to start menu item + \param rec - recursive searching +*/ +QtxActionMenuMgr::MenuNode* QtxActionMenuMgr::find( const QString& title, const int pId, const bool rec ) const +{ + return find( title, find( pId ), rec ); +} + +/*! + Finds menu node + \return true if at least one node is found + \param title - menu text of node + \param lst - list to be filled with found nodes + \param startNode - start menu item +*/ +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(); +} + +/*! + Finds menu node + \return menu node + \param title - menu text of searched node + \param startNode - start menu item + \param rec - recursive searching +*/ +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; +} + +/*! + Find id among children + \return id (>0) if on success or -1 on fail + \param id - id to be searched + \param pid - id of parent, among children of that 'id' must be searched +*/ +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; +} + +/*! + Removes child + \param id - id of child to be removed + \param startNode - parent menu item +*/ void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode ) { MenuNode* start = startNode ? startNode : &myRoot; @@ -427,11 +866,19 @@ void QtxActionMenuMgr::removeMenu( const int id, MenuNode* startNode ) } } +/*! + \return menu item action by id + \param id - id of action +*/ QAction* QtxActionMenuMgr::itemAction( const int id ) const { return action( id ); } +/*! + \return menu action by id + \param id - id of action +*/ QtxActionMenuMgr::MenuAction* QtxActionMenuMgr::menuAction( const int id ) const { MenuAction* a = 0; @@ -442,6 +889,13 @@ QtxActionMenuMgr::MenuAction* QtxActionMenuMgr::menuAction( const int id ) const return a; } +/*! + Updates menu ( isUpdatesEnabled() must return true ) + \param startNode - first menu item to be updated + \param rec - recursive update + \param updParent - update also parent item (without recursion) + \sa isUpdatesEnabled() +*/ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bool updParent ) { if ( !isUpdatesEnabled() ) @@ -464,24 +918,21 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo if ( a ) a->removeFrom( mw ); } - - if ( node != &myRoot ) - { + /* VSR: commented to allow direct creating of menus by calling insertItem() methods 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]; + int idx = it2.current()->idx; + if ( idx < 0 || idx >= (int)lst.count() ) lst.append( it2.current() ); - } + else + lst.insert( idx, it2.current() ); } QIntList groups = idMap.keys(); @@ -501,15 +952,15 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo if ( rec ) updateMenu( iter.current(), rec, false ); + MenuNode* par = iter.current()->parent; + if ( !isVisible( iter.current()->id, par ? par->id : -1 ) ) + continue; + QAction* a = itemAction( iter.current()->id ); + if ( !a ) + a = menuAction( 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 ); - } } } @@ -519,12 +970,22 @@ void QtxActionMenuMgr::updateMenu( MenuNode* startNode, const bool rec, const bo updateMenu( node->parent, false ); } +/*! + Updates menu (virtual variant). To be redefined for custom activity on menu updating +*/ void QtxActionMenuMgr::internalUpdate() { - if ( isUpdatesEnabled() ) - updateMenu(); + if ( !isUpdatesEnabled() ) + return; + + updateMenu(); + myUpdateIds.clear(); } +/*! + \return true if widget is non-empty menu + \param wid - widget to be checked +*/ bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const { if ( !wid ) @@ -536,9 +997,13 @@ bool QtxActionMenuMgr::checkWidget( QWidget* wid ) const else if ( wid->inherits( "QMenuBar" ) ) md = (QMenuBar*)wid; - return md->count(); + return md ? md->count() : false; } +/*! + \return popup of menu item + \param node - menu item +*/ QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node) const { if ( !node || node == &myRoot ) @@ -550,12 +1015,21 @@ QWidget* QtxActionMenuMgr::menuWidget( MenuNode* node) const return myMenus[node->id]->popup(); } +/*! + Removes excess separators of menu + \param wid - menu to be processed +*/ void QtxActionMenuMgr::simplifySeparators( QWidget* wid ) { if ( wid && wid->inherits( "QPopupMenu" ) ) Qtx::simplifySeparators( (QPopupMenu*)wid, false ); } +/*! + Removes special symbols (&) from string + \param txt - string to be processed + \return clear variant of string +*/ QString QtxActionMenuMgr::clearTitle( const QString& txt ) const { QString res = txt; @@ -569,6 +1043,11 @@ QString QtxActionMenuMgr::clearTitle( const QString& txt ) const return res; } +/*! + Creates and inserts many menu items + \param lst - list of menu texts + \param pId - id of action corresponding to parent menu item +*/ int QtxActionMenuMgr::createMenu( const QStringList& lst, const int pId ) { if ( lst.isEmpty() ) @@ -584,29 +1063,97 @@ int QtxActionMenuMgr::createMenu( const QStringList& lst, const int pId ) return insert( title, parentId, -1 ); } +/*! + Loads actions description from file + \param fname - name of file + \param r - reader of file + \return true on success +*/ bool QtxActionMenuMgr::load( const QString& fname, QtxActionMgr::Reader& r ) { MenuCreator cr( &r, this ); return r.read( fname, cr ); } +/*! + \return true if item has such child + \param title - menu text of child + \param pid - id of action corresponding to item +*/ +bool QtxActionMenuMgr::containsMenu( const QString& title, const int pid ) const +{ + return (bool)find( title, pid, false ); +} /*! - Class: QtxActionMenuMgr::MenuCreator - Level: Public + \return true if item has such child + \param id - id of action corresponding to child + \param pid - id of action corresponding to item +*/ +bool QtxActionMenuMgr::containsMenu( const int id, const int pid ) const +{ + return (bool)find( id, pid, false ); +} + +/*! + \Sets trigger for delayed update +*/ +void QtxActionMenuMgr::triggerUpdate( const int id, const bool rec ) +{ + bool isRec = rec; + if ( myUpdateIds.contains( id ) ) + isRec = isRec || myUpdateIds[ id ]; + myUpdateIds.insert( id, isRec ); + + QtxActionMgr::triggerUpdate(); +} + +/*! + \Sets trigger for delayed update */ +void QtxActionMenuMgr::updateContent() +{ + // Warning: For correct updating it is necessary to update the most enclosed submenu firstly + // because not updated empty submenu will be skipped. Now the submenu are iterated in + // ascending order their identifiers. For a submenu with automatically generated identifiers + // will work correctly as the uppermost submenu have the biggest number (identifiers generated + // reduction from -1). Generally when any submenu will have positive identifiers are obviously + // appropriated can to work not truly. In this case it is required to improve the given method + // and to add preliminary sorting a submenu on depth of an enclosure. + for ( QMap::const_iterator it = myUpdateIds.constBegin(); it != myUpdateIds.constEnd(); ++it ) + { + MenuNode* node = it.key() == -1 ? &myRoot : find( it.key() ); + if ( node ) + updateMenu( node, it.data() ); + } + myUpdateIds.clear(); +} -QtxActionMenuMgr::MenuCreator::MenuCreator( QtxActionMgr::Reader* r, - QtxActionMenuMgr* mgr ) +/*! + Constructor + \param r - menu reader + \param mgr - menu manager +*/ +QtxActionMenuMgr::MenuCreator::MenuCreator( QtxActionMgr::Reader* r, QtxActionMenuMgr* mgr ) : QtxActionMgr::Creator( r ), - myMgr( mgr ) +myMgr( mgr ) { } +/*! + Destructor +*/ QtxActionMenuMgr::MenuCreator::~MenuCreator() { } +/*! + Appends new menu items + \param tag - tag of item + \param subMenu - it has submenu + \param attr - list of attributes + \param pId - id of action corresponding to parent item +*/ int QtxActionMenuMgr::MenuCreator::append( const QString& tag, const bool subMenu, const ItemAttributes& attr, const int pId ) { diff --git a/src/Qtx/QtxActionMenuMgr.h b/src/Qtx/QtxActionMenuMgr.h index 89b81aa89..8f310611d 100644 --- a/src/Qtx/QtxActionMenuMgr.h +++ b/src/Qtx/QtxActionMenuMgr.h @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxActionMenuMgr.h // Author: Alexander SOLOVYEV, Sergey TELKOV @@ -35,6 +35,18 @@ class QMainWindow; #pragma warning( disable:4251 ) #endif +/*! + \class QtxActionMenuMgr + Allows to use set of action to automatically build main menu. + With help of methods insert/append/remove it is possible to + describe whole structure of menu. Method hide allows + to temporary remove some items from menu, method show allows to + recreate them. + Actions can be grouped with help of group identifictor. + Inside popup or menu bar items have order by increasing group id. + This manager is able to attune menu: to remove excess separators, + to remove empty popup menu etc. +*/ class QTX_EXPORT QtxActionMenuMgr : public QtxActionMgr { Q_OBJECT @@ -44,6 +56,11 @@ class QTX_EXPORT QtxActionMenuMgr : public QtxActionMgr typedef QPtrList NodeList; typedef QPtrListIterator NodeListIterator; + /*! + \class MenuNode + Represents a menu item inside main menu structure. + For internal purposes only + */ class MenuNode { public: @@ -51,6 +68,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 +97,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 +120,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* ); @@ -118,6 +148,7 @@ protected: void updateMenu( MenuNode* = 0, const bool = true, const bool = true ); virtual void internalUpdate(); + virtual void updateContent(); private: bool checkWidget( QWidget* ) const; @@ -126,6 +157,8 @@ private: QString clearTitle( const QString& ) const; int createMenu( const QStringList&, const int ); + void triggerUpdate( const int, const bool rec = true ); + private: typedef QMap MenuMap; @@ -133,8 +166,13 @@ private: MenuNode myRoot; QWidget* myMenu; MenuMap myMenus; + QMap myUpdateIds; }; +/*! + \class QtxActionMenuMgr::MenuCreator + Allows to create automatically main menu by data read from file +*/ class QtxActionMenuMgr::MenuCreator : public QtxActionMgr::Creator { public: diff --git a/src/Qtx/QtxActionMgr.cxx b/src/Qtx/QtxActionMgr.cxx index 16ec7b5b1..b4acf9880 100644 --- a/src/Qtx/QtxActionMgr.cxx +++ b/src/Qtx/QtxActionMgr.cxx @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxActionMgr.cxx // Author: Alexander SOLOVYEV, Sergey TELKOV @@ -23,13 +23,14 @@ #include "QtxActionMgr.h" #include "QtxAction.h" +#include +#include +#include #include #include #include #include #include -#include -#include static QAction* qtx_separator_action = 0; @@ -58,15 +59,25 @@ private: QMap myTools; }; +/*! + Constructor +*/ QtxActionMgr::SeparatorAction::SeparatorAction( QObject* parent ) : QtxAction( parent ) { } +/*! + Destructor +*/ QtxActionMgr::SeparatorAction::~SeparatorAction() { } +/*! + Adds action to widget + \param wid - widget +*/ bool QtxActionMgr::SeparatorAction::addTo( QWidget* wid ) { if ( !wid ) @@ -90,6 +101,10 @@ bool QtxActionMgr::SeparatorAction::addTo( QWidget* wid ) return res; } +/*! + Removes action from widget + \param wid - widget +*/ bool QtxActionMgr::SeparatorAction::removeFrom( QWidget* wid ) { if ( !wid ) @@ -140,16 +155,29 @@ bool QtxActionMgr::SeparatorAction::removeFrom( QWidget* wid ) Level: Public */ +/*! + Constructor +*/ QtxActionMgr::QtxActionMgr( QObject* parent ) : QObject( parent ), -myUpdate( true ) +myUpdate( true ), +myUpdTimer( 0 ) { } +/*! + Destructor +*/ QtxActionMgr::~QtxActionMgr() { } +/*! + Stores action in internal map + If action with such id is registered already, then it will be unregistered + \param a - action to be registered + \param userId - proposed id (if it is less than 0, then id will be generated automatically) +*/ int QtxActionMgr::registerAction( QAction* a, const int userId ) { if ( !a ) @@ -174,12 +202,20 @@ int QtxActionMgr::registerAction( QAction* a, const int userId ) return theId; } +/*! + Removes action from internal map + \param id - action id +*/ void QtxActionMgr::unRegisterAction( const int id ) { if( contains( id ) ) myActions.remove( id ); } +/*! + \return action by id + \param id - action id +*/ QAction* QtxActionMgr::action( const int id ) const { if ( contains( id ) ) @@ -188,6 +224,10 @@ QAction* QtxActionMgr::action( const int id ) const return 0; } +/*! + \return id by action + \param a - action +*/ int QtxActionMgr::actionId( const QAction* a ) const { if ( !a ) @@ -203,61 +243,105 @@ int QtxActionMgr::actionId( const QAction* a ) const return theId; } +/*! + \return true if internal map contains such id + \param id - action id +*/ bool QtxActionMgr::contains( const int id ) const { return myActions.contains( id ); } +/*! + \return count of actions in internal map +*/ int QtxActionMgr::count() const { return myActions.count(); } +/*! + \return true if internal map is empty +*/ bool QtxActionMgr::isEmpty() const { return myActions.isEmpty(); } +/*! + Fills list with ids of registered actions +*/ void QtxActionMgr::idList( QIntList& lst ) const { lst = myActions.keys(); } +/*! + \return true if updates are enabled +*/ bool QtxActionMgr::isUpdatesEnabled() const { return myUpdate; } +/*! + Enables/disables updates + \param upd - new state +*/ void QtxActionMgr::setUpdatesEnabled( const bool upd ) { myUpdate = upd; } +/*! + \return true if action is visible (by default \return always true) +*/ bool QtxActionMgr::isVisible( const int, const int ) const { return true; } +/*! + Sets visibility of action (by default, empty implementation) +*/ void QtxActionMgr::setVisible( const int, const int, const bool ) { } +/*! + Updates actions, check isUpdatesEnabled() and call internalUpdate() + \sa isUpdatesEnabled(), internalUpdate() +*/ void QtxActionMgr::update() { - if ( isUpdatesEnabled() ) - internalUpdate(); + if ( !isUpdatesEnabled() ) + return; + + internalUpdate(); + if ( myUpdTimer ) + myUpdTimer->stop(); } +/*! + Real update (to be redefined in successors) +*/ void QtxActionMgr::internalUpdate() { } +/*! + \return global free id +*/ int QtxActionMgr::generateId() const { static int id = -1; return --id; } +/*! + \return true if action is enabled + \param id - action id +*/ bool QtxActionMgr::isEnabled( const int id ) const { QAction* a = action( id ); @@ -267,6 +351,11 @@ bool QtxActionMgr::isEnabled( const int id ) const return false; } +/*! + Enables/disables action + \param id - action id + \param en - new state +*/ void QtxActionMgr::setEnabled( const int id, const bool en ) { QAction* a = action( id ); @@ -274,6 +363,11 @@ void QtxActionMgr::setEnabled( const int id, const bool en ) a->setEnabled( en ); } +/*! + \return action for separator + If this action doesn't exist, then it will be created + \param individual - if it is false, then action will be shared, otherwise it will be created on every call +*/ QAction* QtxActionMgr::separator( const bool individual ) { if ( individual ) @@ -287,24 +381,72 @@ QAction* QtxActionMgr::separator( const bool individual ) return qtx_separator_action; } +/*! + \initialise timer for delayed update +*/ +void QtxActionMgr::triggerUpdate() +{ + if ( !isUpdatesEnabled() ) + return; + + if ( !myUpdTimer ) + { + myUpdTimer = new QTimer( this ); + connect( myUpdTimer, SIGNAL( timeout() ), this, SLOT( onUpdateContent() ) ); + } + myUpdTimer->stop(); + // add timer event to event list + myUpdTimer->start( 0, true ); +} + +/*! + \perform delayed update + \default implementation is empty +*/ +void QtxActionMgr::updateContent() +{} + +/*! + \perform delayed update + \default implementation is empty +*/ +void QtxActionMgr::onUpdateContent() +{ + updateContent(); +} + /*! Class: QtxActionMgr::Reader Level: Public */ +/*! + Constructor +*/ QtxActionMgr::Reader::Reader() { } +/*! + Destructor +*/ QtxActionMgr::Reader::~Reader() { } +/*! + \return list of options +*/ QStringList QtxActionMgr::Reader::options() const { return myOptions.keys(); } +/*! + \return value of option + \param name - option name + \param def - default option value (is returned, if there is no such option) +*/ QString QtxActionMgr::Reader::option( const QString& name, const QString& def ) const { if( myOptions.contains( name ) ) @@ -313,6 +455,11 @@ QString QtxActionMgr::Reader::option( const QString& name, const QString& def ) return def; } +/*! + Sets value of option + \param name - option name + \param value - option value +*/ void QtxActionMgr::Reader::setOption( const QString& name, const QString& value ) { myOptions[ name ] = value; @@ -342,10 +489,18 @@ QtxActionMgr::XMLReader::XMLReader( const QString& root, setOption( QString( "toggle" ), QString( "toggle-id" ) ); } +/*! + Destructor +*/ QtxActionMgr::XMLReader::~XMLReader() { } +/*! + Reads file and fills action manager with help of creator + \param fname - file name + \param cr - creator +*/ bool QtxActionMgr::XMLReader::read( const QString& fname, Creator& cr ) const { bool res = false; @@ -386,6 +541,12 @@ bool QtxActionMgr::XMLReader::read( const QString& fname, Creator& cr ) const return res; } +/*! + Create item by xml node + \param parent_node - parent node + \param parent_id - parent id + \param cr - creator +*/ void QtxActionMgr::XMLReader::read( const QDomNode& parent_node, const int parent_id, Creator& cr ) const @@ -420,6 +581,9 @@ void QtxActionMgr::XMLReader::read( const QDomNode& parent_node, } } +/*! + \return true if node satisfies pattern +*/ bool QtxActionMgr::XMLReader::isNodeSimilar( const QDomNode& node, const QString& pattern ) const { @@ -448,6 +612,13 @@ bool QtxActionMgr::XMLReader::isNodeSimilar( const QDomNode& node, Class: QtxActionMgr::Creator Level: Public */ + +/*! + \return integer value by attributes + \param attrs - attributes + \param name - name of attribute + \param def - default value (is returned on fail) +*/ int QtxActionMgr::Creator::intValue( const ItemAttributes& attrs, const QString& name, int def ) { @@ -461,6 +632,12 @@ int QtxActionMgr::Creator::intValue( const ItemAttributes& attrs, return def; } +/*! + \return string value by attributes + \param attrs - attributes + \param name - name of attribute + \param def - default value (is returned on fail) +*/ QString QtxActionMgr::Creator::strValue( const ItemAttributes& attrs, const QString& name, const QString& def ) @@ -471,24 +648,41 @@ QString QtxActionMgr::Creator::strValue( const ItemAttributes& attrs, return def; } +/*! + Constructor +*/ QtxActionMgr::Creator::Creator( QtxActionMgr::Reader* r ) : myReader( r ) { } +/*! + Destructor +*/ QtxActionMgr::Creator::~Creator() { } +/*! + \return corresponding reader +*/ QtxActionMgr::Reader* QtxActionMgr::Creator::reader() const { return myReader; } +/*! + Connects action to some slots (default implementation is empty) +*/ void QtxActionMgr::Creator::connect( QAction* ) const { } +/*! + Loads pixmap + \param fname - file name + \param pix - to return loaded pixmap +*/ bool QtxActionMgr::Creator::loadPixmap( const QString& fname, QPixmap& pix ) const { if( !reader() ) diff --git a/src/Qtx/QtxActionMgr.h b/src/Qtx/QtxActionMgr.h index 60fc342c0..1404d0dee 100644 --- a/src/Qtx/QtxActionMgr.h +++ b/src/Qtx/QtxActionMgr.h @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxActionMgr.h // Author: Alexander SOLOVYEV, Sergey TELKOV @@ -28,14 +28,20 @@ #include #include +class QTimer; class QAction; class QDomNode; - #ifdef WIN32 #pragma warning( disable:4251 ) #endif + +/*! + \class QtxActionMgr + Contains set of actions accessible by id. + Base class for menu, popup creators and other action containers. +*/ class QTX_EXPORT QtxActionMgr : public QObject { Q_OBJECT @@ -81,6 +87,13 @@ protected: virtual void internalUpdate(); int generateId() const; + //! initialise timer for delayed update + void triggerUpdate(); + virtual void updateContent(); + +private slots: + void onUpdateContent(); + private: typedef QGuardedPtr ActionPtr; typedef QMap ActionMap; @@ -88,11 +101,16 @@ private: private: bool myUpdate; ActionMap myActions; + QTimer* myUpdTimer; }; QTX_EXPORT typedef QMap ItemAttributes; +/*! + \class QtxActionMgr::Creator + Allows to fill automatically action manager with actions created by data from file +*/ class QtxActionMgr::Creator { public: @@ -115,6 +133,11 @@ private: QtxActionMgr::Reader* myReader; }; +/*! + \class QtxActionMgr::Reader + This class is used to read files of some format + to create actions and to fill action manager automatically +*/ class QtxActionMgr::Reader { public: @@ -131,6 +154,11 @@ private: QMap< QString, QString > myOptions; }; +/*! + \class QtxActionMgr::Reader + This class is used to read files of XML format + to create actions and to fill action manager automatically +*/ class QtxActionMgr::XMLReader : public Reader { public: diff --git a/src/Qtx/QtxActionToolMgr.cxx b/src/Qtx/QtxActionToolMgr.cxx index f797306f0..4202b438f 100644 --- a/src/Qtx/QtxActionToolMgr.cxx +++ b/src/Qtx/QtxActionToolMgr.cxx @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxActionToolMgr.cxx // Author: Alexander SOLOVYEV, Sergey TELKOV @@ -27,21 +27,36 @@ #include #include +/*! + Constructor +*/ QtxActionToolMgr::QtxActionToolMgr( QMainWindow* p ) : QtxActionMgr( p ), myMainWindow( p ) { } +/*! + Destructor +*/ QtxActionToolMgr::~QtxActionToolMgr() { } +/*! + \return desktop +*/ QMainWindow* QtxActionToolMgr::mainWindow() const { return myMainWindow; } +/*! + Creates toolbar + \return id of just created toolbar + \param name - name of toolbar + \param tid - proposed id (if such id is used already, then it will be returned without creation) +*/ int QtxActionToolMgr::createToolBar( const QString& name, const int tid ) { static int _toolBarId = -1; @@ -75,6 +90,11 @@ int QtxActionToolMgr::createToolBar( const QString& name, const int tid ) return tbId; } +/*! + \return toolbar by title + \param label - toolbar title + \param mw - desktop +*/ QToolBar* QtxActionToolMgr::find( const QString& label, QMainWindow* mw ) const { if ( !mw ) @@ -96,6 +116,10 @@ QToolBar* QtxActionToolMgr::find( const QString& label, QMainWindow* mw ) const return res; } +/*! + Removes toolbar + \param tid - toolbar id +*/ void QtxActionToolMgr::removeToolBar( const int tid ) { if ( !myToolBars.contains( tid ) ) @@ -105,82 +129,158 @@ void QtxActionToolMgr::removeToolBar( const int tid ) myToolBars.remove( tid ); } +/*! + Removes toolbar + \param tname - toolbar name +*/ void QtxActionToolMgr::removeToolBar( const QString& tname ) { removeToolBar( find( tname ) ); } +/*! + Insert action into toolbar + \param id - identificator of action + \param tId - identificator of toolbar + \param idx - position inside toolbar +*/ int QtxActionToolMgr::insert( const int id, const int tid, const int idx ) { if ( !contains( id ) || !hasToolBar( tid ) ) return -1; - +/* + if ( containsAction( id, tid ) ) + remove( id, tid ); +*/ ToolNode node; node.id = id; NodeList& list = myToolBars[tid].nodes; int index = idx < 0 ? list.count() : QMIN( idx, (int)list.count() ); list.insert( list.at( index ), node ); - updateToolBar( tid ); + triggerUpdate( tid ); return id; } +/*! + Insert action into toolbar + \param act - action + \param tId - identificator of toolbar + \param pos - position inside toolbar +*/ int QtxActionToolMgr::insert( QAction* act, const int tid, const int pos ) { return insert( registerAction( act ), tid, pos ); } +/*! + Insert action into toolbar + \param id - identificator of action + \param tname - name of toolbar + \param pos - position inside toolbar +*/ int QtxActionToolMgr::insert( const int id, const QString& tname, const int pos ) { return insert( id, createToolBar( tname ), pos ); } +/*! + Insert action into toolbar + \param act - action + \param tname - name of toolbar + \param pos - position inside toolbar +*/ int QtxActionToolMgr::insert( QAction* act, const QString& tname, const int pos ) { return insert( registerAction( act ), createToolBar( tname ), pos ); } +/*! + Append action into toolbar as last toolbutton + \param id - identificator of action + \param tId - identificator of toolbar +*/ int QtxActionToolMgr::append( const int id, const int tid ) { return insert( id, tid ); } +/*! + Append action into toolbar as last toolbutton + \param act - action + \param tId - identificator of toolbar +*/ int QtxActionToolMgr::append( QAction* act, const int tid ) { return insert( act, tid ); } +/*! + Append action into toolbar as last toolbutton + \param id - identificator of action + \param tname - toolbar name +*/ int QtxActionToolMgr::append( const int id, const QString& tname ) { return insert( id, tname ); } +/*! + Append action into toolbar as last toolbutton + \param act - action + \param tname - toolbar name +*/ int QtxActionToolMgr::append( QAction* act, const QString& tname ) { return insert( act, tname ); } +/*! + Append action into toolbar as first toolbutton + \param id - identificator of action + \param tId - identificator of toolbar +*/ int QtxActionToolMgr::prepend( const int id, const int tid ) { return insert( id, tid, 0 ); } +/*! + Append action into toolbar as first toolbutton + \param act - action + \param tId - identificator of toolbar +*/ int QtxActionToolMgr::prepend( QAction* act, const int tid ) { return insert( act, tid, 0 ); } +/*! + Append action into toolbar as first toolbutton + \param id - identificator of action + \param tname - toolbar name +*/ int QtxActionToolMgr::prepend( const int id, const QString& tname ) { return insert( id, tname, 0 ); } +/*! + Append action into toolbar as first toolbutton + \param act - action + \param tname - toolbar name +*/ int QtxActionToolMgr::prepend( QAction* act, const QString& tname ) { return insert( act, tname, 0 ); } +/*! + Remove action from toolbar + \param id - identificator of action + \param tId - identificator of toolbar +*/ void QtxActionToolMgr::remove( const int id, const int tid ) { if ( !myToolBars.contains( tid ) ) @@ -196,14 +296,23 @@ void QtxActionToolMgr::remove( const int id, const int tid ) myToolBars[tid].nodes = newList; - updateToolBar( tid ); + triggerUpdate( tid ); } +/*! + Remove action from toolbar + \param id - identificator of action + \param tname - name of toolbar +*/ void QtxActionToolMgr::remove( const int id, const QString& tname ) { remove( id, find( tname ) ); } +/*! + \return toolbar by it's id + \param tId - identificator of toolbar +*/ QToolBar* QtxActionToolMgr::toolBar( const int tid ) const { QToolBar* tb = 0; @@ -212,26 +321,64 @@ QToolBar* QtxActionToolMgr::toolBar( const int tid ) const return tb; } +/*! + \return toolbar by it's name + \param tname - name of toolbar +*/ QToolBar* QtxActionToolMgr::toolBar( const QString& tname ) const { return toolBar( find( tname ) ); } +/*! + \return true if manager contains toolbar with such id + \param tId - identificator of toolbar +*/ bool QtxActionToolMgr::hasToolBar( const int tid ) const { return myToolBars.contains( tid ); } +/*! + \return true if manager contains toolbar with such name + \param tname - name of toolbar +*/ bool QtxActionToolMgr::hasToolBar( const QString& tname ) const { return find( tname ) != -1; } +/*! + \return true if toolbar contains action + \param id - identificator of action + \param tId - identificator of toolbar +*/ +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; +} + +/*! + SLOT: called when toolbar is destroyed, removes just destroyed toolbar from map +*/ void QtxActionToolMgr::onToolBarDestroyed() { myToolBars.remove( find( (QToolBar*)sender() ) ); } +/*! + \return id of toolbar by it's name + \param tname - name of toolbar +*/ int QtxActionToolMgr::find( const QString& tname ) const { int id = -1; @@ -243,6 +390,10 @@ int QtxActionToolMgr::find( const QString& tname ) const return id; } +/*! + \return id of toolbar + \param t - toolbar +*/ int QtxActionToolMgr::find( QToolBar* t ) const { int id = -1; @@ -254,6 +405,10 @@ int QtxActionToolMgr::find( QToolBar* t ) const return id; } +/*! + Updates toolbar + \param tId - toolbar id +*/ void QtxActionToolMgr::updateToolBar( const int tId ) { if ( !isUpdatesEnabled() ) @@ -287,34 +442,62 @@ void QtxActionToolMgr::updateToolBar( const int tId ) simplifySeparators( tb ); } +/*! + Updates all toolbars +*/ void QtxActionToolMgr::internalUpdate() { + if ( !isUpdatesEnabled() ) + return; + for ( ToolBarMap::ConstIterator it1 = myToolBars.begin(); it1 != myToolBars.end(); ++it1 ) updateToolBar( it1.key() ); + + myUpdateIds.clear(); } +/*! + Removes excess separators from toolbar +*/ void QtxActionToolMgr::simplifySeparators( QToolBar* t ) { if ( t ) Qtx::simplifySeparators( t ); } +/*! + Shows action in all toolbars + \param actId - action id +*/ void QtxActionToolMgr::show( const int actId ) { setShown( actId, true ); } +/*! + Hides action in all toolbars + \param actId - action id +*/ void QtxActionToolMgr::hide( const int actId ) { setShown( actId, false ); } +/*! + Changes shown status of action in all toolbars + \param id - action id + \param on - new shown status +*/ void QtxActionToolMgr::setShown( const int id, const bool on ) { for ( ToolBarMap::Iterator it = myToolBars.begin(); it != myToolBars.end(); ++it ) setVisible( id, it.key(), on ); } +/*! + \return true if action is shown in all toolbars + \param id - action id +*/ bool QtxActionToolMgr::isShown( const int id ) const { QPtrList nodes; @@ -339,6 +522,11 @@ bool QtxActionToolMgr::isShown( const int id ) const return vis; } +/*! + \return shown status of action in toolbar + \param id - action id + \param tId - toolbar id +*/ bool QtxActionToolMgr::isVisible( const int id, const int tId ) const { if ( !myToolBars.contains( tId ) ) @@ -355,6 +543,12 @@ bool QtxActionToolMgr::isVisible( const int id, const int tId ) const return vis; } +/*! + Changes action shown status in certain toolbar + \param id - action id + \param tId - toolbar id + \param on - new shown status +*/ void QtxActionToolMgr::setVisible( const int id, const int tId, const bool on ) { if ( !myToolBars.contains( tId ) ) @@ -373,15 +567,41 @@ void QtxActionToolMgr::setVisible( const int id, const int tId, const bool on ) } if ( changed ) - updateToolBar( tId ); + triggerUpdate( tId ); } +/*! + Loads toolbar content from file + \param fname - file name + \param r - reader +*/ bool QtxActionToolMgr::load( const QString& fname, QtxActionMgr::Reader& r ) { ToolCreator cr( &r, this ); return r.read( fname, cr ); } +/*! + \Perform delayed update +*/ +void QtxActionToolMgr::updateContent() +{ + if ( !isUpdatesEnabled() ) + return; + + for ( QMap::const_iterator it = myUpdateIds.constBegin(); it != myUpdateIds.constEnd(); ++it ) + updateToolBar( it.key() ); + myUpdateIds.clear(); +} + +/*! + \ Sets trigger to update +*/ +void QtxActionToolMgr::triggerUpdate( const int id ) +{ + myUpdateIds.insert( id, 0 ); + QtxActionMgr::triggerUpdate(); +} /*! Class: QtxActionToolMgr::ToolCreator @@ -394,10 +614,20 @@ QtxActionToolMgr::ToolCreator::ToolCreator( QtxActionMgr::Reader* r, { } +/*! + Destructor +*/ QtxActionToolMgr::ToolCreator::~ToolCreator() { } +/*! + Appends new tool buttons + \param tag - tag of toolmenu + \param subMenu - it has submenu (not used here) + \param attr - list of attributes + \param pId - id of action corresponding to parent item +*/ int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool subMenu, const ItemAttributes& attr, const int tId ) { @@ -441,5 +671,3 @@ int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool subMen return res; } - - diff --git a/src/Qtx/QtxActionToolMgr.h b/src/Qtx/QtxActionToolMgr.h index 31c02209d..bc59b4c61 100644 --- a/src/Qtx/QtxActionToolMgr.h +++ b/src/Qtx/QtxActionToolMgr.h @@ -14,7 +14,7 @@ // 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/ +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File: QtxActionToolMgr.h // Author: Alexander SOLOVYEV, Sergey TELKOV @@ -24,6 +24,7 @@ #include "Qtx.h" +#include #include #include "QtxActionMgr.h" @@ -35,10 +36,22 @@ class QMainWindow; #pragma warning( disable:4251 ) #endif +/*! + \class QtxActionToolMgr + Allows to use set of action to automatically build set of toolbars. + With help of methods insert/append/remove it is possible to + describe toolbars and its internal structure. + This manager is able to attune toolbar by removing excess separators +*/ class QTX_EXPORT QtxActionToolMgr : public QtxActionMgr { Q_OBJECT + /*! + \class ToolNode + Represents a toolbutton inside toolbar + For internal purposes only + */ class ToolNode { public: @@ -95,6 +108,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: @@ -108,8 +123,11 @@ protected: virtual void internalUpdate(); void updateToolBar( const int ); + virtual void updateContent(); + private: void simplifySeparators( QToolBar* ); + void triggerUpdate( const int ); private: typedef struct { NodeList nodes; QToolBar* toolBar; } ToolBarInfo; @@ -118,8 +136,13 @@ private: private: ToolBarMap myToolBars; QMainWindow* myMainWindow; + QMap myUpdateIds; }; +/*! + \class QtxActionToolMgr::ToolCreator + Allows to create automatically toolbar by data read from file +*/ class QtxActionToolMgr::ToolCreator : public QtxActionMgr::Creator { public: diff --git a/src/Qtx/QtxLogoMgr.cxx b/src/Qtx/QtxLogoMgr.cxx index 68811c5f3..aa1189152 100644 --- a/src/Qtx/QtxLogoMgr.cxx +++ b/src/Qtx/QtxLogoMgr.cxx @@ -169,7 +169,7 @@ void QtxLogoMgr::generate() QApplication::sendPostedEvents( cnt, QEvent::ChildInserted ); cnt->addSpacing( 2 ); - myId = menuBar()->insertItem( cnt ); + myId = menuBar()->insertItem( cnt, INT_MAX ); QApplication::sendPostedEvents( menuBar()->parentWidget(), QEvent::LayoutHint ); QApplication::postEvent( menuBar()->parentWidget(), new QEvent( QEvent::LayoutHint ) ); diff --git a/src/Qtx/QtxResourceMgr.cxx b/src/Qtx/QtxResourceMgr.cxx index c4ff62142..7a6c21f34 100644 --- a/src/Qtx/QtxResourceMgr.cxx +++ b/src/Qtx/QtxResourceMgr.cxx @@ -885,7 +885,7 @@ bool QtxResourceMgr::value( const QString& sect, const QString& name, QColor& cV { int pack = val.toInt( &res ); if ( res ) - Qtx::rgbSet( pack, cVal ); + cVal = Qtx::rgbSet( pack ); } return res; -- 2.39.2