]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
no message
authorstv <stv@opencascade.com>
Tue, 14 Nov 2006 13:38:15 +0000 (13:38 +0000)
committerstv <stv@opencascade.com>
Tue, 14 Nov 2006 13:38:15 +0000 (13:38 +0000)
12 files changed:
src/Qtx/Qtx.cxx
src/Qtx/Qtx.h
src/Qtx/QtxAction.cxx
src/Qtx/QtxAction.h
src/Qtx/QtxActionMenuMgr.cxx
src/Qtx/QtxActionMenuMgr.h
src/Qtx/QtxActionMgr.cxx
src/Qtx/QtxActionMgr.h
src/Qtx/QtxActionToolMgr.cxx
src/Qtx/QtxActionToolMgr.h
src/Qtx/QtxLogoMgr.cxx
src/Qtx/QtxResourceMgr.cxx

index 8201c34d24478638f63ce1d602b173ac0d82cabf..6795c52772a152342eae5e7f8197874d652a03dd 100755 (executable)
@@ -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 );
index 864441bede08fd83ecfa5f5df349279eb997554f..1818cf0fc99ef9957922f3976102e676dc88661d 100755 (executable)
@@ -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 <qpixmap.h>
 #include <qnamespace.h>
 
 #ifndef QT_VERSION
 #endif
 #endif
 
-class QImage;
+#include <qcolor.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qpixmap.h>
+
 class QObject;
 class QString;
 class QWidget;
@@ -89,6 +92,10 @@ typedef QValueList<int>    QIntList;
 typedef QValueList<short>  QShortList;
 typedef QValueList<double> 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
index 9fafdb7ac1c0a48a741ce859435264fca581e37c..0dfba4cdaa8e9d2525f301babed66e8991f454a5 100755 (executable)
 // 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 <qmenubar.h>
 #include <qpopupmenu.h>
 
 /*!
@@ -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<QPopupMenu*>( w );
+  else if ( w->inherits( "QMenuBar" ) )
+    pmd = ::qt_cast<QMenuBar*>( 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;
 }
index ffffcc4d8594cae01b49f63a02bfdd3a94bc388d..d60568bf648128a99d032ad9f6d1f749165b8da3 100755 (executable)
@@ -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
 
 #include "Qtx.h"
 
+#include <qmap.h>
 #include <qaction.h>
 
+#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<QWidget*,int> myMenuIds;
 };
 
+#ifdef WIN32
+#pragma warning ( default:4251 )
+#endif
+
 #endif
index 7782a7b57ccb9c64074a8e2df405c0ddf163afe7..aa49bd8bd5d2c5e8b51cbdfbfc39354f28588ed6 100644 (file)
@@ -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
 #include <qmainwindow.h>
 #include <qfile.h>
 #include <qdom.h>
+#include <qvaluelist.h>
+
+// 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<int> prepareIds( const QWidget* w )
+  {
+    QValueList<int> l;
+    const QMenuData* md = 0;
+    if ( w->inherits( "QMenuBar" ) )
+      md = ::qt_cast<QMenuBar*>( w );
+    else if ( w->inherits( "QPopupMenu" ) )
+      md = ::qt_cast<QPopupMenu*>( 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<int>& l, bool retId = true )
+  {
+    const QMenuData* md = 0;
+    if ( w->inherits( "QMenuBar" ) )
+      md = ::qt_cast<QMenuBar*>( w );
+    else if ( w->inherits( "QPopupMenu" ) )
+      md = ::qt_cast<QPopupMenu*>( 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<QMenuBar*>( w );
+    else if ( w->inherits( "QPopupMenu" ) )
+      md = ::qt_cast<QPopupMenu*>( 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
 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<QWidget*, int> 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<int> 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<int> 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<MenuNode*, int> 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<MenuNode*, int>::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<int, NodeList> 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<int, bool>::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 )
 {
index 89b81aa89a8b770a44973cfe756e902656a0d99d..8f310611d2e019d13006b816fd8b860a884fda54 100644 (file)
@@ -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<MenuNode>         NodeList;
   typedef QPtrListIterator<MenuNode> 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<int, MenuAction*> MenuMap;
 
@@ -133,8 +166,13 @@ private:
   MenuNode     myRoot;
   QWidget*     myMenu;
   MenuMap      myMenus;
+  QMap<int, bool> myUpdateIds;
 };
 
+/*!
+  \class QtxActionMenuMgr::MenuCreator
+  Allows to create automatically main menu by data read from file
+*/
 class QtxActionMenuMgr::MenuCreator : public QtxActionMgr::Creator
 {
 public:
index 16ec7b5b1916cb71863ab55c566e8f6d38bcd35c..b4acf9880eacee5f727f7222e6e0edfafb438aa6 100644 (file)
@@ -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
 #include "QtxActionMgr.h"
 #include "QtxAction.h"
 
+#include <qdom.h>
+#include <qfile.h>
+#include <qtimer.h>
 #include <qwidget.h>
 #include <qtoolbar.h>
 #include <qpopupmenu.h>
 #include <qwidgetlist.h>
 #include <qobjectlist.h>
-#include <qfile.h>
-#include <qdom.h>
 
 static QAction* qtx_separator_action = 0;
 
@@ -58,15 +59,25 @@ private:
   QMap<QToolBar*, QWidgetList> 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() )
index 60fc342c04f3828b4bab0ab2d5715c31fe21e78e..1404d0dee71ebc7c54a0ceb7a4112d7a1bdeb03b 100644 (file)
@@ -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
 #include <qobject.h>
 #include <qguardedptr.h>
 
+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<QAction> ActionPtr;
   typedef QMap<int, ActionPtr> ActionMap;
@@ -88,11 +101,16 @@ private:
 private:
   bool             myUpdate;
   ActionMap        myActions;
+  QTimer*          myUpdTimer;
 };
 
 
 QTX_EXPORT typedef QMap<QString, QString> 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:
index f797306f0506c96c5afd1079214e53cc3d70d192..4202b438ff72cd50e1e5fe057e80ae34f13a0111 100644 (file)
@@ -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
 #include <qmainwindow.h>
 #include <qobjectlist.h>
 
+/*!
+  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<ToolNode> 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<int,int>::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;
 }
-
-
index 31c02209d0d2d8fb28fdb500a65c6bea3a788caf..bc59b4c61d22ab6f2bb85d794df11c633b533d1b 100644 (file)
@@ -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 <qmap.h>
 #include <qaction.h>
 
 #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<int,int>   myUpdateIds;
 };
 
+/*!
+  \class QtxActionToolMgr::ToolCreator
+  Allows to create automatically toolbar by data read from file
+*/
 class QtxActionToolMgr::ToolCreator : public QtxActionMgr::Creator
 {
 public:
index 68811c5f3ec727cdcb7de047a9cdd6bf68207341..aa1189152b2d50efe924041b7bb32066a9e06e97 100644 (file)
@@ -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 ) );
index c4ff62142818f6de24204f48d91bef18bb4f40b4..7a6c21f3470586bc78fb2bfaa6bc2841d7dbb7b9 100644 (file)
@@ -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;