]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxDockAction.cxx
Salome HOME
no message
[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() == 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   for ( QPtrListIterator<QDockWindow> itr( dockList ); itr.current(); ++itr )
849   {
850     QDockWindow* dw = itr.current();
851     if ( !geomMap.contains( dw ) )
852       continue;
853
854     const GeomInfo& inf = geomMap[dw];
855     if ( place != DockTornOff )
856     {
857       dw->setNewLine( inf.newLine );
858                   dw->setOffset( inf.offset );
859                   dw->setFixedExtentWidth( inf.fixW );
860                   dw->setFixedExtentHeight( inf.fixH );
861     }
862     dw->setGeometry( inf.x, inf.y, inf.w, inf.h );
863
864     inf.vis ? dw->show() : dw->hide();
865   }
866
867   QWidget* wid = area;
868   if ( wid->layout() )
869   {
870     wid->layout()->invalidate();
871     wid->layout()->activate();
872   }
873 }
874
875 /*!
876         Name: action [private]
877         Desc: Returns action for the given dock window.
878 */
879
880 QAction* QtxDockAction::action( QDockWindow* dw ) const
881 {
882   QAction* a = 0;
883   if ( myInfo.contains( dw ) )
884     a = myInfo[dw].a;
885   return a;
886 }
887
888 /*!
889         Name: dockWindow [private]
890         Desc: Returns dock window for the given action.
891 */
892
893 QDockWindow* QtxDockAction::dockWindow( const QAction* a ) const
894 {
895   QDockWindow* dw = 0;
896   for ( InfoMap::ConstIterator it = myInfo.begin(); it != myInfo.end() && !dw; ++it )
897   {
898     if ( it.data().a == a )
899       dw = it.key();
900   }
901   return dw;
902 }
903
904 /*!
905         Name: initialize [private]
906         Desc: Initialisation of the object. Sets the event filters and add existing dock windows.
907 */
908
909 void QtxDockAction::initialize( QMainWindow* mw )
910 {
911   if ( !mw )
912     return;
913
914   QPtrList<QDockWindow> lst;
915   dockWindows( lst, mw );
916
917   for ( QPtrListIterator<QDockWindow> it( lst ); it.current(); ++it )
918     autoAddDockWindow( it.current() );
919
920   if ( mw->topDock() )
921     mw->topDock()->installEventFilter( this );
922   if ( mw->leftDock() )
923     mw->leftDock()->installEventFilter( this );
924   if ( mw->rightDock() )
925     mw->rightDock()->installEventFilter( this );
926   if ( mw->bottomDock() )
927     mw->bottomDock()->installEventFilter( this );
928
929   connect( mw, SIGNAL( dockWindowPositionChanged( QDockWindow* ) ),
930            this, SLOT( onDockWindowPositionChanged( QDockWindow* ) ) );
931 }
932
933 /*!
934         Name: windowName [private]
935         Desc: Generate the dock window name.
936 */
937
938 QString QtxDockAction::windowName( QDockWindow* dw ) const
939 {
940   QString name;
941
942   if ( dw )
943   {
944     name = dw->name( "" );
945     if ( name.isEmpty() )
946       name = dw->caption();
947   }
948
949   return name;
950 }
951
952 /*!
953         Name: autoAddDockWindow [private]
954         Desc: Add the dock window if auto add property is setted.
955 */
956
957 bool QtxDockAction::autoAddDockWindow( QDockWindow* dw )
958 {
959   if ( !isAutoAdd() )
960     return false;
961
962   return addDockWindow( dw );
963 }
964
965 /*!
966         Name: autoLoadPlaceInfo [private]
967         Desc: Retieve the dock window place geometry if auto place property is setted.
968 */
969
970 void QtxDockAction::autoLoadPlaceInfo( QDockWindow* dw )
971 {
972   if ( isAutoPlace() )
973     loadPlaceInfo( dw );
974 }
975
976 /*!
977         Name: splitMenuText [private]
978         Desc: 
979 */
980
981 void QtxDockAction::splitMenuText( QString& dock, QString& tool ) const
982 {
983   dock = tool = menuText();
984   if ( !isSeparate() )
985     return;
986
987   QStringList lst = splitText( menuText(), "|" );
988   if ( lst.count() < 2 )
989     lst = splitText( menuText(), "and" );
990
991   dock = lst.first();
992   tool = lst.last();
993 }
994
995 /*!
996         Name: splitText [private]
997         Desc: 
998 */
999
1000 QStringList QtxDockAction::splitText( const QString& str, const QString& sep ) const
1001 {
1002   QStringList res;
1003
1004   int idx = str.lower().find( sep.lower() );
1005   if ( idx != -1 )
1006   {
1007     res.append( str.mid( 0, idx ).stripWhiteSpace() );
1008     res.append( str.mid( idx + sep.length() ).stripWhiteSpace() );
1009   }
1010
1011   return res;
1012 }
1013
1014 /*!
1015         Name: dockPlace [private]
1016         Desc: 
1017 */
1018
1019 int QtxDockAction::dockPlace( const QString& dockName ) const
1020 {
1021   static QMap<QString, int> dockNameMap;
1022   if ( dockNameMap.isEmpty() )
1023   {
1024     dockNameMap["top"]       = DockTop;
1025     dockNameMap["bottom"]    = DockBottom;
1026     dockNameMap["left"]      = DockLeft;
1027     dockNameMap["right"]     = DockRight;
1028     dockNameMap["tornoff"]   = DockTornOff;
1029     dockNameMap["torn_off"]  = DockTornOff;
1030     dockNameMap["outside"]   = DockTornOff;
1031     dockNameMap["undock"]    = DockTornOff;
1032     dockNameMap["minimized"] = DockMinimized;
1033     dockNameMap["unmanaged"] = DockUnmanaged;
1034   }
1035
1036   int res = -1;
1037   if ( dockNameMap.contains( dockName.lower() ) )
1038     res = dockNameMap[dockName.lower()];
1039   return res;
1040 }
1041
1042 /*!
1043         Name: dockArea [private]
1044         Desc: 
1045 */
1046
1047 QDockArea* QtxDockAction::dockArea( const int place ) const
1048 {
1049   if ( !mainWindow() )
1050     return 0;
1051
1052   QDockArea* area = 0;
1053   switch ( place )
1054   {
1055   case DockTop:
1056     area = mainWindow()->topDock();
1057     break;
1058   case DockBottom:
1059     area = mainWindow()->bottomDock();
1060     break;
1061   case DockLeft:
1062     area = mainWindow()->leftDock();
1063     break;
1064   case DockRight:
1065     area = mainWindow()->rightDock();
1066     break;
1067   }
1068   return area;
1069 }
1070
1071 /*!
1072         Name: loadGeometry [private]
1073         Desc: 
1074 */
1075
1076 bool QtxDockAction::loadGeometry( QtxResourceMgr* resMgr, const QString& sec,
1077                                   const QString& name, GeomInfo& inf ) const
1078 {
1079   if ( !resMgr || sec.isEmpty() || name.isEmpty() )
1080     return false;
1081
1082   QString tmpl = QString( "%1.%2" ).arg( name );
1083
1084   inf.vis     = resMgr->booleanValue( sec, tmpl.arg( "visible" ), inf.vis );
1085   inf.newLine = resMgr->booleanValue( sec, tmpl.arg( "new_line" ), inf.newLine );
1086
1087   inf.index   = resMgr->integerValue( sec, tmpl.arg( "index" ), inf.index );
1088   inf.offset  = resMgr->integerValue( sec, tmpl.arg( "offset" ), inf.offset );
1089
1090   inf.x       = resMgr->integerValue( sec, tmpl.arg( "x" ), inf.x );
1091   inf.y       = resMgr->integerValue( sec, tmpl.arg( "y" ), inf.y );
1092   inf.w       = resMgr->integerValue( sec, tmpl.arg( "width" ), inf.w );
1093   inf.h       = resMgr->integerValue( sec, tmpl.arg( "height" ), inf.h );
1094
1095   inf.fixW    = resMgr->integerValue( sec, tmpl.arg( "fixed_width" ), inf.fixW );
1096   inf.fixH    = resMgr->integerValue( sec, tmpl.arg( "fixed_height" ), inf.fixH );
1097
1098   int place = -1;
1099   if ( !resMgr->value( sec, tmpl.arg( "place" ), place ) )
1100   {
1101     QString placeStr;
1102     if ( resMgr->value( sec, tmpl.arg( "place" ), placeStr ) )
1103       place = dockPlace( placeStr );
1104   }
1105
1106   if ( place >= DockUnmanaged && place <= DockMinimized )
1107     inf.place = place;
1108
1109   return true;
1110 }
1111
1112 /*!
1113         Name: saveGeometry [private]
1114         Desc: 
1115 */
1116
1117 bool QtxDockAction::saveGeometry( QtxResourceMgr* resMgr, const QString& sec,
1118                                   const QString& name, const GeomInfo& inf ) const
1119 {
1120   if ( !resMgr || sec.isEmpty() || name.isEmpty() )
1121     return false;
1122
1123   QString tmpl = QString( "%1.%2" ).arg( name );
1124
1125   resMgr->setValue( sec, tmpl.arg( "visible" ), inf.vis );
1126   resMgr->setValue( sec, tmpl.arg( "new_line" ), inf.newLine );
1127   resMgr->setValue( sec, tmpl.arg( "index" ), inf.index );
1128   resMgr->setValue( sec, tmpl.arg( "offset" ), inf.offset );
1129   resMgr->setValue( sec, tmpl.arg( "x" ), inf.x );
1130   resMgr->setValue( sec, tmpl.arg( "y" ), inf.y );
1131   resMgr->setValue( sec, tmpl.arg( "width" ), inf.w );
1132   resMgr->setValue( sec, tmpl.arg( "height" ), inf.h );
1133   resMgr->setValue( sec, tmpl.arg( "fixed_width" ), inf.fixW );
1134   resMgr->setValue( sec, tmpl.arg( "fixed_height" ), inf.fixH );
1135   resMgr->setValue( sec, tmpl.arg( "place" ), inf.place );
1136
1137   return true;
1138 }
1139
1140 /*!
1141         Name: collectNames [private]
1142         Desc: 
1143 */
1144
1145 void QtxDockAction::collectNames( const int place, QStringList& lst ) const
1146 {
1147   QPtrList<QDockWindow> winList;
1148   QDockArea* area = dockArea( place );
1149   if ( area )
1150     winList = area->dockWindowList();
1151   else
1152     winList = mainWindow()->dockWindows( (Qt::Dock)place );
1153
1154   for ( QPtrListIterator<QDockWindow> it( winList ); it.current(); ++it )
1155   {
1156     QString name;
1157     if ( myInfo.contains( it.current() ) )
1158       name = myInfo[it.current()].name;
1159     if ( name.isEmpty() )
1160       name = windowName( it.current() );
1161     if ( name.isEmpty() )
1162       continue;
1163
1164     lst.append( name );
1165   }
1166 }