-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
//
// 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
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
*/
QMutex myInitMutex;
+/*! DEBUG mode */
+const bool DEBUG = false;
+
/*!
\var IsCallOldMethods
\brief Allow calling obsolete callback methods.
etc. is blocked.
CALL_OLD_METHODS macro can be defined, for example, by adding
- -DCALL_OLD_METHODS compilation option to the Makefile.
+ -DCALL_OLD_METHODS compilation option to the CMakeLists.txt.
*/
#ifdef CALL_OLD_METHODS
const bool IsCallOldMethods = true;
FuncMsg( const QString& funcName )
{
myName = funcName;
- MESSAGE( qPrintable( myName ) << " [ begin ]" );
+ if ( DEBUG )
+ MESSAGE( qPrintable( myName ) << " [ begin ]" );
}
~FuncMsg()
{
- MESSAGE( qPrintable( myName ) << " [ end ]" );
+ if ( DEBUG )
+ MESSAGE( qPrintable( myName ) << " [ end ]" );
}
void message( const QString& msg )
{
- MESSAGE( qPrintable( myName ) << " : " << qPrintable( msg ) );
+ if ( DEBUG )
+ MESSAGE( qPrintable( myName ) << " : " << qPrintable( msg ) );
}
private:
QString myName;
XmlHandler( PyModuleHelper* helper, const QString& fileName );
void createActions();
void createPopup( QMenu* menu,
- const QString& context,
- const QString& parent,
- const QString& object );
+ const QString& context,
+ const QString& parent,
+ const QString& object );
void activateMenus( bool );
private:
QIcon loadIcon( const QString& fileName );
void createMenu( QDomNode& parentNode,
- const int parentMenuId = -1,
- QMenu* parentPopup = 0 );
+ const int parentMenuId = -1,
+ QMenu* parentPopup = 0 );
void createToolBar( QDomNode& parentNode );
void insertPopupItems( QDomNode& parentNode,
- QMenu* menu );
+ QMenu* menu );
private:
PyModuleHelper* myHelper;
\param fileName path to the XML menu description file
*/
PyModuleHelper::XmlHandler::XmlHandler( PyModuleHelper* helper,
- const QString& fileName )
+ const QString& fileName )
: myHelper( helper )
{
if ( !fileName.isEmpty() ) {
\param context popup menu object name
*/
void PyModuleHelper::XmlHandler::createPopup( QMenu* menu,
- const QString& context,
- const QString& parent,
- const QString& object )
+ const QString& context,
+ const QString& parent,
+ const QString& object )
{
// get document element
QDomElement aDocElem = myDoc.documentElement();
if ( module() && !fileName.isEmpty() ) {
SUIT_ResourceMgr* resMgr = module()->getApp()->resourceMgr();
QPixmap pixmap = resMgr->loadPixmap( module()->name(),
- QApplication::translate( module()->name().toLatin1().data(),
- fileName.toLatin1().data() ) );
- if ( !pixmap.isNull() )
- icon = QIcon( pixmap );
+ QApplication::translate( module()->name().toLatin1().data(),
+ fileName.toLatin1().data() ) );
+ if ( !pixmap.isNull() )
+ icon = QIcon( pixmap );
}
return icon;
\param parentPopup parent popup menu (0 for top-level menu)
*/
void PyModuleHelper::XmlHandler::createMenu( QDomNode& parentNode,
- const int parentMenuId,
- QMenu* parentPopup )
+ const int parentMenuId,
+ QMenu* parentPopup )
{
if ( !module() || parentNode.isNull() )
return;
if ( id != -1 ) {
// create menu action
QAction* action = module()->createAction( id, // ID
- tooltip, // tooltip
- icon, // icon
- label, // menu text
- tooltip, // status-bar text
- QKeySequence( accel ), // keyboard accelerator
- module(), // action owner
- toggle ); // toogled action
- myHelper->connectAction( action );
+ tooltip, // tooltip
+ icon, // icon
+ label, // menu text
+ tooltip, // status-bar text
+ QKeySequence( accel ), // keyboard accelerator
+ module(), // action owner
+ toggle ); // toogled action
+ myHelper->connectAction( action );
module()->createMenu( action, // action
menuId, // parent menu ID
id, // ID (same as for createAction())
QDomElement parentElement = parentNode.toElement();
if ( !parentElement.isNull() ) {
QString aLabel = attribute( parentElement, "label-id" );
+ QString aName = attribute( parentElement, "name-id" );
if ( !aLabel.isEmpty() ) {
// create toolbar
- int tbId = module()->createTool( aLabel );
+ int tbId = module()->createTool( aLabel, aName );
QDomNode node = parentNode.firstChild();
while ( !node.isNull() ) {
if ( node.isElement() ) {
// -1 action ID is not allowed : it means that <item-id> attribute is missed in the XML file!
// also check if the action with given ID is already created
if ( id != -1 ) {
- // create toolbar action
- QAction* action = module()->createAction( id, // ID
- tooltip, // tooltip
- icon, // icon
- label, // menu text
- tooltip, // status-bar text
- QKeySequence( accel ), // keyboard accelerator
- module(), // action owner
- toggle ); // toogled action
- myHelper->connectAction( action );
- module()->createTool( action, tbId, -1, pos );
+ // create toolbar action
+ QAction* action = module()->createAction( id, // ID
+ tooltip, // tooltip
+ icon, // icon
+ label, // menu text
+ tooltip, // status-bar text
+ QKeySequence( accel ), // keyboard accelerator
+ module(), // action owner
+ toggle ); // toogled action
+ myHelper->connectAction( action );
+ module()->createTool( action, tbId, -1, pos );
}
}
else if ( aTagName == "separatorTB" || aTagName == "separator" ) {
// -1 action ID is not allowed : it means that <item-id> attribute is missed in the XML file!
// also check if the action with given ID is already created
if ( id != -1 ) {
- QAction* action = module()->createAction( id, // ID
- tooltip, // tooltip
- icon, // icon
- label, // menu text
- tooltip, // status-bar text
- QKeySequence( accel ), // keyboard accelerator
- module(), // action owner
- toggle ); // toogled action
- myHelper->connectAction( action );
+ QAction* action = module()->createAction( id, // ID
+ tooltip, // tooltip
+ icon, // icon
+ label, // menu text
+ tooltip, // status-bar text
+ QKeySequence( accel ), // keyboard accelerator
+ module(), // action owner
+ toggle ); // toogled action
+ myHelper->connectAction( action );
QAction* before = ( pos >= 0 && pos < actions.count() ) ? actions[ pos ] : 0;
menu->insertAction( before, action );
}
{
delete myXmlHandler;
if ( myInterp && myPyModule ) {
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
Py_XDECREF( myPyModule );
}
}
{
if ( myModule && a )
QObject::connect( a, SIGNAL( triggered( bool ) ),
- this, SLOT( actionActivated() ),
- Qt::UniqueConnection );
+ this, SLOT( actionActivated() ),
+ Qt::UniqueConnection );
}
/*!
\brief Initialization of the Python-based SALOME module.
This method can be used for creation of the menus, toolbars and
- other such staff.
+ other such stuff.
There are two ways to do this:
- 1) for obsolete modules implementatino this method first tries to read
- <module>_<language>.xml resource file which contains a menu,
+ 1) for obsolete modules, the implementation of this method first tries to read
+ the <module>_<language>.xml resource file which contains a menu,
toolbars and popup menus description;
2) new modules can create menus by direct calling of the
corresponding methods of SalomePyQt Python API in the Python
\note SALOME supports two modes of modules loading:
- immediate (all the modules are created and initialized
- immediately when the application object is created;
+ immediately when the application object is created);
- postponed modules loading (used currently); in this mode
the module is loaded only by explicit request.
If postponed modules loading is not used, the active
{
public:
InitializeReq( PyModuleHelper* _helper,
- CAM_Application* _app )
+ CAM_Application* _app )
: PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ),
- myApp( _app )
+ myApp( _app )
{}
protected:
virtual void execute()
{
public:
ActivateReq( PyModuleHelper* _helper,
- SUIT_Study* _study,
- bool _customize )
- : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true)
- myHelper( _helper ),
- myStudy ( _study ),
- myCustomize( _customize )
- {}
+ SUIT_Study* _study,
+ bool _customize )
+ : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true)
+ myHelper( _helper ),
+ myStudy ( _study ),
+ myCustomize( _customize )
+ {}
protected:
virtual void execute()
- {
- if ( !myCustomize )
- myHelper->internalActivate( myStudy ); // first activation stage
- else
- myHelper->internalCustomize( myStudy ); // second activation stage
- }
+ {
+ if ( !myCustomize )
+ myHelper->internalActivate( myStudy ); // first activation stage
+ else
+ myHelper->internalCustomize( myStudy ); // second activation stage
+ }
private:
PyModuleHelper* myHelper;
SUIT_Study* myStudy;
if ( myLastActivateStatus ) {
// connect preferences changing signal
connect( myModule->getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ),
- this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) );
+ this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) );
// connect active view change signal
SUIT_Desktop* d = study->application()->desktop();
connect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
- this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) );
+ this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) );
// if active window exists, call activeViewChanged() function;
// temporary solution: if a getActiveView() in SalomePyQt available
// we no longer need this
{
public:
DeactivateReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
+ PyModuleHelper* _helper,
SUIT_Study* _study )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ),
- myStudy ( _study )
+ myStudy ( _study )
{}
protected:
virtual void execute()
// disconnect the SUIT_Desktop signal windowActivated()
SUIT_Desktop* d = study->application()->desktop();
disconnect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
- this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) );
+ this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) );
// deactivate menus, toolbars, etc
if ( myXmlHandler ) myXmlHandler->activateMenus( false );
return true;
}
+/*!
+ \brief Close of the module.
+
+ This function is usually used in order to close the module's
+ specific menus and toolbars and perform other such actions
+ required when the module is closed.
+*/
+void PyModuleHelper::modelClosed( SUIT_Study* study )
+{
+ FuncMsg fmsg( "PyModuleHelper::modelClosed()" );
+
+ class StudyClosedReq : public PyInterp_LockRequest
+ {
+ public:
+ StudyClosedReq( PyInterp_Interp* _py_interp,
+ PyModuleHelper* _helper,
+ SUIT_Study* _study )
+ : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
+ myHelper( _helper ),
+ myStudy ( _study )
+ {}
+ protected:
+ virtual void execute()
+ {
+ myHelper->internalClosedStudy( myStudy );
+ }
+ private:
+ PyModuleHelper* myHelper;
+ SUIT_Study* myStudy;
+ };
+
+ // post request
+ PyInterp_Dispatcher::Get()->Exec( new StudyClosedReq( myInterp, this, study ) );
+
+ // disconnect preferences changing signal
+ disconnect( myModule->getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ),
+ this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) );
+
+ // disconnect the SUIT_Desktop signal windowActivated()
+ SUIT_Desktop* d = study->application()->desktop();
+ disconnect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
+ this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) );
+
+ // deactivate menus, toolbars, etc
+ if ( myXmlHandler ) myXmlHandler->activateMenus( false );
+
+ // hide menus / toolbars
+ myModule->setMenuShown( false );
+ myModule->setToolShown( false );
+}
+
+
/*!
\brief Process module's preferences changing.
\param parameter preference resources parameter name
*/
void PyModuleHelper::preferencesChanged( const QString& section,
- const QString& parameter )
+ const QString& parameter )
{
FuncMsg fmsg( "PyModuleHelper::preferencesChanged()" );
{
public:
PrefChangeReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- const QString& _section,
- const QString& _parameter )
+ PyModuleHelper* _helper,
+ const QString& _section,
+ const QString& _parameter )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper ( _helper ),
mySection( _section ),
\param parameter preference resources parameter name
*/
void PyModuleHelper::preferenceChanged( const QString& module,
- const QString& section,
- const QString& parameter )
+ const QString& section,
+ const QString& parameter )
{
FuncMsg fmsg( "PyModuleHelper::preferenceChanged()" );
{
public:
StudyChangedReq( PyModuleHelper* _helper,
- SUIT_Study* _study )
- : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true)
+ SUIT_Study* _study )
+ : PyInterp_Request(0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ),
- myStudy ( _study )
+ myStudy ( _study )
{}
protected:
virtual void execute()
{
public:
ActionReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- int _id )
+ PyModuleHelper* _helper,
+ int _id )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ),
myId ( _id )
PyInterp_Dispatcher::Get()->Exec( new ActionReq( myInterp, this, myModule->actionId( action ) ) );
}
+/*!
+ \brief update selection from other views or modules.
+
+ Called when selection is modified outside.
+*/
+void PyModuleHelper::selectionUpdated(const QStringList& entries)
+{
+ FuncMsg fmsg( "PyModuleHelper::selectionUpdated()" );
+ MESSAGE("selectionUpdated");
+
+ // perform synchronous request to Python event dispatcher
+ class SelectionReq : public PyInterp_LockRequest
+ {
+ public:
+ SelectionReq( PyInterp_Interp* _py_interp,
+ PyModuleHelper* _helper,
+ const QStringList& _entries )
+ : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
+ myHelper( _helper ),
+ myEntries( _entries )
+ {
+ MESSAGE("SelectionReq");
+ }
+ protected:
+ virtual void execute()
+ {
+ MESSAGE("execute");
+ myHelper->internalSelectionUpdated( myEntries );
+ }
+ private:
+ PyModuleHelper* myHelper;
+ const QStringList& myEntries;
+ };
+
+ // post request
+ PyInterp_Dispatcher::Get()->Exec( new SelectionReq( myInterp, this, entries ) );
+}
+
/*!
\brief Process context popup menu request.
const QString& _context,
QMenu* _menu )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
- myHelper ( _helper ),
+ myHelper ( _helper ),
myContext( _context ),
myMenu ( _menu )
{}
{
public:
CreatePrefReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper )
+ PyModuleHelper* _helper )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper )
{}
{
public:
ActiveViewChangeReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- SUIT_ViewWindow* _view )
+ PyModuleHelper* _helper,
+ SUIT_ViewWindow* _view )
: PyInterp_LockRequest( _py_interp, 0, true ),
myHelper( _helper ),
- myView( _view )
+ myView( _view )
{}
protected:
virtual void execute()
{
public:
TryCloseViewReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- SUIT_ViewWindow* _view )
+ PyModuleHelper* _helper,
+ SUIT_ViewWindow* _view )
: PyInterp_LockRequest( _py_interp, 0, true ),
myHelper( _helper ),
- myView( _view )
+ myView( _view )
{}
protected:
virtual void execute()
{
public:
CloseViewReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- SUIT_ViewWindow* _view )
+ PyModuleHelper* _helper,
+ SUIT_ViewWindow* _view )
: PyInterp_LockRequest( _py_interp, 0, true ),
myHelper( _helper ),
myView( _view )
{
public:
CloneViewReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- SUIT_ViewWindow* _view )
+ PyModuleHelper* _helper,
+ SUIT_ViewWindow* _view )
: PyInterp_LockRequest( _py_interp, 0, true ),
myHelper( _helper ),
- myView( _view )
+ myView( _view )
{}
protected:
virtual void execute()
/*!
\brief Save module data. Called when user saves study.
\param files output list of files where module stores data
+ \param url study URL
*/
-void PyModuleHelper::save( QStringList& files )
+void PyModuleHelper::save( QStringList& files, const QString& url )
{
FuncMsg fmsg( "PyModuleHelper::save()" );
{
public:
SaveReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- QStringList& _files )
+ PyModuleHelper* _helper,
+ QStringList& _files,
+ const QString& _url )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ) ,
- myFiles( _files )
+ myFiles( _files ),
+ myUrl( _url )
{}
protected:
virtual void execute()
{
- myHelper->internalSave( myFiles );
+ myHelper->internalSave( myFiles, myUrl );
}
private:
PyModuleHelper* myHelper;
QStringList& myFiles;
+ QString myUrl;
};
// Posting the request only if dispatcher is not busy!
// Executing the request synchronously
if ( !PyInterp_Dispatcher::Get()->IsBusy() )
- PyInterp_Dispatcher::Get()->Exec( new SaveReq( myInterp, this, files ) );
+ PyInterp_Dispatcher::Get()->Exec( new SaveReq( myInterp, this, files, url ) );
}
/*
- \brief Load module data. Called when user opens study
- and activates module.
- \param files list of files where module data is stored
+ \brief Load module data. Called when user opens study
+ and activates module.
+ \param files list of files where module data is stored
+ \param url study URL
+ \return \c true if loading has been finished successfully or \c false otherwise
*/
-bool PyModuleHelper::load( const QStringList& files )
+bool PyModuleHelper::load( const QStringList& files, const QString& url )
{
FuncMsg fmsg( "PyModuleHelper::load()" );
{
public:
LoadReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- QStringList _files,
- bool& _loaded )
+ PyModuleHelper* _helper,
+ QStringList _files,
+ const QString& _url,
+ bool& _loaded )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ) ,
myFiles( _files ),
+ myUrl( _url ),
myLoaded( _loaded )
{}
protected:
virtual void execute()
{
- myHelper->internalLoad( myFiles, myLoaded );
+ myHelper->internalLoad( myFiles, myUrl, myLoaded );
}
private:
PyModuleHelper* myHelper;
QStringList myFiles;
+ QString myUrl;
bool& myLoaded;
};
// Posting the request only if dispatcher is not busy!
// Executing the request synchronously
if ( !PyInterp_Dispatcher::Get()->IsBusy() )
- PyInterp_Dispatcher::Get()->Exec( new LoadReq( myInterp, this, files, loaded ) );
+ PyInterp_Dispatcher::Get()->Exec( new LoadReq( myInterp, this, files, url, loaded ) );
return loaded;
}
{
public:
DumpPythonReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- QStringList& _files )
+ PyModuleHelper* _helper,
+ QStringList& _files )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ) ,
myFiles( _files )
{
public:
IsDraggableReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- LightApp_DataObject* _data_object,
- bool& _is_draggable )
+ PyModuleHelper* _helper,
+ LightApp_DataObject* _data_object,
+ bool& _is_draggable )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ) ,
myDataObject( _data_object ),
// Executing the request synchronously
if ( !PyInterp_Dispatcher::Get()->IsBusy() )
PyInterp_Dispatcher::Get()->Exec( new IsDraggableReq( myInterp,
- const_cast<PyModuleHelper*>( this ),
- const_cast<LightApp_DataObject*>( data_object ),
- draggable ) );
+ const_cast<PyModuleHelper*>( this ),
+ const_cast<LightApp_DataObject*>( data_object ),
+ draggable ) );
}
return draggable;
{
public:
IsDropAcceptedReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- LightApp_DataObject* _data_object,
- bool& _is_drop_accepted )
+ PyModuleHelper* _helper,
+ LightApp_DataObject* _data_object,
+ bool& _is_drop_accepted )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ) ,
myDataObject( _data_object ),
// Executing the request synchronously
if ( !PyInterp_Dispatcher::Get()->IsBusy() )
PyInterp_Dispatcher::Get()->Exec( new IsDropAcceptedReq( myInterp,
- const_cast<PyModuleHelper*>( this ),
- const_cast<LightApp_DataObject*>( data_object ),
- dropAccepted ) );
+ const_cast<PyModuleHelper*>( this ),
+ const_cast<LightApp_DataObject*>( data_object ),
+ dropAccepted ) );
}
return dropAccepted;
\param action current drop action (copy or move)
*/
void PyModuleHelper::dropObjects( const DataObjectList& what, SUIT_DataObject* where,
- const int row, Qt::DropAction action )
+ const int row, Qt::DropAction action )
{
FuncMsg fmsg( "PyModuleHelper::dropObjects()" );
{
public:
DropObjectsReq( PyInterp_Interp* _py_interp,
- PyModuleHelper* _helper,
- const DataObjectList& _what,
- SUIT_DataObject* _where,
- const int _row,
- Qt::DropAction _action )
+ PyModuleHelper* _helper,
+ const DataObjectList& _what,
+ SUIT_DataObject* _where,
+ const int _row,
+ Qt::DropAction _action )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ) ,
myWhat( _what ),
- myWhere( _where ),
- myRow( _row ),
- myAction ( _action )
+ myWhere( _where ),
+ myRow( _row ),
+ myAction ( _action )
{}
protected:
virtual void execute()
public:
EngineIORReq( PyInterp_Interp* _py_interp,
PyModuleHelper* _helper,
- QString& _ior )
+ QString& _ior )
: PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
myHelper( _helper ),
- myIOR( _ior )
+ myIOR( _ior )
{}
protected:
virtual void execute()
if ( anIOR.isEmpty() ) {
// post request
PyInterp_Dispatcher::Get()->Exec( new EngineIORReq( myInterp,
- const_cast<PyModuleHelper*>( this ),
- anIOR ) );
+ const_cast<PyModuleHelper*>( this ),
+ anIOR ) );
}
return anIOR;
// import 'salome' module and call 'salome_init' method;
// do it only once on interpreter creation
// ... first get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
// ... then import a module
PyObjWrapper aMod = PyImport_ImportModule( "salome" );
if ( !aMod ) {
\brief Import Python GUI module and store reference to the module.
\internal
- Attention! initInterp() should be called first!!!
+ Warning! initInterp() should be called first!!!
*/
void PyModuleHelper::importModule()
{
// import Python GUI module and put it in <myPyModule> attribute
// ... first get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
// ... then import a module
QString aMod = QString( "%1GUI" ).arg( myModule->name() );
try {
// call setWorkSpace() method
// ... first get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
// ... then try to import SalomePyQt module. If it's not possible don't go on.
PyObjWrapper aQtModule( PyImport_ImportModule( "SalomePyQt" ) );
// then call Python module's initialize() method
// ... first get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
// ... (the Python module is already imported)
// ... finally call Python module's initialize() method
// parse the return value
// it should be a map: {integer:integer}
int aKey, aValue;
- if( key && PyInt_Check( key ) && value && PyInt_Check( value ) ) {
- aKey = PyInt_AsLong( key );
- aValue = PyInt_AsLong( value );
+ if( key && PyLong_Check( key ) && value && PyLong_Check( value ) ) {
+ aKey = PyLong_AsLong( key );
+ aValue = PyLong_AsLong( value );
myWindowsMap[ aKey ] = aValue;
}
}
else {
// parse the return value
// result can be one string...
- if ( PyString_Check( res2 ) ) {
- myViewMgrList.append( PyString_AsString( res2 ) );
+ if ( PyUnicode_Check( res2 ) ) {
+ myViewMgrList.append( PyUnicode_AsUTF8( res2 ) );
}
// ... or list of strings
else if ( PyList_Check( res2 ) ) {
int size = PyList_Size( res2 );
for ( int i = 0; i < size; i++ ) {
PyObject* value = PyList_GetItem( res2, i );
- if( value && PyString_Check( value ) ) {
- myViewMgrList.append( PyString_AsString( value ) );
+ if( value && PyUnicode_Check( value ) ) {
+ myViewMgrList.append( PyUnicode_AsUTF8( value ) );
}
}
}
}
// get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
// call Python module's activate() method (for the new modules)
if ( PyObject_HasAttrString( myPyModule , (char*)"activate" ) ) {
setWorkSpace();
// get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
if ( IsCallOldMethods ) {
// call Python module's setSettings() method (obsolete)
}
}
+/*!
+ \brief Internal closure:
+
+ Performs the following actions:
+ - call Python module's closeStudy() method
+
+ \param theStudy parent study object
+*/
+void PyModuleHelper::internalClosedStudy( SUIT_Study* theStudy )
+{
+ FuncMsg fmsg( "--- PyModuleHelper::internalClosedStudy()" );
+
+ // Get study Id
+ // get study Id
+ LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( theStudy );
+ int aStudyId = aStudy ? aStudy->id() : 0;
+
+ // check that Python subinterpreter is initialized and Python module is imported
+ if ( !myInterp || !myPyModule ) {
+ // Error! Python subinterpreter should be initialized and module should be imported first!
+ return;
+ }
+ // then call Python module's deactivate() method
+ if ( PyObject_HasAttrString( myPyModule , (char*)"closeStudy" ) ) {
+ PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"closeStudy", (char*)"i", aStudyId ) );
+ if( !res ) {
+ PyErr_Print();
+ }
+ }
+}
+
+
+
/*!
\brief Preference changing callback function.
\internal
setWorkSpace();
// get python lock
- PyLockWrapper aLock = myInterp->GetLockWrapper();
+ PyLockWrapper aLock; // Acquire GIL
// call Python module's activeStudyChanged() method
if ( PyObject_HasAttrString( myPyModule, (char*)"activeStudyChanged" ) ) {
}
}
+/*!
+ \brief update selection from other views or modules
+ \internal
+
+ Performs the following actions:
+ - calls Python module's onSelectionpdated(entries) method
+
+ \param list of entries
+*/
+void PyModuleHelper::internalSelectionUpdated(const QStringList& entries)
+{
+ FuncMsg fmsg("--- PyModuleHelper::internalSelectionUpdated()");
+ MESSAGE("internalSelectionUpdated");
+
+ // Python interpreter should be initialized and Python module should be imported first
+ if (!myInterp || !myPyModule)
+ return; // Error
+
+ QStringList* theList = new QStringList(entries);
+
+#if SIP_VERSION < 0x040800
+ PyObjWrapper sipList(sipBuildResult(0, "M", theList, sipClass_QStringList));
+#else
+ PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) );
+#endif
+ if (PyObject_HasAttrString(myPyModule, (char*) "onSelectionUpdated"))
+ {
+ MESSAGE("call onSelectionUpdated");
+ PyObjWrapper res(PyObject_CallMethod(myPyModule, (char*) "onSelectionUpdated", (char*) "O", sipList.get()));
+
+ if (!res)
+ {
+ PyErr_Print();
+ }
+ }
+}
+
/*!
\brief Context popup menu handling callback function
\internal
\brief Module data saving callback function.
\internal
\param files output list of files where module stores data
+ \param url study URL
*/
-void PyModuleHelper::internalSave( QStringList& files )
+void PyModuleHelper::internalSave( QStringList& files, const QString& url )
{
FuncMsg fmsg( "--- PyModuleHelper::internalSave()" );
if ( PyObject_HasAttrString(myPyModule, (char*)"saveFiles") ) {
+ // try with two parameters (new syntax)
PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"saveFiles",
- (char*)"s", files.first().toLatin1().constData() ) );
-
+ (char*)"ss",
+ files.first().toLatin1().constData(),
+ url.toLatin1().constData() ) );
+ if ( !res )
+ // try with single parameter (old syntax)
+ res = PyObject_CallMethod( myPyModule, (char*)"saveFiles",
+ (char*)"s", files.first().toLatin1().constData() );
+
if ( !res ) {
PyErr_Print();
}
else {
// parse the return value
// result can be one string...
- if ( PyString_Check( res ) ) {
- QString astr = PyString_AsString( res );
+ if ( PyUnicode_Check( res ) ) {
+ QString astr = PyUnicode_AsUTF8( res );
files.append( astr );
}
//also result can be a list...
int size = PyList_Size( res );
for ( int i = 0; i < size; i++ ) {
PyObject* value = PyList_GetItem( res, i );
- if ( value && PyString_Check( value ) ) {
- files.append( PyString_AsString( value ) );
+ if ( value && PyUnicode_Check( value ) ) {
+ files.append( PyUnicode_AsUTF8( value ) );
}
}
}
\brief Module data loading callback function.
\internal
\param files list of files where module data is stored
+ \param url study URL
\param opened output success flag
*/
-void PyModuleHelper::internalLoad( const QStringList& files, bool& opened )
+void PyModuleHelper::internalLoad( const QStringList& files, const QString& url, bool& opened )
{
FuncMsg fmsg( "--- PyModuleHelper::internalLoad()" );
PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) );
#endif
if ( PyObject_HasAttrString(myPyModule , (char*)"openFiles") ) {
+
+ // try with two parameters (new syntax)
PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"openFiles",
- (char*)"O", sipList.get()));
- if( !res || !PyBool_Check( res )) {
+ (char*)"Os", sipList.get(),
+ url.toLatin1().constData() ) );
+
+ if ( !res )
+ // try with single parameter (old syntax)
+ res = PyObject_CallMethod( myPyModule, (char*)"openFiles",
+ (char*)"O", sipList.get() );
+
+ if ( !res || !PyBool_Check( res ) ) {
PyErr_Print();
opened = false;
}
- else{
+ else {
opened = PyObject_IsTrue( res );
}
}
else {
// parse the return value
// result can be one string...
- if ( PyString_Check( res ) ) {
- QString astr = PyString_AsString( res );
+ if ( PyUnicode_Check( res ) ) {
+ QString astr = PyUnicode_AsUTF8( res );
//SCRUTE(astr);
files.append(astr);
}
int size = PyList_Size( res );
for ( int i = 0; i < size; i++ ) {
PyObject* value = PyList_GetItem( res, i );
- if( value && PyString_Check( value ) ) {
- files.append( PyString_AsString( value ) );
+ if( value && PyUnicode_Check( value ) ) {
+ files.append( PyUnicode_AsUTF8( value ) );
}
}
}
if ( PyObject_HasAttrString(myPyModule , (char*)"isDraggable") ) {
PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"isDraggable",
- (char*)"s", what->entry().toLatin1().constData() ) );
+ (char*)"s", what->entry().toLatin1().constData() ) );
if( !res || !PyBool_Check( res )) {
PyErr_Print();
draggable = false;
if ( PyObject_HasAttrString(myPyModule , (char*)"isDropAccepted") ) {
PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"isDropAccepted",
- (char*)"s", where->entry().toLatin1().constData() ) );
+ (char*)"s", where->entry().toLatin1().constData() ) );
if( !res || !PyBool_Check( res )) {
PyErr_Print();
dropAccepted = false;
\param action current drop action (copy or move)
*/
void PyModuleHelper::internalDropObjects( const DataObjectList& what, SUIT_DataObject* where,
- const int row, Qt::DropAction action )
+ const int row, Qt::DropAction action )
{
FuncMsg fmsg( "--- PyModuleHelper::internalDropObjects()" );
PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL) );
#endif
if ( PyObject_HasAttrString(myPyModule, (char*)"dropObjects") ) {
- PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"dropObjects", (char*)"Osii",
- sipList.get(),
- whereObject->entry().toLatin1().constData(),
- row, action ) );
+ PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"dropObjects", (char*)"Osii",
+ sipList.get(),
+ whereObject->entry().toLatin1().constData(),
+ row, action ) );
if( !res ) {
PyErr_Print();
if ( PyObject_HasAttrString( myPyModule , "engineIOR" ) ) {
PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"engineIOR", (char*)"" ) );
if ( !res ) {
- PyErr_Print();
+ PyErr_Print();
}
else {
- // parse the return value, result chould be string
- if ( PyString_Check( res ) ) {
- ior = PyString_AsString( res );
- }
+ // parse the return value, result chould be string
+ if ( PyUnicode_Check( res ) ) {
+ ior = PyUnicode_AsUTF8( res );
+ }
}
}
}
// Connect tryCloseView() and deleteView() signals
if ( viewMgr ) {
connect( viewMgr, SIGNAL( tryCloseView( SUIT_ViewWindow* ) ),
- this, SLOT( tryCloseView( SUIT_ViewWindow* ) ),
- Qt::UniqueConnection );
+ this, SLOT( tryCloseView( SUIT_ViewWindow* ) ),
+ Qt::UniqueConnection );
connect( viewMgr, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
this, SLOT( closeView( SUIT_ViewWindow* ) ),
- Qt::UniqueConnection );
+ Qt::UniqueConnection );
}
// Connect cloneView() signal of an OCC View
if ( view->inherits( "OCCViewer_ViewWindow" ) ) {
connect( view, SIGNAL( viewCloned( SUIT_ViewWindow* ) ),
this, SLOT( cloneView( SUIT_ViewWindow* ) ),
- Qt::UniqueConnection );
+ Qt::UniqueConnection );
}
// Connect cloneView() signal of Plot2d View
else if ( viewModel && viewModel->inherits( "Plot2d_Viewer" ) ) {
connect( viewModel, SIGNAL( viewCloned( SUIT_ViewWindow* ) ),
this, SLOT( cloneView( SUIT_ViewWindow* ) ),
- Qt::UniqueConnection );
+ Qt::UniqueConnection );
}
}
+
+
+
+void PyModuleHelper::internalOBClickedPython( const QString& theObj, int theColumn)
+{
+ FuncMsg fmsg( "--- PyModuleHelper::internalOBClickedPython()" );
+
+ // Python interpreter should be initialized and Python module should be
+ // import first
+ if ( !myInterp || !myPyModule )
+ return; // Error
+
+ if ( PyObject_HasAttrString( myPyModule, (char*)"onObjectBrowserClicked" ) ) {
+ PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"onObjectBrowserClicked", (char*)"si", theObj.toLatin1().constData(), theColumn ) );
+ if( !res ) {
+ PyErr_Print();
+ }
+ }
+}
+
+
+
+void PyModuleHelper::onObjectBrowserClicked(SUIT_DataObject* theObj, int theColumn)
+{
+ FuncMsg fmsg( "PyModuleHelper::onObjectBrowserClicked()" );
+
+ // temporary set myInitModule because dumpPython() method
+ // might be called by the framework when this module is inactive,
+ // but still it should be possible to access this module's data
+ // from Python
+ InitLocker lock( myModule );
+
+ class PythonReq: public PyInterp_LockRequest
+ {
+ public:
+ PythonReq( PyInterp_Interp* _py_interp,
+ PyModuleHelper* _helper,
+ const QString& _entry,
+ int _column )
+ : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
+ myHelper( _helper ) ,
+ myEntry( _entry ),
+ myColumn( _column )
+ {}
+ protected:
+ virtual void execute()
+ {
+ myHelper->internalOBClickedPython( myEntry, myColumn );
+ }
+ private:
+ PyModuleHelper* myHelper;
+ int myColumn;
+ QString myEntry;
+ };
+
+ // Posting the request only if dispatcher is not busy!
+ // Executing the request synchronously
+ const LightApp_DataObject* data_object = dynamic_cast<const LightApp_DataObject*>( theObj );
+ if ( (!PyInterp_Dispatcher::Get()->IsBusy()) && data_object )
+ PyInterp_Dispatcher::Get()->Exec( new PythonReq( myInterp, this, data_object->entry(), theColumn ) );
+}
+