Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / Qtx / QtxDockWindow.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/ or email : webmaster.salome@opencascade.com
18 //
19 // File:      QtxDockWindow.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxDockWindow.h"
23
24 #include <qlayout.h>
25 #include <qpixmap.h>
26 #include <qdockarea.h>
27 #include <qmainwindow.h>
28 #include <qapplication.h>
29
30 /*!
31   \class QtxDockWindow::Watcher [Internal]
32   Internal object with event filter.
33 */
34 class QtxDockWindow::Watcher : public QObject
35 {
36 public:
37   Watcher( QtxDockWindow* );
38
39   void           shown( QtxDockWindow* );
40   void           hided( QtxDockWindow* );
41
42   virtual bool   eventFilter( QObject*, QEvent* );
43
44 protected:
45   virtual void   customEvent( QCustomEvent* );
46
47 private:
48   void           installFilters();
49
50   void           showContainer();
51   void           hideContainer();
52
53   void           updateIcon();
54   void           updateCaption();
55   void           updateVisibility();
56
57 private:
58   QtxDockWindow* myCont;
59   bool           myState;
60   bool           myEmpty;
61   bool           myVisible;
62 };
63
64 /*!
65   Constructor
66 */
67 QtxDockWindow::Watcher::Watcher( QtxDockWindow* cont )
68 : QObject( cont ), myCont( cont ),
69 myState( true ),
70 myEmpty( true )
71 {
72   if ( myCont->mainWindow() )
73     myState = myCont->mainWindow()->appropriate( myCont );
74
75   myCont->installEventFilter( this );
76   myVisible = myCont->isVisibleTo( myCont->parentWidget() );
77
78   installFilters();
79 }
80
81 /*!
82   Custom event filter
83 */
84 bool QtxDockWindow::Watcher::eventFilter( QObject* o, QEvent* e )
85 {
86   if ( o == myCont &&
87        ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
88          e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ||
89          e->type() == QEvent::ChildInserted ) )
90     QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
91
92   if ( o != myCont && e->type() == QEvent::IconChange )
93     updateIcon();
94
95   if ( o != myCont && e->type() == QEvent::CaptionChange )
96     updateCaption();
97
98   if ( ( o != myCont && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) ) ||
99        ( o == myCont && ( e->type() == QEvent::ChildRemoved ) ) ||
100        ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
101     updateVisibility();
102
103   return false;
104 }
105
106 /*!
107   Sets internal status to shown
108 */
109 void QtxDockWindow::Watcher::shown( QtxDockWindow* dw )
110 {
111   if ( dw != myCont )
112     return;
113
114   myVisible = true;
115 }
116
117 /*!
118   Sets internal status to hidden
119 */
120 void QtxDockWindow::Watcher::hided( QtxDockWindow* dw )
121 {
122   if ( dw != myCont )
123     return;
124
125   myVisible = false;
126 }
127
128 /*!
129   Shows corresponding dock window
130 */
131 void QtxDockWindow::Watcher::showContainer()
132 {
133   if ( !myCont )
134     return;
135
136   QtxDockWindow* cont = myCont;
137   myCont = 0;
138   cont->show();
139   myCont = cont;
140 }
141
142 /*!
143   Hides corresponding dock window
144 */
145 void QtxDockWindow::Watcher::hideContainer()
146 {
147   if ( !myCont )
148     return;
149
150   QtxDockWindow* cont = myCont;
151   myCont = 0;
152   cont->hide();
153   myCont = cont;
154 }
155
156 /*!
157   Event filter of custom events
158 */
159 void QtxDockWindow::Watcher::customEvent( QCustomEvent* e )
160 {
161   installFilters();
162
163   updateIcon();
164   updateCaption();
165   updateVisibility();
166 }
167
168 /*!
169   Installs this object as event filter to all widgets inside corresponding main window
170 */
171 void QtxDockWindow::Watcher::installFilters()
172 {
173   if ( !myCont )
174     return;
175
176   QBoxLayout* bl = myCont->boxLayout();
177   if ( !bl )
178     return;
179
180   for ( QLayoutIterator it = bl->iterator(); it.current(); ++it )
181   {
182     if ( it.current()->widget() )
183       it.current()->widget()->installEventFilter( this );
184   }
185 }
186
187 /*!
188   Updates visibility of all widgets inside corresponding main window
189 */
190 void QtxDockWindow::Watcher::updateVisibility()
191 {
192   if ( !myCont )
193     return;
194
195   QBoxLayout* bl = myCont->boxLayout();
196   if ( !bl )
197     return;
198
199   bool vis = false;
200   for ( QLayoutIterator it = bl->iterator(); it.current() && !vis; ++it )
201     vis = it.current()->widget() && it.current()->widget()->isVisibleTo( myCont );
202
203   QMainWindow* mw = myCont->mainWindow();
204   if ( mw && myEmpty == vis )
205   {
206     myEmpty = !vis;
207     if ( !myEmpty )
208       mw->setAppropriate( myCont, myState );
209     else
210     {
211       myState = mw->appropriate( myCont );
212       mw->setAppropriate( myCont, false );
213     }
214   }
215
216   vis = !myEmpty && myVisible;
217   if ( vis != myCont->isVisibleTo( myCont->parentWidget() ) )
218     vis ? showContainer() : hideContainer();
219 }
220
221 /*!
222   Updates icon of corresponding main window
223 */
224 void QtxDockWindow::Watcher::updateIcon()
225 {
226   if ( !myCont || !myCont->widget() )
227     return;
228   
229   const QPixmap* ico = myCont->widget()->icon();
230   myCont->setIcon( ico ? *ico : QPixmap() );
231 }
232
233 /*!
234   Updates caption of corresponding main window
235 */
236 void QtxDockWindow::Watcher::updateCaption()
237 {
238   if ( myCont && myCont->widget() && !myCont->widget()->caption().isNull() )
239     myCont->setCaption( myCont->widget()->caption() );
240 }
241
242 /*!
243   Constructor
244 */
245 QtxDockWindow::QtxDockWindow( Place p, QWidget* parent, const char* name, WFlags f )
246 : QDockWindow( p, parent, name, f ),
247 myWatcher( 0 ),
248 myStretch( false )
249 {
250 }
251
252 /*!
253   Constructor
254 */
255 QtxDockWindow::QtxDockWindow( const bool watch, QWidget* parent, const char* name, WFlags f )
256 : QDockWindow( InDock, parent, name, f ),
257 myWatcher( 0 ),
258 myStretch( false )
259 {
260   if ( watch )
261     myWatcher = new Watcher( this );
262 }
263
264 /*!
265   Constructor
266 */
267 QtxDockWindow::QtxDockWindow( QWidget* parent, const char* name, WFlags f )
268 : QDockWindow( InDock, parent, name, f ),
269 myWatcher( 0 ),
270 myStretch( false )
271 {
272 }
273
274 /*!
275   Destructor
276 */
277 QtxDockWindow::~QtxDockWindow()
278 {
279 }
280
281 /*!
282   Sets the dock window's main widget
283   \param wid - new main widget
284 */
285 void QtxDockWindow::setWidget( QWidget* wid )
286 {
287   if ( wid )
288     wid->reparent( this, QPoint( 0, 0 ), wid->isVisibleTo( wid->parentWidget() ) );
289
290   QDockWindow::setWidget( wid );
291 }
292
293 /*!
294   \return true if the dock window is stretchable
295 */
296 bool QtxDockWindow::isStretchable() const
297 {
298   return myStretch;
299 }
300
301 /*!
302   Sets the dock window "stretchable" state
303   \param on - new state
304 */
305 void QtxDockWindow::setStretchable( const bool on )
306 {
307   if ( myStretch == on )
308     return;
309
310   myStretch = on;
311
312   boxLayout()->setStretchFactor( widget(), myStretch ? 1 : 0 );
313
314   if ( myStretch != isHorizontalStretchable() ||
315        myStretch != isVerticalStretchable() )
316   {
317           if ( orientation() == Horizontal )
318             setHorizontalStretchable( myStretch );
319           else
320             setVerticalStretchable( myStretch );
321   }
322 }
323
324 /*!
325   \return the recommended size for the widget
326 */
327 QSize QtxDockWindow::sizeHint() const
328 {
329   QSize sz = QDockWindow::sizeHint();
330
331   if ( place() == InDock && isStretchable() && area() )
332   {
333     if ( orientation() == Horizontal )
334       sz.setWidth( area()->width() );
335     else
336       sz.setHeight( area()->height() );
337   }
338
339   return sz;
340 }
341
342 /*!
343   \return the recommended minimum size for the widget
344 */
345 QSize QtxDockWindow::minimumSizeHint() const
346 {
347   QSize sz = QDockWindow::minimumSizeHint();
348
349   if ( orientation() == Horizontal )
350           sz = QSize( 0, QDockWindow::minimumSizeHint().height() );
351   else
352     sz = QSize( QDockWindow::minimumSizeHint().width(), 0 );
353
354   if ( place() == InDock && isStretchable() && area() )
355   {
356     if ( orientation() == Horizontal )
357       sz.setWidth( area()->width() );
358     else
359       sz.setHeight( area()->height() );
360   }
361
362   return sz;
363 }
364
365 /*!
366   \return corresponding main window
367 */
368 QMainWindow* QtxDockWindow::mainWindow() const
369 {
370   QMainWindow* mw = 0;
371
372   QWidget* wid = parentWidget();
373   while ( !mw && wid )
374   {
375     if ( wid->inherits( "QMainWindow" ) )
376       mw = (QMainWindow*)wid;
377     wid = wid->parentWidget();
378   }
379
380   return mw;
381 }
382
383 /*!
384   Shows window
385 */
386 void QtxDockWindow::show()
387 {
388   if ( myWatcher )
389     myWatcher->shown( this );
390
391   QDockWindow::show();
392 }
393
394 /*!
395   Hides window
396 */
397 void QtxDockWindow::hide()
398 {
399   if ( myWatcher )
400     myWatcher->hided( this );
401
402   QDockWindow::hide();
403 }