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