Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / Qtx / QtxDockAction.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File:      QtxDockAction.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxDockAction.h"
23
24 #include "QtxResourceMgr.h"
25
26 #include <qevent.h>
27 #include <qtoolbar.h>
28 #include <qdockarea.h>
29 #include <qdockwindow.h>
30 #include <qmainwindow.h>
31 #include <qobjectlist.h>
32 #include <qapplication.h>
33
34 /*!
35         Name: QtxDockAction [public]
36         Desc: Constructs an Dock action with given main window and name.
37 */
38
39 QtxDockAction::QtxDockAction( QMainWindow* mw, const char* name )
40 : QtxAction( "Windows and Toolbars", "Windows and Toolbars", 0, mw, name ),
41 myMain( mw ),
42 myAutoAdd( true ),
43 mySeparate( true ),
44 myAutoPlace( false )
45 {
46   initialize( mw );
47 }
48
49 /*!
50         Name: QtxDockAction [public]
51         Desc: This constructor creates an action with the following properties: the
52                     description text, the menu text and. It is a child of given main window
53         and named specified name.
54 */
55
56 QtxDockAction::QtxDockAction( const QString& text, const QString& menuText, QMainWindow* mw, const char* name )
57 : QtxAction( text, menuText, 0, mw, name ),
58 myMain( mw ),
59 myAutoAdd( true ),
60 mySeparate( true ),
61 myAutoPlace( false )
62 {
63   initialize( mw );
64 }
65
66 /*!
67         Name: QtxDockAction [public]
68         Desc: This constructor creates an action with the following properties: the
69                     description text, the menu text, the icon or iconset icon and keyboard
70         accelerator. It is a child of given main window and named specified name.
71 */
72
73 QtxDockAction::QtxDockAction( const QString& text, const QIconSet& icon, const QString& menuText, QMainWindow* mw, const char* name )
74 : QtxAction( text, icon, menuText, 0, mw, name ),
75 myMain( mw ),
76 myAutoAdd( true ),
77 mySeparate( true ),
78 myAutoPlace( false )
79 {
80   initialize( mw );
81 }
82
83 /*!
84         Name: ~QtxDockAction [public]
85         Desc: Removes all added popup items.
86 */
87
88 QtxDockAction::~QtxDockAction()
89 {
90   for ( MenuMap::ConstIterator mIt = myMenu.begin(); mIt != myMenu.end(); ++mIt )
91     removeFrom( mIt.key() );
92
93   for ( InfoMap::ConstIterator iIt = myInfo.begin(); iIt != myInfo.end(); ++iIt )
94     delete iIt.data().a;
95 }
96
97 /*!
98         Name: mainWindow [public]
99         Desc: Returns the main window which contains managed dock windows.
100 */
101
102 QMainWindow* QtxDockAction::mainWindow() const
103 {
104   return myMain;
105 }
106
107 /*!
108         Name: isAutoAdd [public]
109         Desc: Returns the auto add property. If this property is setted then all newly
110         appeared dock windows will be automatically added.
111 */
112
113 bool QtxDockAction::isAutoAdd() const
114 {
115   return myAutoAdd;
116 }
117
118 /*!
119         Name: setAutoAdd [public]
120         Desc: Sets the auto add property. If this property is setted then all newly
121         appeared dock windows will be automatically added.
122 */
123
124 void QtxDockAction::setAutoAdd( const bool on )
125 {
126   myAutoAdd = on;
127 }
128
129 /*!
130         Name: isAutoPlace [public]
131         Desc: Returns the auto place property. If this property is setted then all newly
132         added dock windows will be automatically placed according stored place information.
133 */
134
135 bool QtxDockAction::isAutoPlace() const
136 {
137   return myAutoPlace;
138 }
139
140 /*!
141         Name: setAutoPlace [public]
142         Desc: Sets the auto place property. If this property is setted then all newly
143         added dock windows will be automatically placed according stored place
144         information.
145 */
146
147 void QtxDockAction::setAutoPlace( const bool on )
148 {
149   myAutoPlace = on;
150 }
151
152 /*!
153         Name: isSeparate [public]
154         Desc: Returns the 'separate' property.
155 */
156
157 bool QtxDockAction::isSeparate() const
158 {
159   return mySeparate;
160 }
161
162 /*!
163         Name: setSeparate [public]
164         Desc: Sets the 'separate' property. If this property is 'true' then toolbars and
165         dock windows menu items will be placed in different popup menus  otherwise
166         their will  be placed  in  one  common  popup  menu. This property will be
167         affected in next method 'addTo'.
168 */
169
170 void QtxDockAction::setSeparate( const bool on )
171 {
172   if ( mySeparate == on )
173     return;
174
175   mySeparate = on;
176   updateMenus();
177 }
178
179 /*!
180         Name: addTo [public]
181         Desc: Add the dock windows sub menu item to the end of specified popup.
182 */
183
184 bool QtxDockAction::addTo( QWidget* wid )
185 {
186   return addTo( wid, -1 );
187 }
188
189 /*!
190         Name: addTo [public]
191         Desc: Add the dock windows sub menu item to specified popup at the given index.
192 */
193
194 bool QtxDockAction::addTo( QWidget* wid, const int idx )
195 {
196   if ( !wid || !wid->inherits( "QPopupMenu" ) )
197     return false;
198
199   QPopupMenu* pm = (QPopupMenu*)wid;
200   checkPopup( pm );
201
202   if ( myMenu.contains( pm ) )
203     return false;
204
205   MenuInfo mInfo;
206   mInfo.dock = new QPopupMenu( pm );
207   mInfo.tool = isSeparate() ? new QPopupMenu( pm ) : 0;
208
209   QString dock, tool;
210   splitMenuText( dock, tool );
211
212   myMenu.insert( pm, mInfo );
213
214   int index = idx;
215
216   if ( mInfo.dock )
217     iconSet().isNull() ? pm->insertItem ( dock, mInfo.dock, -1, index ) :
218                          pm->insertItem ( iconSet(), dock, mInfo.dock, -1, index );
219
220   if ( index >= 0 )
221     index++;
222
223   if ( mInfo.tool )
224     iconSet().isNull() ? pm->insertItem ( tool, mInfo.tool, -1, index ) :
225                          pm->insertItem ( iconSet(), tool, mInfo.tool, -1, index );
226
227   connect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
228   connect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
229
230   return true;
231 }
232
233 /*!
234         Name: removeFrom [public]
235         Desc: Removes dock window sub menu from specified popup.
236 */
237
238 bool QtxDockAction::removeFrom( QWidget* wid )
239 {
240   QPopupMenu* pm = (QPopupMenu*)wid;
241
242   if ( myMenu.contains( pm ) )
243   {
244     pm->removeItem( findId( pm, myMenu[pm].dock ) );
245     pm->removeItem( findId( pm, myMenu[pm].tool ) );
246
247     delete myMenu[pm].dock;
248     delete myMenu[pm].tool;
249     myMenu.remove( pm );
250
251     disconnect( pm, SIGNAL( aboutToShow() ), this, SLOT( onAboutToShow() ) );
252     disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onPopupDestroyed( QObject* ) ) );
253   }
254
255   return QtxAction::removeFrom( wid );
256 }
257
258 /*!
259   Sets menu text of action
260   \param txt - new menu text
261 */
262 void QtxDockAction::setMenuText( const QString& txt )
263 {
264   if ( menuText() == txt )
265     return;
266
267   QtxAction::setMenuText( txt );
268   updateMenus();
269 }
270
271 /*!
272         Name: addDockWindow [public]
273         Desc: Add dock window to internal data structures. Action will be include all added
274         dock windows in to menu and manage their place configuration.
275 */
276
277 bool QtxDockAction::addDockWindow( QDockWindow* dw )
278 {
279   if ( !dw || !mainWindow() )
280     return false;
281
282   if ( myInfo.contains( dw ) )
283     return false;
284
285   myInfo.insert( dw, DockInfo() );
286
287   DockInfo& inf = myInfo[dw];
288   inf.name = windowName( dw );
289   QAction* a = inf.a = new QAction( mainWindow(), 0, true );
290
291   autoLoadPlaceInfo( dw );
292
293   bool block = a->signalsBlocked();
294   a->blockSignals( true );
295   a->setOn( dw->isVisibleTo( mainWindow() ) );
296   a->blockSignals( block );
297
298   updateInfo( dw );
299   savePlaceInfo( dw );
300
301   dw->installEventFilter( this );
302
303   connect( a, SIGNAL( toggled( bool ) ), this, SLOT( onToggled( bool ) ) );
304   connect( dw, SIGNAL( destroyed( QObject* ) ), this, SLOT( onWindowDestroyed( QObject* ) ) );
305   connect( dw, SIGNAL( visibilityChanged( bool ) ), this, SLOT( onVisibilityChanged( bool ) ) );
306
307   return true;
308 }
309
310 /*!
311         Name: removeDockWindow [public]
312         Desc: Remove dock window from internal data structures. Action will not manage this window.
313 */
314
315 bool QtxDockAction::removeDockWindow( QDockWindow* dw )
316 {
317   if ( !myInfo.contains( dw ) )
318     return false;
319
320   myGeom.remove( myInfo[dw].name );
321
322   delete myInfo[dw].a;
323   myInfo.remove( dw );
324
325   dw->removeEventFilter( this );
326
327   disconnect( dw, SIGNAL( destroyed( QObject* ) ), this, SLOT( onWindowDestroyed( QObject* ) ) );
328   disconnect( dw, SIGNAL( visibilityChanged( bool ) ), this, SLOT( onVisibilityChanged( bool ) ) );
329
330   return true;
331 }
332
333 /*!
334         Name: eventFilter [public]
335         Desc: Event filter process caption and icon changing of managed dock windows
336         and try to add newly appeared dock windows.
337 */
338
339 bool QtxDockAction::eventFilter( QObject* o, QEvent* e )
340 {
341   if ( o->inherits( "QDockWindow" ) && ( e->type() == QEvent::CaptionChange ||
342                                          e->type() == QEvent::IconChange ) )
343     updateInfo( (QDockWindow*)o );
344
345   if ( o->inherits( "QDockArea" ) && e->type() == QEvent::ChildRemoved )
346   {
347     QChildEvent* ce = (QChildEvent*)e;
348     if ( ce->child() && ce->child()->inherits( "QDockWindow" ) )
349       savePlaceInfo( (QDockWindow*)ce->child() );
350   }
351
352   if ( o->inherits( "QDockArea" ) && e->type() == QEvent::ChildInserted )
353   {
354     QChildEvent* ce = (QChildEvent*)e;
355     if ( ce->child() && ce->child()->inherits( "QDockWindow" ) )
356       QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)AutoAdd, ce->child() ) );
357   }
358
359   return false;
360 }
361
362 /*!
363         Name: restoreGeometry [public]
364         Desc: Retrieve the dock window geometry. If dock window specified as 0
365         then all windows geometry will be restored.
366 */
367
368 void QtxDockAction::restoreGeometry( QDockWindow* dw ) const
369 {
370   if ( !dw )
371     loadPlaceInfo();
372   else
373     loadPlaceInfo( dw );
374 }
375
376 /*!
377         Name: storeGeometry [public]
378         Desc: Store the dock window geometry. If dock window specified as 0
379         then all windows geometry will be stored.
380 */
381
382 void QtxDockAction::storeGeometry( QDockWindow* dw )
383 {
384   QPtrList<QDockWindow> dwList;
385
386   if ( dw )
387     dwList.append( dw );
388   else
389     dockWindows( dwList );
390
391   for ( QPtrListIterator<QDockWindow> it( dwList ); it.current(); ++it )
392     savePlaceInfo( it.current() );
393 }
394
395 /*!
396         Name: loadGeometry [public]
397         Desc: Retrieve the dock windows geometry information from the specified resource manager section.
398 */
399
400 void QtxDockAction::loadGeometry( QtxResourceMgr* resMgr, const QString& section, const bool clear )
401 {
402   QString sec = section.stripWhiteSpace();
403   if ( !resMgr || sec.isEmpty() )
404     return;
405
406   myNames = QStringList::split( "|", resMgr->stringValue( sec, "windows_list", QString::null ) );
407
408   QMap<QString, int> map;
409   QStringList params = resMgr->parameters( sec );
410   for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it )
411   {
412     QString p = QStringList::split( ".", *it, true ).first().stripWhiteSpace();
413     if ( !p.isEmpty() )
414       map.insert( p, 0 );
415   }
416
417   for ( QMap<QString, int>::ConstIterator itr = map.begin(); itr != map.end(); ++itr )
418   {
419     GeomInfo inf;
420     if ( !clear && myGeom.contains( itr.key() ) )
421       inf = myGeom[itr.key()];
422     else
423     {
424       inf.vis = true; inf.newLine = false; inf.place = DockTop;
425       inf.index = 0; inf.offset = 0;
426       inf.x = 0; inf.y = 0; inf.w = 0; inf.h = 0;
427       inf.fixW = -1; inf.fixH = -1;
428     }
429     if ( loadGeometry( resMgr, sec, itr.key(), inf ) )
430       myGeom.insert( itr.key(), inf );
431   }
432 }
433
434 /*!
435         Name: saveGeometry [public]
436         Desc: Store the dock windows geometry information into the specified resource manager section.
437 */
438
439 void QtxDockAction::saveGeometry( QtxResourceMgr* resMgr, const QString& section, const bool clear ) const
440 {
441   QString sec = section.stripWhiteSpace();
442   if ( !resMgr || sec.isEmpty() )
443     return;
444
445   QtxDockAction* that = (QtxDockAction*)this;
446   that->storeGeometry();
447
448   that->myNames.clear();
449   collectNames( Minimized, that->myNames );
450   for ( int i = DockTornOff; i < Minimized; i++ )
451     collectNames( i, that->myNames );
452
453   if ( clear )
454     resMgr->remove( sec );
455
456   resMgr->setValue( sec, "windows_list", myNames.join( "|" ) );
457
458   for ( GeomMap::ConstIterator it = myGeom.begin(); it != myGeom.end(); ++it )
459     saveGeometry( resMgr, sec, it.key(), it.data() );
460 }
461
462 /*!
463         Name: onAboutToShow [private slots]
464         Desc: Prepare sub popup with dock windows list when parent popup is shown.
465 */
466
467 void QtxDockAction::onAboutToShow()
468 {
469   const QObject* obj = sender();
470   if ( obj && obj->inherits( "QPopupMenu" ) )
471   {
472     QPopupMenu* pm = (QPopupMenu*)obj;
473     fillPopup( pm );
474     pm->setItemEnabled( findId( pm, myMenu[pm].dock ), isEnabled() && myMenu[pm].dock && myMenu[pm].dock->count() );
475     pm->setItemEnabled( findId( pm, myMenu[pm].tool ), isEnabled() && myMenu[pm].tool && myMenu[pm].tool->count() );
476   }
477 }
478
479 /*!
480         Name: onToggled [private slots]
481         Desc: Show or hide dock window when user toggled window item in popup.
482 */
483
484 void QtxDockAction::onToggled( bool on )
485 {
486   QDockWindow* dw = dockWindow( (QAction*)sender() );
487   if ( dw )
488     on ? dw->show() : dw->hide();
489 }
490
491 /*!
492         Name: onPopupDestroyed [private slots]
493         Desc: Remove destroyed popup from data structures.
494 */
495
496 void QtxDockAction::onPopupDestroyed( QObject* obj )
497 {
498   myMenu.remove( (QPopupMenu*)obj );
499 }
500
501 /*!
502         Name: onWindowDestroyed [private slots]
503         Desc: Remove information about destroyed dock window.
504 */
505
506 void QtxDockAction::onWindowDestroyed( QObject* obj )
507 {
508   QDockWindow* dw = (QDockWindow*)obj;
509   if ( !myInfo.contains( dw ) )
510     return;
511
512   delete myInfo[dw].a;
513   myInfo.remove( dw );
514 }
515
516 /*!
517         Name: onVisibilityChanged [private slots]
518         Desc: Toggle corresponded action when visibility state of dock window changed.
519 */
520
521 void QtxDockAction::onVisibilityChanged( bool on )
522 {
523   const QObject* obj = sender();
524   if ( !obj || !obj->inherits( "QDockWindow" ) )
525     return;
526
527   QDockWindow* dw = (QDockWindow*)obj;
528
529   QAction* a = action( dw );
530   if ( a && a->isOn() != on )
531   {
532     bool block = a->signalsBlocked();
533     a->blockSignals( true );
534     a->setOn( on );
535     a->blockSignals( block );
536   }
537
538   savePlaceInfo( dw );
539 }
540
541 /*!
542         Name: onDockWindowPositionChanged [private slots]
543         Desc: Update dock window place information
544 */
545
546 void QtxDockAction::onDockWindowPositionChanged( QDockWindow* dw )
547 {
548   savePlaceInfo( dw );
549 }
550
551 /*!
552         Name: event [protected]
553         Desc: Check consistency the popup content and internal datas.
554         Synchronize internal data structures with popup content.
555 */
556
557 bool QtxDockAction::event( QEvent* e )
558 {
559   if ( e->type() == (int)AutoAdd )
560   {
561     QCustomEvent* ce = (QCustomEvent*)e;
562     QDockWindow* dw = (QDockWindow*)ce->data();
563     if ( !myInfo.contains( dw ) )
564     {
565       autoAddDockWindow( dw );
566       autoLoadPlaceInfo( dw );
567     }
568   }
569
570   return QtxAction::event( e );
571 }
572
573 /*!
574         Name: checkPopup [private]
575         Desc: Check consistency the popup content and internal datas.
576         Synchronize internal data structures with popup content.
577 */
578
579 void QtxDockAction::checkPopup( QPopupMenu* pm )
580 {
581   if ( !myMenu.contains( pm ) )
582     return;
583
584   int id = findId( pm, myMenu[pm].dock );
585   if ( id == -1 )
586   {
587     delete myMenu[pm].dock;
588     myMenu[pm].dock = 0;
589   }
590   id = findId( pm, myMenu[pm].tool );
591   if ( id == -1 )
592   {
593     delete myMenu[pm].tool;
594     myMenu[pm].tool = 0;
595   }
596
597   if ( !myMenu[pm].dock )
598   {
599     delete myMenu[pm].tool;
600     myMenu.remove( pm );
601     disconnect( pm, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
602   }
603 }
604
605 /*!
606         Name: fillPopup [private]
607         Desc: Clear the popup and the add to it required actions.
608 */
609
610 void QtxDockAction::fillPopup( QPopupMenu* pm ) const
611 {
612   if ( !pm || !mainWindow() )
613     return;
614
615   if ( !myMenu.contains( pm ) )
616     return;
617
618   QPopupMenu* dockMenu = myMenu[pm].dock;
619   QPopupMenu* toolMenu = myMenu[pm].tool;
620
621   for ( InfoMap::ConstIterator mit = myInfo.begin(); mit != myInfo.end(); ++mit )
622   {
623     mit.data().a->removeFrom( dockMenu );
624     mit.data().a->removeFrom( toolMenu );
625   }
626
627   if ( dockMenu )
628     dockMenu->clear();
629
630   if ( toolMenu )
631     toolMenu->clear();
632
633   QPtrList<QDockWindow> dockList;
634   dockWindows( dockList, mainWindow() );
635
636   if ( dockList.isEmpty() )
637     return;
638
639   QPtrList<QAction> toolBars, windows;
640   for ( QPtrListIterator<QDockWindow> it( dockList ); it.current(); ++it )
641   {
642     if ( !myInfo.contains( it.current() ) )
643     {
644       QtxDockAction* that = (QtxDockAction*)this;
645       that->autoAddDockWindow( it.current() );
646     }
647
648     if ( !mainWindow()->appropriate( it.current() ) ||
649          it.current()->caption().isEmpty() || !action( it.current() ) )
650       continue;
651
652     if ( isToolBar( it.current() ) )
653       toolBars.append( action( it.current() ) );
654     else
655       windows.append( action( it.current() ) );
656   }
657
658   for ( QPtrListIterator<QAction> wit( windows ); wit.current(); ++wit )
659     wit.current()->addTo( dockMenu );
660
661   dockMenu->insertSeparator();
662
663   for ( QPtrListIterator<QAction> tit( toolBars ); tit.current(); ++tit )
664     tit.current()->addTo( toolMenu ? toolMenu : dockMenu );
665
666   Qtx::simplifySeparators( dockMenu );
667   Qtx::simplifySeparators( toolMenu );
668 }
669
670 /*!
671         Name: isToolBar [private]
672         Desc: Returns 'true' if dock window is a toolbar.
673 */
674
675 bool QtxDockAction::isToolBar( QDockWindow* dw ) const
676 {
677   return dw && dw->inherits( "QToolBar" );
678 }
679
680 /*!
681         Name: findId [private]
682         Desc: Returns identificator of popup item which contains sub popup 'pm' in the popup 'cont'.
683 */
684
685 int QtxDockAction::findId( QPopupMenu* cont, QPopupMenu* pm ) const
686 {
687   if ( !cont || !pm )
688     return -1;
689
690   int id = -1;
691
692   for ( int i = 0; i < (int)cont->count() && id == -1; i++ )
693   {
694     QMenuData* md = 0;
695     QMenuItem* item = cont->findItem( cont->idAt( i ), &md );
696     if ( item && md == cont && item->popup() == pm )
697       id = item->id();
698   }
699   return id;
700 }
701
702 /*!
703         Name: dockWindows [private]
704         Desc: Returns all dock windows of the main window.
705 */
706
707 void QtxDockAction::dockWindows( QPtrList<QDockWindow>& lst, QMainWindow* main ) const
708 {
709   lst.clear();
710
711   QMainWindow* mw = main ? main : mainWindow();
712   if ( !mw )
713     return;
714
715   QObjectList* objs = mw->queryList( "QDockWindow" );
716   if ( objs )
717   {
718     for ( QObjectListIt it( *objs ); it.current(); ++it )
719     {
720       QDockWindow* dockWin = ::qt_cast<QDockWindow*>( it.current() );
721       if ( dockWin && dockMainWindow( mw, dockWin ) )
722         lst.append( dockWin );
723     }
724   }
725   delete objs;
726 }
727
728 /*!
729   \return true if main window is parent of object
730   \param mw - main window
731   \param win - object
732 */
733 bool QtxDockAction::dockMainWindow( QMainWindow* mw, QObject* win ) const
734 {
735   if ( !mw || !win )
736     return false;
737
738   while ( win )
739   {
740     if ( win->parent() && win->parent() == mw )
741       return true;
742
743     if ( ::qt_cast<QMainWindow*>( win->parent() ) )
744       return false;
745
746     win = win->parent();
747   }
748
749   return false;
750 }
751
752 /*!
753         Name: updateInfo [private]
754         Desc: Updates icon and caption info of dock window in the corresponded action.
755 */
756
757 void QtxDockAction::updateInfo( QDockWindow* dw )
758 {
759   QAction* a = action( dw );
760   if ( !a )
761     return;
762
763   a->setText( dw->caption() );
764   a->setMenuText( dw->caption() );
765
766   if ( isToolBar( dw ) )
767     a->setStatusTip( tr( "Toggles toolbar \"%1\" on/off" ).arg( dw->caption() ) );
768   else
769     a->setStatusTip( tr( "Toggles window \"%1\" on/off" ).arg( dw->caption() ) );
770
771   const QPixmap* icon = dw->icon();
772   if ( icon )
773     a->setIconSet( *icon );
774 }
775
776 /*!
777         Name: savePlaceInfo [private]
778         Desc: Store the place and geometry information from specified dock window.
779 */
780
781 void QtxDockAction::savePlaceInfo( QDockWindow* dw )
782 {
783   if ( !myInfo.contains( dw ) )
784     return;
785
786   if ( !myGeom.contains( myInfo[dw].name ) )
787     myGeom.insert( myInfo[dw].name, GeomInfo() );
788
789   GeomInfo& inf = myGeom[myInfo[dw].name];
790
791   Dock dock;
792   inf.vis = dw->isVisibleTo( mainWindow() );
793   mainWindow()->getLocation( dw, dock, inf.index, inf.newLine, inf.offset );
794
795   inf.place = dock;
796   inf.x = dw->x();
797   inf.y = dw->y();
798   inf.w = dw->width();
799   inf.h = dw->height();
800   inf.fixW = dw->fixedExtent().width();
801   inf.fixH = dw->fixedExtent().height();
802 }
803
804 /*!
805         Name: loadPlaceInfo [private]
806         Desc: Retrieve the stored place and geometry information to specified dock window.
807 */
808
809 void QtxDockAction::loadPlaceInfo( QDockWindow* dw ) const
810 {
811   if ( !myInfo.contains( dw ) )
812     return;
813
814   QMainWindow* mw = mainWindow();
815   if ( !mw )
816     return;
817
818   QObject* p = dw->parent();
819   if ( !( !p || p == mw || ( p->parent() && p->parent() == mw ) ) )
820     return;
821
822   QString winName = myInfo[dw].name;
823   if ( winName.isEmpty() || !myGeom.contains( winName ) )
824     return;
825
826   GeomInfo inf = myGeom[myInfo[dw].name];
827
828   mainWindow()->moveDockWindow( dw, (Qt::Dock)inf.place, inf.newLine, inf.index, inf.offset );
829   dw->setGeometry( inf.x, inf.y, inf.w, inf.h );
830
831   dw->setFixedExtentWidth( inf.fixW );
832   dw->setFixedExtentHeight( inf.fixH );
833
834   QtxDockAction* that = (QtxDockAction*)this;
835   that->myGeom.insert( myInfo[dw].name, inf );
836 }
837
838 /*!
839         Name: loadPlaceInfo [private]
840         Desc: Retrieve the stored place and geometry information to all dock windows.
841 */
842
843 void QtxDockAction::loadPlaceInfo() const
844 {
845   QMainWindow* mw = mainWindow();
846   if ( !mw )
847     return;
848
849   typedef QPtrList<QDockWindow> DockWinList;
850
851   DockWinList lst;
852   dockWindows( lst, mw );
853
854   QMap<QString, QDockWindow*> nameMap;
855   for ( QPtrListIterator<QDockWindow> itr( lst ); itr.current(); ++itr )
856   {
857     QObject* p = itr.current()->parent();
858     if ( !( !p || p == mw || ( p->parent() && p->parent() == mw ) ) )
859       continue;
860
861     QString name;
862     if ( myInfo.contains( itr.current() ) )
863       name = myInfo[itr.current()].name;
864
865     if ( !myGeom.contains( name ) )
866       continue;
867
868     nameMap.insert( name, itr.current() );
869   }
870
871   DockWinList winList;
872   for ( QStringList::const_iterator iter = myNames.begin(); iter != myNames.end(); ++iter )
873   {
874     if ( nameMap.contains( *iter ) )
875       winList.append( nameMap[*iter] );
876     nameMap.remove( *iter );
877   }
878
879   for ( QMap<QString, QDockWindow*>::ConstIterator mIt = nameMap.begin(); mIt != nameMap.end(); ++mIt )
880     winList.append( mIt.data() );
881
882   QMap<int, DockWinList> winMap;
883   QMap<QDockWindow*, GeomInfo*> geomMap;
884
885   for ( QPtrListIterator<QDockWindow> it( winList ); it.current(); ++it )
886   {
887     QString name;
888     if ( myInfo.contains( it.current() ) )
889       name = myInfo[it.current()].name;
890
891     if ( !myGeom.contains( name ) )
892       continue;
893
894     //! collect pointer of info to have fresh info data after processEvents();
895     GeomInfo* inf = (GeomInfo*)&( myGeom[name] );
896     geomMap.insert( it.current(), inf );
897     if ( !winMap.contains( inf->place ) )
898       winMap.insert( inf->place, DockWinList() );
899     winMap[inf->place].append( it.current() );
900   }
901
902   loadPlaceArea( DockMinimized, mw, 0,
903                  winMap.contains( DockMinimized ) ? winMap[DockMinimized] : DockWinList(), geomMap );
904   for ( int i = DockTornOff; i < DockMinimized; i++ )
905   {
906     loadPlaceArea( i, mw, dockArea( i ), winMap.contains( i ) ? winMap[i] : DockWinList(), geomMap );
907   }
908 }
909
910 /*!
911         Name: loadPlaceArea [private]
912         Desc: Set the place and geometry information to all dock windows in the area.
913 */
914
915 void QtxDockAction::loadPlaceArea( const int place, QMainWindow* mw, QDockArea* area,
916                                    const QPtrList<QDockWindow>& dockList,
917                                    const QMap<QDockWindow*, GeomInfo*>& geomMap ) const
918 {
919   for ( QPtrListIterator<QDockWindow> it( dockList ); it.current(); ++it )
920   {
921     if ( !geomMap.contains( it.current() ) )
922       continue;
923
924     GeomInfo* inf = geomMap[it.current()];
925     mw->moveDockWindow( it.current(), (Qt::Dock)place, inf->newLine, inf->index, inf->offset );
926   }
927
928   if ( !area )
929     return;
930
931   qApp->processEvents();
932
933   for ( QPtrListIterator<QDockWindow> itr( dockList ); itr.current(); ++itr )
934   {
935     QDockWindow* dw = itr.current();
936     if ( !geomMap.contains( dw ) )
937       continue;
938
939     GeomInfo* inf = geomMap[dw];
940     if ( place != DockTornOff )
941     {
942       dw->setNewLine( inf->newLine );
943                   dw->setOffset( inf->offset );
944                   dw->setFixedExtentWidth( inf->fixW );
945                   dw->setFixedExtentHeight( inf->fixH );
946     }
947     dw->setGeometry( inf->x, inf->y, inf->w, inf->h );
948
949     QAction* a = action( dw );
950     if ( a )
951     {
952       bool block = a->signalsBlocked();
953       a->blockSignals( true );
954       a->setOn( inf->vis );
955       a->blockSignals( block );
956     }
957
958     if ( mainWindow() && mainWindow()->appropriate( dw ) )
959       inf->vis ? dw->show() : dw->hide();
960   }
961
962   QWidget* wid = area;
963   if ( wid->layout() )
964   {
965     wid->layout()->invalidate();
966     wid->layout()->activate();
967   }
968 }
969
970 /*!
971         Name: action [private]
972         Desc: Returns action for the given dock window.
973 */
974
975 QAction* QtxDockAction::action( QDockWindow* dw ) const
976 {
977   QAction* a = 0;
978   if ( myInfo.contains( dw ) )
979     a = myInfo[dw].a;
980   return a;
981 }
982
983 /*!
984         Name: dockWindow [private]
985         Desc: Returns dock window for the given action.
986 */
987
988 QDockWindow* QtxDockAction::dockWindow( const QAction* a ) const
989 {
990   QDockWindow* dw = 0;
991   for ( InfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !dw; ++it )
992   {
993     if ( it.data().a == a )
994       dw = it.key();
995   }
996   return dw;
997 }
998
999 /*!
1000         Name: initialize [private]
1001         Desc: Initialisation of the object. Sets the event filters and add existing dock windows.
1002 */
1003
1004 void QtxDockAction::initialize( QMainWindow* mw )
1005 {
1006   if ( !mw )
1007     return;
1008
1009   QPtrList<QDockWindow> lst;
1010   dockWindows( lst, mw );
1011
1012   for ( QPtrListIterator<QDockWindow> it( lst ); it.current(); ++it )
1013     QApplication::postEvent( this, new QCustomEvent( (QEvent::Type)AutoAdd, it.current() ) );
1014
1015   if ( mw->topDock() )
1016     mw->topDock()->installEventFilter( this );
1017   if ( mw->leftDock() )
1018     mw->leftDock()->installEventFilter( this );
1019   if ( mw->rightDock() )
1020     mw->rightDock()->installEventFilter( this );
1021   if ( mw->bottomDock() )
1022     mw->bottomDock()->installEventFilter( this );
1023
1024   connect( mw, SIGNAL( dockWindowPositionChanged( QDockWindow* ) ),
1025            this, SLOT( onDockWindowPositionChanged( QDockWindow* ) ) );
1026 }
1027
1028 /*!
1029         Name: windowName [private]
1030         Desc: Generate the dock window name.
1031 */
1032
1033 QString QtxDockAction::windowName( QDockWindow* dw ) const
1034 {
1035   QString name;
1036
1037   if ( dw )
1038   {
1039     name = dw->name( "" );
1040     if ( name.isEmpty() )
1041       name = dw->caption();
1042   }
1043
1044   return name;
1045 }
1046
1047 /*!
1048         Name: autoAddDockWindow [private]
1049         Desc: Add the dock window if auto add property is setted.
1050 */
1051
1052 bool QtxDockAction::autoAddDockWindow( QDockWindow* dw )
1053 {
1054   if ( !isAutoAdd() )
1055     return false;
1056
1057   return addDockWindow( dw );
1058 }
1059
1060 /*!
1061         Name: autoLoadPlaceInfo [private]
1062         Desc: Retieve the dock window place geometry if auto place property is setted.
1063 */
1064
1065 void QtxDockAction::autoLoadPlaceInfo( QDockWindow* dw )
1066 {
1067   if ( isAutoPlace() )
1068     loadPlaceInfo( dw );
1069 }
1070
1071 /*!
1072         Name: splitMenuText [private]
1073         Desc: 
1074 */
1075
1076 void QtxDockAction::splitMenuText( QString& dock, QString& tool ) const
1077 {
1078   dock = tool = menuText();
1079   if ( !isSeparate() )
1080     return;
1081
1082   QStringList lst = splitText( menuText(), "|" );
1083   if ( lst.count() < 2 )
1084     lst = splitText( menuText(), "and" );
1085
1086   dock = lst.first();
1087   tool = lst.last();
1088 }
1089
1090 /*!
1091         Name: splitText [private]
1092         Desc: 
1093 */
1094
1095 QStringList QtxDockAction::splitText( const QString& str, const QString& sep ) const
1096 {
1097   QStringList res;
1098
1099   int idx = str.lower().find( sep.lower() );
1100   if ( idx != -1 )
1101   {
1102     res.append( str.mid( 0, idx ).stripWhiteSpace() );
1103     res.append( str.mid( idx + sep.length() ).stripWhiteSpace() );
1104   }
1105
1106   return res;
1107 }
1108
1109 /*!
1110         Name: dockPlace [private]
1111         Desc: 
1112 */
1113
1114 int QtxDockAction::dockPlace( const QString& dockName ) const
1115 {
1116   static QMap<QString, int> dockNameMap;
1117   if ( dockNameMap.isEmpty() )
1118   {
1119     dockNameMap["top"]       = DockTop;
1120     dockNameMap["bottom"]    = DockBottom;
1121     dockNameMap["left"]      = DockLeft;
1122     dockNameMap["right"]     = DockRight;
1123     dockNameMap["tornoff"]   = DockTornOff;
1124     dockNameMap["torn_off"]  = DockTornOff;
1125     dockNameMap["outside"]   = DockTornOff;
1126     dockNameMap["undock"]    = DockTornOff;
1127     dockNameMap["minimized"] = DockMinimized;
1128     dockNameMap["unmanaged"] = DockUnmanaged;
1129   }
1130
1131   int res = -1;
1132   if ( dockNameMap.contains( dockName.lower() ) )
1133     res = dockNameMap[dockName.lower()];
1134   return res;
1135 }
1136
1137 /*!
1138         Name: dockArea [private]
1139         Desc: 
1140 */
1141
1142 QDockArea* QtxDockAction::dockArea( const int place ) const
1143 {
1144   if ( !mainWindow() )
1145     return 0;
1146
1147   QDockArea* area = 0;
1148   switch ( place )
1149   {
1150   case DockTop:
1151     area = mainWindow()->topDock();
1152     break;
1153   case DockBottom:
1154     area = mainWindow()->bottomDock();
1155     break;
1156   case DockLeft:
1157     area = mainWindow()->leftDock();
1158     break;
1159   case DockRight:
1160     area = mainWindow()->rightDock();
1161     break;
1162   }
1163   return area;
1164 }
1165
1166 /*!
1167         Name: loadGeometry [private]
1168         Desc: 
1169 */
1170
1171 bool QtxDockAction::loadGeometry( QtxResourceMgr* resMgr, const QString& sec,
1172                                   const QString& name, GeomInfo& inf ) const
1173 {
1174   if ( !resMgr || sec.isEmpty() || name.isEmpty() )
1175     return false;
1176
1177   QString tmpl = QString( "%1.%2" ).arg( name );
1178
1179   inf.vis     = resMgr->booleanValue( sec, tmpl.arg( "visible" ), inf.vis );
1180   inf.newLine = resMgr->booleanValue( sec, tmpl.arg( "new_line" ), inf.newLine );
1181
1182   inf.index   = resMgr->integerValue( sec, tmpl.arg( "index" ), inf.index );
1183   inf.offset  = resMgr->integerValue( sec, tmpl.arg( "offset" ), inf.offset );
1184
1185   inf.x       = resMgr->integerValue( sec, tmpl.arg( "x" ), inf.x );
1186   inf.y       = resMgr->integerValue( sec, tmpl.arg( "y" ), inf.y );
1187   inf.w       = resMgr->integerValue( sec, tmpl.arg( "width" ), inf.w );
1188   inf.h       = resMgr->integerValue( sec, tmpl.arg( "height" ), inf.h );
1189
1190   inf.fixW    = resMgr->integerValue( sec, tmpl.arg( "fixed_width" ), inf.fixW );
1191   inf.fixH    = resMgr->integerValue( sec, tmpl.arg( "fixed_height" ), inf.fixH );
1192
1193   int place = -1;
1194   if ( !resMgr->value( sec, tmpl.arg( "place" ), place ) )
1195   {
1196     QString placeStr;
1197     if ( resMgr->value( sec, tmpl.arg( "place" ), placeStr ) )
1198       place = dockPlace( placeStr );
1199   }
1200
1201   if ( place >= DockUnmanaged && place <= DockMinimized )
1202     inf.place = place;
1203
1204   return true;
1205 }
1206
1207 /*!
1208         Name: saveGeometry [private]
1209         Desc: 
1210 */
1211
1212 bool QtxDockAction::saveGeometry( QtxResourceMgr* resMgr, const QString& sec,
1213                                   const QString& name, const GeomInfo& inf ) const
1214 {
1215   if ( !resMgr || sec.isEmpty() || name.isEmpty() )
1216     return false;
1217
1218   QString tmpl = QString( "%1.%2" ).arg( name );
1219
1220   resMgr->setValue( sec, tmpl.arg( "visible" ), inf.vis );
1221   resMgr->setValue( sec, tmpl.arg( "new_line" ), inf.newLine );
1222   resMgr->setValue( sec, tmpl.arg( "index" ), inf.index );
1223   resMgr->setValue( sec, tmpl.arg( "offset" ), inf.offset );
1224   resMgr->setValue( sec, tmpl.arg( "x" ), inf.x );
1225   resMgr->setValue( sec, tmpl.arg( "y" ), inf.y );
1226   resMgr->setValue( sec, tmpl.arg( "width" ), inf.w );
1227   resMgr->setValue( sec, tmpl.arg( "height" ), inf.h );
1228   resMgr->setValue( sec, tmpl.arg( "fixed_width" ), inf.fixW );
1229   resMgr->setValue( sec, tmpl.arg( "fixed_height" ), inf.fixH );
1230   resMgr->setValue( sec, tmpl.arg( "place" ), inf.place );
1231
1232   return true;
1233 }
1234
1235 /*!
1236         Name: collectNames [private]
1237         Desc: 
1238 */
1239
1240 void QtxDockAction::collectNames( const int place, QStringList& lst ) const
1241 {
1242   QPtrList<QDockWindow> winList;
1243   QDockArea* area = dockArea( place );
1244   if ( area )
1245     winList = area->dockWindowList();
1246   else
1247     winList = mainWindow()->dockWindows( (Qt::Dock)place );
1248
1249   for ( QPtrListIterator<QDockWindow> it( winList ); it.current(); ++it )
1250   {
1251     QString name;
1252     if ( myInfo.contains( it.current() ) )
1253       name = myInfo[it.current()].name;
1254     if ( name.isEmpty() )
1255       name = windowName( it.current() );
1256     if ( name.isEmpty() )
1257       continue;
1258
1259     lst.append( name );
1260   }
1261 }
1262
1263 /*!
1264   Updates menu of action
1265 */
1266 void QtxDockAction::updateMenus()
1267 {
1268   for ( MenuMap::Iterator it = myMenu.begin(); it != myMenu.end(); ++it )
1269   {
1270     QPopupMenu* pm = it.key();
1271     MenuInfo& inf = it.data();
1272
1273     int toolId = findId( pm, inf.tool );
1274     int dockId = findId( pm, inf.dock );
1275
1276     int index = pm->indexOf( dockId );
1277
1278     if ( isSeparate() && !inf.tool )
1279       inf.tool = new QPopupMenu( pm );
1280
1281     pm->removeItem( dockId );
1282     pm->removeItem( toolId );
1283
1284     if ( !isSeparate() && inf.tool )
1285     {
1286       delete inf.tool;
1287       inf.tool = 0;
1288     }
1289
1290     QString dock, tool;
1291     splitMenuText( dock, tool );
1292
1293     if ( inf.dock )
1294       iconSet().isNull() ? pm->insertItem ( dock, inf.dock, -1, index ) :
1295                            pm->insertItem ( iconSet(), dock, inf.dock, -1, index );
1296
1297     if ( index >= 0 )
1298       index++;
1299
1300     if ( inf.tool )
1301       iconSet().isNull() ? pm->insertItem ( tool, inf.tool, -1, index ) :
1302                           pm->insertItem ( iconSet(), tool, inf.tool, -1, index );
1303   }
1304 }