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