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