Salome HOME
5920d6fea967187503c4cb25c10c833c9ce9fef6
[modules/gui.git] / src / Qtx / QtxInfoPanel.cxx
1 // Copyright (C) 2007-2022  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 #include "QtxInfoPanel.h"
24
25 #include <QAction>
26 #include <QFont>
27 #include <QGroupBox>
28 #include <QLabel>
29 #include <QMap>
30 #include <QPalette>
31 #include <QSizePolicy>
32 #include <QToolButton>
33 #include <QVBoxLayout>
34 #include <QScrollArea>
35
36 /*!
37   \internal
38   \class QtxInfoPanel::Container
39   \brief Container to store widgets within info panel
40 */
41 class QtxInfoPanel::Container: public QWidget
42 {
43 public:
44   Container( QWidget* = 0 );
45   Container( const QString&, QWidget* = 0 );
46
47   void addAction( QAction*, const int );
48   void addLabel( const QString&, Qt::Alignment, const int );
49   void addGroup( const QString&, const int );
50
51   QWidget* find( const int ) const;
52
53   void remove( const int );
54   void clear();
55
56   void put( QWidget* );
57
58 private:
59   QMap<int, QWidget*> ids;
60   QGroupBox* group;
61 };
62
63 QtxInfoPanel::Container::Container( QWidget* parent )
64   : QWidget( parent ), group( 0 )
65 {
66   QVBoxLayout* l = new QVBoxLayout( this );
67   l->setContentsMargins( 0, 0, 0, 0 );
68 }
69
70 QtxInfoPanel::Container::Container( const QString& title, QWidget* parent )
71   : Container( parent )
72 {
73   QVBoxLayout* l = dynamic_cast<QVBoxLayout*>( layout() );
74   group = new QGroupBox( title );
75   group->setLayout( new QVBoxLayout() );
76   l->addWidget( group );
77 }
78
79 void QtxInfoPanel::Container::put( QWidget* widget )
80 {
81   QVBoxLayout* l = group ? dynamic_cast<QVBoxLayout*>( group->layout() ) : dynamic_cast<QVBoxLayout*>( layout() );
82   l->addWidget( widget );
83 }
84
85 void QtxInfoPanel::Container::addLabel( const QString& text, Qt::Alignment alignment, const int id )
86 {
87   QLabel* label = new QLabel( text );
88   QFont f = label->font();
89   f.setItalic( true );
90   label->setFont( f );
91   label->setAlignment( alignment );
92   label->setWordWrap( true );
93   put( label );
94   ids[ id ] = label;
95 }
96
97 void QtxInfoPanel::Container::addAction( QAction* action, const int id )
98 {
99   QToolButton* button = new QToolButton( this );
100   button->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
101   button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
102   button->setAutoRaise( true );
103   button->setDefaultAction( action );
104   put( button );
105   ids[ id ] = button;
106 }
107
108 void QtxInfoPanel::Container::addGroup( const QString& text, const int id )
109 {
110   Container* group = new Container( text, this );
111   put( group );
112   ids[ id ] = group;
113 }
114
115 QWidget* QtxInfoPanel::Container::find( const int id ) const
116 {
117   if ( ids.contains( id ) )
118     return ids[id];
119
120   QMap<int, QWidget*>::ConstIterator it;
121   QWidget* widget = 0;
122   for( it = ids.begin(); it != ids.end() && !widget; ++it )
123   {
124     Container* group = dynamic_cast<Container*>( it.value() );
125     if ( group )
126       widget = group->find( id );
127   }
128
129   return widget;
130 }
131
132 void QtxInfoPanel::Container::remove( const int id )
133 {
134   if ( ids.contains( id ) )
135   {
136     QVBoxLayout* l = group ? dynamic_cast<QVBoxLayout*>( group->layout() ) : dynamic_cast<QVBoxLayout*>( layout() );
137     l->removeWidget( ids[id] );
138     ids[id]->deleteLater();
139     l->invalidate();
140     ids.remove( id );
141   }
142 }
143
144 void QtxInfoPanel::Container::clear()
145 {
146   QVBoxLayout* l = group ? dynamic_cast<QVBoxLayout*>( group->layout() ) : dynamic_cast<QVBoxLayout*>( layout() );
147
148   QList<QWidget*> widgets = ids.values();
149   foreach( QWidget* widget, widgets )
150   {
151     l->removeWidget( widget );
152     widget->deleteLater();
153   }
154
155   l->invalidate();
156   ids.clear();
157 }
158
159
160 /*!
161   \internal
162   \class QtxInfoPanel::Title
163   \brief Info panel's title widget
164 */
165 class QtxInfoPanel::Title: public QLabel
166 {
167 public:
168   Title( QWidget* parent = 0 );
169 };
170
171 QtxInfoPanel::Title::Title( QWidget* parent )
172   : QLabel( parent )
173 {
174   setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
175   QString bg = palette().color( QPalette::Highlight ).name();
176   QString fg = palette().color( QPalette::HighlightedText ).name();
177   setStyleSheet( QString( "QLabel { background:%1; color:%2; }" ).arg( bg ).arg( fg ) );
178   setTextFormat( Qt::PlainText );
179   QFont f = font();
180   f.setBold( true );
181   setFont( f );
182   setContentsMargins( 2, 5, 2, 5 );
183 }
184
185
186 /*!
187   \class QtxInfoPanel
188   \brief Info panel which allows presenting welcome, useful hints
189   and other information dynamically, e.g. in the dock panel of main
190   application's window.
191
192   The *Info panel* normally has a title (aimed to shortly present the
193   current application's context) and a set of buttons and text labels
194   combined into the groups (which may be nested).
195
196   Buttons normally represent some quick actions which are applicable in
197   the current context. Text labels can be used to show additional information
198   like hints, proposed actions, etc.
199
200   To set the title to the panel, use method setTitle(). Text label can be
201   added to the panel with addLabel() method, action (button) is added via
202   addAction() method.
203
204   By default, items are added to the top level, untitled group. Additionally,
205   panel allows arranging items into groups; new group can be added with the
206   addGroup() method.
207
208   Each of addAction(), addLabel(), addGroup() methods return item's unique
209   identifier. This identifier can be used, for instance, to enable/disable
210   item with setEnabled() method, hide/show with setVisible() method, remove
211   from panel with remove() method. The same action can be added to the panel
212   several times, e.g. to the different groups - the corresponding buttons will
213   have different unique ids.
214
215   To remove all contents of panel, use clear() method.
216 */
217
218 /*!
219   \brief Create panel.
220   \param parent Parent widget.
221  */
222 QtxInfoPanel::QtxInfoPanel( QWidget* parent )
223   : QWidget( parent )
224 {
225   title = new Title( this );
226   container = new Container( this );
227
228   QVBoxLayout* layout = new QVBoxLayout( this );
229   layout->setContentsMargins( 0, 0, 0, 0 );
230
231   QWidget* wg = new QWidget();
232   QVBoxLayout* wg_layout = new QVBoxLayout( wg );
233   wg_layout->setContentsMargins( 0, 0, 0, 0 );
234   wg_layout->addWidget( container );
235   wg_layout->addStretch();
236   
237   QScrollArea* scroll = new QScrollArea();
238   scroll->setWidgetResizable( true );
239   scroll->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
240   scroll->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding );
241   scroll->setSizeAdjustPolicy( QScrollArea::AdjustToContents );
242   scroll->setFrameStyle( QScrollArea::NoFrame );
243   scroll->setContentsMargins( 0, 0, 0, 0 );
244   scroll->setWidget( wg );
245   
246   layout->addWidget( title );
247   layout->addWidget( scroll );
248   setTitle( "" );
249 }
250
251 /*!
252   \brief Destructor.
253 */
254 QtxInfoPanel::~QtxInfoPanel()
255 {
256 }
257
258 /*!
259   \brief Add left-aligned text label to the given group.
260   \param text Label's text.
261   \param groupId Group's identifier. Value -1 (default) is used
262   to add label to the top-level (untitled) group.
263   \return Label's unique identifier.
264 */
265 int QtxInfoPanel::addLabel( const QString& text, const int groupId )
266 {
267   return addLabel( text, Qt::AlignLeft, groupId );
268 }
269
270 /*!
271   \brief Add text label to the given group.
272   \param text Label's text.
273   \param alignment Label's alignment.
274   \param groupId Group's identifier. Value -1 (default) is used
275   to add label to the top-level (untitled) group.
276   \return Label's unique identifier.
277 */
278 int QtxInfoPanel::addLabel( const QString& text, Qt::Alignment alignment, const int groupId )
279 {
280   int id = 0;
281   Container* c = dynamic_cast<Container*>( find( groupId ) );
282   if ( c )
283   {
284     id = generateId();
285     c->addLabel( text, alignment, id );
286   }
287   return id;
288 }
289
290 /*!
291   \brief Add action button to the given group.
292   \param action Action being added (note: parent is not changed).
293   \param groupId Group's identifier. Value -1 (default) is used
294   to add button to the top-level (untitled) group.
295   \return Button's unique identifier.
296 */
297 int QtxInfoPanel::addAction( QAction* action, const int groupId )
298 {
299   int id = 0;
300   Container* c = dynamic_cast<Container*>( find( groupId ) );
301   if ( c )
302   {
303     id = generateId();
304     c->addAction( action, id );
305   }
306   return id;
307 }
308
309 /*!
310   \brief Add (sub-)group to the given group.
311   \param text Group's title.
312   \param groupId Parent group's identifier. Value -1 (default) is used
313   to add (sub-)group to the top-level (untitled) group (i.e. panel itself).
314   \return Group's unique identifier.
315 */
316 int QtxInfoPanel::addGroup( const QString& text, const int groupId )
317 {
318   int id = 0;
319   Container* c = dynamic_cast<Container*>( find( groupId ) );
320   if ( c )
321   {
322     id = generateId();
323     c->addGroup( text, id );
324   }
325   return id;
326 }
327
328 /*!
329   \brief Set panel's title.
330   \param text %Title text (empty string removes title).
331 */
332 void QtxInfoPanel::setTitle( const QString& text )
333 {
334   title->setText( text );
335   title->setVisible( !title->text().isEmpty() );
336 }
337
338 /*!
339   \brief Remove given item from panel.
340   \note If a group is removed, all its contents (recursively) is removed
341   as well.
342   \param id Item's (label's, button's, group's) identifier.
343 */
344 void QtxInfoPanel::remove( const int id )
345 {
346   QWidget* widget = find( id );
347   if ( widget )
348   {
349     Container* group = dynamic_cast<Container*>( widget->parentWidget() );
350     if ( !group )
351       group = dynamic_cast<Container*>( widget->parentWidget()->parentWidget() );
352     if ( group )
353       group->remove( id );
354   }
355 }
356
357 /*!
358   \brief Clear contents of panel of group.
359   \param groupId Group's identifier. Value -1 (default) is used
360   to clear all contents of panel.
361 */
362 void QtxInfoPanel::clear( const int groupId )
363 {
364   Container* c = dynamic_cast<Container*>( find( groupId ) );
365   if ( c )
366     c->clear();
367 }
368
369 /*!
370   \internal
371   \brief Find widget that represents given item.
372   \param id Item's (label's, button's, group's) identifier.
373   \return Item's widget (0 if not found).
374 */
375 QWidget* QtxInfoPanel::find( const int id ) const
376 {
377   if ( id == -1 )
378     return container;
379   return container->find( id );
380 }
381
382 /*!
383   \brief Change item's visibility.
384   \param id Item's (label's, button's, group's) identifier.
385   \param visible \c true to show item, \c false to hide it.
386 */
387 void QtxInfoPanel::setVisible( const int id, bool visible )
388 {
389   QWidget* widget = find( id );
390   if ( widget )
391     widget->setVisible( visible );
392 }
393
394 /*!
395   \brief Enable / disable item.
396   \param id Item's (label's, button's, group's) identifier.
397   \param enabled \c true to enable item, \c false to disable it.
398 */
399 void QtxInfoPanel::setEnabled( const int id, bool enabled )
400 {
401   QWidget* widget = find( id );
402   if ( widget )
403     widget->setEnabled( enabled );
404 }
405
406 /*!
407   \internal
408   \brief Generate new unique identifier.
409   \return Unique identifier.
410 */
411 int QtxInfoPanel::generateId() const
412 {
413   static int id = -100;
414   return --id;
415 }