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