Salome HOME
Fix for bug 10438: Crash during Explode on Blocks operation (Global selection on...
[modules/gui.git] / src / Qtx / QtxDockWindow.cxx
1 // File:      QtxDockWindow.cxx
2 // Author:    Sergey TELKOV
3
4 #include "QtxDockWindow.h"
5
6 #include <qlayout.h>
7 #include <qpixmap.h>
8 #include <qdockarea.h>
9 #include <qmainwindow.h>
10 #include <qapplication.h>
11
12 /*!
13     Class: QtxDockWindow::Watcher [Internal]
14     Descr: Internal object with event filter.
15 */
16
17 class QtxDockWindow::Watcher : public QObject
18 {
19 public:
20   Watcher( QtxDockWindow* );
21
22   void           shown( QtxDockWindow* );
23   void           hided( QtxDockWindow* );
24
25   virtual bool   eventFilter( QObject*, QEvent* );
26
27 protected:
28   virtual void   customEvent( QCustomEvent* );
29
30 private:
31   void           installFilters();
32
33   void           showContainer();
34   void           hideContainer();
35
36   void           updateIcon();
37   void           updateCaption();
38   void           updateVisibility();
39
40 private:
41   QtxDockWindow* myCont;
42   bool           myState;
43   bool           myEmpty;
44   bool           myVisible;
45 };
46
47 QtxDockWindow::Watcher::Watcher( QtxDockWindow* cont )
48 : QObject( cont ), myCont( cont ),
49 myState( true ),
50 myEmpty( true )
51 {
52   if ( myCont->mainWindow() )
53     myState = myCont->mainWindow()->appropriate( myCont );
54
55   myCont->installEventFilter( this );
56   myVisible = myCont->isVisibleTo( myCont->parentWidget() );
57
58   installFilters();
59 }
60
61 bool QtxDockWindow::Watcher::eventFilter( QObject* o, QEvent* e )
62 {
63   if ( o == myCont &&
64        ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
65          e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ||
66          e->type() == QEvent::ChildInserted ) )
67     QApplication::postEvent( this, new QCustomEvent( QEvent::User ) );
68
69   if ( o != myCont && e->type() == QEvent::IconChange )
70     updateIcon();
71
72   if ( o != myCont && e->type() == QEvent::CaptionChange )
73     updateCaption();
74
75   if ( ( o != myCont && ( e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) ) ||
76        ( o == myCont && ( e->type() == QEvent::ChildRemoved ) ) ||
77        ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ) )
78     updateVisibility();
79
80   return false;
81 }
82
83 void QtxDockWindow::Watcher::shown( QtxDockWindow* dw )
84 {
85   if ( dw != myCont )
86     return;
87
88   myVisible = true;
89 }
90
91 void QtxDockWindow::Watcher::hided( QtxDockWindow* dw )
92 {
93   if ( dw != myCont )
94     return;
95
96   myVisible = false;
97 }
98
99 void QtxDockWindow::Watcher::showContainer()
100 {
101   if ( !myCont )
102     return;
103
104   QtxDockWindow* cont = myCont;
105   myCont = 0;
106   cont->show();
107   myCont = cont;
108 }
109
110 void QtxDockWindow::Watcher::hideContainer()
111 {
112   if ( !myCont )
113     return;
114
115   QtxDockWindow* cont = myCont;
116   myCont = 0;
117   cont->hide();
118   myCont = cont;
119 }
120
121 void QtxDockWindow::Watcher::customEvent( QCustomEvent* e )
122 {
123   installFilters();
124
125   updateIcon();
126   updateCaption();
127   updateVisibility();
128 }
129
130 void QtxDockWindow::Watcher::installFilters()
131 {
132   if ( !myCont )
133     return;
134
135   QBoxLayout* bl = myCont->boxLayout();
136   if ( !bl )
137     return;
138
139   for ( QLayoutIterator it = bl->iterator(); it.current(); ++it )
140   {
141     if ( it.current()->widget() )
142       it.current()->widget()->installEventFilter( this );
143   }
144 }
145
146 void QtxDockWindow::Watcher::updateVisibility()
147 {
148   if ( !myCont )
149     return;
150
151   QBoxLayout* bl = myCont->boxLayout();
152   if ( !bl )
153     return;
154
155   bool vis = false;
156   for ( QLayoutIterator it = bl->iterator(); it.current() && !vis; ++it )
157     vis = it.current()->widget() && it.current()->widget()->isVisibleTo( myCont );
158
159   QMainWindow* mw = myCont->mainWindow();
160   if ( mw && myEmpty == vis )
161   {
162     myEmpty = !vis;
163     if ( !myEmpty )
164       mw->setAppropriate( myCont, myState );
165     else
166     {
167       myState = mw->appropriate( myCont );
168       mw->setAppropriate( myCont, false );
169     }
170   }
171
172   vis = !myEmpty && myVisible;
173   if ( vis != myCont->isVisibleTo( myCont->parentWidget() ) )
174     vis ? showContainer() : hideContainer();
175 }
176
177 void QtxDockWindow::Watcher::updateIcon()
178 {
179   if ( !myCont || !myCont->widget() )
180     return;
181   
182   const QPixmap* ico = myCont->widget()->icon();
183   myCont->setIcon( ico ? *ico : QPixmap() );
184 }
185
186 void QtxDockWindow::Watcher::updateCaption()
187 {
188   if ( myCont && myCont->widget() && !myCont->widget()->caption().isNull() )
189     myCont->setCaption( myCont->widget()->caption() );
190 }
191
192 /*!
193     Class: QtxDockWindow [Public]
194     Descr: 
195 */
196
197 QtxDockWindow::QtxDockWindow( Place p, QWidget* parent, const char* name, WFlags f )
198 : QDockWindow( p, parent, name, f ),
199 myWatcher( 0 ),
200 myStretch( false )
201 {
202 }
203
204 QtxDockWindow::QtxDockWindow( const bool watch, QWidget* parent, const char* name, WFlags f )
205 : QDockWindow( InDock, parent, name, f ),
206 myWatcher( 0 ),
207 myStretch( false )
208 {
209   if ( watch )
210     myWatcher = new Watcher( this );
211 }
212
213 QtxDockWindow::QtxDockWindow( QWidget* parent, const char* name, WFlags f )
214 : QDockWindow( InDock, parent, name, f ),
215 myWatcher( 0 ),
216 myStretch( false )
217 {
218 }
219
220 QtxDockWindow::~QtxDockWindow()
221 {
222 }
223
224 void QtxDockWindow::setWidget( QWidget* wid )
225 {
226   if ( wid )
227     wid->reparent( this, QPoint( 0, 0 ), wid->isVisibleTo( wid->parentWidget() ) );
228
229   QDockWindow::setWidget( wid );
230 }
231
232 bool QtxDockWindow::isStretchable() const
233 {
234   return myStretch;
235 }
236
237 void QtxDockWindow::setStretchable( const bool on )
238 {
239   if ( myStretch == on )
240     return;
241
242   myStretch = on;
243
244   boxLayout()->setStretchFactor( widget(), myStretch ? 1 : 0 );
245
246   if ( myStretch != isHorizontalStretchable() ||
247        myStretch != isVerticalStretchable() )
248   {
249           if ( orientation() == Horizontal )
250             setHorizontalStretchable( myStretch );
251           else
252             setVerticalStretchable( myStretch );
253   }
254 }
255
256 QSize QtxDockWindow::sizeHint() const
257 {
258   QSize sz = QDockWindow::sizeHint();
259
260   if ( place() == InDock && isStretchable() && area() )
261   {
262     if ( orientation() == Horizontal )
263       sz.setWidth( area()->width() );
264     else
265       sz.setHeight( area()->height() );
266   }
267
268   return sz;
269 }
270
271 QSize QtxDockWindow::minimumSizeHint() const
272 {
273   QSize sz = QDockWindow::minimumSizeHint();
274
275   if ( orientation() == Horizontal )
276           sz = QSize( 0, QDockWindow::minimumSizeHint().height() );
277   else
278     sz = QSize( QDockWindow::minimumSizeHint().width(), 0 );
279
280   if ( place() == InDock && isStretchable() && area() )
281   {
282     if ( orientation() == Horizontal )
283       sz.setWidth( area()->width() );
284     else
285       sz.setHeight( area()->height() );
286   }
287
288   return sz;
289 }
290
291 QMainWindow* QtxDockWindow::mainWindow() const
292 {
293   QMainWindow* mw = 0;
294
295   QWidget* wid = parentWidget();
296   while ( !mw && wid )
297   {
298     if ( wid->inherits( "QMainWindow" ) )
299       mw = (QMainWindow*)wid;
300     wid = wid->parentWidget();
301   }
302
303   return mw;
304 }
305
306 void QtxDockWindow::show()
307 {
308   if ( myWatcher )
309     myWatcher->shown( this );
310
311   QDockWindow::show();
312 }
313
314 void QtxDockWindow::hide()
315 {
316   if ( myWatcher )
317     myWatcher->hided( this );
318
319   QDockWindow::hide();
320 }