// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-//
+//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
+// License as published by the Free Software Foundation; either
// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//
+// This library is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#include <SUIT_Session.h>
#include <SUIT_ResourceMgr.h>
-/*!
+/*!
\class CAM_Module
\brief Base implementation of the module in the CAM application architecture.
-
+
Provides support of menu/toolbars management.
*/
/*!
\brief Constructor.
-
+
Creates module with the specified \a name.
\param name module name
/*!
\brief Destructor.
-
+
Destroy data model.
*/
CAM_Module::~CAM_Module()
/*!
\brief Initialize module.
- This method is usually called when the module is created (for example,
+ This method is usually called when the module is created (for example,
on the module library loading).
Successor classes can use this method to create menu/toolbar actions
and perform other module initialization.
/*!
\brief Get data model.
-
+
Creates data model, if it is not yet created.
-
+
\return data model pointer
\sa createDataModel()
*/
for example, to show own menus, toolbars, etc.
Default implementation always returns \c true.
-
+
\return \c true if module is activated successfully.
\sa initialize(), deactivateModule()
*/
for example, to hide own menus, toolbars, etc.
Default implementation always returns \c true.
-
+
\return \c true if module is deactivated successfully.
\sa initialize(), activateModule()
*/
\brief Called when study is closed.
Removes data model from the \a study.
-
+
\param study study being closed
*/
void CAM_Module::studyClosed( SUIT_Study* study )
{
CAM_Study* camDoc = dynamic_cast<CAM_Study*>( study );
- if ( !camDoc )
+ if ( !camDoc )
return;
CAM_DataModel* dm = dataModel();
\brief Called when study is changed (obsolete).
Default implementation does nothing.
-
+
\param oldStudy old study
\param newStudy new study
*/
/*!
\brief Put the text message into the status bar of the application main window.
-
+
If \a msec > 0, the message will be shown \a msec milliseconds.
If \a msec < 0, the message will be constantly displayed until module is active.
\return created data model object or 0 if it could not be created
*/
CAM_DataModel* CAM_Module::createDataModel()
-{
+{
return new CAM_DataModel( this );
}
myName = name;
}
-/*!
+/*!
\brief Get menu manager.
\return menu manager pointer
*/
return mgr;
}
-/*!
+/*!
\brief Get toolbar manager.
\return toolbar manager pointer
*/
return mgr;
}
-/*!
+/*!
\brief Create toolbar with speicifed \a name.
If the toolbar has been already created, its ID is just returned.
-
+
\param name toolbar name
\return toolbar ID or -1 if toolbar could not be created
*/
\brief Add toolbar item.
Insert action \a to the toolbar manager and register it with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If action has been already added previously, its ID is just returned.
If \a id < 0, the action ID is generated automatically.
If \a idx < 0, the action is added to the end of the toolbar.
-
+
\param a action
\param tBar toolbar ID
\param id requested action ID
\brief Add toolbar item.
Insert action \a to the toolbar manager and register it with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If action has been already added previously, its ID is just returned.
If \a id < 0, the action ID is generated automatically.
If \a idx < 0, the action is added to the end of the toolbar.
-
+
\param a action
\param tBar toolbar name
\param id requested action ID
Insert action with \a id identifier to the toolbar manager.
It is assumed that action has been already registered.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If action has been already added previously, its ID is just returned.
If \a idx < 0, the action is added to the end of the toolbar.
-
+
\param id action ID
\param tBar toolbar ID
\param idx action index (desired position in the toolbar)
Insert action with \a id identifier to the toolbar manager.
It is assumed that action has been already registered.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If action has been already added previously, its ID is just returned.
If \a idx < 0, the action is added to the end of the toolbar.
-
+
\param id action ID
\param tBar toolbar name
\param idx action index (desired position in the toolbar)
\brief Create menu or submenu.
Create main menu or popup submenu and register it with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If \a id < 0, the menu ID is generated automatically.
If menu has been already created previously, its ID is just returned.
The \a menu parameter represents the menu name - it could be a sequence
- of strings, separated by '|' symbol. For example, "File|Edit" means
+ of strings, separated by '|' symbol. For example, "File|Edit" means
File->Edit submenu. If menu doesn't exist, it is created automatically.
Parameter \a idx defines the index of the menu item in the menu group which
- is defined by the \a group. If \a idx < 0, the menu/submenu is added to the
+ is defined by the \a group. If \a idx < 0, the menu/submenu is added to the
end of the menu group.
\param subMenu subMenu name
\brief Create menu or submenu.
Create main menu or popup submenu and register it with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If \a id < 0, the menu ID is generated automatically.
If menu has been already created previously, its ID is just returned.
The \a menu parameter represents the menu name - it could be a sequence
- of strings, separated by '|' symbol. For example, "File|Edit" means
+ of strings, separated by '|' symbol. For example, "File|Edit" means
File->Edit submenu. If menu doesn't exist, it is created automatically.
Parameter \a idx defines the index of the menu item in the menu group which
- is defined by the \a group. If \a idx < 0, the menu/submenu is added to the
+ is defined by the \a group. If \a idx < 0, the menu/submenu is added to the
end of the menu group.
\param subMenu subMenu name
\brief Add menu item.
Insert action \a to the menu manager and register it with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If \a id < 0, the action ID is generated automatically.
If action has been already added previously, its ID is just returned.
Parameter \a idx defines the index of the menu item in the menu group which
- is defined by the \a group. If \a idx < 0, the action is added to the
+ is defined by the \a group. If \a idx < 0, the action is added to the
end of the menu group.
\param a action
\brief Add menu item.
Insert action \a to the menu manager and register it with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If \a id < 0, the action ID is generated automatically.
If action has been already added previously, its ID is just returned.
The \a menu parameter represents the menu name - it could be a sequence
- of strings, separated by '|' symbol. For example, "File|Edit" means
+ of strings, separated by '|' symbol. For example, "File|Edit" means
File->Edit submenu. If menu doesn't exist, it is created automatically.
Parameter \a idx defines the index of the menu item in the menu group which
- is defined by the \a group. If \a idx < 0, the action is added to the
+ is defined by the \a group. If \a idx < 0, the action is added to the
end of the menu group.
\param a action
Insert action with \a id identifier to the menu manager.
It is assumed that action has been already registered.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If action has been already added previously, its ID is just returned.
Parameter \a idx defines the index of the menu item in the menu group which
- is defined by the \a group. If \a idx < 0, the action is added to the
+ is defined by the \a group. If \a idx < 0, the action is added to the
end of the menu group.
\param id action ID
Insert action with \a id identifier to the menu manager.
It is assumed that action has been already registered.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If action has been already added previously, its ID is just returned.
The \a menu parameter represents the menu name - it could be a sequence
- of strings, separated by '|' symbol. For example, "File|Edit" means
+ of strings, separated by '|' symbol. For example, "File|Edit" means
File->Edit submenu. If menu doesn't exist, it is created automatically.
Parameter \a idx defines the index of the menu item in the menu group which
- is defined by the \a group. If \a idx < 0, the action is added to the
+ is defined by the \a group. If \a idx < 0, the action is added to the
end of the menu group.
\param id action ID
/*!
\brief Create new instance of QtxAction and register action with specified \a id.
- Resulting action ID may differ from the requested one. This can happen if
+ Resulting action ID may differ from the requested one. This can happen if
requested ID is already in use.
If \a id < 0, the action ID is generated automatically.
if ( toolMgr() )
toolMgr()->registerAction( a );
+ if ( application() && application()->desktop() )
+ application()->desktop()->addAction( a );
+
return ident;
}
/*!
\brief Create separator action.
-
+
Separator action can be used in menus or toolbars.
\return new separator action
moduleAction->insertModule( *it, icon );
}
-
+
connect( moduleAction, SIGNAL( moduleActivated( const QString& ) ), this, SLOT( onModuleActivation( const QString& ) ) );
registerAction( ModulesListId, moduleAction );
}
viewMgr = new QxScene_ViewManager( activeStudy(), desktop() );
QxScene_Viewer* vm = new QxScene_Viewer();
viewMgr->setViewModel( vm );
- QxScene_ViewWindow* wnd = dynamic_cast<QxScene_ViewWindow*>( viewMgr->getActiveView() );
+ //QxScene_ViewWindow* wnd = dynamic_cast<QxScene_ViewWindow*>( viewMgr->getActiveView() );
}
//#ifndef DISABLE_SUPERVGRAPHVIEWER
// if( vmType == SUPERVGraph_Viewer::Type() )
{
viewMgr = new OCCViewer_ViewManager( activeStudy(), desktop() );
OCCViewer_Viewer* vm;
- bool staticTrihedron = resMgr->booleanValue( "OCCViewer", "static_trihedron", true );
#ifndef DISABLE_SALOMEOBJECT
vm = new SOCC_Viewer();
#else
- vm = new OCCViewer_Viewer( true, staticTrihedron );
+ vm = new OCCViewer_Viewer( true, resMgr->booleanValue( "OCCViewer", "static_trihedron", true ) );
#endif
vm->setBackgroundColor( resMgr->colorValue( "OCCViewer", "background", vm->backgroundColor() ) );
vm->setTrihedronSize( resMgr->doubleValue( "OCCViewer", "trihedron_size", vm->trihedronSize() ) );
that->myPrefs = _prefs_;
+ SUIT_ResourceMgr* resMgr = resourceMgr();
+
QList<SUIT_Application*> appList = SUIT_Session::session()->applications();
- QListIterator<SUIT_Application*> appIt ( appList );
- while ( appIt.hasNext() )
+ for ( QList<SUIT_Application*>::iterator appIt = appList.begin(); appIt != appList.end(); ++appIt )
{
- SUIT_Application* anItem = appIt.next();
- if ( !anItem->inherits( "LightApp_Application" ) )
+ LightApp_Application* app = ::qobject_cast<LightApp_Application*>( *appIt );
+ if ( !app )
continue;
- LightApp_Application* app = (LightApp_Application*)anItem;
-
QStringList modNameList;
app->modules( modNameList, false );
- for ( QStringList::const_iterator it = modNameList.begin();
- it != modNameList.end(); ++it )
- _prefs_->addPreference( *it );
+
+ QMap<QString, QString> iconMap;
+ app->moduleIconNames( iconMap );
+
+ for ( QStringList::const_iterator it = modNameList.begin(); it != modNameList.end(); ++it )
+ {
+ if ( !app->isLibExists( *it ) )
+ continue;
+
+ int modId = _prefs_->addPreference( *it );
+ if ( iconMap.contains( *it ) )
+ _prefs_->setItemIcon( modId, Qtx::scaleIcon( resMgr->loadPixmap( moduleName( *it ), iconMap[*it], false ), 20 ) );
+ }
ModuleList modList;
app->modules( modList );
_prefs_->addPreference( mod->moduleName() );
if( toCreate )
mod->createPreferences();
- QtxPreferenceItem* item = _prefs_->findItem( mod->moduleName(), true );
- if ( item && item->isEmpty() )
- delete item;
+ that->emptyPreferences( mod->moduleName() );
}
}
}
{
myPrefs->addPreference( mod->moduleName() );
lightMod->createPreferences();
- QtxPreferenceItem* item = myPrefs->findItem( mod->moduleName(), true );
- if ( item && item->isEmpty() )
- delete item;
+ emptyPreferences( mod->moduleName() );
}
}
+void LightApp_Application::emptyPreferences( const QString& modName )
+{
+ QtxPreferenceItem* item = myPrefs->findItem( modName, true );
+ if ( !item || !item->isEmpty() )
+ return;
+
+ QtxPagePrefFrameItem* frm = new QtxPagePrefFrameItem( item->title(), item->parentItem() );
+ frm->setIcon( item->icon() );
+ frm->setStretch( false );
+ item->parentItem()->insertItem( frm, item );
+ new QtxPagePrefLabelItem( Qt::AlignCenter, tr( "PREFERENCES_NOT_SUPPORTED" ).arg( modName ), frm );
+ delete item;
+}
+
/*!
Create preferences
*/
QList<QVariant> anIndicesList;
int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
+ pref->setItemIcon( salomeCat, Qtx::scaleIcon( resourceMgr()->loadPixmap( "LightApp", tr( "APP_DEFAULT_ICO" ), false ), 20 ) );
int genTab = pref->addPreference( tr( "PREF_TAB_GENERAL" ), salomeCat );
int studyGroup = pref->addPreference( tr( "PREF_GROUP_STUDY" ), genTab );
int supervGroup = pref->addPreference( tr( "PREF_GROUP_SUPERV" ), viewTab );
- pref->setItemProperty( "columns", 4, occGroup );
+ pref->setItemProperty( "columns", 2, occGroup );
pref->setItemProperty( "columns", 1, vtkGroup );
- pref->setItemProperty( "columns", 4, plot2dGroup );
+ pref->setItemProperty( "columns", 2, plot2dGroup );
// OCC Viewer
int occTS = pref->addPreference( tr( "PREF_TRIHEDRON_SIZE" ), occGroup,
#endif
#ifndef DISABLE_VTKVIEWER
- if ( sec == QString( "VTKViewer" ) && (param == QString( "spacemouse_func1_btn" ) ||
+ if ( sec == QString( "VTKViewer" ) && (param == QString( "spacemouse_func1_btn" ) ||
param == QString( "spacemouse_func2_btn" ) ||
param == QString( "spacemouse_func5_btn" ) ) )
{
void showPreferences( const QString& = QString() );
+private:
+ void emptyPreferences( const QString& );
+
protected:
typedef QPointer<QWidget> WinPtr;
typedef QMap<int, WinPtr> WinMap;
<translation>Full</translation>
</message>
<message>
- <source></source>
- <translation></translation>
+ <source>PREFERENCES_NOT_SUPPORTED</source>
+ <translation>Preferences for module "%1" not supported</translation>
</message>
</context>
<context>
{
QSize sz = QDockWidget::sizeHint();
+ printf( "----------------> QtxDockWidget::sizeHint()\n" );
+
+ return QSize( 500, 100 );
+
return sz;
}
if ( !tb )
return 0;
- QToolButton* w = new Button( tb );
+ QToolButton* w = new QToolButton( tb );
w->setMenu( new Menu( w ) );
w->setMouseTracking( true );
w->setFocusPolicy( Qt::NoFocus );
}
}
+/*!
+ \class QtxPagePrefLabelItem
+ \brief Label item which can be used in the preferences editor dialog box.
+*/
+
+/*!
+ \brief Constructor.
+
+ Creates label item with specified title.
+
+ \param text label text
+ \param parent parent preference item
+*/
+QtxPagePrefLabelItem::QtxPagePrefLabelItem( const QString& text, QtxPreferenceItem* parent )
+: QtxPagePrefItem( text, parent )
+{
+ setWidget( myLabel = new QLabel( text ) );
+}
+
+QtxPagePrefLabelItem::QtxPagePrefLabelItem( Qt::Alignment align, const QString& text, QtxPreferenceItem* parent )
+: QtxPagePrefItem( text, parent )
+{
+ setWidget( myLabel = new QLabel( text ) );
+ myLabel->setAlignment( align );
+}
+
+QtxPagePrefLabelItem::~QtxPagePrefLabelItem()
+{
+}
+
+void QtxPagePrefLabelItem::setTitle( const QString& text )
+{
+ QtxPagePrefItem::setTitle( text );
+
+ if ( myLabel )
+ myLabel->setText( text );
+}
+
+Qt::Alignment QtxPagePrefLabelItem::alignment() const
+{
+ return myLabel->alignment();
+}
+
+void QtxPagePrefLabelItem::setAlignment( Qt::Alignment align )
+{
+ myLabel->setAlignment( align );
+}
+
+QVariant QtxPagePrefLabelItem::optionValue( const QString& name ) const
+{
+ QVariant val;
+ if ( name == "alignment" )
+ val = (int)alignment();
+ return val;
+}
+
+void QtxPagePrefLabelItem::setOptionValue( const QString& name, const QVariant& val )
+{
+ if ( name == "alignment" )
+ {
+ if ( val.canConvert( QVariant::Int ) )
+ setAlignment( (Qt::Alignment)val.toInt() );
+ }
+}
+
/*!
\class QtxPagePrefSpaceItem
\brief Simple spacer item which can be used in the preferences
QtxGroupBox* myGroup;
};
+class QTX_EXPORT QtxPagePrefLabelItem : public QtxPagePrefItem
+{
+public:
+ QtxPagePrefLabelItem( const QString&, QtxPreferenceItem* = 0 );
+ QtxPagePrefLabelItem( Qt::Alignment, const QString&, QtxPreferenceItem* = 0 );
+ virtual ~QtxPagePrefLabelItem();
+
+ virtual void setTitle( const QString& );
+
+ Qt::Alignment alignment() const;
+ void setAlignment( Qt::Alignment );
+
+protected:
+ virtual QVariant optionValue( const QString& ) const;
+ virtual void setOptionValue( const QString&, const QVariant& );
+
+private:
+ QPointer<QLabel> myLabel;
+};
+
class QTX_EXPORT QtxPagePrefSpaceItem : public QtxPagePrefItem
{
public:
\param item item to be added
\sa removeItem()
*/
-void QtxPreferenceItem::insertItem( QtxPreferenceItem* item )
+void QtxPreferenceItem::appendItem( QtxPreferenceItem* item )
{
- if ( !item || myChildren.contains( item ) )
+ insertItem( item, 0 );
+}
+
+/*!
+ \brief Insert child preference item before specified item.
+ If the before item is 0 then new item is appended.
+
+ Removes (if necessary) the item from the previous parent.
+
+ \param item item to be added
+ \param before item before which is inserted new \aitem
+ \sa removeItem()
+*/
+void QtxPreferenceItem::insertItem( QtxPreferenceItem* item, QtxPreferenceItem* before )
+{
+ if ( !item )
+ return;
+
+ if ( myChildren.contains( item ) && item == before )
return;
+ if ( myChildren.contains( item ) )
+ myChildren.removeAll( item );
+
+ int idx = myChildren.indexOf( before );
+ if ( idx < 0 )
+ idx = myChildren.count();
+
if ( item->parentItem() && item->parentItem() != this )
item->parentItem()->removeItem( item );
item->myParent = this;
- myChildren.append( item );
+ myChildren.insert( idx, item );
itemAdded( item );
}
QVariant val;
if ( name == "eval" || name == "evaluation" || name == "subst" || name == "substitution" )
val = isEvaluateValues();
+ else if ( name == "title" )
+ val = title();
return val;
}
if ( val.canConvert( QVariant::Bool ) )
setEvaluateValues( val.toBool() );
}
+ else if ( name == "title" )
+ {
+ if ( val.canConvert( QVariant::String ) )
+ setTitle( val.toString() );
+ }
}
/*!
int count() const;
virtual bool isEmpty() const;
- void insertItem( QtxPreferenceItem* );
+ void appendItem( QtxPreferenceItem* );
void removeItem( QtxPreferenceItem* );
+ void insertItem( QtxPreferenceItem*, QtxPreferenceItem* = 0 );
QIcon icon() const;
QString title() const;
// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-//
+//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
+// License as published by the Free Software Foundation; either
// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//
+// This library is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
/*!
Destructor
*/
-SUIT_Application::~SUIT_Application()
+SUIT_Application::~SUIT_Application()
{
SUIT_Study* s = myStudy;
setActiveStudy( 0 );
}
/*!
- \return FALSE if application can not be closed (because of non saved data for example).
+ \return FALSE if application can not be closed (because of non saved data for example).
This method called by SUIT_Session whin closing of application was requested.
*/
bool SUIT_Application::isPossibleToClose( bool& )
}
/*!
- \return number of Studies.
+ \return number of Studies.
Must be redefined in Applications which support several studies for one Application instance.
*/
int SUIT_Application::getNbStudies() const
#define DEFAULT_MESSAGE_DELAY 3000
/*!
- Puts the message to the status bar
+ Puts the message to the status bar
\param msg - text of message
\param msec - time in milliseconds, after that the status label will be cleared
*/
return;
if ( myStudy )
- disconnect( myStudy, SIGNAL( studyModified( SUIT_Study* ) ),
+ disconnect( myStudy, SIGNAL( studyModified( SUIT_Study* ) ),
this, SLOT( updateCommandsStatus() ) );
if ( study )
- connect( study, SIGNAL( studyModified( SUIT_Study* ) ),
+ connect( study, SIGNAL( studyModified( SUIT_Study* ) ),
this, SLOT( updateCommandsStatus() ) );
-
+
myStudy = study;
}
{
if ( !a || !desktop() )
return;
-
+
QtxActionMenuMgr* mMgr = desktop()->menuMgr();
if ( mMgr )
mMgr->setShown( mMgr->actionId( a ), on );
{
if ( !a || !desktop() )
return;
-
+
QtxActionToolMgr* tMgr = desktop()->toolMgr();
if ( tMgr )
tMgr->setShown( tMgr->actionId( a ), on );
static int generatedId = -1;
ident = id == -1 ? --generatedId : id;
- if ( action( ident ) )
+ if ( action( ident ) )
qWarning( "Action registration id is already in use: %d", ident );
myActionMap.insert( ident, a );
if ( desktop() && desktop()->toolMgr() )
desktop()->toolMgr()->registerAction( a );
+ if ( desktop() )
+ desktop()->addAction( a );
+
return ident;
}