Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / Qtx / QtxActionSet.cxx
1 //  Copyright (C) 2007-2008  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.
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 // File:      QtxActionSet.cxx
23 // Author:    Sergey TELKOV
24 //
25 #include "QtxActionSet.h"
26
27 #include <QApplication>
28
29 /*!
30   \class QtxActionSet
31   \brief An action class which is represented in the menu bar (or toolbar) as
32   a group of items (which can be customized).
33
34   Example: Window menu in the MDI application with menu items:
35   - Cascade
36   - Tile vertically
37   - Tile horizontally
38   - <separator>
39   - Window1
40   - Window2
41 */
42
43 /*!
44   \brief Constructor.
45   \param parent parent object
46 */
47 QtxActionSet::QtxActionSet( QObject* parent )
48 : QtxAction( parent )
49 {
50   connect( this, SIGNAL( changed() ), this, SLOT( onChanged() ) );
51
52   setVisible( false );
53 }
54
55 /*!
56   \brief Destructor.
57 */
58 QtxActionSet::~QtxActionSet()
59 {
60 }
61
62 /*!
63   \brief Get list of child actions.
64   \return list of assigned actions
65 */
66 QList<QAction*> QtxActionSet::actions() const
67 {
68   return mySet;
69 }
70
71 /*!
72   \brief Assign child actions.
73   \param lst list of actions
74 */
75 void QtxActionSet::setActions( const QList<QAction*>& lst )
76 {
77   for ( ActionList::iterator it = mySet.begin(); it != mySet.end(); ++it )
78   {
79     if ( !lst.contains( *it ) )
80       delete *it;
81   }
82
83   mySet.clear();
84
85   insertActions( lst );
86 }
87
88 /*!
89   \brief Insert actions at the specified position.
90   \param lst list of actions
91   \param index position in the action list (if < 0, items are appended to the end of list)
92 */
93 void QtxActionSet::insertActions( const QList<QAction*>& lst, const int index )
94 {
95   int idx = qMin( index < 0 ? mySet.count() : index, mySet.count() );
96
97   for ( QList<QAction*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
98   {
99     QAction* a = *it;
100     int ident = generateId();
101
102     a->setParent( this );
103     mySet.insert( idx++, a );
104     a->setData( ident );
105
106     connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onActionTriggered( bool ) ) );
107   }
108
109   updateAction();
110 }
111
112 /*!
113   \brief Insert action at the specified position.
114
115   If \a id < 0, it is generated automatically.
116
117   \param a action being inserted
118   \param id action ID
119   \param index position in the action list (if < 0, item is appended to the end of list)
120   \return action identifier
121 */
122 int QtxActionSet::insertAction( QAction* a, const int id, const int index )
123 {
124   if ( !a )
125     return -1;
126
127   int ident = id < 0 ? generateId() : id;
128   int idx = qMin( index < 0 ? mySet.count() : index, mySet.count() );
129
130   a->setParent( this );
131   mySet.insert( idx, a );
132   a->setData( ident );
133
134   connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onActionTriggered( bool ) ) );
135
136   actionAdded( a );
137
138   updateAction();
139
140   return ident;
141 }
142
143 /*!
144   \brief Insert action at the specified position.
145
146   If \a id < 0, it is generated automatically.
147
148   \param txt action text
149   \param id action ID
150   \param index position in the action list (if < 0, item is appended to the end of list)
151   \return action identifier
152 */
153 int QtxActionSet::insertAction( const QString& txt, const int id, const int index )
154 {
155   return insertAction( new QtxAction( txt, txt, 0, this ), id, index );
156 }
157
158 /*!
159   \brief Insert action at the specified position.
160
161   If \a id < 0, it is generated automatically.
162
163   \param txt action text
164   \param icon action icon
165   \param id action ID
166   \param index position in the action list (if < 0, item is appended to the end of list)
167   \return action identifier
168 */
169 int QtxActionSet::insertAction( const QString& txt, const QIcon& icon, const int id, const int index )
170 {
171   return insertAction( new QtxAction( txt, icon, txt, 0, this ), id, index );
172 }
173
174 /*!
175   \brief Remove specified action.
176
177   An action is removed from the action list and destroyed.
178
179   \param a action to be removed.
180 */
181 void QtxActionSet::removeAction( QAction* a )
182 {
183   if ( !mySet.contains( a ) )
184     return;
185
186   mySet.removeAll( a );
187   actionRemoved( a );
188   delete a;
189 }
190
191 /*!
192   \brief Remove specified action.
193
194   An action is removed from the action list and destroyed.
195
196   \param id action identifier
197 */
198 void QtxActionSet::removeAction( const int id )
199 {
200   removeAction( action( id ) );
201 }
202
203 /*!
204   \brief Remove all actions.
205
206   An actions list is cleared and all actions are destroyed.
207 */
208 void QtxActionSet::clear()
209 {
210   qDeleteAll( mySet );
211   mySet.clear();
212
213   updateAction();
214 }
215
216 /*!
217   \brief Called when action is changed.
218
219   Update action state.
220 */
221 void QtxActionSet::onChanged()
222 {
223   QList<QWidget*> lst = createdWidgets();
224   for ( QList<QWidget*>::iterator it = lst.begin(); it != lst.end(); ++it )
225     (*it)->setEnabled( isEnabled() );
226
227   if ( !isVisible() || !isEmptyAction() )
228     return;
229
230   bool block = signalsBlocked();
231   blockSignals( true );
232   setVisible( false );
233   blockSignals( block );
234 }
235
236 /*!
237   \brief Called when some action is activated by the user.
238   \param on toggled state (not used)
239 */
240 void QtxActionSet::onActionTriggered( bool /*on*/ )
241 {
242   QAction* a = ::qobject_cast<QAction*>( sender() );
243   if ( !a )
244     return;
245
246   int id = actionId( a );
247   if ( id != -1 )
248     emit triggered( id );
249   emit triggered( a );
250 }
251
252 /*!
253   \brief Called when this action set is added to the menu bar (or toolbar).
254   \param w widget this action set is added to
255 */
256 void QtxActionSet::addedTo( QWidget* w )
257 {
258   QtxAction::addedTo( w );
259
260   updateAction( w );
261 }
262
263 /*!
264   \brief Called when this action set is removed from the menu bar (or toolbar).
265   \param w widget this action set is removed from
266 */
267 void QtxActionSet::removedFrom( QWidget* w )
268 {
269   QtxAction::removedFrom( w );
270
271   updateAction( w );
272 }
273
274 /*!
275   \brief Get action by specified identifier.
276   \param id action ID
277   \return action or 0 if it is not found
278 */
279 QAction* QtxActionSet::action( int id ) const
280 {
281   QAction* a = 0;
282   for ( ActionList::const_iterator it = mySet.begin(); it != mySet.end() && !a; ++it )
283   {
284     if ( actionId( *it ) == id )
285       a = *it;
286   }
287   return a;
288 }
289
290 /*!
291   \brief Get action identifier for the action.
292   \param a action
293   \return action ID or -1 if it is not found
294 */
295 int QtxActionSet::actionId( QAction* a ) const
296 {
297   int id = -1;
298   if ( a && a->data().canConvert( QVariant::Int ) )
299     id = a->data().toInt();
300   return id;
301 }
302
303 /*!
304   \brief Set action identifier for the action.
305   \param a action
306   \param id new action ID
307 */
308 void QtxActionSet::setActionId( QAction* a, const int id )
309 {
310   if ( !a || id == -1 )
311     return;
312
313   a->setData( id );
314 }
315
316 /*!
317   \brief Notify that action was added
318 */
319 void QtxActionSet::actionAdded( QAction* )
320 {
321 }
322
323 /*!
324   \brief Notify that action was removed
325 */
326 void QtxActionSet::actionRemoved( QAction* )
327 {
328 }
329
330 /*!
331   \brief Getneration unique action identifier
332   \return generation action ID
333 */
334 int QtxActionSet::generateId() const
335 {
336   QMap<int, int> map;
337   for ( ActionList::const_iterator it = mySet.begin(); it != mySet.end(); ++it )
338     map.insert( (*it)->data().toInt(), 0 );
339
340   int id = -2;
341   while ( map.contains( id ) )
342     id--;
343
344   return id;
345 }
346
347 /*!
348   \brief Update action set.
349 */
350 void QtxActionSet::updateAction()
351 {
352   QList<QWidget*> lst = associatedWidgets();
353   for ( QList<QWidget*>::iterator it = lst.begin(); it != lst.end(); ++it )
354     updateAction( *it );
355 }
356
357 /*!
358   \brief Update action set for the specified widget.
359   \param w a widget this action is added to
360 */
361 void QtxActionSet::updateAction( QWidget* w )
362 {
363   if ( !w )
364     return;
365
366   for ( ActionList::iterator it = mySet.begin(); it != mySet.end(); ++it )
367     w->removeAction( *it );
368
369   if ( !w->actions().contains( this ) )
370     return;
371
372   QAction* first = 0;
373   for ( int i = 0; i < mySet.count(); i++ )
374   {
375     QAction* a = mySet.at( i );
376     if ( !first )
377       first = a;
378     w->insertAction( this, a );
379   }
380   if ( first )
381   {
382     QApplication::instance()->removeEventFilter( this );
383
384     w->insertAction( first, this );
385
386     QApplication::instance()->installEventFilter( this );
387   }
388 }
389
390 /*!
391   \brief Check if the action itself should be invisible
392   (only child action are shown)
393   \return \c true if the action itself should be visible
394 */
395 bool QtxActionSet::isEmptyAction() const
396 {
397   return true;
398 }
399
400 /*!
401   \fn void QtxActionSet::triggered( int id );
402   \brief Emitted when some child action is activated by the user.
403   \param action ID
404 */
405
406 /*!
407   \fn void QtxActionSet::triggered( QAction* a );
408   \brief Emitted when some child action is activated by the user.
409   \param a action being activated
410 */