1 // Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : LightApp_ModuleAction.cxx
21 // Author : Sergey TELKOV, Vadim SANDLER
23 #include "LightApp_ModuleAction.h"
25 #include <QtxActionSet.h>
26 #include <QtxComboBox.h>
27 #include <QtxResourceMgr.h>
28 #include <QVBoxLayout>
29 #include <QApplication>
32 #include <QSignalMapper>
35 \class LightApp_ModuleAction::ActionSet
36 \brief Internal class to represent list of modules buttons.
40 class LightApp_ModuleAction::ActionSet : public QtxActionSet
43 ActionSet( QObject* );
44 QAction* moduleAction( const QString& ) const;
45 int moduleId( const QString& ) const;
46 int moduleId( QAction* ) const;
47 void setVisible( bool );
53 \param parent parent object
55 LightApp_ModuleAction::ActionSet::ActionSet( QObject* parent )
56 : QtxActionSet( parent )
61 \brief Get action corresponding to the specified module.
63 \param name module name
64 \return module action or 0 if \a name is invalid
66 QAction* LightApp_ModuleAction::ActionSet::moduleAction( const QString& name ) const
70 QList<QAction*> alist = actions();
71 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end() && !a; ++it )
73 if ( (*it)->text() == name )
81 \brief Get module action identifier.
83 \param name module name
84 \return module action ID or -1 if \a name is invalid
86 int LightApp_ModuleAction::ActionSet::moduleId( const QString& name ) const
90 QList<QAction*> alist = actions();
91 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end() && id == -1; ++it )
93 if ( (*it)->text() == name )
101 \brief Get module action identifier.
103 \param a module action
104 \return module action ID or -1 if \a a is null or invalid
106 int LightApp_ModuleAction::ActionSet::moduleId( QAction* a ) const
108 return actionId( a );
112 \brief Show/hide modules actions.
114 \param on new visibility state
116 void LightApp_ModuleAction::ActionSet::setVisible( bool on )
118 QList<QAction*> alist = actions();
119 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end(); ++it )
120 (*it)->setVisible( on );
122 QtxActionSet::setVisible( on );
126 \class LightApp_ModuleAction::ComboAction
127 \brief Internal class to represent combo box with the list of modules in the toolbar.
134 \param parent parent object
136 LightApp_ModuleAction::ComboAction::ComboAction( QObject* parent )
137 : QtxAction( parent )
142 \brief Get list of associated widgets.
144 \return list of created widgets (QtxComboBox)
146 QList<QtxComboBox*> LightApp_ModuleAction::ComboAction::widgets() const
148 QList<QtxComboBox*> lst;
150 QList<QWidget*> wlist = createdWidgets();
151 for ( QList<QWidget*>::const_iterator wit = wlist.begin(); wit != wlist.end(); ++wit )
152 lst += qobject_cast<QtxComboBox*>(*wit);
158 \brief Create combo box widget by request from the toolbar.
160 \param parent parent widget (should be QToolBar or its successor)
161 \return new custom widget, containing combo box
163 QWidget* LightApp_ModuleAction::ComboAction::createWidget( QWidget* parent )
165 if ( !parent->inherits( "QToolBar" ) )
168 QtxComboBox* cb = new QtxComboBox( parent );
169 cb->setSizeAdjustPolicy( QComboBox::AdjustToContents );
170 cb->setFocusPolicy( Qt::NoFocus );
171 connect( cb, SIGNAL( activatedId( int ) ), this, SIGNAL( activatedId( int ) ) );
176 \fn void LightApp_ModuleAction::ComboAction::activatedId( int id );
178 \brief Emitted when the combo box item is activated
179 \param item identifier
183 \class LightApp_ModuleAction::ActivateEvent
184 \brief Internal class to represent custom event for transfer the activation item id.
187 class LightApp_ModuleAction::ActivateEvent : public QEvent
190 ActivateEvent( QEvent::Type type, int id ) : QEvent( type ), myId( id ) {};
193 int id() const { return myId; }
200 \class LightApp_ModuleAction
201 \brief An action, representing the list of modules to be inserted to the
204 In the toolbar this action is represented as the combo box with the list of
205 available modules, and a set of buttons for each module. Additionally, combo box
206 contains an item representing "neutral point" of the application (i.e. no active module).
208 In menu, the action is represented as a plain list of items, one per module.
210 Only one module can be active at the moment. It can be set programmatically
211 with setActiveModule() function. Use this method with empty string to turn
212 to the "neutral point". To get active module, use activeModule() function.
214 When user activates/deactivates a module, the moduleActivated() signal
217 The action also provides an additional separate item "Add modules"; when
218 this button is pressed, a adding() signal is emitted. This signal
219 can be connected to a dedicated slot aimed to dynamically add a new module
220 into the application. In addition, a button "Remove module" shows a dropdown menu
221 with the list of user modules; when any item is selected, the removing() signal
222 is emitted. This signal may be connected to a slot aimed to dynamically remove
223 selected user module from application.
225 It is possible to customize which elements to show via the setMode() of setModeEnabled()
226 functions. By default, all elements are shown. The following choices are possible:
228 - LightApp_ModuleAction::Buttons: show separate items for all modules
229 - LightApp_ModuleAction::List: show combo box with list of modules (in toolbar only)
230 - LightApp_ModuleAction::AddRemove: show "Add modules" and "Remove modules" items
231 - LightApp_ModuleAction::All: show all items
236 \param resMgr resource manager
237 \param parent parent object
239 LightApp_ModuleAction::LightApp_ModuleAction( QtxResourceMgr* resMgr, QObject* parent )
240 : QtxAction( parent )
242 setText( tr( "APP_NAME" ) );
243 setIcon( resMgr->loadPixmap( "LightApp", tr( "APP_DEFAULT_ICO" ), false ) );
247 myCombo = new ComboAction( this );
248 myAdd = new QtxAction( tr( "ADD_MODULE"),
249 resMgr->loadPixmap( "LightApp", tr( "ICON_ADD_MODULE" ), false ),
252 myRemove = new QtxAction( tr( "REMOVE_MODULE"),
253 resMgr->loadPixmap( "LightApp", tr( "ICON_REMOVE_MODULE" ), false ),
254 tr( "REMOVE_MODULE"),
256 myRemove->setEnabled( false );
257 myRemove->setMenu( new QMenu() );
258 mySeparator = new QAction( this );
259 mySeparator->setSeparator( true );
260 mySet = new ActionSet( this );
262 myMapper = new QSignalMapper( this );
264 connect( this, SIGNAL( changed() ), this, SLOT( onChanged() ) );
265 connect( myAdd, SIGNAL( triggered( bool ) ), this, SIGNAL( adding() ) );
266 connect( mySet, SIGNAL( triggered( int ) ), this, SLOT( onTriggered( int ) ) );
267 connect( myCombo, SIGNAL( activatedId( int ) ), this, SLOT( onComboActivated( int ) ) );
268 connect( myMapper, SIGNAL( mapped( QString ) ), this, SIGNAL( removing( QString ) ) );
274 LightApp_ModuleAction::~LightApp_ModuleAction()
279 \brief Get number of registered modules.
280 \return modules count
282 int LightApp_ModuleAction::count() const
284 return modules().count();
288 \brief Get list of modules.
289 \return modules names list
291 QStringList LightApp_ModuleAction::modules() const
295 QList<QAction*> alist = mySet->actions();
296 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end(); ++it )
297 lst.append( (*it)->text() );
303 \brief Get module icon.
304 \param name module name
308 QIcon LightApp_ModuleAction::moduleIcon( const QString& name ) const
310 QAction* a = mySet->moduleAction( name );
311 return a ? a->icon() : QIcon();
315 \brief Set module icon.
316 \param name module name
317 \param ico new module icon
320 void LightApp_ModuleAction::setModuleIcon( const QString& name, const QIcon& ico )
322 QAction* a = mySet->moduleAction( name );
331 \brief Get module action.
332 \param name module name
334 QAction* LightApp_ModuleAction::moduleAction( const QString& name ) const
336 return mySet->moduleAction( name );
340 \brief Add module into the list.
341 \param name module name
342 \param ico module icon
343 \param idx position in the module list (if -1, the module is added to the end of list)
346 void LightApp_ModuleAction::insertModule( const QString& name, const QIcon& ico,
349 insertModule( name, ico, false, idx );
353 \brief Add module into the list.
354 \param name module name
355 \param ico module icon
356 \param isCustom \c false to insert regular module, \c true to insert user module
357 \param idx position in the module list (if -1, the module is added to the end of list)
360 void LightApp_ModuleAction::insertModule( const QString& name, const QIcon& ico,
361 bool isCustom, const int idx)
364 QtxAction* a = new QtxAction( name, ico, name, 0, this, true );
365 a->setStatusTip( tr( "ACTIVATE_MODULE_TOP" ).arg( name ) );
366 a->setData( isCustom );
369 myRemove->setEnabled( true );
370 QAction* inserted = myRemove->menu()->addAction( name );
371 connect( inserted, SIGNAL( triggered() ), myMapper, SLOT( map() ) );
372 myMapper->setMapping( inserted, name );
375 mySet->insertAction( a, -1, idx );
380 \brief Remove module from the list.
381 \param name module name
384 void LightApp_ModuleAction::removeModule( const QString& name )
386 int id = mySet->moduleId( name );
390 QAction* a = moduleAction( name );
391 bool isCustom = a->data().toBool();
393 mySet->removeAction( id );
396 foreach ( QAction* ma, myRemove->menu()->actions() )
398 if ( ma->text() == name )
400 myRemove->menu()->removeAction( ma );
404 myRemove->setEnabled( !myRemove->menu()->actions().isEmpty() );
411 \brief Get active module.
413 If there is no active module ("neutral point"), then the null string
416 \return active module name
417 \sa setActiveModule()
419 QString LightApp_ModuleAction::activeModule() const
421 QAction* a = active();
422 return a ? a->text() : QString();
426 \brief Set active module.
428 To turn to the "neutral point" (no active module), pass empty string.
430 \param name new active module name
433 void LightApp_ModuleAction::setActiveModule( const QString& name )
435 if ( name == activeModule() )
438 int id = mySet->moduleId( name );
439 if ( name.isEmpty() || id != -1 )
440 activate( id, false );
444 \brief Set action display mode.
445 \param mode action display options (combination of flags)
448 void LightApp_ModuleAction::setMode( const LightApp_ModuleAction::Mode& mode )
455 \brief Enable / disable action display mode.
456 \param mode action display options (combination of flags)
457 \param enabled \c true to enable mode, \c false to disable mode
460 void LightApp_ModuleAction::setModeEnabled( const LightApp_ModuleAction::Mode& mode, bool enabled )
470 \brief Get action display mode.
471 \param mode action display mode
474 bool LightApp_ModuleAction::isModeEnabled( const LightApp_ModuleAction::Mode& mode ) const
476 return (bool)( myMode & mode );
480 \brief Called when the action is added to the widget.
481 \param w widget (not used)
483 void LightApp_ModuleAction::addedTo( QWidget* w )
485 if ( w->inherits( "QToolBar" ) )
486 w->insertAction( this, myCombo );
487 w->insertAction( this, myAdd );
488 w->insertAction( this, myRemove );
489 w->insertAction( this, mySeparator );
490 w->insertAction( this, mySet );
495 \brief Remove action from widget.
496 \param w widget (menu or toolbar)
497 \return \c true if the action is removed successfully and \c false otherwise.
500 void LightApp_ModuleAction::removedFrom( QWidget* w )
502 if ( w->inherits( "QToolBar" ) )
503 w->removeAction( myCombo );
504 w->removeAction( myAdd );
505 w->removeAction( myRemove );
506 w->removeAction( mySeparator );
507 w->removeAction( mySet );
511 \brief Perform delayed activation with specified id.
512 \param e custom event
513 \return \c true if the event was processed successfully and \c false otherwise.
515 bool LightApp_ModuleAction::event( QEvent* e )
517 if ( e->type() == QEvent::MaxUser ) {
518 activate( ((ActivateEvent*)e)->id(), false );
521 return QtxAction::event( e );
525 \fn void LightApp_ModuleAction::moduleActivated( const QString& name );
526 \brief Emitted when the module is activated
527 \param name module name (empty string for neutral point)
531 \brief Update an action.
534 void LightApp_ModuleAction::update()
536 QList<QtxComboBox*> lst = myCombo->widgets();
537 for ( QList<QtxComboBox*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
540 myCombo->setVisible( myMode & List );
541 myAdd->setVisible( myMode & AddRemove );
542 myRemove->setVisible( myMode & AddRemove );
543 mySet->setVisible( myMode & Buttons );
547 \brief Update combo box.
551 void LightApp_ModuleAction::update( QtxComboBox* cb )
556 bool blocked = cb->blockSignals( true );
557 int curId = mySet->moduleId( active() );
558 QList<QAction*> alist = mySet->actions();
561 cb->addItem( icon(), text() );
564 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end(); ++it )
567 int id = mySet->moduleId( a );
568 cb->addItem( a->icon(), a->text() );
569 cb->setId( cb->count() - 1, id );
572 cb->setCurrentId( curId );
573 cb->blockSignals( blocked );
577 \brief Get an action corresponding to the active module.
579 \return active module action or 0 if there is no active module
581 QAction* LightApp_ModuleAction::active() const
585 QList<QAction*> alist = mySet->actions();
586 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end() && !a; ++it )
588 if ( (*it)->isChecked() )
596 \brief Activate a module item.
598 \param id module identifier
599 \param fromAction \c true if function is called from the module button
601 void LightApp_ModuleAction::activate( int id, bool fromAction )
603 bool checked = false;
605 QList<QAction*> alist = mySet->actions();
606 for ( QList<QAction*>::const_iterator it = alist.begin(); it != alist.end(); ++it )
608 if ( mySet->moduleId( *it ) != id ) {
609 (*it)->setChecked( false );
613 (*it)->setChecked( true );
614 checked = (*it)->isChecked();
618 QList<QtxComboBox*> widgets = myCombo->widgets();
619 for ( QList<QtxComboBox*>::const_iterator wit = widgets.begin(); wit != widgets.end(); ++wit )
621 QtxComboBox* cb = *wit;
622 bool blocked = cb->signalsBlocked();
623 cb->blockSignals( true );
624 cb->setCurrentId( checked ? id : -1 );
625 cb->blockSignals( blocked );
628 emit moduleActivated( activeModule() );
632 \brief Called when module button is triggered.
634 \param id module identifier
636 void LightApp_ModuleAction::onTriggered( int id )
642 \brief Called when action state is changed.
645 This slot is used to prevent making the parent action visible.
647 void LightApp_ModuleAction::onChanged()
652 bool block = signalsBlocked();
653 blockSignals( true );
655 blockSignals( block );
659 \brief Called when combo box item is activated.
660 \param id module identifier
662 void LightApp_ModuleAction::onComboActivated( int id )
664 QApplication::postEvent( this, new ActivateEvent( QEvent::MaxUser, id ) );