#include <QMenu>
#include <QSignalMapper>
+#include <utilities.h>
+
+// Prevent slot compilation error
+#pragma push_macro("slots")
+#undef slots
+#include "PyInterp_Utils.h"
+#pragma pop_macro("slots")
+
/*!
\class LightApp_ModuleAction::ActionSet
\brief Internal class to represent list of modules buttons.
\param parent parent object
*/
LightApp_ModuleAction::ActionSet::ActionSet( QObject* parent )
-: QtxActionSet( parent )
+: QtxActionSet( parent )
{
}
In menu, the action is represented as a plain list of items, one per module.
- Only one module can be active at the moment. It can be set programmatically
+ Only one module can be active at the moment. It can be set programmatically
with setActiveModule() function. Use this method with empty string to turn
to the "neutral point". To get active module, use activeModule() function.
0, this );
myRemove->setEnabled( false );
myRemove->setMenu( new QMenu() );
+ myInfo = new QtxAction( tr( "INFO_MODULE"),
+ resMgr->loadPixmap( "LightApp", tr( "ICON_INFO_MODULE" ), false ),
+ tr( "INFO_MODULE"),
+ 0, this );
mySeparator = new QAction( this );
mySeparator->setSeparator( true );
mySet = new ActionSet( this );
connect( this, SIGNAL( changed() ), this, SLOT( onChanged() ) );
connect( myAdd, SIGNAL( triggered( bool ) ), this, SIGNAL( adding() ) );
+ connect( myInfo, SIGNAL( triggered( bool ) ), this, SIGNAL( showExtInfo() ) );
connect( mySet, SIGNAL( triggered( int ) ), this, SLOT( onTriggered( int ) ) );
connect( myCombo, SIGNAL( activatedId( int ) ), this, SLOT( onComboActivated( int ) ) );
connect( myMapper, SIGNAL( mapped( QString ) ), this, SIGNAL( removing( QString ) ) );
{
QtxAction* a = new QtxAction( name, ico, name, 0, this, true );
a->setStatusTip( tr( "ACTIVATE_MODULE_TOP" ).arg( name ) );
- a->setData( isCustom );
- if ( isCustom )
- {
- myRemove->setEnabled( true );
- QAction* inserted = myRemove->menu()->addAction( name );
- connect( inserted, SIGNAL( triggered() ), myMapper, SLOT( map() ) );
- myMapper->setMapping( inserted, name );
- }
+
+ // Commented because the next call mySet->insertAction() overrides it with
+ // action id int != 0 value, so test a->data().toBool() is always true after that.
+ // Leave it here to mention that we need other approach to mark module as custom.
+ // a->setData( isCustom );
mySet->insertAction( a, -1, idx );
update();
*/
void LightApp_ModuleAction::removeModule( const QString& name )
{
+ MESSAGE("Start to remove module...");
+
int id = mySet->moduleId( name );
+ SCRUTE(id);
if ( id == -1 )
+ {
+ MESSAGE("Can't get a module's id! Return");
return;
+ }
+
+ MESSAGE("Remove action by id...");
+ mySet->removeAction(id);
+
+ update();
+
+ MESSAGE("Module was removed");
+}
+
+/*!
+ \brief Add an installed extension. Now only to the Remove button's menu.
+ \param name an extension's name
+ \sa removeExtension()
+*/
+void LightApp_ModuleAction::insertExtension(const QString& name)
+{
+ MESSAGE("Insert an extension's action...");
+ SCRUTE(name.toStdString());
- QAction* a = moduleAction( name );
- bool isCustom = a->data().toBool();
+ myRemove->setEnabled(true);
- mySet->removeAction( id );
- if ( isCustom )
+ // Find a place to insert in the alphabetical order
+ QAction* insertBefore = nullptr;
+ foreach(QAction* curAction, myRemove->menu()->actions())
{
- foreach ( QAction* ma, myRemove->menu()->actions() )
+ int compareRes = QString::compare(curAction->text(), name, Qt::CaseInsensitive);
+ if (!compareRes)
{
- if ( ma->text() == name )
- {
- myRemove->menu()->removeAction( ma );
- break;
- }
+ return; // already added
+ }
+ else if (compareRes > 0)
+ {
+ insertBefore = curAction;
+
+ SCRUTE(insertBefore->text().toStdString());
+ break;
+ }
+ }
+
+ QAction* inserted = new QAction(name);
+
+ myRemove->menu()->insertAction(insertBefore, inserted);
+ connect(inserted, SIGNAL(triggered()), myMapper, SLOT(map()));
+ myMapper->setMapping(inserted, name);
+
+ MESSAGE("An extension's action was inserted");
+}
+
+/*!
+ \brief Remove an installed extension.
+ \param name an extension's name
+ \sa insertExtension()
+*/
+void LightApp_ModuleAction::removeExtension(const QString& name)
+{
+ MESSAGE("Remove an extension's action...");
+ SCRUTE(name.toStdString());
+
+ foreach(QAction* ma, myRemove->menu()->actions())
+ {
+ if (ma->text() == name)
+ {
+ myRemove->menu()->removeAction(ma);
+
+ MESSAGE("Extension's action was removed");
+ break;
}
- myRemove->setEnabled( !myRemove->menu()->actions().isEmpty() );
}
+ myRemove->setEnabled(!myRemove->menu()->actions().isEmpty());
+
+ updateExtActions();
update();
}
/*!
\brief Get active module.
- If there is no active module ("neutral point"), then the null string
+ If there is no active module ("neutral point"), then the null string
is returned.
\return active module name
w->insertAction( this, myCombo );
w->insertAction( this, myAdd );
w->insertAction( this, myRemove );
+ w->insertAction( this, myInfo );
w->insertAction( this, mySeparator );
w->insertAction( this, mySet );
update();
w->removeAction( myCombo );
w->removeAction( myAdd );
w->removeAction( myRemove );
+ w->removeAction( myInfo );
w->removeAction( mySeparator );
w->removeAction( mySet );
}
for ( QList<QtxComboBox*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
update( *it );
+
myCombo->setVisible( myMode & List );
- myAdd->setVisible( myMode & AddRemove );
- myRemove->setVisible( myMode & AddRemove );
+ if ( QString::compare(getenv("SALOME_ON_DEMAND"),"HIDE", Qt::CaseInsensitive) != 0)
+ {
+ myAdd->setVisible( myMode & AddRemove );
+ myRemove->setVisible( myMode & AddRemove );
+ myInfo->setVisible( myMode & All );
+ }
+ else
+ {
+ myAdd->setVisible(false);
+ myRemove->setVisible( false );
+ myInfo->setVisible( false );
+ }
mySet->setVisible( myMode & Buttons );
}
int curId = mySet->moduleId( active() );
QList<QAction*> alist = mySet->actions();
cb->clear();
-
+
cb->addItem( icon(), text() );
cb->setId( 0, -1 );
cb->blockSignals( blocked );
}
+/*!
+ \brief Update extension actions based on dependencies.
+ \internal
+ \param
+*/
+void LightApp_ModuleAction::updateExtActions()
+{
+ MESSAGE("Check dependencies to update extensions actions...");
+
+ // It should be set on the app start
+ auto extRootDir = getenv("SALOME_APPLICATION_DIR");
+ if (!extRootDir)
+ {
+ MESSAGE("Cannot get SALOME_APPLICATION_DIR env variable! Cancel adding selected extensions.");
+ return;
+ }
+ SCRUTE(extRootDir);
+
+ // Import Python module that manages SALOME extensions.
+ PyLockWrapper lck; // acquire GIL
+ PyObjWrapper extensionQuery = PyImport_ImportModule((char*)"SalomeOnDemandTK.extension_query");
+ PyObjWrapper extCanRemoveDict = PyObject_CallMethod(extensionQuery, (char*)"ext_canremove_flags", (char*)"s", extRootDir);
+ if (!extCanRemoveDict || extCanRemoveDict == Py_None)
+ {
+ MESSAGE("Couldn't get <ext>:<can_remove> dictionary from SalomeOnDemandTK.extension_query! Return.");
+ return;
+ }
+
+ // Iterate extensions' actions to disable ones we can't remove because of dependencies.
+ foreach(QAction* curAction, myRemove->menu()->actions())
+ {
+ const std::string action_name = curAction->text().toStdString();
+ SCRUTE(action_name);
+
+ PyObject* canRemoveObject = PyDict_GetItemString(extCanRemoveDict, action_name.c_str());
+ if (!canRemoveObject)
+ {
+ MESSAGE("Couldn't get can remove flag from dictionary! Skip.");
+ continue;
+ }
+
+ const int isTrueRes = PyObject_IsTrue(canRemoveObject);
+ if (isTrueRes == -1)
+ {
+ MESSAGE("PyObject_IsTrue() failed. Using false value instead.");
+ }
+ const bool canRemove = isTrueRes == 1;
+ SCRUTE(canRemove);
+
+ curAction->setEnabled(canRemove);
+ }
+}
+
/*!
\brief Get an action corresponding to the active module.
\internal
/*!
\brief Called when action state is changed.
\internal
-
+
This slot is used to prevent making the parent action visible.
*/
void LightApp_ModuleAction::onChanged()
void LightApp_ModuleAction::onComboActivated( int id )
{
QApplication::postEvent( this, new ActivateEvent( QEvent::MaxUser, id ) );
-}
+}