Salome HOME
Cyclic invocation of method "show" was removed.
[modules/gui.git] / src / Qtx / QtxMainWindow.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:      QtxMainWindow.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxMainWindow.h"
23
24 #include "QtxToolBar.h"
25 #include "QtxResourceMgr.h"
26
27 #include <qlayout.h>
28 #include <qmenubar.h>
29 #include <qstatusbar.h>
30 #include <qapplication.h>
31
32 /*!
33     Class: QtxMainWindow::Filter [Internal]
34     Descr: Internal object with event filter for QtxMainWindow.
35 */
36
37 class QtxMainWindow::Filter : public QObject
38 {
39 public:
40   Filter( QWidget*, QtxMainWindow*, QObject* = 0 );
41   virtual ~Filter();
42
43   virtual bool eventFilter( QObject*, QEvent* );
44
45 private:
46   QMainWindow* myMain;
47   QWidget*     myWidget;
48 };
49
50 QtxMainWindow::Filter::Filter( QWidget* wid, QtxMainWindow* mw, QObject* parent )
51 : QObject( parent ),
52 myMain( mw ),
53 myWidget( wid )
54 {
55   myMain->installEventFilter( this );
56 };
57
58 QtxMainWindow::Filter::~Filter()
59 {
60 }
61
62 bool QtxMainWindow::Filter::eventFilter( QObject* o, QEvent* e )
63 {
64   if ( myMain == o && e->type() == QEvent::ChildRemoved &&
65        myWidget == ((QChildEvent*)e)->child() )
66     return true;
67
68   return QObject::eventFilter( o, e );
69 }
70
71 /*!
72     Class: QtxMainWindow [Public]
73     Descr: Main window with support of dockable menubar/status bar
74            and geometry store/retrieve.
75 */
76
77 QtxMainWindow::QtxMainWindow( QWidget* parent, const char* name, WFlags f )
78 : QMainWindow( parent, name, f ),
79 myMode( -1 ),
80 myMenuBar( NULL ),
81 myStatusBar( NULL )
82 {
83 }
84
85 QtxMainWindow::~QtxMainWindow()
86 {
87   setDockableMenuBar( false );
88   setDockableStatusBar( false );
89 }
90
91 bool QtxMainWindow::isDockableMenuBar() const
92 {
93   return myMenuBar;
94 }
95
96 void QtxMainWindow::setDockableMenuBar( const bool on )
97 {
98   if ( isDockableMenuBar() == on )
99     return;
100
101   QMenuBar* mb = menuBar();
102   if ( !mb )
103     return;
104
105   if ( on && !myMenuBar )
106   {
107     mb->setCaption( tr( "Menu bar" ) );
108     QtxToolBar* dockMb = new QtxToolBar( true, this, "menu bar container" );
109     myMenuBar = dockMb;
110     new Filter( mb, this, myMenuBar );
111     dockMb->setWidget( mb );
112     dockMb->setNewLine( true );
113     dockMb->setStretchable( true );
114     dockMb->setResizeEnabled( false );
115
116     moveDockWindow( dockMb, DockTop );
117     setDockEnabled( dockMb, Left, false );
118     setDockEnabled( dockMb, Right, false );
119
120     setAppropriate( dockMb, false );
121
122     connect( dockMb, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
123   }
124   else if ( !on && myMenuBar )
125   {
126     mb->reparent( this, QPoint( 0, 0 ), mb->isVisibleTo( mb->parentWidget() ) );
127     disconnect( myMenuBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
128     delete myMenuBar;
129     myMenuBar = 0;
130     QChildEvent ce( QEvent::ChildRemoved, mb );
131     QApplication::sendEvent( this, &ce );
132   }
133
134   setUpLayout();
135 }
136
137 bool QtxMainWindow::isDockableStatusBar() const
138 {
139   return myStatusBar;
140 }
141
142 void QtxMainWindow::setDockableStatusBar( const bool on )
143 {
144   if ( isDockableStatusBar() == on )
145     return;
146
147   QStatusBar* sb = statusBar();
148   if ( !sb )
149     return;
150
151   if ( on && !myStatusBar )
152   {
153     sb->setCaption( tr( "Status bar" ) );
154     QtxToolBar* dockSb = new QtxToolBar( true, this, "status bar container" );
155     myStatusBar = dockSb;
156     new Filter( sb, this, myStatusBar );
157     dockSb->setWidget( sb );
158     dockSb->setNewLine( true );
159     dockSb->setStretchable( true );
160     dockSb->setResizeEnabled( false );
161     sb->setMinimumWidth( 250 );
162
163     sb->setSizeGripEnabled( false );
164
165     moveDockWindow( dockSb, DockBottom );
166     setDockEnabled( dockSb, Left, false );
167     setDockEnabled( dockSb, Right, false );
168
169     setAppropriate( dockSb, false );
170
171     connect( dockSb, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
172   }
173   else if ( !on && myStatusBar )
174   {
175     sb->reparent( this, QPoint( 0, 0 ), sb->isVisibleTo( sb->parentWidget() ) );
176     disconnect( myStatusBar, SIGNAL( destroyed( QObject* ) ), this, SLOT( onDestroyed( QObject* ) ) );
177     delete myStatusBar;
178     myStatusBar = 0;
179     QChildEvent ce( QEvent::ChildRemoved, sb );
180     QApplication::sendEvent( this, &ce );
181
182     sb->setSizeGripEnabled( true );
183   }
184
185   setUpLayout();
186 }
187
188 void QtxMainWindow::loadGeometry( QtxResourceMgr* resMgr, const QString& section )
189 {
190   QString sec = section.stripWhiteSpace();
191   if ( !resMgr || sec.isEmpty() )
192     return;
193
194   int winState = -1;
195   if ( !resMgr->value( sec, "state", winState ) )
196   {
197     QString stateStr;
198     if ( resMgr->value( sec, "state", stateStr ) )
199       winState = windowState( stateStr );
200   }
201
202   int win_w = resMgr->integerValue( sec, "width", width() );
203   int win_h = resMgr->integerValue( sec, "height", height() );
204
205   int winPosX = windowPosition( resMgr->stringValue( sec, QString( "pos_x" ), QString::null ) );
206   int winPosY = windowPosition( resMgr->stringValue( sec, QString( "pos_y" ), QString::null ) );
207
208   QWidget* desk = QApplication::desktop();
209
210   int win_x = 0;
211   if ( winPosX == WP_Absolute )
212     win_x = resMgr->integerValue( sec, "pos_x", x() );
213   else if ( desk )
214     win_x = relativeCoordinate( winPosX, desk->width(), win_w );
215
216   int win_y = 0;
217   if ( winPosX == WP_Absolute )
218     win_y = resMgr->integerValue( sec, "pos_y", y() );
219   else if ( desk )
220     win_y = relativeCoordinate( winPosY, desk->height(), win_h );
221
222   bool vis = isVisibleTo( parentWidget() );
223
224   resize( win_w, win_h );
225   move( win_x, win_y );
226
227   myMode = -1;
228
229   if ( vis )
230     QApplication::postEvent( this, new QCustomEvent( QEvent::User, (void*)winState ) );
231   else
232     myMode = winState;
233 }
234
235 void QtxMainWindow::show()
236 {
237   if ( myMode != -1 )
238     QApplication::postEvent( this, new QCustomEvent( QEvent::User, (void*)myMode ) );
239
240   myMode = -1;
241
242   QMainWindow::show();
243 }
244
245 void QtxMainWindow::customEvent( QCustomEvent* e )
246 {
247   QMainWindow::customEvent( e );
248
249   int mode = (int)e->data();
250   switch ( mode )
251   {
252   case WS_Normal:
253     showNormal();
254     break;
255   case WS_Minimized:
256     showMinimized();
257     break;
258   case WS_Maximized:
259     showMaximized();
260     break;
261   }
262 }
263
264 int QtxMainWindow::relativeCoordinate( const int type, const int WH, const int wh ) const
265 {
266   int res = 0;
267   switch ( type )
268   {
269   case WP_Center:
270     res = ( WH - wh ) / 2;
271     break;
272   case WP_Left:
273     res = 0;
274     break;
275   case WP_Right:
276     res = WH - wh;
277     break;
278   }
279   return res;
280 }
281
282 void QtxMainWindow::saveGeometry( QtxResourceMgr* resMgr, const QString& section ) const
283 {
284   QString sec = section.stripWhiteSpace();
285   if ( !resMgr || sec.isEmpty() )
286     return;
287
288   resMgr->setValue( sec, "pos_x", pos().x() );
289   resMgr->setValue( sec, "pos_y", pos().y() );
290   resMgr->setValue( sec, "width", width() );
291   resMgr->setValue( sec, "height", height() );
292
293   int winState = WS_Normal;
294   if ( isMinimized() )
295     winState = WS_Minimized;
296   else if ( isMaximized() )
297     winState = WS_Maximized;
298
299   resMgr->setValue( sec, "state", winState );
300 }
301
302 bool QtxMainWindow::eventFilter( QObject* o, QEvent* e )
303 {
304   return QMainWindow::eventFilter( o, e );
305 }
306
307 void QtxMainWindow::setAppropriate( QDockWindow* dw, bool a )
308 {
309   QMainWindow::setAppropriate( dw, myStatusBar != dw && myMenuBar != dw && a );
310 }
311
312 void QtxMainWindow::setUpLayout()
313 {
314   QMainWindow::setUpLayout();
315
316   if ( myMenuBar && layout() )
317     layout()->setMenuBar( 0 );
318 }
319
320 void QtxMainWindow::onDestroyed( QObject* obj )
321 {
322   QObject* o = 0;
323   if ( obj == myMenuBar )
324   {
325     myMenuBar = 0;
326     o = menuBar();
327   }
328   else if ( obj == myStatusBar )
329   {
330     myStatusBar = 0;
331     o = statusBar();
332   }
333
334   if ( o )
335   {
336     QChildEvent ce( QEvent::ChildRemoved, o );
337     QApplication::sendEvent( this, &ce );
338   }
339 }
340
341 int QtxMainWindow::windowState( const QString& str ) const
342 {
343   static QMap<QString, int> winStateMap;
344   if ( winStateMap.isEmpty() )
345   {
346     winStateMap["normal"]    = WS_Normal;
347     winStateMap["min"]       = WS_Minimized;
348     winStateMap["mini"]      = WS_Minimized;
349     winStateMap["minimized"] = WS_Minimized;
350     winStateMap["max"]       = WS_Maximized;
351     winStateMap["maxi"]      = WS_Maximized;
352     winStateMap["maximized"] = WS_Maximized;
353     winStateMap["hidden"]    = WS_Hidden;
354     winStateMap["hided"]     = WS_Hidden;
355     winStateMap["hide"]      = WS_Hidden;
356     winStateMap["invisible"] = WS_Hidden;
357   }
358
359   int res = -1;
360   QString stateStr = str.stripWhiteSpace().lower();
361   if ( winStateMap.contains( stateStr ) )
362     res = winStateMap[stateStr];
363   return res;
364 }
365
366 int QtxMainWindow::windowPosition( const QString& str ) const
367 {
368   static QMap<QString, int> winPosMap;
369   if ( winPosMap.isEmpty() )
370   {
371     winPosMap["center"] = WP_Center;
372     winPosMap["left"]   = WP_Left;
373     winPosMap["right"]  = WP_Right;
374     winPosMap["top"]    = WP_Top;
375     winPosMap["bottom"] = WP_Bottom;
376   }
377
378   int res = WP_Absolute;
379   QString posStr = str.stripWhiteSpace().lower();
380   if ( winPosMap.contains( posStr ) )
381     res = winPosMap[posStr];
382   return res;
383 }