1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: QtxActionToolMgr.cxx
24 // Author: Alexander SOLOVYOV, Sergey TELKOV
26 #include "QtxActionToolMgr.h"
28 #include "QtxAction.h"
29 #include "QtxToolBar.h"
31 #include <QApplication>
33 #include <QMainWindow>
36 \class QtxActionToolMgr::ToolNode
37 \brief Represents a toolbutton inside toolbar structure.
42 \fn QtxActionToolMgr::ToolNode::ToolNode()
44 \brief Default constructor.
48 \fn QtxActionToolMgr::ToolNode::ToolNode( const int _id )
51 \param _id toolbar node ID
55 \class QtxActionToolMgr
56 \brief Toolbar actions manager.
58 Toolbar manager allows using of set of action for automatic generating of
59 application toolbars and dynamic update of toolbars contents.
61 Use insert(), append() and remove() methods to create toolbar and add actions to it.
62 Methods show(), hide() allow displaying/erasing of specified toolbar items.
64 Toolbar manager automatically optimizes toolbars by removing extra separators, etc.
69 \param p parent main window
71 QtxActionToolMgr::QtxActionToolMgr( QMainWindow* p )
80 QtxActionToolMgr::~QtxActionToolMgr()
85 \brief Get parent main window.
86 \return main window pointer
88 QMainWindow* QtxActionToolMgr::mainWindow() const
94 \brief Create toolbar and assign \a id to it.
96 If \a tid is less than 0, the identifier is generated automatically.
97 If toolbar with given \a tid is already registered, the toolbar will not be created.
99 \param title toolbar title
100 \param tid requested toolbar ID
101 \param mw parent main window; if it is null, the tool manager's main window is used
102 \param vis show toolbar visible immediately after creation (true by default)
103 \return id of created/found toolbar
105 int QtxActionToolMgr::createToolBar( const QString& title, const int tid, QMainWindow* mw, bool vis )
107 return createToolBar( title, true, Qt::AllToolBarAreas, tid, mw, vis );
111 \brief Create toolbar and assign \a id to it.
113 If \a tid is less than 0, the identifier is generated automatically.
114 If toolbar with given \a tid is already registered, the toolbar will not be created.
116 The parameter \a name can be specified to give an unique string identifier to the toolbar.
117 This can be useful in the multi-language environment where identifier of the toolbar should
118 not be dependant on the language chosen (e.g. to store positions of toolbars of main menu
121 \param title toolbar title
122 \param name toolbar name (identifier)
123 \param tid requested toolbar ID
124 \param mw parent main window; if it is null, the tool manager's main window is used
125 \param vis show toolbar visible immediately after creation (true by default)
126 \return id of created/found toolbar
128 int QtxActionToolMgr::createToolBar( const QString& title, const QString& name, const int tid, QMainWindow* mw, bool vis )
130 return createToolBar( title, name, true, Qt::AllToolBarAreas, tid, mw, vis );
134 \brief Create toolbar and assign \a id to it.
136 If \a tid is less than 0, the identifier is generated automatically.
137 If toolbar with given \a tid is already registered, the toolbar will not be created.
139 The parameter \a name can be specified to give an unique string identifier to the toolbar.
140 This can be useful in the multi-language environment where identifier of the toolbar should
141 not be dependant on the language chosen (e.g. to store positions of toolbars of main menu
144 \param title toolbar title
145 \param name toolbar name (identifier)
146 \param floatable if \c true, new toolbar is made floatable
147 \param dockAreas dock areas of the main window where the new toolbar can be situated
148 \param tid requested toolbar ID
149 \param mw parent main window; if it is null, the tool manager's main window is used
150 \param vis show toolbar visible immediately after creation (true by default)
151 \return id of created/found toolbar
153 int QtxActionToolMgr::createToolBar( const QString& title, const QString& name, bool floatable, Qt::ToolBarAreas dockAreas,
154 int tid, QMainWindow* mw, bool vis )
156 static int _toolBarId = -1;
159 for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && tbId == -1; ++it )
161 if( it.value().toolBar->windowTitle().toLower() == title.toLower() &&
162 ( !mw || it.value().toolBar->parent()==mw ) )
169 QMainWindow* tbw = mw ? mw : mainWindow();
170 QToolBar* tb = find( title, tbw );
172 tbId = tid < 0 ? --_toolBarId : tid;
174 myToolBars.insert( tbId, ToolBarInfo() );
175 ToolBarInfo& tInfo = myToolBars[tbId];
179 tb = new QtxToolBar( true, tbw );
180 //tb->setVisible( false ); // VSR: create toolbar visible initially
181 tb->setFloatable( floatable );
182 tb->setAllowedAreas( dockAreas );
183 tb->setMovable( dockAreas & Qt::AllToolBarAreas );
184 //mainWindow()->addToolBar( tb );
185 tb->setWindowTitle( title );
186 tb->setObjectName( name.isEmpty() ? title : name );
187 tb->setToolTip( title );
189 QApplication::postEvent( tb, new QHideEvent());
193 connect( tInfo.toolBar, SIGNAL( destroyed() ), this, SLOT( onToolBarDestroyed() ) );
199 \brief Create toolbar and assign \a id to it.
201 If \a tid is less than 0, the identifier is generated automatically.
202 If toolbar with given \a tid is already registered, the toolbar will not be created.
204 \param title toolbar title
205 \param floatable if \c true, new toolbar is made floatable
206 \param dockAreas dock areas of the main window where the new toolbar can be situated
207 \param tid requested toolbar ID
208 \param mw parent main window; if it is null, the tool manager's main window is used
209 \param vis show toolbar visible immediately after creation (true by default)
210 \return id of created/found toolbar
212 int QtxActionToolMgr::createToolBar( const QString& title, bool floatable, Qt::ToolBarAreas dockAreas,
213 int tid, QMainWindow* mw, bool vis )
215 return createToolBar( title, QString(), floatable, dockAreas, tid, mw, vis );
219 \brief Search toolbar with given \a title owned by main window \mw.
220 \param title toolbar title
221 \param mw main window
222 \return toolbar or 0 if it is not found
224 QToolBar* QtxActionToolMgr::find( const QString& title, QMainWindow* mw ) const
229 QString pattern = title.toLower();
232 QList<QToolBar*> toolbars = mw->findChildren<QToolBar*>();
233 for ( QList<QToolBar*>::iterator it = toolbars.begin(); it != toolbars.end() && !res; ++it )
235 if ( (*it)->windowTitle().toLower() == pattern )
242 \brief Remove toolbar.
243 \param tid toolbar ID
245 void QtxActionToolMgr::removeToolBar( const int tid )
247 if ( !myToolBars.contains( tid ) )
250 delete myToolBars[tid].toolBar;
251 myToolBars.remove( tid );
255 \brief Remove toolbar.
256 \param title toolbar title
258 void QtxActionToolMgr::removeToolBar( const QString& title )
260 removeToolBar( find( title ) );
264 \brief Insert action into toolbar.
266 \param tid toolbar ID
267 \param idx action index in the toolbar (if < 0, action is appended to the end)
270 int QtxActionToolMgr::insert( const int id, const int tid, const int idx )
272 if ( !contains( id ) || !hasToolBar( tid ) )
275 if ( containsAction( id, tid ) )
280 NodeList& list = myToolBars[tid].nodes;
281 int index = idx < 0 ? list.count() : qMin( idx, (int)list.count() );
282 list.insert( index, node );
283 triggerUpdate( tid );
289 \brief Insert action into toolbar.
291 \param tid toolbar ID
292 \param idx action index in the toolbar (if < 0, action is appended to the end)
295 int QtxActionToolMgr::insert( QAction* a, const int tid, const int idx )
297 return insert( registerAction( a ), tid, idx );
301 \brief Insert action into toolbar.
303 \param title toolbar title
304 \param idx action index in the toolbar (if < 0, action is appended to the end)
307 int QtxActionToolMgr::insert( const int id, const QString& title, const int idx )
309 return insert( id, createToolBar( title ), idx );
313 \brief Insert action into toolbar.
315 \param title toolbar title
316 \param idx action index in the toolbar (if < 0, action is appended to the end)
319 int QtxActionToolMgr::insert( QAction* a, const QString& title, const int idx )
321 return insert( registerAction( a ), createToolBar( title ), idx );
325 \brief Append action to the end of toolbar.
327 \param tid toolbar ID
330 int QtxActionToolMgr::append( const int id, const int tid )
332 return insert( id, tid );
336 \brief Append action to the end of toolbar.
338 \param tid toolbar ID
341 int QtxActionToolMgr::append( QAction* a, const int tid )
343 return insert( a, tid );
347 \brief Append action to the end of toolbar.
349 \param title toolbar title
352 int QtxActionToolMgr::append( const int id, const QString& title )
354 return insert( id, title );
358 \brief Append action to the end of toolbar.
360 \param title toolbar title
363 int QtxActionToolMgr::append( QAction* a, const QString& title )
365 return insert( a, title );
369 \brief Insert action to the beginning of toolbar.
371 \param tid toolbar ID
374 int QtxActionToolMgr::prepend( const int id, const int tid )
376 return insert( id, tid, 0 );
380 \brief Insert action to the beginning of toolbar.
382 \param tid toolbar ID
385 int QtxActionToolMgr::prepend( QAction* a, const int tid )
387 return insert( a, tid, 0 );
391 \brief Insert action to the beginning of toolbar.
393 \param title toolbar title
396 int QtxActionToolMgr::prepend( const int id, const QString& title )
398 return insert( id, title, 0 );
402 \brief Insert action to the beginning of toolbar.
404 \param title toolbar title
407 int QtxActionToolMgr::prepend( QAction* a, const QString& title )
409 return insert( a, title, 0 );
413 \brief Remove action from toolbar.
415 \param tid toolbar ID
417 void QtxActionToolMgr::remove( const int id, const int tid )
419 if ( !myToolBars.contains( tid ) )
423 const NodeList& nodes = myToolBars[tid].nodes;
424 for ( NodeList::const_iterator it = nodes.begin(); it != nodes.end(); ++it )
426 if ( (*it).id != id )
427 newList.append( *it );
430 myToolBars[tid].nodes = newList;
432 triggerUpdate( tid );
436 \brief Remove action from toolbar.
438 \param title toolbar title
440 void QtxActionToolMgr::remove( const int id, const QString& title )
442 remove( id, find( title ) );
446 \brief Remove all actions from toolbar.
447 \param tid toolbar ID
449 void QtxActionToolMgr::clear( const int tid )
451 if ( !myToolBars.contains( tid ) )
454 myToolBars[tid].nodes.clear();
456 triggerUpdate( tid );
460 \brief Remove all actions from toolbar.
461 \param title toolbar title
463 void QtxActionToolMgr::clear( const QString& title )
465 clear( find( title ) );
469 \brief Get toolbar by given \a tid.
470 \param tid toolbar ID
471 \return toolbar or 0 if it is not found
473 QToolBar* QtxActionToolMgr::toolBar( const int tid ) const
476 if ( myToolBars.contains( tid ) )
477 tb = myToolBars[tid].toolBar;
482 \brief Get toolbar by given \a title.
483 \param title toolbar title
484 \return toolbar or 0 if it is not found
486 QToolBar* QtxActionToolMgr::toolBar( const QString& title ) const
488 return toolBar( find( title ) );
492 \bried Get all registered toolbars identifiers
493 \return list of toolbars ids
495 QIntList QtxActionToolMgr::toolBarsIds() const
497 return myToolBars.keys();
501 \brief Check if toolbar with given \a id already registered.
502 \param tid toolbar ID
503 \return \c true if toolbar is registered in the toolbar manager
505 bool QtxActionToolMgr::hasToolBar( const int tid ) const
507 return myToolBars.contains( tid );
511 \brief Check if toolbar with given \a id already registered.
512 \param title toolbar title
513 \return \c true if toolbar is registered in the toolbar manager
515 bool QtxActionToolMgr::hasToolBar( const QString& title ) const
517 return find( title ) != -1;
521 \brief Check if toolbar contains given action.
523 \param tid toolbar ID
524 \return \c true if toolbar contains action
526 bool QtxActionToolMgr::containsAction( const int id, const int tid ) const
528 for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
530 if ( tid == -1 || it.key() == tid )
532 const NodeList& list = it.value().nodes;
533 for ( NodeList::const_iterator nit = list.begin(); nit != list.end(); ++nit )
534 if ( (*nit).id == id )
542 \brief Get index of the action \a id within the toolbar \a tid
544 \param tid toolbar ID
545 \return index of the action in the toolbar or -1 if action is not contained in the toolbar
547 int QtxActionToolMgr::index( const int id, const int tid ) const
549 for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
551 if ( it.key() == tid )
553 const NodeList& list = it.value().nodes;
555 for ( NodeList::const_iterator nit = list.begin(); nit != list.end(); ++nit, ++idx )
556 if ( (*nit).id == id ) return idx;
563 \brief Called when toolbar is destroyed.
565 Clears internal pointer to the toolbar to disable crashes.
567 void QtxActionToolMgr::onToolBarDestroyed()
569 myToolBars.remove( find( (QToolBar*)sender() ) );
573 \brief Search toolbar by given \a name.
574 \param title toolbar title
575 \return toolbar ID or -1 if it is not found
577 int QtxActionToolMgr::find( const QString& title ) const
580 for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && id == -1; ++it )
582 if ( it.value().toolBar->windowTitle() == title )
589 \brief Get toolbar identifier.
591 \return toolbar ID or -1 if toolbar is not registered
593 int QtxActionToolMgr::find( QToolBar* tb ) const
596 for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && id == -1; ++it )
598 if ( it.value().toolBar == tb )
605 \brief Update toolbar.
606 \param tid toolbar ID
608 void QtxActionToolMgr::updateToolBar( const int tid )
610 if ( !isUpdatesEnabled() )
613 if ( !myToolBars.contains( tid ) )
616 QToolBar* tb = myToolBars[tid].toolBar;
617 const NodeList& list = myToolBars[tid].nodes;
619 for ( NodeList::const_iterator it = list.begin(); it != list.end(); ++it )
621 QAction* a = action( (*it).id );
622 tb->removeAction( a );
624 // a->removeFrom( tb );
629 for ( NodeList::const_iterator itr = list.begin(); itr != list.end(); ++itr )
631 if ( !isVisible( (*itr).id, tid ) )
634 QAction* a = action( (*itr).id );
640 simplifySeparators( tb );
643 if ( !tb->isVisible() )
649 \brief Update all registered toolbars.
651 void QtxActionToolMgr::internalUpdate()
653 if ( !isUpdatesEnabled() )
656 for ( ToolBarMap::ConstIterator it1 = myToolBars.begin(); it1 != myToolBars.end(); ++it1 )
657 updateToolBar( it1.key() );
663 \brief Remove extra separators from the toolbar.
666 void QtxActionToolMgr::simplifySeparators( QToolBar* tb )
668 Qtx::simplifySeparators( tb );
672 \brief Show action (in all toolbars).
675 void QtxActionToolMgr::show( const int id )
677 setShown( id, true );
681 \brief Hide action (in all toolbars).
684 void QtxActionToolMgr::hide( const int id )
686 setShown( id, false );
690 \brief Set visibility status for toolbar action with given \a id.
692 \param on new visibility status
694 void QtxActionToolMgr::setShown( const int id, const bool on )
696 for ( ToolBarMap::Iterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
697 setVisible( id, it.key(), on );
701 \brief Get visibility status for toolbar action with given \a id.
703 \return \c true if action is shown in all toolbars
705 bool QtxActionToolMgr::isShown( const int id ) const
707 QList<const ToolNode*> nodes;
708 for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
710 const NodeList& nl = it.value().nodes;
711 for ( NodeList::const_iterator itr = nl.begin(); itr != nl.end(); ++itr )
713 const ToolNode& node = *itr;
715 nodes.append( &node );
719 if ( nodes.isEmpty() )
723 for ( QList<const ToolNode*>::iterator itr = nodes.begin(); itr != nodes.end() && vis; ++itr )
724 vis = (*itr)->visible;
730 \brief Check if an action with given \a id is visible in the toolbar \a tid.
732 \param tid toolbar ID
733 \return \c true if action is shown in the toolbar
735 bool QtxActionToolMgr::isVisible( const int id, const int tid ) const
737 if ( !myToolBars.contains( tid ) )
741 const ToolBarInfo& inf = myToolBars[tid];
742 for ( NodeList::const_iterator it = inf.nodes.begin(); it != inf.nodes.end() && !vis; ++it )
744 const ToolNode& node = *it;
753 \brief Show/hide action with given \a id in the toolbar \a tid.
755 \param tid toolbar ID
756 \param on new visibility status
758 void QtxActionToolMgr::setVisible( const int id, const int tid, const bool on )
760 if ( !myToolBars.contains( tid ) )
763 bool changed = false;
764 NodeList& lst = myToolBars[tid].nodes;
765 for ( NodeList::iterator it = lst.begin(); it != lst.end(); ++it )
767 ToolNode& node = *it;
770 changed = changed || node.visible != on;
776 triggerUpdate( tid );
782 \brief Load toolbar contents from the file.
783 \param fname file name
784 \param r actions reader
785 \return \c true on success and \c false on error
787 bool QtxActionToolMgr::load( const QString& fname, QtxActionMgr::Reader& r )
789 ToolCreator cr( &r, this );
790 return r.read( fname, cr );
794 \brief Called when delayed content update is performed.
796 Customizes the content update operation.
798 void QtxActionToolMgr::updateContent()
800 if ( !isUpdatesEnabled() )
803 for ( QMap<int,int>::const_iterator it = myUpdateIds.constBegin(); it != myUpdateIds.constEnd(); ++it )
804 updateToolBar( it.key() );
809 \brief Perform delayed toolbar update.
810 \param tid toolbar ID
812 void QtxActionToolMgr::triggerUpdate( const int tid )
814 myUpdateIds.insert( tid, 0 );
815 QtxActionMgr::triggerUpdate();
820 \class QtxActionToolMgr::ToolCreator
821 \brief Toolbars creator.
823 Used by Reader to create actions by reading descriptions from the file,
824 create toolbars and fill in the toolbara with the actions.
829 \param r actions reader
830 \param mgr toolbar manager
832 QtxActionToolMgr::ToolCreator::ToolCreator( QtxActionMgr::Reader* r,
833 QtxActionToolMgr* mgr )
834 : QtxActionMgr::Creator( r ),
842 QtxActionToolMgr::ToolCreator::~ToolCreator()
847 \brief Create and append to the action manager a new toolbar or toolbar action.
848 \param tag item tag name
849 \param subMenu \c true if this item is submenu (not used)
850 \param attr attributes map
851 \param tid toolbar ID
852 \return toolbar or toolbar action ID
854 int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool /*subMenu*/,
855 const ItemAttributes& attr, const int tid )
857 if( !myMgr || !reader() )
860 QString label = reader()->option( "label", "label" ),
861 id = reader()->option( "id", "id" ),
862 pos = reader()->option( "pos", "pos" ),
863 group = reader()->option( "group", "group" ),
864 tooltip = reader()->option( "tooltip", "tooltip" ),
865 sep = reader()->option( "separator", "separator" ),
866 accel = reader()->option( "accel", "accel" ),
867 icon = reader()->option( "icon", "icon" ),
868 toggle = reader()->option( "toggle", "toggle" );
870 int res = -1, actId = intValue( attr, id, -1 );
872 res = myMgr->createToolBar( strValue( attr, label ), intValue( attr, id, -1 ) );
874 res = myMgr->insert( separator(), tid, intValue( attr, pos, -1 ) );
879 QString name = strValue( attr, icon );
880 if( !name.isEmpty() && loadPixmap( name, pix ) )
883 QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, strValue( attr, label ),
884 QKeySequence( strValue( attr, accel ) ), myMgr );
885 QString toggleact = strValue( attr, toggle );
886 newAct->setCheckable( !toggleact.isEmpty() );
887 newAct->setChecked( toggleact.toLower() == "true" );
890 int aid = myMgr->registerAction( newAct, actId );
891 res = myMgr->insert( aid, tid, intValue( attr, pos, -1 ) );