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