Salome HOME
88c4c1d125e5c3574f5ae7654d5fe37c080b480d
[modules/gui.git] / src / Qtx / QtxToolBar.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:      QtxToolBar.cxx
24 // Author:    Sergey TELKOV
25 //
26 #include "QtxToolBar.h"
27
28 #include <QAction>
29 #include <QMainWindow>
30 #include <QApplication>
31
32 /*!
33   \class QtxToolBar::Watcher
34   \internal
35   \brief Internal class which goal is to watch parent toolbar state changing.
36 */
37
38 class QtxToolBar::Watcher : public QObject
39 {
40 public:
41   Watcher( QtxToolBar* );
42
43   void         shown( QtxToolBar* );
44   void         hidden( QtxToolBar* );
45
46   virtual bool eventFilter( QObject*, QEvent* );
47
48   bool           isEmpty() const;
49   bool           isVisible() const;
50
51 protected:
52   virtual void customEvent( QEvent* );
53
54 private:
55   enum { Install = QEvent::User, Update };
56
57 private:
58   void         installFilters();
59
60   void         showContainer();
61   void         hideContainer();
62
63   void         updateVisibility();
64
65   void         setEmpty( const bool );
66   void         setVisible( const bool );
67
68 private:
69   QtxToolBar*  myCont;
70   bool         myState;
71   bool         myEmpty;
72 };
73
74 /*!
75   \brief Constructor.
76   \param cont toolbar to be watched
77 */
78 QtxToolBar::Watcher::Watcher( QtxToolBar* cont )
79 : QObject( cont ),
80   myCont( cont ),
81   myState( true ),
82   myEmpty( false )
83 {
84   setVisible( myCont->isVisibleTo( myCont->parentWidget() ) );
85
86   myCont->installEventFilter( this );
87
88   installFilters();
89 }
90
91 /*!
92   \brief Custom event filter.
93   \param o event receiver object
94   \param e event sent to object
95   \return \c true if further event processing should be stopped
96 */
97 bool QtxToolBar::Watcher::eventFilter( QObject* o, QEvent* e )
98 {
99   if ( o == myCont && e->type() == QEvent::ChildAdded )
100     QApplication::postEvent( this, new QEvent( (QEvent::Type)Install ) );
101
102   bool updVis = ( o != myCont && ( e->type() == QEvent::Show || e->type() == QEvent::ShowToParent ||
103                                    e->type() == QEvent::Hide || e->type() == QEvent::HideToParent ) ) ||
104                 ( o == myCont && ( e->type() == QEvent::ChildAdded   || e->type() == QEvent::ChildRemoved || e->type() == QEvent::Show ||
105                                    e->type() == QEvent::ShowToParent || e->type() == QEvent::Hide ||
106                                    e->type() == QEvent::HideToParent || e->type() == QEvent::ActionAdded ||
107                                    e->type() == QEvent::ActionRemoved ) );
108
109   if ( updVis )
110   {
111     QtxToolBar* cont = myCont;
112     myCont = 0;
113     QApplication::sendPostedEvents( this, Update );
114     myCont = cont;
115     QApplication::postEvent( this, new QEvent( (QEvent::Type)Update ) );
116   }
117
118   return false;
119 }
120
121 /*!
122   \brief Set internal status to "shown"
123   \param tb toolbar
124 */
125 void QtxToolBar::Watcher::shown( QtxToolBar* tb )
126 {
127   if ( tb != myCont )
128     return;
129
130   setVisible( true );
131 }
132
133 /*!
134   \brief Set internal status to "hidden"
135   \param tb toolbar
136 */
137 void QtxToolBar::Watcher::hidden( QtxToolBar* tb )
138 {
139   if ( tb != myCont )
140     return;
141
142   setVisible( false );
143 }
144
145 bool QtxToolBar::Watcher::isEmpty() const
146 {
147   return myEmpty;
148 }
149
150 bool QtxToolBar::Watcher::isVisible() const
151 {
152   bool vis = false;
153   if ( myCont && myCont->toggleViewAction() )
154     vis = myCont->toggleViewAction()->isChecked();
155   return vis;
156 }
157
158 void QtxToolBar::Watcher::setEmpty( const bool on )
159 {
160   myEmpty = on;
161 }
162
163 void QtxToolBar::Watcher::setVisible( const bool on )
164 {
165   if ( !myCont || !myCont->toggleViewAction() )
166     return;
167
168   bool block = myCont->toggleViewAction()->signalsBlocked();
169   myCont->toggleViewAction()->blockSignals( true );
170   myCont->toggleViewAction()->setChecked( on );
171   myCont->toggleViewAction()->blockSignals( block );
172 }
173
174 /*!
175   \brief Show the toolbar being watched
176 */
177 void QtxToolBar::Watcher::showContainer()
178 {
179   if ( !myCont )
180     return;
181
182   bool vis = isVisible();
183
184   QtxToolBar* cont = myCont;
185   myCont = 0;
186   cont->show();
187   myCont = cont;
188
189   setVisible( vis );
190 }
191
192 /*!
193   \brief Hide the toolbar being watched
194 */
195 void QtxToolBar::Watcher::hideContainer()
196 {
197   if ( !myCont )
198     return;
199
200   bool vis = isVisible();
201
202   QtxToolBar* cont = myCont;
203   myCont = 0;
204   cont->hide();
205   myCont = cont;
206
207   setVisible( vis );
208 }
209
210 /*!
211   \brief Proces custom events.
212   \param e custom event
213 */
214 void QtxToolBar::Watcher::customEvent( QEvent* e )
215 {
216   switch ( (int)e->type() )
217   {
218   case Install:
219     installFilters();
220     break;
221   case Update:
222     updateVisibility();
223     break;
224   default:
225     break;
226   }
227 }
228
229 /*!
230   \brief Install this object as event dilter to all children widgets
231          of the toolbar being watched.
232 */
233 void QtxToolBar::Watcher::installFilters()
234 {
235   if ( !myCont )
236     return;
237
238   const QObjectList& objList = myCont->children();
239   for ( QObjectList::const_iterator it = objList.begin(); it != objList.end(); ++it )
240   {
241     if ( (*it)->isWidgetType() && qstrcmp( "qt_dockwidget_internal", (*it)->objectName().toUtf8() ) )
242       (*it)->installEventFilter( this );
243   }
244 }
245
246 /*!
247   \brief Update visibility state of all children widgets of the toolbar
248          being watched.
249 */
250 void QtxToolBar::Watcher::updateVisibility()
251 {
252   if ( !myCont )
253     return;
254
255   bool vis = false;
256   QList<QAction*> actList = myCont->actions();
257   for ( QList<QAction*>::const_iterator it = actList.begin(); it != actList.end() && !vis; ++it )
258   {
259     if ( (*it)->isSeparator() )
260       continue;
261
262     vis = (*it)->isVisible();
263   }
264
265   QMainWindow* mw = myCont->mainWindow();
266   bool empty = isEmpty();
267   if ( mw && empty == vis )
268   {
269     empty = !vis;
270     setEmpty( empty );
271     if ( !empty )
272       myCont->toggleViewAction()->setVisible( myState );
273     else
274     {
275       myState = myCont->toggleViewAction()->isVisible();
276       myCont->toggleViewAction()->setVisible( false );
277     }
278   }
279
280   vis = (!isEmpty() && isVisible());
281   if ( vis != myCont->isVisibleTo( myCont->parentWidget() ) )
282     vis ? showContainer() : hideContainer();
283 }
284
285 /*!
286   \class QtxToolBar
287   \brief Enhanced toolbar class.
288 */
289
290 /*!
291   \brief Constructor.
292   \param watch if \c true the event filter is installed to watch toolbar state changes 
293          to update it properly
294   \param label toolbar title
295   \param parent parent widget
296 */
297 QtxToolBar::QtxToolBar( const bool watch, const QString& label, QWidget* parent )
298 : QToolBar( label, parent ),
299   myWatcher( 0 ),
300   myStretch( false )
301 {
302   if ( watch )
303     myWatcher = new Watcher( this );
304
305   if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
306     mw->addToolBar( this );
307 }
308
309 /*!
310   \brief Constructor.
311   \param label toolbar title
312   \param parent parent widget
313 */
314 QtxToolBar::QtxToolBar( const QString& label, QWidget* parent )
315 : QToolBar( label, parent ),
316   myWatcher( 0 ),
317   myStretch( false )
318 {
319   if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
320     mw->addToolBar( this );
321 }
322
323 /*!
324   \brief Constructor.
325   \param watch if \c true the event filter is installed to watch toolbar state changes 
326          to update it properly
327   \param parent parent widget
328 */
329 QtxToolBar::QtxToolBar( const bool watch, QWidget* parent )
330 : QToolBar( parent ),
331   myWatcher( 0 ),
332   myStretch( false )
333 {
334   if ( watch )
335     myWatcher = new Watcher( this );
336
337   if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
338     mw->addToolBar( this );
339 }
340
341 /*!
342   \brief Constructor.
343   \param parent parent widget
344 */
345 QtxToolBar::QtxToolBar( QWidget* parent )
346 : QToolBar( parent ),
347   myWatcher( 0 ),
348   myStretch( false )
349 {
350   if ( QMainWindow* mw = ::qobject_cast<QMainWindow*>( parent ) )
351     mw->addToolBar( this );
352 }
353
354 /*!
355   \brief Destructor.
356 */
357 QtxToolBar::~QtxToolBar()
358 {
359 }
360
361 /*!
362   \brief Show/hide the toolbar.
363   \param on new visibility state
364 */
365 void QtxToolBar::setVisible( bool visible )
366 {
367   if ( isVisible() != visible ) {
368     if ( myWatcher )
369       {
370         if ( visible )
371           myWatcher->shown( this );
372         else
373           myWatcher->hidden( this );
374       }
375   }
376
377   QToolBar::setVisible( visible );
378 }
379
380 /*!
381   \brief Get parent main window.
382   \return main window pointer
383 */
384 QMainWindow* QtxToolBar::mainWindow() const
385 {
386   QMainWindow* mw = 0;
387   QWidget* wid = parentWidget();
388   while ( !mw && wid )
389   {
390     mw = ::qobject_cast<QMainWindow*>( wid );
391     wid = wid->parentWidget();
392   }
393   return mw;
394 }
395
396 bool QtxToolBar::event( QEvent* e )
397 {
398   if ( e->type() == QEvent::WindowTitleChange && objectName().isEmpty() )
399     setObjectName( windowTitle() );
400
401   return QToolBar::event( e );
402 }