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 PyLockWrapper lck; // GIL acquisition
88 alreadyInitialized = !alreadyInitialized;
91 return new SALOME_PYQT_ModuleLight();
96 \class SALOME_PYQT_ModuleLight
97 \brief This class implements GUI module for "light-weight" (no-CORBA-engine)
98 Python-based SALOME modules.
104 SALOME_PYQT_ModuleLight::SALOME_PYQT_ModuleLight()
105 : LightApp_Module( "noname" ) // name is set explicitly at the module initialization
108 myHelper = new PyModuleHelper( this );
114 SALOME_PYQT_ModuleLight::~SALOME_PYQT_ModuleLight()
116 // as myHelper is a QObject, it should be deleted automatically
120 \brief Initialization of the module.
121 \param app parent application object
122 \sa PyModuleHelper::initialize()
124 void SALOME_PYQT_ModuleLight::initialize( CAM_Application* app )
126 // call base implementation
127 LightApp_Module::initialize( app );
129 // ... then call helper
130 myHelper->initialize( app );
134 \brief Activation of the module.
135 \param study parent study
136 \return \c true if activation is successful and \c false otherwise
137 \sa PyModuleHelper::activate()
139 bool SALOME_PYQT_ModuleLight::activateModule( SUIT_Study* study )
141 // call base implementation and then helper
142 return LightApp_Module::activateModule( study ) && myHelper->activate( study );
146 \brief Deactivation of the module.
147 \param study parent study
148 \return \c true if deactivation is successful and \c false otherwise
149 \sa PyModuleHelper::deactivate()
151 bool SALOME_PYQT_ModuleLight::deactivateModule( SUIT_Study* study )
154 bool res = myHelper->deactivate( study );
156 // ... then call base implementation
157 return LightApp_Module::deactivateModule( study ) && res;
161 \brief Close of the module.
163 This function is usually used in order to close the module's
164 specific menus and toolbars and perform other such actions
165 required when the module is closed.
167 void SALOME_PYQT_ModuleLight::onModelClosed()
170 myHelper->modelClosed(application()->activeStudy());
171 LightApp_Module::onModelClosed();
176 \brief Get the dockable windows associated with the module.
177 \param winMap output map of dockable windows in form { <window_type> : <dock_area> }
178 \sa PyModuleHelper::windows()
180 void SALOME_PYQT_ModuleLight::windows( QMap<int, int>& winMap ) const
182 // get list of dockable windows from helper
183 winMap = myHelper->windows();
187 \brief Define the compatible view windows associated with the module.
188 \param viewList output list of view windows types
189 \sa PyModuleHelper::viewManagers()
191 void SALOME_PYQT_ModuleLight::viewManagers( QStringList& viewList ) const
193 // get list of view types from helper
194 viewList = myHelper->viewManagers();
198 \brief Process study activation.
199 \sa PyModuleHelper::studyActivated()
201 void SALOME_PYQT_ModuleLight::studyActivated()
204 myHelper->studyActivated( application()->activeStudy() );
208 \brief Process context popup menu request.
209 \param context popup menu context (e.g. "ObjectBrowser")
210 \param menu popup menu
211 \param title popup menu title (not used)
212 \sa PyModuleHelper::contextMenu()
214 void SALOME_PYQT_ModuleLight::contextMenuPopup( const QString& context,
219 myHelper->contextMenu( context, menu );
223 \brief Export preferences for the Python module.
224 \sa PyModuleHelper::createPreferences()
226 void SALOME_PYQT_ModuleLight::createPreferences()
229 myHelper->createPreferences();
233 \brief Process module's preferences changing.
234 \param section preference resources section
235 \param parameter preference resources parameter name
236 \sa PyModuleHelper::preferencesChanged()
238 void SALOME_PYQT_ModuleLight::preferencesChanged( const QString& section, const QString& parameter )
241 myHelper->preferencesChanged( section, parameter );
245 \brief Save module data. Called when user saves study.
246 \param files output list of files where module stores data
247 \sa PyModuleHelper::save()
249 void SALOME_PYQT_ModuleLight::save( QStringList& files )
252 myHelper->save( files );
256 \brief Load module data. Called when user opens study
257 and activates module.
258 \param files list of files where module data is stored
259 \sa PyModuleHelper::load()
261 bool SALOME_PYQT_ModuleLight::load( const QStringList& files )
264 return myHelper->load( files );
268 \brief Dump module data to the Python script.
269 Called when user activates dump study operation.
270 \param files output list of files where module stores python script
271 \sa PyModuleHelper::dumpPython()
273 void SALOME_PYQT_ModuleLight::dumpPython( QStringList& files )
276 myHelper->dumpPython( files );
280 \brief Test if object \a what can be dragged by the user.
281 \param what data object being tested
282 \return \c true if object can be dragged or \c false otherwise
283 \sa PyModuleHelper::isDraggable()
285 bool SALOME_PYQT_ModuleLight::isDraggable( const SUIT_DataObject* what ) const
288 return myHelper->isDraggable( what );
292 \brief Test if drop operation can be done on the \a where object.
293 \param where data object being tested
294 \return \c true if if drop operation is supported by object or \c false otherwise
295 \sa PyModuleHelper::isDropAccepted()
297 bool SALOME_PYQT_ModuleLight::isDropAccepted( const SUIT_DataObject* where ) const
300 return myHelper->isDropAccepted( where );
304 \brief Perform drop operation
305 \param what list of data objects being dropped
306 \param where target data object for drop operation
307 \param row line (child item index) where drop operation is performed to
308 \param action current drop action (copy or move)
309 \sa PyModuleHelper::dropObjects()
311 void SALOME_PYQT_ModuleLight::dropObjects( const DataObjectList& what, SUIT_DataObject* where,
312 const int row, Qt::DropAction action )
315 myHelper->dropObjects( what, where, row, action );
319 \brief Create new empty data object
320 \param parent entry of parent data object
321 \return entry of created data object
323 QString SALOME_PYQT_ModuleLight::createObject( const QString& parent )
326 SALOME_PYQT_DataObjectLight* obj = 0;
328 if ( !parent.isEmpty() ) {
329 SALOME_PYQT_DataObjectLight* parentObj = findObject( parent );
331 obj = new SALOME_PYQT_DataObjectLight( parentObj );
334 SALOME_PYQT_DataModelLight* dm =
335 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
337 obj = new SALOME_PYQT_DataObjectLight( dm->getRoot() );
340 entry = obj->entry();
345 \brief Create new data object with specified name, icon and tooltip
346 \param name data object name
347 \param icon data object icon
348 \param toolTip data object tooltip
349 \param parent entry of parent data object
350 \return entry of created data object
352 QString SALOME_PYQT_ModuleLight::createObject( const QString& name,
354 const QString& toolTip,
355 const QString& parent )
357 QString entry = createObject( parent );
358 SALOME_PYQT_DataObjectLight* obj = findObject( entry );
361 obj->setToolTip( toolTip );
362 obj->setIcon( icon );
368 \brief Set data object name
369 \param entry data object entry
370 \param name data object name
372 void SALOME_PYQT_ModuleLight::setName( const QString& entry, const QString& name )
374 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
376 dataObj->setName( name );
380 \brief Get data object name
381 \param entry data object entry
382 \return data object name
384 QString SALOME_PYQT_ModuleLight::getName( const QString& entry ) const
387 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
389 name = dataObj->name();
394 \brief Set data object icon
395 \param entry data object entry
396 \param icon data object icon file name (icon is loaded from module resources)
398 void SALOME_PYQT_ModuleLight::setIcon( const QString& entry, const QString& icon )
400 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
402 dataObj->setIcon( icon );
406 \brief Set data object tooltip
407 \param entry data object entry
408 \param toolTip data object tooltip
410 void SALOME_PYQT_ModuleLight::setToolTip( const QString& entry, const QString& toolTip )
412 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
414 dataObj->setToolTip( toolTip );
418 \brief Get data object tooltip
419 \param entry data object entry
420 \return data object tooltip
422 QString SALOME_PYQT_ModuleLight::getToolTip( const QString& entry ) const
425 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
427 toolTip = dataObj->toolTip();
432 \brief Set data object color
433 \param entry data object entry
434 \param color data object color
436 void SALOME_PYQT_ModuleLight::setColor( const QString& entry, const QColor& color )
438 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
440 dataObj->setColor( color );
444 \brief Get data object color
445 \param entry data object entry
446 \return data object color
448 QColor SALOME_PYQT_ModuleLight::getColor( const QString& entry ) const
451 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
453 color = dataObj->color( SUIT_DataObject::Foreground );
458 \brief Set reference to another data object
459 \param entry data object entry
460 \param refEntry referenced data object entry
462 void SALOME_PYQT_ModuleLight::setReference( const QString& entry, const QString& refEntry )
464 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
466 dataObj->setRefEntry( refEntry );
470 \brief Get entry of the referenced object (if there's any)
471 \param entry data object entry
472 \return referenced data object entry
474 QString SALOME_PYQT_ModuleLight::getReference( const QString& entry ) const
477 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
479 refEntry = dataObj->refEntry();
484 \brief Remove object by entry
485 \param entry data object entry
487 void SALOME_PYQT_ModuleLight::removeObject( const QString& entry )
489 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
490 if ( dataObj && dataObj->parent() )
491 dataObj->parent()->removeChild( dataObj );
495 \brief Remove all child data objects from specified data object
496 \param entry data object entry
498 void SALOME_PYQT_ModuleLight::removeChildren( const QString& entry )
500 SUIT_DataObject* dataObj = 0;
501 if ( !entry.isEmpty() ) {
502 dataObj = findObject( entry );
505 SALOME_PYQT_DataModelLight* dm =
506 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
507 if ( dm ) dataObj = dm->getRoot();
510 DataObjectList children;
511 dataObj->children( children );
512 QListIterator<SUIT_DataObject*> it( children );
513 while ( it.hasNext() ) {
514 dataObj->removeChild( it.next() );
520 \brief Get entries of all child data objects of specified data object
521 \param entry data object entry
522 \param recursive \c true for recursive processing
524 QStringList SALOME_PYQT_ModuleLight::getChildren( const QString& entry, const bool recursive ) const
526 QStringList entryList;
527 SUIT_DataObject* dataObj = 0;
528 if ( !entry.isEmpty() ) {
529 dataObj = findObject( entry );
532 SALOME_PYQT_DataModelLight* dm =
533 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
534 if ( dm ) dataObj = dm->getRoot();
538 dataObj->children( lst, recursive );
539 QListIterator<SUIT_DataObject*> it( lst );
540 while ( it.hasNext() ) {
541 SALOME_PYQT_DataObjectLight* sobj = dynamic_cast<SALOME_PYQT_DataObjectLight*>( it.next() );
542 entryList.append( sobj->entry() );
549 \brief Create new instance of data model and return it.
551 CAM_DataModel* SALOME_PYQT_ModuleLight::createDataModel()
553 return new SALOME_PYQT_DataModelLight( this );
557 \brief Find data object by its entry
558 \param entry data object entry
559 \return data object with given entry or 0 if object isn't found
561 SALOME_PYQT_DataObjectLight* SALOME_PYQT_ModuleLight::findObject( const QString& entry ) const
563 SALOME_PYQT_DataObjectLight* obj = 0;
564 SALOME_PYQT_DataModelLight* dm =
565 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
566 if ( !entry.isEmpty() && dm ) {
567 for ( SUIT_DataObjectIterator it( dm->getRoot(), SUIT_DataObjectIterator::DepthLeft ); it.current() && !obj; ++it ) {
568 SALOME_PYQT_DataObjectLight* curentobj =
569 dynamic_cast<SALOME_PYQT_DataObjectLight*>( it.current() );
570 if ( curentobj && curentobj->entry() == entry )