]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxActionToolMgr.cxx
Salome HOME
8f3b8804eb4af2b221e72503c9dee68fbb8e7a42
[modules/gui.git] / src / Qtx / QtxActionToolMgr.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File:      QtxActionToolMgr.cxx
23 // Author:    Alexander SOLOVYOV, Sergey TELKOV
24 //
25 #include "QtxActionToolMgr.h"
26
27 #include "QtxAction.h"
28 #include "QtxToolBar.h"
29
30 #include <QMainWindow>
31
32 /*!
33   \class QtxActionToolMgr::ToolNode
34   \brief Represents a toolbutton inside toolbar structure.
35   \internal
36 */
37
38 /*!
39   \fn QtxActionToolMgr::ToolNode::ToolNode()
40   \internal
41   \brief Default constructor.
42 */
43
44 /*!
45   \fn QtxActionToolMgr::ToolNode::ToolNode( const int _id )
46   \brief Constructor.
47   \internal
48   \param _id toolbar node ID
49 */
50
51 /*!
52   \class QtxActionToolMgr
53   \brief Toolbar actions manager.
54   
55   Toolbar manager allows using of set of action for automatic generating of
56   application toolbars and dynamic update of toolbars contents.
57
58   Use insert(), append() and remove() methods to create toolbar and add actions to it.
59   Methods show(), hide() allow displaying/erasing of specified toolbar items.
60
61   Toolbar manager automatically optimizes toolbars by removing extra separators, etc.
62 */
63
64 /*!
65   \brief Constructor.
66   \param p parent main window
67 */
68 QtxActionToolMgr::QtxActionToolMgr( QMainWindow* p )
69 : QtxActionMgr( p ),
70   myMainWindow( p )
71 {
72 }
73
74 /*!
75   \brief Destructor.
76 */
77 QtxActionToolMgr::~QtxActionToolMgr()
78 {
79 }
80
81 /*!
82   \brief Get parent main window.
83   \return main window pointer
84 */
85 QMainWindow* QtxActionToolMgr::mainWindow() const
86 {
87   return myMainWindow;
88 }
89
90 /*!
91   \brief Create toolbar and assign \a id to it.
92
93   If \a tid is less than 0, the identifier is generated automatically.
94   If toolbar with given \a tid is already registered, the toolbar will not be created.
95
96   \param title toolbar title
97   \param tid requested toolbar ID
98   \param mw parent main window; if it is null, the tool manager's main window is used
99   \return id of created/found toolbar
100 */
101 int QtxActionToolMgr::createToolBar( const QString& title, const int tid, QMainWindow* mw )
102 {
103   static int _toolBarId = -1;
104
105   int tbId = -1;
106   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && tbId == -1; ++it )
107   {
108     if( it.value().toolBar->windowTitle().toLower() == title.toLower() &&
109         ( !mw || it.value().toolBar->parent()==mw ) )
110       tbId = it.key();
111   }
112
113   if ( tbId != -1 )
114     return tbId;
115
116   QMainWindow* tbw = mw ? mw : mainWindow();
117   QToolBar* tb = find( title, tbw );
118
119   tbId = tid < 0 ? --_toolBarId : tid;
120
121   myToolBars.insert( tbId, ToolBarInfo() );
122   ToolBarInfo& tInfo = myToolBars[tbId];
123
124   if ( !tb )
125   {
126     tb = new QtxToolBar( true, tbw );
127     //mainWindow()->addToolBar( tb );
128     tb->setWindowTitle( title );
129     tb->setObjectName( title );
130     tb->setToolTip( title );
131    }
132
133   tInfo.toolBar = tb;
134   connect( tInfo.toolBar, SIGNAL( destroyed() ), this, SLOT( onToolBarDestroyed() ) );
135
136   return tbId;
137 }
138
139 /*!
140   \brief Search toolbar with given \a title owned by main window \mw. 
141   \param title toolbar title
142   \param mw main window
143   \return toolbar or 0 if it is not found
144 */
145 QToolBar* QtxActionToolMgr::find( const QString& title, QMainWindow* mw ) const
146 {
147   if ( !mw )
148     return 0;
149
150   QString pattern = title.toLower();
151
152   QToolBar* res = 0;
153   QList<QToolBar*> toolbars = qFindChildren<QToolBar*>( mw );
154   for ( QList<QToolBar*>::iterator it = toolbars.begin(); it != toolbars.end() && !res; ++it )
155   {
156     if ( (*it)->windowTitle().toLower() == pattern )
157       res = *it;
158   }
159   return res;
160 }
161
162 /*!
163   \brief Remove toolbar.
164   \param tid toolbar ID
165 */
166 void QtxActionToolMgr::removeToolBar( const int tid )
167 {
168   if ( !myToolBars.contains( tid ) )
169     return;
170
171   delete myToolBars[tid].toolBar;
172   myToolBars.remove( tid );
173 }
174
175 /*!
176   \brief Remove toolbar.
177   \param title toolbar title
178 */
179 void QtxActionToolMgr::removeToolBar( const QString& title )
180 {
181   removeToolBar( find( title ) );
182 }
183
184 /*!
185   \brief Insert action into toolbar.
186   \param id action ID
187   \param tid toolbar ID
188   \param idx action index in the toolbar (if < 0, action is appended to the end)
189   \return action ID
190 */
191 int QtxActionToolMgr::insert( const int id, const int tid, const int idx )
192 {
193   if ( !contains( id ) || !hasToolBar( tid ) )
194     return -1;
195 /*
196   if ( containsAction( id, tid ) )
197     remove( id, tid );
198 */
199   ToolNode node( id );
200
201   NodeList& list = myToolBars[tid].nodes;
202   int index = idx < 0 ? list.count() : qMin( idx, (int)list.count() );
203   list.insert( index, node );
204   triggerUpdate( tid );
205
206   return id;
207 }
208
209 /*!
210   \brief Insert action into toolbar.
211   \param a action
212   \param tid toolbar ID
213   \param idx action index in the toolbar (if < 0, action is appended to the end)
214   \return action ID
215 */
216 int QtxActionToolMgr::insert( QAction* a, const int tid, const int idx )
217 {
218   return insert( registerAction( a ), tid, idx );
219 }
220
221 /*!
222   \brief Insert action into toolbar.
223   \param id action ID
224   \param title toolbar title
225   \param idx action index in the toolbar (if < 0, action is appended to the end)
226   \return action ID
227 */
228 int QtxActionToolMgr::insert( const int id, const QString& title, const int idx )
229 {
230   return insert( id, createToolBar( title ), idx );
231 }
232
233 /*!
234   \brief Insert action into toolbar.
235   \param a action
236   \param title toolbar title
237   \param idx action index in the toolbar (if < 0, action is appended to the end)
238   \return action ID
239 */
240 int QtxActionToolMgr::insert( QAction* a, const QString& title, const int idx )
241 {
242   return insert( registerAction( a ), createToolBar( title ), idx );
243 }
244
245 /*!
246   \brief Append action to the end of toolbar.
247   \param id action ID
248   \param tid toolbar ID
249   \return action ID
250 */
251 int QtxActionToolMgr::append( const int id, const int tid )
252 {
253   return insert( id, tid );
254 }
255
256 /*!
257   \brief Append action to the end of toolbar.
258   \param a action
259   \param tid toolbar ID
260   \return action ID
261 */
262 int QtxActionToolMgr::append( QAction* a, const int tid )
263 {
264   return insert( a, tid );
265 }
266
267 /*!
268   \brief Append action to the end of toolbar.
269   \param id action ID
270   \param title toolbar title
271   \return action ID
272 */
273 int QtxActionToolMgr::append( const int id, const QString& title )
274 {
275   return insert( id, title );
276 }
277
278 /*!
279   \brief Append action to the end of toolbar.
280   \param a action
281   \param title toolbar title
282   \return action ID
283 */
284 int QtxActionToolMgr::append( QAction* a, const QString& title )
285 {
286   return insert( a, title );
287 }
288
289 /*!
290   \brief Insert action to the beginning of toolbar.
291   \param id action ID
292   \param tid toolbar ID
293   \return action ID
294 */
295 int QtxActionToolMgr::prepend( const int id, const int tid )
296 {
297   return insert( id, tid, 0 );
298 }
299
300 /*!
301   \brief Insert action to the beginning of toolbar.
302   \param a action
303   \param tid toolbar ID
304   \return action ID
305 */
306 int QtxActionToolMgr::prepend( QAction* a, const int tid )
307 {
308   return insert( a, tid, 0 );
309 }
310
311 /*!
312   \brief Insert action to the beginning of toolbar.
313   \param id action ID
314   \param title toolbar title
315   \return action ID
316 */
317 int QtxActionToolMgr::prepend( const int id, const QString& title )
318 {
319   return insert( id, title, 0 );
320 }
321
322 /*!
323   \brief Insert action to the beginning of toolbar.
324   \param a action ID
325   \param title toolbar title
326   \return action ID
327 */
328 int QtxActionToolMgr::prepend( QAction* a, const QString& title )
329 {
330   return insert( a, title, 0 );
331 }
332
333 /*!
334   \brief Remove action from toolbar.
335   \param id action ID
336   \param tid toolbar ID
337 */
338 void QtxActionToolMgr::remove( const int id, const int tid )
339 {
340   if ( !myToolBars.contains( tid ) )
341     return;
342
343   NodeList newList;
344   const NodeList& nodes = myToolBars[tid].nodes;
345   for ( NodeList::const_iterator it = nodes.begin(); it != nodes.end(); ++it )
346   {
347     if ( (*it).id != id )
348       newList.append( *it );
349   }
350
351   myToolBars[tid].nodes = newList;
352
353   triggerUpdate( tid );
354 }
355
356 /*!
357   \brief Remove action from toolbar.
358   \param id action ID
359   \param title toolbar title
360 */
361 void QtxActionToolMgr::remove( const int id, const QString& title )
362 {
363   remove( id, find( title ) );
364 }
365
366 /*!
367   \brief Get toolbar by given \a tid.
368   \param tid toolbar ID
369   \return toolbar or 0 if it is not found
370 */
371 QToolBar* QtxActionToolMgr::toolBar( const int tid ) const
372 {
373   QToolBar* tb = 0;
374   if ( myToolBars.contains( tid ) )
375     tb = myToolBars[tid].toolBar;
376   return tb;
377 }
378
379 /*!
380   \brief Get toolbar by given \a title.
381   \param title toolbar title
382   \return toolbar or 0 if it is not found
383 */
384 QToolBar* QtxActionToolMgr::toolBar( const QString& title ) const
385 {
386   return toolBar( find( title ) );
387 }
388
389 /*!
390   \brief Check if toolbar with given \a id already registered.
391   \param tid toolbar ID
392   \return \c true if toolbar is registered in the toolbar manager
393 */
394 bool QtxActionToolMgr::hasToolBar( const int tid ) const
395 {
396   return myToolBars.contains( tid );
397 }
398
399 /*!
400   \brief Check if toolbar with given \a id already registered.
401   \param title toolbar title
402   \return \c true if toolbar is registered in the toolbar manager
403 */
404 bool QtxActionToolMgr::hasToolBar( const QString& title ) const
405 {
406   return find( title ) != -1;
407 }
408
409 /*!
410   \brief Check if toolbar contains given action.
411   \param id action ID
412   \param tid toolbar ID
413   \return \c true if toolbar contains action
414 */
415 bool QtxActionToolMgr::containsAction( const int id, const int tid ) const
416 {
417   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
418   {
419     if ( tid == -1 || it.key() == tid )
420     {
421       const NodeList& list = it.value().nodes;
422       for ( NodeList::const_iterator nit = list.begin(); nit != list.end(); ++nit )
423         if ( (*nit).id == id )
424           return true;
425     }
426   }
427   return false;
428 }
429
430 /*!
431   \brief Called when toolbar is destroyed.
432
433   Clears internal pointer to the toolbar to disable crashes.
434 */
435 void QtxActionToolMgr::onToolBarDestroyed()
436 {
437   myToolBars.remove( find( (QToolBar*)sender() ) );
438 }
439
440 /*!
441   \brief Search toolbar by given \a name.
442   \param title toolbar title
443   \return toolbar ID or -1 if it is not found
444 */
445 int QtxActionToolMgr::find( const QString& title ) const
446 {
447   int id = -1;
448   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && id == -1; ++it )
449   {
450     if ( it.value().toolBar->windowTitle() == title )
451       id = it.key();
452   }
453   return id;
454 }
455
456 /*!
457   \brief Get toolbar identifier.
458   \param tb toolbar
459   \return toolbar ID or -1 if toolbar is not registered
460 */
461 int QtxActionToolMgr::find( QToolBar* tb ) const
462 {
463   int id = -1;
464   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end() && id == -1; ++it )
465   {
466     if ( it.value().toolBar == tb )
467       id = it.key();
468   }
469   return id;
470 }
471
472 /*!
473   \brief Update toolbar.
474   \param tid toolbar ID
475 */
476 void QtxActionToolMgr::updateToolBar( const int tid )
477 {
478   if ( !isUpdatesEnabled() )
479     return;
480
481   if ( !myToolBars.contains( tid ) )
482     return;
483
484   QToolBar* tb = myToolBars[tid].toolBar;
485   const NodeList& list = myToolBars[tid].nodes;
486
487   for ( NodeList::const_iterator it = list.begin(); it != list.end(); ++it )
488   {
489     QAction* a = action( (*it).id );
490     tb->removeAction( a );
491 //    if ( a )
492 //      a->removeFrom( tb );
493   }
494
495   tb->clear();
496
497   for ( NodeList::const_iterator itr = list.begin(); itr != list.end(); ++itr )
498   {
499     if ( !isVisible( (*itr).id, tid ) )
500       continue;
501
502     QAction* a = action( (*itr).id );
503     tb->addAction( a );
504 //    if ( a )
505 //      a->addTo( tb );
506   }
507
508   simplifySeparators( tb );
509   
510   // fix of 19921 -->
511   if ( !tb->isVisible() )
512     tb->adjustSize();
513   // fix of 19921 <--
514 }
515
516 /*!
517   \brief Update all registered toolbars.
518 */
519 void QtxActionToolMgr::internalUpdate()
520 {
521   if ( !isUpdatesEnabled() )
522     return;
523
524   for ( ToolBarMap::ConstIterator it1 = myToolBars.begin(); it1 != myToolBars.end(); ++it1 )
525     updateToolBar( it1.key() );
526
527   myUpdateIds.clear();
528 }
529
530 /*!
531   \brief Remove extra separators from the toolbar.
532   \param tb toolbar
533 */
534 void QtxActionToolMgr::simplifySeparators( QToolBar* tb )
535 {
536   Qtx::simplifySeparators( tb );
537 }
538
539 /*!
540   \brief Show action (in all toolbars).
541   \param id action ID
542 */
543 void QtxActionToolMgr::show( const int id )
544 {
545   setShown( id, true );
546 }
547
548 /*!
549   \brief Hide action (in all toolbars).
550   \param id action ID
551 */
552 void QtxActionToolMgr::hide( const int id )
553 {
554   setShown( id, false );
555 }
556
557 /*!
558   \brief Set visibility status for toolbar action with given \a id.
559   \param id action ID
560   \param on new visibility status
561 */
562 void QtxActionToolMgr::setShown( const int id, const bool on )
563 {
564   for ( ToolBarMap::Iterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
565     setVisible( id, it.key(), on );
566 }
567
568 /*!
569   \brief Get visibility status for toolbar action with given \a id.
570   \param id action ID
571   \return \c true if action is shown in all toolbars
572 */
573 bool QtxActionToolMgr::isShown( const int id ) const
574 {
575   QList<const ToolNode*> nodes;
576   for ( ToolBarMap::ConstIterator it = myToolBars.begin(); it != myToolBars.end(); ++it )
577   {
578     const NodeList& nl = it.value().nodes;
579     for ( NodeList::const_iterator itr = nl.begin(); itr != nl.end(); ++itr )
580     {
581       const ToolNode& node = *itr;
582       if ( node.id == id )
583         nodes.append( &node );
584     }
585   }
586
587   if ( nodes.isEmpty() )
588     return false;
589
590   bool vis = true;
591   for ( QList<const ToolNode*>::iterator itr = nodes.begin(); itr != nodes.end() && vis; ++itr )
592     vis = (*itr)->visible;
593
594   return vis;
595 }
596
597 /*!
598   \brief Check if an action with given \a id is visible in the toolbar \a tid.
599   \param id action ID
600   \param tid toolbar ID
601   \return \c true if action is shown in the toolbar
602 */
603 bool QtxActionToolMgr::isVisible( const int id, const int tid ) const
604 {
605   if ( !myToolBars.contains( tid ) )
606     return false;
607
608   bool vis = false;
609   const ToolBarInfo& inf = myToolBars[tid];
610   for ( NodeList::const_iterator it = inf.nodes.begin(); it != inf.nodes.end() && !vis; ++it )
611   {
612     const ToolNode& node = *it;
613     if ( node.id == id )
614
615       vis = node.visible;
616   }
617   return vis;
618 }
619
620 /*!
621   \brief Show/hide action with given \a id in the toolbar \a tid.
622   \param id action ID
623   \param tid toolbar ID
624   \param on new visibility status
625 */
626 void QtxActionToolMgr::setVisible( const int id, const int tid, const bool on )
627 {
628   if ( !myToolBars.contains( tid ) )
629     return;
630
631   bool changed = false;
632   NodeList& lst = myToolBars[tid].nodes;
633   for ( NodeList::iterator it = lst.begin(); it != lst.end(); ++it )
634   {
635     ToolNode& node = *it;
636     if ( node.id == id )
637     {
638       changed = changed || node.visible != on;
639       node.visible = on;
640     }
641   }
642
643   if ( changed )
644     triggerUpdate( tid );
645 }
646
647 /*!
648   \brief Load toolbar contents from the file.
649   \param fname file name
650   \param r actions reader
651   \return \c true on success and \c false on error
652 */
653 bool QtxActionToolMgr::load( const QString& fname, QtxActionMgr::Reader& r )
654 {
655   ToolCreator cr( &r, this );
656   return r.read( fname, cr );
657 }
658
659 /*!
660   \brief Called when delayed content update is performed.
661
662   Customizes the content update operation.
663 */
664 void QtxActionToolMgr::updateContent()
665 {
666   if ( !isUpdatesEnabled() )
667     return;
668
669   for ( QMap<int,int>::const_iterator it = myUpdateIds.constBegin(); it != myUpdateIds.constEnd(); ++it )
670     updateToolBar( it.key() );
671   myUpdateIds.clear();
672 }
673
674 /*!
675   \brief Perform delayed toolbar update.
676   \param tid toolbar ID
677 */
678 void QtxActionToolMgr::triggerUpdate( const int tid )
679 {
680   myUpdateIds.insert( tid, 0 );
681   QtxActionMgr::triggerUpdate();
682 }
683
684
685 /*!
686   \class QtxActionToolMgr::ToolCreator
687   \brief Toolbars creator.
688
689   Used by Reader to create actions by reading descriptions from the file,
690   create toolbars and fill in the toolbara with the actions.
691 */
692
693 /*!
694   \brief Constructor.
695   \param r actions reader
696   \param mgr toolbar manager
697 */
698 QtxActionToolMgr::ToolCreator::ToolCreator( QtxActionMgr::Reader* r,
699                                             QtxActionToolMgr* mgr )
700 : QtxActionMgr::Creator( r ),
701   myMgr( mgr )
702 {
703 }
704
705 /*!
706   \brief Destructor.
707 */
708 QtxActionToolMgr::ToolCreator::~ToolCreator()
709 {
710 }
711
712 /*!
713   \brief Create and append to the action manager a new toolbar or toolbar action.
714   \param tag item tag name
715   \param subMenu \c true if this item is submenu (not used)
716   \param attr attributes map
717   \param tid toolbar ID
718   \return toolbar or toolbar action ID
719 */
720 int QtxActionToolMgr::ToolCreator::append( const QString& tag, const bool /*subMenu*/,
721                                            const ItemAttributes& attr, const int tid )
722 {  
723   if( !myMgr || !reader() )
724     return -1;
725
726   QString label   = reader()->option( "label",     "label"     ),
727           id      = reader()->option( "id",        "id"        ),
728           pos     = reader()->option( "pos",       "pos"       ),
729           group   = reader()->option( "group",     "group"     ),
730           tooltip = reader()->option( "tooltip",   "tooltip"   ),
731           sep     = reader()->option( "separator", "separator" ),
732           accel   = reader()->option( "accel",     "accel"     ),
733           icon    = reader()->option( "icon",      "icon"      ),
734           toggle  = reader()->option( "toggle",    "toggle"    );
735
736   int res = -1, actId = intValue( attr, id, -1 );
737   if( tid==-1 )
738     res = myMgr->createToolBar( strValue( attr, label ), intValue( attr, id, -1 ) );
739   else if( tag==sep )
740     res = myMgr->insert( separator(), tid, intValue( attr, pos, -1 ) );
741   else
742   {
743     QIcon set;
744     QPixmap pix;
745     QString name = strValue( attr, icon );
746     if( !name.isEmpty() && loadPixmap( name, pix ) )
747       set = QIcon( pix );
748
749     QtxAction* newAct = new QtxAction( strValue( attr, tooltip ), set, strValue( attr, label ),
750                                        QKeySequence( strValue( attr, accel ) ), myMgr );
751     QString toggleact = strValue( attr, toggle );
752     newAct->setCheckable( !toggleact.isEmpty() );
753     newAct->setChecked( toggleact.toLower() == "true" );
754         
755     connect( newAct );
756     int aid = myMgr->registerAction( newAct, actId );
757     res = myMgr->insert( aid, tid, intValue( attr, pos, -1 ) );
758   }
759
760   return res;
761 }