Salome HOME
updated copyright message
[modules/gui.git] / src / Qtx / QtxGroupBox.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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:      QtxGroupBox.cxx
24 // Author:    Sergey TELKOV
25 //
26 #include "QtxGroupBox.h"
27
28 #include <QVBoxLayout>
29 #include <QHBoxLayout>
30 #include <QEvent>
31 #include <QObjectList>
32 #include <QApplication>
33
34 /*!
35   \class QtxGroupBox
36   \brief Enhanced group box widget.
37
38   The QtxGroupBox class allows inserting custom widgets in the 
39   group box title. Use insertTitleWidget() method to add
40   custom widget to the title and removeTitleWidget() to remove it.
41 */
42
43 /*!
44   \brief Constructor.
45   \param parent parent widget 
46 */
47 QtxGroupBox::QtxGroupBox( QWidget* parent )
48 : QGroupBox( parent ),
49   myContainer( 0 )
50 {
51   initialize();
52 }
53
54 /*!
55   \brief Constructor.
56   \param title group box title text
57   \param parent parent widget 
58 */
59 QtxGroupBox::QtxGroupBox( const QString& title, QWidget* parent )
60 : QGroupBox( title, parent ),
61   myContainer( 0 )
62 {
63   initialize();
64 }
65
66 /*!
67   \brief Destructor.
68 */
69 QtxGroupBox::~QtxGroupBox()
70 {
71 }
72
73 /*!
74   \brief Initialize the group box.
75
76   Creates horizontal box as container for title widgets.
77 */
78 void QtxGroupBox::initialize()
79 {
80   myContainer = new QWidget( this );
81   QHBoxLayout* base = new QHBoxLayout( myContainer );
82   base->setMargin( 0 );
83   base->setSpacing( 0 );
84
85   updateTitle();
86 }
87
88 /*!
89   \brief Add widget to the group box title.
90   \param wid widget being added to the title
91 */
92 void QtxGroupBox::insertTitleWidget( QWidget* wid )
93 {
94   if ( !myContainer )
95     return;
96
97   myContainer->layout()->addWidget( wid );
98   wid->installEventFilter( this );
99
100   updateTitle();
101 }
102
103 /*!
104   \brief Remove widget from the group box title.
105   \param wid widget to be removed from the title
106 */
107 void QtxGroupBox::removeTitleWidget( QWidget* wid )
108 {
109   if ( !myContainer || wid->parentWidget() != myContainer )
110     return;
111
112   myContainer->layout()->removeWidget( wid );
113   wid->setParent( 0 );
114   wid->removeEventFilter( this );
115   wid->hide();
116
117   updateTitle();
118 }
119
120 /*!
121   \brief Show/hide group box.
122   \param on if \c true, show group box, otherwise, hide it
123 */
124 void QtxGroupBox::setVisible( bool on )
125 {
126   if ( on )
127     updateTitle();
128
129   QGroupBox::setVisible( on );
130 }
131
132 /*!
133   \brief Get recommended size for the widget.
134   \return recommended size for the widget
135 */
136 QSize QtxGroupBox::sizeHint() const
137 {
138   return expandTo( QGroupBox::sizeHint() );
139 }
140
141 /*!
142   \brief Get recommended minimum size for the widget.
143   \return recommended minimum size for the widget
144 */
145 QSize QtxGroupBox::minimumSizeHint() const
146 {
147   return expandTo( QGroupBox::minimumSizeHint() );
148 }
149
150 /*!
151   \brief Custom event filter.
152   \param obj event receiver
153   \param e event
154   \return \c true if event processing should be stopped
155 */
156 bool QtxGroupBox::eventFilter( QObject* obj, QEvent* e )
157 {
158   QEvent::Type type = e->type();
159   if ( myContainer && obj->parent() == myContainer &&
160        ( type == QEvent::Show || type == QEvent::ShowToParent ||
161          type == QEvent::Hide || type == QEvent::HideToParent ) )
162     QApplication::postEvent( this, new QEvent( QEvent::User ) );
163
164   return QGroupBox::eventFilter( obj, e );
165 }
166 /*!
167   \brief Get central widget (or first found one).
168   \return widget
169 */
170 QWidget* QtxGroupBox::widget() const
171 {
172   if ( !layout() )
173     return 0;
174
175   QWidget* w = 0;
176   for ( int i = 0; i < (int)layout()->count() && !w; i++ )
177     w = layout()->itemAt( i )->widget();
178   return w;
179 }
180
181 /*!
182   \brief Set central widget to the group box.
183   \param wid widget being added to the group box
184 */
185 void QtxGroupBox::setWidget( QWidget* wid )
186 {
187   QWidget* w = widget();
188   if ( w == wid )
189     return;
190
191   if ( layout() )
192     layout()->removeWidget( w );
193
194   if ( !wid )
195     delete layout();
196   else if ( !layout() )
197   {
198     QLayout* bl = new QVBoxLayout( this );
199     bl->setMargin( 0 );
200     bl->setSpacing( 0 );
201   }
202
203   if ( layout() )
204     layout()->addWidget( wid );
205
206   if ( wid )
207     wid->updateGeometry();
208 }
209
210 /*!
211   \brief Customize resize event.
212   \param e resize event
213 */
214 void QtxGroupBox::resizeEvent( QResizeEvent* e )
215 {
216   QGroupBox::resizeEvent( e );
217
218   updateTitle();
219 }
220
221 /*!
222   \brief Customize child event.
223   \param e child event
224 */
225 void QtxGroupBox::childEvent( QChildEvent* e )
226 {
227 /*
228   if ( e->type() == QEvent::ChildAdded && e->child() == myContainer )
229     return;
230 */
231   QGroupBox::childEvent( e );
232 }
233
234 /*!
235   \brief Process custom events.
236   \param e custom event (not used)
237 */
238 void QtxGroupBox::customEvent( QEvent* /*e*/ )
239 {
240   updateTitle();
241 }
242
243 /*!
244   \brief Get the group box title size.
245   \return title size
246 */
247 QSize QtxGroupBox::titleSize() const
248 {
249   return QSize( fontMetrics().width( title() ), fontMetrics().height() );
250 }
251
252 /*!
253   \brief Update the group box title.
254 */
255 void QtxGroupBox::updateTitle()
256 {
257   if ( !myContainer )
258     return;
259
260   int align = alignment();
261
262   if ( title().isEmpty() )
263     align = Qt::AlignRight;
264
265   QSize ts = titleSize();
266
267   int m = 5;
268
269   int w = width() - ts.width();
270   if ( align == Qt::AlignCenter )
271     w = w / 2;
272
273   w -= m;
274
275   myContainer->resize( myContainer->minimumSizeHint() );
276
277   bool vis = false;
278   const QObjectList list = myContainer->children();
279   for ( QObjectList::const_iterator it = list.begin(); it != list.end() && !vis; ++it )
280     vis = (*it)->isWidgetType() && ((QWidget*)(*it))->isVisibleTo( myContainer );
281
282   if ( !vis )
283     myContainer->hide();
284   else
285   {
286     int x = 0;
287     if ( align == Qt::AlignRight )
288       x = rect().left() + m;
289     else
290       x = rect().right() - myContainer->width() - m;
291
292     int y = rect().top() - ( myContainer->height() - ts.height() ) / 2;
293
294     QPoint pos( x, qMax( 0, y ) );
295     myContainer->move( pos );
296     myContainer->show();
297   }
298
299   if ( layout() )
300   {
301     if ( myContainer && myContainer->isVisibleTo( this ) )
302       setInsideMargin( qMax( 0, myContainer->height() - ts.height() ) );
303     else
304       setInsideMargin( 0 );
305   }
306
307   updateGeometry();
308 }
309
310 /*!
311   \brief Expand group box to the specified size.
312   \param sz new size
313 */
314 QSize QtxGroupBox::expandTo( const QSize& sz ) const
315 {
316   int sh = 0;
317   int sw = titleSize().width();
318   if ( myContainer && myContainer->isVisibleTo( (QWidget*)this ) )
319   {
320     if ( alignment() == Qt::AlignCenter )
321       sw += 2 * ( myContainer->width() + 5 );
322     else
323       sw += 1 * ( myContainer->width() + 5 );
324     sw += 20;
325     sh = myContainer->height() + 5;
326   }
327   return QSize( qMax( sz.width(), sw ), qMax( sz.height(), sh ) );
328 }
329
330 /*!
331   \brief Set group box's inside margin size.
332   \param m new inside margin size
333 */
334 void QtxGroupBox::setInsideMargin( const int m )
335 {
336   QVBoxLayout* bl = ::qobject_cast<QVBoxLayout*>( layout() );
337
338   if ( !bl )
339     return;
340
341   QSpacerItem* spacer = 0;
342   if ( bl->count() )
343     spacer = bl->itemAt( 0 )->spacerItem();
344
345   if ( !spacer )
346     bl->insertSpacing( 0, m );
347   else
348     spacer->changeSize( 0, m );
349 }