Salome HOME
Improve locale selection actvation in case if sub-shape of any type can be selected...
[modules/gui.git] / src / Qtx / QtxWorkspaceAction.cxx
index c630ff47d099c2d85769408f497475d4af2f883a..5bac837df3e87f8504936e52d15af368f7535ebb 100644 (file)
-// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-// 
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either 
-// version 2.1 of the License.
-// 
-// This library is distributed in the hope that it will be useful 
-// but WITHOUT ANY WARRANTY; without even the implied warranty of 
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 // Lesser General Public License for more details.
 //
-// You should have received a copy of the GNU Lesser General Public  
-// License along with this library; if not, write to the Free Software 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 // File:      QtxWorkspaceAction.cxx
 // Author:    Sergey TELKOV
-
+//
 #include "QtxWorkspaceAction.h"
 
-#include <qpopupmenu.h>
-#include <qworkspace.h>
-#include <qwidgetlist.h>
-
-QtxWorkspaceAction::QtxWorkspaceAction( QWorkspace* ws, QObject* parent, const char* name )
-: QtxAction( tr( "Controls windows into workspace" ), tr( "Workspace management" ), 0, parent, name ),
-myFlags( Standard ),
-myWorkspace( ws )
+#include "QtxWorkspace.h"
+
+#include <QMenu>
+#include <QWidgetList>
+
+/*!
+  \class QtxWorkspaceAction
+  \brief Implements actions group for menu Windows with standard operations, like
+         "Cascade", "Tile", "Tile Horizontally", etc.
+*/
+
+/*!
+  \brief Constructor.
+  \param ws parent workspace
+  \param parent parent object (owner of the action)
+*/
+QtxWorkspaceAction::QtxWorkspaceAction( QtxWorkspace* ws, QObject* parent )
+: QtxActionSet( parent ),
+  myWorkspace( ws ),
+  myWindowsFlag( true )
 {
-  myItem.insert( Cascade, new QtxAction( tr( "Arranges the windows as overlapping tiles" ),
-                                         tr( "Cascade" ), 0, this, 0, false ) );
-  myItem.insert( Tile,    new QtxAction( tr( "Arranges the windows as nonoverlapping tiles" ),
-                                         tr( "Tile" ), 0, this, 0, false ) );
-  myItem.insert( HTile,   new QtxAction( tr( "Arranges the windows as nonoverlapping horizontal tiles" ),
-                                         tr( "Tile horizontally" ), 0, this, 0, false ) );
-  myItem.insert( VTile,   new QtxAction( tr( "Arranges the windows as nonoverlapping vertical tiles" ),
-                                         tr( "Tile vertically" ), 0, this, 0, false ) );
-
-  connect( myItem[Tile], SIGNAL( activated() ), this, SLOT( tile() ) );
-  connect( myItem[Cascade], SIGNAL( activated() ), this, SLOT( cascade() ) );
-  connect( myItem[HTile], SIGNAL( activated() ), this, SLOT( tileVertical() ) );
-  connect( myItem[VTile], SIGNAL( activated() ), this, SLOT( tileHorizontal() ) );
+  insertAction( new QtxAction( tr( "Arranges the windows as overlapping tiles" ),
+                               tr( "Cascade" ), 0, this ), Cascade );
+  insertAction( new QtxAction( tr( "Arranges the windows as nonoverlapping tiles" ),
+                               tr( "Tile" ), 0, this ), Tile );
+  insertAction( new QtxAction( tr( "Arranges the windows as nonoverlapping horizontal tiles" ),
+                               tr( "Tile horizontally" ), 0, this ), HTile );
+  insertAction( new QtxAction( tr( "Arranges the windows as nonoverlapping vertical tiles" ),
+                               tr( "Tile vertically" ), 0, this ), VTile );
+
+  connect( this, SIGNAL( triggered( int ) ), this, SLOT( onTriggered( int ) ) );
+
+  setMenuActions( Standard );
 }
 
+/*!
+  \brief Destructor.
+*/
 QtxWorkspaceAction::~QtxWorkspaceAction()
 {
 }
 
-QWorkspace* QtxWorkspaceAction::workspace() const
+/*!
+  \brief Get workspace.
+  \return parent workspace
+*/
+QtxWorkspace* QtxWorkspaceAction::workspace() const
 {
   return myWorkspace;
 }
 
-int QtxWorkspaceAction::items() const
-{
-  return myFlags;
-}
+/*!
+  \brief Set actions to be visible in the menu.
+  
+  Actions, which IDs are set in \a flags parameter, will be shown in the 
+  menu bar. Other actions will not be shown.
 
-void QtxWorkspaceAction::setItems( const int flags )
+  \param flags ORed together actions flags
+*/
+void QtxWorkspaceAction::setMenuActions( const int flags )
 {
-  if ( !flags || flags == myFlags || !( flags & Operations ) )
-    return;
-
-  myFlags = flags;
+  action( Cascade )->setVisible( flags & Cascade );
+  action( Tile )->setVisible( flags & Tile );
+  action( VTile )->setVisible( flags & VTile );
+  action( HTile )->setVisible( flags & HTile );
+  myWindowsFlag = flags & Windows;
 }
 
-bool QtxWorkspaceAction::hasItems( const int flags ) const
+/*!
+  \brief Get menu actions which are currently visible in the menu bar.
+  \return ORed together actions flags
+  \sa setMenuActions()
+*/
+int QtxWorkspaceAction::menuActions() const
 {
-  return ( myFlags & flags ) == flags;
+  int ret = 0;
+  ret = ret | ( action( Cascade )->isVisible() ? Cascade : 0 );
+  ret = ret | ( action( Tile )->isVisible() ? Tile : 0 );
+  ret = ret | ( action( VTile )->isVisible() ? VTile : 0 );
+  ret = ret | ( action( HTile )->isVisible() ? HTile : 0 );
+  ret = ret | ( myWindowsFlag ? Windows : 0 );
+  return ret;
 }
 
+/*!
+  \brief Get keyboard accelerator for the specified action.
+  \param id menu action ID
+  \return keyboard accelerator of menu item or 0 if there is no such action
+*/
 int QtxWorkspaceAction::accel( const int id ) const
 {
   int a = 0;
-  if ( myItem.contains( id ) )
-    a = myItem[id]->accel();
+  if ( action( id ) )
+    a = action( id )->shortcut();
   return a;
 }
 
-QIconSet QtxWorkspaceAction::iconSet( const int id ) const
+/*!
+  \brief Get icon for the specified action.
+
+  If \a id is invalid, null icon is returned.
+
+  \param id menu action ID
+  \return menu item icon
+*/
+QIcon QtxWorkspaceAction::icon( const int id ) const
 {
-  QIconSet ico;
-  if ( myItem.contains( id ) )
-    ico = myItem[id]->iconSet();
+  QIcon ico;
+  if ( action( id ) )
+    ico = action( id )->icon();
   return ico;
 }
 
-QString QtxWorkspaceAction::menuText( const int id ) const
+/*!
+  \brief Get menu item text for the specified action.
+  \param id menu action ID
+  \return menu item text or null QString if there is no such action
+*/
+QString QtxWorkspaceAction::text( const int id ) const
 {
   QString txt;
-  if ( myItem.contains( id ) )
-    txt = myItem[id]->menuText();
+  if ( action( id ) )
+    txt = action( id )->text();
   return txt;
 }
 
+/*!
+  \brief Get status bar tip for the specified action.
+  \param id menu action ID
+  \return status bar tip menu item or null QString if there is no such action
+*/
 QString QtxWorkspaceAction::statusTip( const int id ) const
 {
   QString txt;
-  if ( myItem.contains( id ) )
-    txt = myItem[id]->statusTip();
+  if ( action( id ) )
+    txt = action( id )->statusTip();
   return txt;
 }
 
+/*!
+  \brief Set keyboard accelerator for the specified action.
+  \param id menu action ID
+  \param a new keyboard accelerator
+*/
 void QtxWorkspaceAction::setAccel( const int id, const int a )
 {
-  if ( myItem.contains( id ) )
-    myItem[id]->setAccel( a );
+  if ( action( id ) )
+    action( id )->setShortcut( a );
 }
 
-void QtxWorkspaceAction::setIconSet( const int id, const QIconSet& ico )
+/*!
+  \brief Set menu item icon for the specified action.
+  \param id menu action ID
+  \param ico new menu item icon
+*/
+void QtxWorkspaceAction::setIcon( const int id, const QIcon& icon )
 {
-  if ( myItem.contains( id ) )
-    myItem[id]->setIconSet( ico );
+  if ( action( id ) )
+    action( id )->setIcon( icon );
 }
 
-void QtxWorkspaceAction::setMenuText( const int id, const QString& txt )
+/*!
+  \brief Set menu item text for the specified action.
+  \param id menu action ID
+  \param txt new menu item text
+*/
+void QtxWorkspaceAction::setText( const int id, const QString& txt )
 {
-  if ( myItem.contains( id ) )
-    myItem[id]->setMenuText( txt );
+  if ( action( id ) )
+    action( id )->setText( txt );
 }
 
+/*!
+  \brief Set menu item status bar tip for the specified action.
+  \param id menu action ID
+  \param txt new menu item status bar tip
+*/
 void QtxWorkspaceAction::setStatusTip( const int id, const QString& txt )
 {
-  if ( myItem.contains( id ) )
-    myItem[id]->setStatusTip( txt );
-}
-
-bool QtxWorkspaceAction::addTo( QWidget* wid )
-{
-  return addTo( wid, -1 );
-}
-
-bool QtxWorkspaceAction::addTo( QWidget* wid, const int idx )
-{
-  if ( !wid || !wid->inherits( "QPopupMenu" ) )
-    return false;
-
-  QPopupMenu* pm = (QPopupMenu*)wid;
-  checkPopup( pm );
-
-  if ( myMenu.contains( pm ) )
-    return false;
-
-  myMenu.insert( pm, QIntList() );
-  fillPopup( pm, idx );
-
-  connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
-  connect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
-
-  return true;
-}
-
-bool QtxWorkspaceAction::removeFrom( QWidget* wid )
-{
-  if ( !wid || !wid->inherits( "QPopupMenu" ) )
-    return false;
-
-  QPopupMenu* pm = (QPopupMenu*)wid;
-  if ( !myMenu.contains( pm ) )
-    return false;
-
-  clearPopup( pm );
-
-  disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
-  disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
-
-  myMenu.remove( pm );
-
-  return true;
+  if ( action( id ) )
+    action( id )->setStatusTip( txt );
 }
 
+/*!
+  \brief Process action activated by the user.
+  \param type action ID
+*/
 void QtxWorkspaceAction::perform( const int type )
 {
   switch ( type )
@@ -191,229 +231,187 @@ void QtxWorkspaceAction::perform( const int type )
   }
 }
 
+/*!
+  \brief Tile child windows in the workspace.
+*/
 void QtxWorkspaceAction::tile()
 {
-  QWorkspace* ws = workspace();
-  if ( !ws )
-    return;
-
-  ws->tile();
+  QtxWorkspace* ws = workspace();
+  if ( ws )
+    ws->tile();
 }
 
+/*!
+  \brief Cascade child windows in the workspace.
+*/
 void QtxWorkspaceAction::cascade()
 {
-  QWorkspace* ws = workspace();
+  QtxWorkspace* ws = workspace();
   if ( !ws )
     return;
 
   ws->cascade();
 
-       int w = ws->width();
-       int h = ws->height();
+        int w = ws->width();
+        int h = ws->height();
 
-       QWidgetList winList = ws->windowList();
-       for ( QWidgetListIt it( winList ); it.current(); ++it )
-               it.current()->resize( int( w * 0.8 ), int( h * 0.8 ) );
+        QWidgetList winList = ws->windowList();
+  for ( QWidgetList::iterator it = winList.begin(); it != winList.end(); ++it )
+                (*it)->resize( int( w * 0.8 ), int( h * 0.8 ) );
 }
 
+/*!
+  \brief Tile child windows in the workspace in the vertical direction.
+*/
 void QtxWorkspaceAction::tileVertical()
 {
-  QWorkspace* wrkSpace = workspace();
-       if ( !wrkSpace )
-               return;
-       
-       QWidgetList winList = wrkSpace->windowList();
-       if ( winList.isEmpty() )
-    return;
-
-  int count = 0;
-       for ( QWidgetListIt itr( winList ); itr.current(); ++itr )
-    if ( !itr.current()->testWState( WState_Minimized ) )
-      count++;
-
-  if ( !count )
-    return;
-
-       int y = 0;
-
-       int heightForEach = wrkSpace->height() / count;
-       for ( QWidgetListIt it( winList ); it.current(); ++it )
-       {
-    QWidget* win = it.current();
-    if ( win->testWState( WState_Minimized ) )
-      continue;
-
-    if ( win->testWState( WState_Maximized ) )
-               {
-                       win->hide();
-                       win->showNormal();
-    }
-    int prefH = win->minimumHeight() + win->parentWidget()->baseSize().height();
-    int actualH = QMAX( heightForEach, prefH );
-
-    win->parentWidget()->setGeometry( 0, y, wrkSpace->width(), actualH );
-    y += actualH;
-       }
+  QtxWorkspace* ws = workspace();
+  if ( ws )
+    ws->tileVertical();
 }
 
+/*!
+  \brief Tile child windows in the workspace in the horizontal direction.
+*/
 void QtxWorkspaceAction::tileHorizontal()
 {
-  QWorkspace* wrkSpace = workspace();
-       if ( !wrkSpace )
-               return;
-
-       QWidgetList winList = wrkSpace->windowList();
-       if ( winList.isEmpty() )
-    return;
-
-  int count = 0;
-       for ( QWidgetListIt itr( winList ); itr.current(); ++itr )
-    if ( !itr.current()->testWState( WState_Minimized ) )
-      count++;
-
-  if ( !count )
-    return;
-
-       int x = 0;
-       int widthForEach = wrkSpace->width() / count;
-       for ( QWidgetListIt it( winList ); it.current(); ++it )
-       {
-    QWidget* win = it.current();
-    if ( win->testWState( WState_Minimized ) )
-      continue;
-
-    if ( win->testWState( WState_Maximized ) )
-               {
-                       win->hide();
-                       win->showNormal();
-    }
-    int prefW = win->minimumWidth();
-    int actualW = QMAX( widthForEach, prefW );
-        
-               win->parentWidget()->setGeometry( x, 0, actualW, wrkSpace->height() );
-    x += actualW;
-       }
+  QtxWorkspace* ws = workspace();
+  if ( ws )
+    ws->tileHorizontal();
 }
 
-void QtxWorkspaceAction::onAboutToShow()
+/*!
+  \brief Called when action is added to the menu bar.
+  \param w menu bar widget this action is being added to
+*/
+void QtxWorkspaceAction::addedTo( QWidget* w )
 {
-  const QObject* obj = sender();
-  if ( !obj || !obj->inherits( "QPopupMenu" ) )
-    return;
+  QtxActionSet::addedTo( w );
 
-  updatePopup( (QPopupMenu*)obj );
+  QMenu* pm = ::qobject_cast<QMenu*>( w );
+  if ( pm )
+    connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
 }
 
-void QtxWorkspaceAction::onPopupDestroyed( QObject* obj )
+/*!
+  \brief Called when action is removed from the menu bar.
+  \param w menu bar widget this action is being removed from
+*/
+void QtxWorkspaceAction::removedFrom( QWidget* w )
 {
-  myMenu.remove( (QPopupMenu*)obj );
-}
-
-void QtxWorkspaceAction::checkPopup( QPopupMenu* pm )
-{
-  if ( !myMenu.contains( pm ) )
-    return;
+  QtxActionSet::removedFrom( w );
 
-  QIntList updList;
-  for ( QIntList::const_iterator it = myMenu[pm].begin(); it != myMenu[pm].end(); ++it )
-  {
-    if ( pm->indexOf( *it ) != -1 )
-      updList.append( *it );
-  }
-
-  myMenu.remove( pm );
-
-  if ( !updList.isEmpty() )
-    myMenu.insert( pm, updList );
-  else
-  {
+  QMenu* pm = ::qobject_cast<QMenu*>( w );
+  if ( pm )
     disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
-    disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
-  }
 }
 
-void QtxWorkspaceAction::updatePopup( QPopupMenu* pm )
+/*!
+  \brief Update all menu action state.
+*/
+void QtxWorkspaceAction::updateContent()
 {
-  if ( !myMenu.contains( pm ) )
-    return;
-
-  fillPopup( pm, clearPopup( pm ) );
-
   bool count = workspace() ? workspace()->windowList().count() : 0;
-  myItem[Cascade]->setEnabled( count );
-  myItem[Tile]->setEnabled( count );
-  myItem[HTile]->setEnabled( count );
-  myItem[VTile]->setEnabled( count );
-}
-
-int QtxWorkspaceAction::clearPopup( QPopupMenu* pm )
-{
-  if ( !myMenu.contains( pm ) )
-    return -1;
+  action( Cascade )->setEnabled( count );
+  action( Tile )->setEnabled( count );
+  action( HTile )->setEnabled( count );
+  action( VTile )->setEnabled( count );
 
-  int idx = -1;
-  const QIntList& lst = myMenu[pm];
-  for ( QIntList::const_iterator it = lst.begin(); it != lst.end() && idx == -1; ++it )
-    idx = pm->indexOf( *it );
-
-  for ( ItemMap::ConstIterator mit = myItem.begin(); mit != myItem.end(); ++mit )
-    mit.data()->removeFrom( pm );
-
-  for ( QIntList::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
-    pm->removeItem( *itr );
-
-  return idx;
+  updateWindows();
 }
 
-void QtxWorkspaceAction::fillPopup( QPopupMenu* pm, const int idx )
+/*!
+  \brief Update actions which refer to the opened child windows.
+*/
+void QtxWorkspaceAction::updateWindows()
 {
-  if ( !pm )
+  QtxWorkspace* ws = workspace();
+  if ( !ws )
     return;
 
-  int index = idx < 0 ? pm->count() : QMIN( (int)pm->count(), idx );
+  QList<QAction*> lst = actions();
+  for ( QList<QAction*>::iterator it = lst.begin(); it != lst.end(); ++it )
+  {
+    int id = actionId( *it );
+    if ( id >= Windows )
+      removeAction( *it );
+  }
 
-  myMenu.insert( pm, QIntList() );
-  QIntList& lst = myMenu[pm];
+  bool base = action( Cascade )->isVisible() || action( Tile )->isVisible() ||
+              action( HTile )->isVisible() || action( VTile )->isVisible();
 
-  for ( ItemMap::ConstIterator mit = myItem.begin(); mit != myItem.end(); ++mit )
+  QList<QAction*> items;
+  QMap<QAction*, int> map;
+  if ( menuActions() & Windows )
   {
-    if ( !hasItems( mit.key() ) )
-      continue;
+    int index = 1;
+    QWidgetList wList = ws->windowList();
+    for ( QWidgetList::iterator it = wList.begin(); it != wList.end(); ++it, index++ )
+    {
+      QWidget* wid = *it;
+      QAction* a = new QtxAction( wid->windowTitle(), wid->windowTitle(), 0, this, true );
+      a->setChecked( wid == ws->activeWindow() );
+      items.append( a );
+      map.insert( a, Windows + index );
+    }
 
-    mit.data()->addTo( pm, index );
-    lst.append( pm->idAt( index++ ) );
+    if ( base && !items.isEmpty() )
+    {
+      QAction* sep = new QtxAction( this );
+      sep->setSeparator( true );
+      items.prepend( sep );
+      map.insert( sep, Windows );
+    }
   }
 
-  QWorkspace* ws = workspace();
-  if ( !ws || !hasItems( Windows ) )
-    return;
+  if ( !items.isEmpty() )
+    insertActions( items );
 
-  QWidgetList wList = ws->windowList();
-  if ( wList.isEmpty() )
-    return;
+  for ( QMap<QAction*, int>::const_iterator itr = map.begin(); itr != map.end(); ++itr )
+    setActionId( itr.key(), itr.value() );
+}
 
-  lst.append( pm->insertSeparator( index++ ) );
+/*!
+  \brief Called when parent menu is about to show.
 
-  int param = 0;
-  pm->setCheckable( true );
-  for ( QWidgetListIt it( wList ); it.current(); ++it )
-  {
-    int id = pm->insertItem( it.current()->caption(), this, SLOT( onItemActivated( int ) ), 0, -1, index++ );
-    pm->setItemParameter( id, param++ );
-    pm->setItemChecked( id, it.current() == ws->activeWindow() );
-    lst.append( id );
-  }
+  Updates all menu items.
+*/
+void QtxWorkspaceAction::onAboutToShow()
+{
+  QMenu* pm = ::qobject_cast<QMenu*>( sender() );
+  if ( pm )
+    updateContent();
 }
 
-void QtxWorkspaceAction::onItemActivated( int idx )
+/*!
+  \brief Called when menu item corresponding to some child window is activated.
+
+  Activates correposponding child window.
+
+  \param idx menu item index
+*/
+void QtxWorkspaceAction::activateItem( const int idx )
 {
-  QWorkspace* ws = workspace();
+  QtxWorkspace* ws = workspace();
   if ( !ws )
     return;
 
   QWidgetList wList = ws->windowList();
-  if ( idx < 0 || idx >= (int)wList.count() )
-    return;
+  if ( idx >= 0 && idx < (int)wList.count() )
+    wList.at( idx )->setFocus();
+}
+
+/*!
+  \brief Called when menu item is activated by the user.
+  
+  Perform the corresponding action.
 
-  wList.at( idx )->setFocus();
+  \param id menu item identifier
+*/
+void QtxWorkspaceAction::onTriggered( int id )
+{
+  if ( id < Windows )
+    perform( id );
+  else
+    activateItem( id - Windows - 1 );
 }