1 // Copyright (C) 2007-2013 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.
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 : SALOME_PYQT_ModuleLight.cxx
21 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
23 #include "SALOME_PYQT_DataModelLight.h"
24 #include "SALOME_PYQT_ModuleLight.h"
25 #include "SALOME_PYQT_PyModule.h"
27 #include "CAM_Application.h"
28 #include "SUITApp_init_python.hxx"
29 #include "SUIT_DataObjectIterator.h"
31 #include "sipAPISalomePyQtGUILight.h"
33 #ifndef GUI_DISABLE_CORBA
34 #include <Container_init_python.hxx>
37 // Py_ssize_t for old Pythons
38 // This code is as recommended by"
39 // http://www.python.org/dev/peps/pep-0353/#conversion-guidelines
40 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
41 typedef int Py_ssize_t;
42 # define PY_SSIZE_T_MAX INT_MAX
43 # define PY_SSIZE_T_MIN INT_MIN
47 // NB: Python requests.
48 // General rule for Python requests created by Python-based GUI modules
49 // (SALOME_PYQT_ModuleLight and other ones):
50 // all requests should be executed SYNCHRONOUSLY within the main GUI thread.
51 // However, it is obligatory that ANY Python call is wrapped with a request object,
52 // so that ALL Python API calls are serialized with PyInterp_Dispatcher.
54 // NB: Library initialization
55 // Since the SalomePyQtGUILight library is not imported in Python it's initialization function
56 // should be called manually (and only once) in order to initialize global sip data
57 // and to get C API from sip : sipBuildResult for example
60 #define INIT_FUNCTION initSalomePyQtGUILight
61 #if defined(SIP_STATIC_MODULE)
62 extern "C" void INIT_FUNCTION();
64 PyMODINIT_FUNC INIT_FUNCTION();
68 \fn CAM_Module* createModule()
69 \brief Module factory function.
72 Creates an instance of SALOME_PYQT_Module object by request
73 of an application when the module is loaded and initialized.
75 \return new module object
80 SALOME_PYQT_LIGHT_EXPORT CAM_Module* createModule()
82 static bool alreadyInitialized = false;
84 // make initialization only once (see comment above) !
85 if ( !alreadyInitialized ) {
86 static PyThreadState* gtstate = 0;
87 #ifndef GUI_DISABLE_CORBA
88 if ( SUIT_PYTHON::initialized )
89 gtstate = SUIT_PYTHON::_gtstate;
91 gtstate = KERNEL_PYTHON::_gtstate;
93 gtstate = SUIT_PYTHON::_gtstate;
95 PyEval_RestoreThread( gtstate );
99 PyEval_ReleaseThread( gtstate );
101 alreadyInitialized = !alreadyInitialized;
104 return new SALOME_PYQT_ModuleLight();
109 \class SALOME_PYQT_ModuleLight
110 \brief This class implements GUI module for "light-weight" (no-CORBA-engine)
111 Python-based SALOME modules.
117 SALOME_PYQT_ModuleLight::SALOME_PYQT_ModuleLight()
118 : LightApp_Module( "noname" ) // name is set explicitly at the module initialization
121 myHelper = new PyModuleHelper( this );
127 SALOME_PYQT_ModuleLight::~SALOME_PYQT_ModuleLight()
129 // as myHelper is a QObject, it should be deleted automatically
133 \brief Initialization of the module.
134 \param app parent application object
135 \sa PyModuleHelper::initialize()
137 void SALOME_PYQT_ModuleLight::initialize( CAM_Application* app )
139 // call base implementation
140 LightApp_Module::initialize( app );
142 // ... then call helper
143 myHelper->initialize( app );
147 \brief Activation of the module.
148 \param study parent study
149 \return \c true if activation is successful and \c false otherwise
150 \sa PyModuleHelper::activate()
152 bool SALOME_PYQT_ModuleLight::activateModule( SUIT_Study* study )
154 // call base implementation and then helper
155 return LightApp_Module::activateModule( study ) && myHelper->activate( study );
159 \brief Deactivation of the module.
160 \param study parent study
161 \return \c true if deactivation is successful and \c false otherwise
162 \sa PyModuleHelper::deactivate()
164 bool SALOME_PYQT_ModuleLight::deactivateModule( SUIT_Study* study )
167 bool res = myHelper->deactivate( study );
169 // ... then call base implementation
170 return LightApp_Module::deactivateModule( study ) && res;
174 \brief Get the dockable windows associated with the module.
175 \param winMap output map of dockable windows in form { <window_type> : <dock_area> }
176 \sa PyModuleHelper::windows()
178 void SALOME_PYQT_ModuleLight::windows( QMap<int, int>& winMap ) const
180 // get list of dockable windows from helper
181 winMap = myHelper->windows();
185 \brief Define the compatible view windows associated with the module.
186 \param viewList output list of view windows types
187 \sa PyModuleHelper::viewManagers()
189 void SALOME_PYQT_ModuleLight::viewManagers( QStringList& viewList ) const
191 // get list of view types from helper
192 viewList = myHelper->viewManagers();
196 \brief Process study activation.
197 \sa PyModuleHelper::studyActivated()
199 void SALOME_PYQT_ModuleLight::studyActivated()
202 myHelper->studyActivated( application()->activeStudy() );
206 \brief Process context popup menu request.
207 \param context popup menu context (e.g. "ObjectBrowser")
208 \param menu popup menu
209 \param title popup menu title (not used)
210 \sa PyModuleHelper::contextMenu()
212 void SALOME_PYQT_ModuleLight::contextMenuPopup( const QString& context,
217 myHelper->contextMenu( context, menu );
221 \brief Export preferences for the Python module.
222 \sa PyModuleHelper::createPreferences()
224 void SALOME_PYQT_ModuleLight::createPreferences()
227 myHelper->createPreferences();
231 \brief Process module's preferences changing.
232 \param section preference resources section
233 \param parameter preference resources parameter name
234 \sa PyModuleHelper::preferencesChanged()
236 void SALOME_PYQT_ModuleLight::preferencesChanged( const QString& section, const QString& parameter )
239 myHelper->preferencesChanged( section, parameter );
243 \brief Save module data. Called when user saves study.
244 \param files output list of files where module stores data
245 \sa PyModuleHelper::save()
247 void SALOME_PYQT_ModuleLight::save( QStringList& files )
250 myHelper->save( files );
254 \brief Load module data. Called when user opens study
255 and activates module.
256 \param files list of files where module data is stored
257 \sa PyModuleHelper::load()
259 bool SALOME_PYQT_ModuleLight::load( const QStringList& files )
262 return myHelper->load( files );
266 \brief Dump module data to the Python script.
267 Called when user activates dump study operation.
268 \param files output list of files where module stores python script
269 \sa PyModuleHelper::dumpPython()
271 void SALOME_PYQT_ModuleLight::dumpPython( QStringList& files )
274 myHelper->dumpPython( files );
278 \brief Test if object \a what can be dragged by the user.
279 \param what data object being tested
280 \return \c true if object can be dragged or \c false otherwise
281 \sa PyModuleHelper::isDraggable()
283 bool SALOME_PYQT_ModuleLight::isDraggable( const SUIT_DataObject* what ) const
286 return myHelper->isDraggable( what );
290 \brief Test if drop operation can be done on the \a where object.
291 \param where data object being tested
292 \return \c true if if drop operation is supported by object or \c false otherwise
293 \sa PyModuleHelper::isDropAccepted()
295 bool SALOME_PYQT_ModuleLight::isDropAccepted( const SUIT_DataObject* where ) const
298 return myHelper->isDropAccepted( where );
302 \brief Perform drop operation
303 \param what list of data objects being dropped
304 \param where target data object for drop operation
305 \param row line (child item index) where drop operation is performed to
306 \param action current drop action (copy or move)
307 \sa PyModuleHelper::dropObjects()
309 void SALOME_PYQT_ModuleLight::dropObjects( const DataObjectList& what, SUIT_DataObject* where,
310 const int row, Qt::DropAction action )
313 myHelper->dropObjects( what, where, row, action );
317 \brief Create new empty data object
318 \param parent entry of parent data object
319 \return entry of created data object
321 QString SALOME_PYQT_ModuleLight::createObject( const QString& parent )
324 SALOME_PYQT_DataObjectLight* obj = 0;
326 if ( !parent.isEmpty() ) {
327 SALOME_PYQT_DataObjectLight* parentObj = findObject( parent );
329 obj = new SALOME_PYQT_DataObjectLight( parentObj );
332 SALOME_PYQT_DataModelLight* dm =
333 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
335 obj = new SALOME_PYQT_DataObjectLight( dm->getRoot() );
338 entry = obj->entry();
343 \brief Create new data object with specified name, icon and tooltip
344 \param name data object name
345 \param icon data object icon
346 \param toolTip data object tooltip
347 \param parent entry of parent data object
348 \return entry of created data object
350 QString SALOME_PYQT_ModuleLight::createObject( const QString& name,
352 const QString& toolTip,
353 const QString& parent )
355 QString entry = createObject( parent );
356 SALOME_PYQT_DataObjectLight* obj = findObject( entry );
359 obj->setToolTip( toolTip );
360 obj->setIcon( icon );
366 \brief Set data object name
367 \param entry data object entry
368 \param name data object name
370 void SALOME_PYQT_ModuleLight::setName( const QString& entry, const QString& name )
372 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
374 dataObj->setName( name );
378 \brief Get data object name
379 \param entry data object entry
380 \return data object name
382 QString SALOME_PYQT_ModuleLight::getName( const QString& entry ) const
385 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
387 name = dataObj->name();
392 \brief Set data object icon
393 \param entry data object entry
394 \param icon data object icon file name (icon is loaded from module resources)
396 void SALOME_PYQT_ModuleLight::setIcon( const QString& entry, const QString& icon )
398 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
400 dataObj->setIcon( icon );
404 \brief Set data object tooltip
405 \param entry data object entry
406 \param toolTip data object tooltip
408 void SALOME_PYQT_ModuleLight::setToolTip( const QString& entry, const QString& toolTip )
410 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
412 dataObj->setToolTip( toolTip );
416 \brief Get data object tooltip
417 \param entry data object entry
418 \return data object tooltip
420 QString SALOME_PYQT_ModuleLight::getToolTip( const QString& entry ) const
423 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
425 toolTip = dataObj->toolTip();
430 \brief Set data object color
431 \param entry data object entry
432 \param color data object color
434 void SALOME_PYQT_ModuleLight::setColor( const QString& entry, const QColor& color )
436 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
438 dataObj->setColor( color );
442 \brief Get data object color
443 \param entry data object entry
444 \return data object color
446 QColor SALOME_PYQT_ModuleLight::getColor( const QString& entry ) const
449 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
451 color = dataObj->color( SUIT_DataObject::Foreground );
456 \brief Set reference to another data object
457 \param entry data object entry
458 \param refEntry referenced data object entry
460 void SALOME_PYQT_ModuleLight::setReference( const QString& entry, const QString& refEntry )
462 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
464 dataObj->setRefEntry( refEntry );
468 \brief Get entry of the referenced object (if there's any)
469 \param entry data object entry
470 \return referenced data object entry
472 QString SALOME_PYQT_ModuleLight::getReference( const QString& entry ) const
475 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
477 refEntry = dataObj->refEntry();
482 \brief Remove object by entry
483 \param entry data object entry
485 void SALOME_PYQT_ModuleLight::removeObject( const QString& entry )
487 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
488 if ( dataObj && dataObj->parent() )
489 dataObj->parent()->removeChild( dataObj );
493 \brief Remove all child data objects from specified data object
494 \param entry data object entry
496 void SALOME_PYQT_ModuleLight::removeChildren( const QString& entry )
498 SUIT_DataObject* dataObj = 0;
499 if ( !entry.isEmpty() ) {
500 dataObj = findObject( entry );
503 SALOME_PYQT_DataModelLight* dm =
504 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
505 if ( dm ) dataObj = dm->getRoot();
508 DataObjectList children;
509 dataObj->children( children );
510 QListIterator<SUIT_DataObject*> it( children );
511 while ( it.hasNext() ) {
512 dataObj->removeChild( it.next() );
518 \brief Get entries of all child data objects of specified data object
519 \param entry data object entry
520 \param recursive \c true for recursive processing
522 QStringList SALOME_PYQT_ModuleLight::getChildren( const QString& entry, const bool recursive ) const
524 QStringList entryList;
525 SUIT_DataObject* dataObj = 0;
526 if ( !entry.isEmpty() ) {
527 dataObj = findObject( entry );
530 SALOME_PYQT_DataModelLight* dm =
531 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
532 if ( dm ) dataObj = dm->getRoot();
536 dataObj->children( lst, recursive );
537 QListIterator<SUIT_DataObject*> it( lst );
538 while ( it.hasNext() ) {
539 SALOME_PYQT_DataObjectLight* sobj = dynamic_cast<SALOME_PYQT_DataObjectLight*>( it.next() );
540 entryList.append( sobj->entry() );
547 \brief Create new instance of data model and return it.
549 CAM_DataModel* SALOME_PYQT_ModuleLight::createDataModel()
551 return new SALOME_PYQT_DataModelLight( this );
555 \brief Find data object by its entry
556 \param entry data object entry
557 \return data object with given entry or 0 if object isn't found
559 SALOME_PYQT_DataObjectLight* SALOME_PYQT_ModuleLight::findObject( const QString& entry ) const
561 SALOME_PYQT_DataObjectLight* obj = 0;
562 SALOME_PYQT_DataModelLight* dm =
563 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
564 if ( !entry.isEmpty() && dm ) {
565 for ( SUIT_DataObjectIterator it( dm->getRoot(), SUIT_DataObjectIterator::DepthLeft ); it.current() && !obj; ++it ) {
566 SALOME_PYQT_DataObjectLight* curentobj =
567 dynamic_cast<SALOME_PYQT_DataObjectLight*>( it.current() );
568 if ( curentobj && curentobj->entry() == entry )