1 // Copyright (C) 2007-2014 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, or (at your option) any later version.
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"
30 #include "LightApp_Application.h"
31 #include "SUIT_DataBrowser.h"
32 #include "sipAPISalomePyQtGUILight.h"
34 #ifndef GUI_DISABLE_CORBA
35 #include <Container_init_python.hxx>
38 // Py_ssize_t for old Pythons
39 // This code is as recommended by"
40 // http://www.python.org/dev/peps/pep-0353/#conversion-guidelines
41 //#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
42 //typedef int Py_ssize_t;
43 //# define PY_SSIZE_T_MAX INT_MAX
44 //# define PY_SSIZE_T_MIN INT_MIN
48 // NB: Python requests.
49 // General rule for Python requests created by Python-based GUI modules
50 // (SALOME_PYQT_ModuleLight and other ones):
51 // all requests should be executed SYNCHRONOUSLY within the main GUI thread.
52 // However, it is obligatory that ANY Python call is wrapped with a request object,
53 // so that ALL Python API calls are serialized with PyInterp_Dispatcher.
55 // NB: Library initialization
56 // Since the SalomePyQtGUILight library is not imported in Python it's initialization function
57 // should be called manually (and only once) in order to initialize global sip data
58 // and to get C API from sip : sipBuildResult for example
61 #define INIT_FUNCTION initSalomePyQtGUILight
62 #if defined(SIP_STATIC_MODULE)
63 extern "C" void INIT_FUNCTION();
65 PyMODINIT_FUNC INIT_FUNCTION();
69 \fn CAM_Module* createModule()
70 \brief Module factory function.
73 Creates an instance of SALOME_PYQT_Module object by request
74 of an application when the module is loaded and initialized.
76 \return new module object
81 SALOME_PYQT_LIGHT_EXPORT CAM_Module* createModule()
83 static bool alreadyInitialized = false;
85 // make initialization only once (see comment above) !
86 if ( !alreadyInitialized ) {
87 PyLockWrapper lck; // GIL acquisition
89 alreadyInitialized = !alreadyInitialized;
92 return new SALOME_PYQT_ModuleLight();
97 \class SALOME_PYQT_ModuleLight
98 \brief This class implements GUI module for "light-weight" (no-CORBA-engine)
99 Python-based SALOME modules.
105 SALOME_PYQT_ModuleLight::SALOME_PYQT_ModuleLight()
106 : LightApp_Module( "noname" ) // name is set explicitly at the module initialization
109 myHelper = new PyModuleHelper( this );
115 SALOME_PYQT_ModuleLight::~SALOME_PYQT_ModuleLight()
117 // as myHelper is a QObject, it should be deleted automatically
121 \brief Initialization of the module.
122 \param app parent application object
123 \sa PyModuleHelper::initialize()
125 void SALOME_PYQT_ModuleLight::initialize( CAM_Application* app )
127 // call base implementation
128 LightApp_Module::initialize( app );
130 // ... then call helper
131 myHelper->initialize( app );
132 SUIT_DataBrowser* ob = getApp()->objectBrowser();
133 if (ob && ob->model()) {
134 connect( ob->model(), SIGNAL( clicked( SUIT_DataObject*, int ) ),
135 myHelper, SLOT( onObjectBrowserClicked( SUIT_DataObject*, int ) ), Qt::UniqueConnection );
140 \brief Activation of the module.
141 \param study parent study
142 \return \c true if activation is successful and \c false otherwise
143 \sa PyModuleHelper::activate()
145 bool SALOME_PYQT_ModuleLight::activateModule( SUIT_Study* study )
147 // call base implementation and then helper
148 return LightApp_Module::activateModule( study ) && myHelper->activate( study );
152 \brief Deactivation of the module.
153 \param study parent study
154 \return \c true if deactivation is successful and \c false otherwise
155 \sa PyModuleHelper::deactivate()
157 bool SALOME_PYQT_ModuleLight::deactivateModule( SUIT_Study* study )
160 bool res = myHelper->deactivate( study );
162 // ... then call base implementation
163 return LightApp_Module::deactivateModule( study ) && res;
167 \brief Close of the module.
169 This function is usually used in order to close the module's
170 specific menus and toolbars and perform other such actions
171 required when the module is closed.
173 void SALOME_PYQT_ModuleLight::onModelClosed()
176 myHelper->modelClosed(application()->activeStudy());
177 LightApp_Module::onModelClosed();
182 \brief Get the dockable windows associated with the module.
183 \param winMap output map of dockable windows in form { <window_type> : <dock_area> }
184 \sa PyModuleHelper::windows()
186 void SALOME_PYQT_ModuleLight::windows( QMap<int, int>& winMap ) const
188 // get list of dockable windows from helper
189 winMap = myHelper->windows();
193 \brief Define the compatible view windows associated with the module.
194 \param viewList output list of view windows types
195 \sa PyModuleHelper::viewManagers()
197 void SALOME_PYQT_ModuleLight::viewManagers( QStringList& viewList ) const
199 // get list of view types from helper
200 viewList = myHelper->viewManagers();
204 \brief Process study activation.
205 \sa PyModuleHelper::studyActivated()
207 void SALOME_PYQT_ModuleLight::studyActivated()
210 myHelper->studyActivated( application()->activeStudy() );
214 \brief Process context popup menu request.
215 \param context popup menu context (e.g. "ObjectBrowser")
216 \param menu popup menu
217 \param title popup menu title (not used)
218 \sa PyModuleHelper::contextMenu()
220 void SALOME_PYQT_ModuleLight::contextMenuPopup( const QString& context,
225 myHelper->contextMenu( context, menu );
229 \brief Export preferences for the Python module.
230 \sa PyModuleHelper::createPreferences()
232 void SALOME_PYQT_ModuleLight::createPreferences()
235 myHelper->createPreferences();
239 \brief Process module's preferences changing.
240 \param section preference resources section
241 \param parameter preference resources parameter name
242 \sa PyModuleHelper::preferencesChanged()
244 void SALOME_PYQT_ModuleLight::preferencesChanged( const QString& section, const QString& parameter )
247 myHelper->preferencesChanged( section, parameter );
251 \brief Save module data. Called when user saves study.
252 \param files output list of files where module stores data
253 \sa PyModuleHelper::save()
255 void SALOME_PYQT_ModuleLight::save( QStringList& files )
258 myHelper->save( files );
262 \brief Load module data. Called when user opens study
263 and activates module.
264 \param files list of files where module data is stored
265 \sa PyModuleHelper::load()
267 bool SALOME_PYQT_ModuleLight::load( const QStringList& files )
270 return myHelper->load( files );
274 \brief Dump module data to the Python script.
275 Called when user activates dump study operation.
276 \param files output list of files where module stores python script
277 \sa PyModuleHelper::dumpPython()
279 void SALOME_PYQT_ModuleLight::dumpPython( QStringList& files )
282 myHelper->dumpPython( files );
286 \brief Test if object \a what can be dragged by the user.
287 \param what data object being tested
288 \return \c true if object can be dragged or \c false otherwise
289 \sa PyModuleHelper::isDraggable()
291 bool SALOME_PYQT_ModuleLight::isDraggable( const SUIT_DataObject* what ) const
294 return myHelper->isDraggable( what );
298 \brief Test if drop operation can be done on the \a where object.
299 \param where data object being tested
300 \return \c true if if drop operation is supported by object or \c false otherwise
301 \sa PyModuleHelper::isDropAccepted()
303 bool SALOME_PYQT_ModuleLight::isDropAccepted( const SUIT_DataObject* where ) const
306 return myHelper->isDropAccepted( where );
310 \brief Perform drop operation
311 \param what list of data objects being dropped
312 \param where target data object for drop operation
313 \param row line (child item index) where drop operation is performed to
314 \param action current drop action (copy or move)
315 \sa PyModuleHelper::dropObjects()
317 void SALOME_PYQT_ModuleLight::dropObjects( const DataObjectList& what, SUIT_DataObject* where,
318 const int row, Qt::DropAction action )
321 myHelper->dropObjects( what, where, row, action );
325 \brief Create new empty data object
326 \param parent entry of parent data object
327 \return entry of created data object
329 QString SALOME_PYQT_ModuleLight::createObject( const QString& parent )
332 SALOME_PYQT_DataObjectLight* obj = 0;
334 if ( !parent.isEmpty() ) {
335 SALOME_PYQT_DataObjectLight* parentObj = findObject( parent );
337 obj = new SALOME_PYQT_DataObjectLight( parentObj );
340 SALOME_PYQT_DataModelLight* dm =
341 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
343 obj = new SALOME_PYQT_DataObjectLight( dm->getRoot() );
346 entry = obj->entry();
351 \brief Create new data object with specified name, icon and tooltip
352 \param name data object name
353 \param icon data object icon
354 \param toolTip data object tooltip
355 \param parent entry of parent data object
356 \return entry of created data object
358 QString SALOME_PYQT_ModuleLight::createObject( const QString& name,
360 const QString& toolTip,
361 const QString& parent )
363 QString entry = createObject( parent );
364 SALOME_PYQT_DataObjectLight* obj = findObject( entry );
367 obj->setToolTip( toolTip );
368 obj->setIcon( icon );
374 \brief Set data object name
375 \param entry data object entry
376 \param name data object name
378 void SALOME_PYQT_ModuleLight::setName( const QString& entry, const QString& name )
380 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
382 dataObj->setName( name );
386 \brief Get data object name
387 \param entry data object entry
388 \return data object name
390 QString SALOME_PYQT_ModuleLight::getName( const QString& entry ) const
393 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
395 name = dataObj->name();
400 \brief Set data object icon
401 \param entry data object entry
402 \param icon data object icon file name (icon is loaded from module resources)
404 void SALOME_PYQT_ModuleLight::setIcon( const QString& entry, const QString& icon )
406 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
408 dataObj->setIcon( icon );
412 \brief Set data object tooltip
413 \param entry data object entry
414 \param toolTip data object tooltip
416 void SALOME_PYQT_ModuleLight::setToolTip( const QString& entry, const QString& toolTip )
418 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
420 dataObj->setToolTip( toolTip );
424 \brief Get data object tooltip
425 \param entry data object entry
426 \return data object tooltip
428 QString SALOME_PYQT_ModuleLight::getToolTip( const QString& entry ) const
431 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
433 toolTip = dataObj->toolTip();
438 \brief Set data object color
439 \param entry data object entry
440 \param color data object color
442 void SALOME_PYQT_ModuleLight::setColor( const QString& entry, const QColor& color )
444 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
446 dataObj->setColor( color );
450 \brief Get data object color
451 \param entry data object entry
452 \return data object color
454 QColor SALOME_PYQT_ModuleLight::getColor( const QString& entry ) const
457 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
459 color = dataObj->color( SUIT_DataObject::Foreground );
463 void SALOME_PYQT_ModuleLight::setObjectPosition( const QString& theEntry, int thePos )
465 SALOME_PYQT_DataObjectLight* dataObj = findObject( theEntry );
467 dataObj->setPosition(thePos);
470 int SALOME_PYQT_ModuleLight::getObjectPosition( const QString& theEntry )
472 SALOME_PYQT_DataObjectLight* dataObj = findObject( theEntry );
474 return dataObj->position();
480 \brief Set reference to another data object
481 \param entry data object entry
482 \param refEntry referenced data object entry
484 void SALOME_PYQT_ModuleLight::setReference( const QString& entry, const QString& refEntry )
486 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
488 dataObj->setRefEntry( refEntry );
492 \brief Get entry of the referenced object (if there's any)
493 \param entry data object entry
494 \return referenced data object entry
496 QString SALOME_PYQT_ModuleLight::getReference( const QString& entry ) const
499 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
501 refEntry = dataObj->refEntry();
506 \brief Remove object by entry
507 \param entry data object entry
509 void SALOME_PYQT_ModuleLight::removeObject( const QString& entry )
511 SALOME_PYQT_DataObjectLight* dataObj = findObject( entry );
512 if ( dataObj && dataObj->parent() )
513 dataObj->parent()->removeChild( dataObj );
517 \brief Remove all child data objects from specified data object
518 \param entry data object entry
520 void SALOME_PYQT_ModuleLight::removeChildren( const QString& entry )
522 SUIT_DataObject* dataObj = 0;
523 if ( !entry.isEmpty() ) {
524 dataObj = findObject( entry );
527 SALOME_PYQT_DataModelLight* dm =
528 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
529 if ( dm ) dataObj = dm->getRoot();
532 DataObjectList children;
533 dataObj->children( children );
534 QListIterator<SUIT_DataObject*> it( children );
535 while ( it.hasNext() ) {
536 dataObj->removeChild( it.next() );
542 \brief Get entries of all child data objects of specified data object
543 \param entry data object entry
544 \param recursive \c true for recursive processing
546 QStringList SALOME_PYQT_ModuleLight::getChildren( const QString& entry, const bool recursive ) const
548 QStringList entryList;
549 SUIT_DataObject* dataObj = 0;
550 if ( !entry.isEmpty() ) {
551 dataObj = findObject( entry );
554 SALOME_PYQT_DataModelLight* dm =
555 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
556 if ( dm ) dataObj = dm->getRoot();
560 dataObj->children( lst, recursive );
561 QListIterator<SUIT_DataObject*> it( lst );
562 while ( it.hasNext() ) {
563 SALOME_PYQT_DataObjectLight* sobj = dynamic_cast<SALOME_PYQT_DataObjectLight*>( it.next() );
564 entryList.append( sobj->entry() );
571 \brief Create new instance of data model and return it.
573 CAM_DataModel* SALOME_PYQT_ModuleLight::createDataModel()
575 return new SALOME_PYQT_DataModelLight( this );
579 \brief Find data object by its entry
580 \param entry data object entry
581 \return data object with given entry or 0 if object isn't found
583 SALOME_PYQT_DataObjectLight* SALOME_PYQT_ModuleLight::findObject( const QString& entry ) const
585 SALOME_PYQT_DataObjectLight* obj = 0;
586 SALOME_PYQT_DataModelLight* dm =
587 dynamic_cast<SALOME_PYQT_DataModelLight*>( dataModel() );
588 if ( !entry.isEmpty() && dm ) {
589 for ( SUIT_DataObjectIterator it( dm->getRoot(), SUIT_DataObjectIterator::DepthLeft ); it.current() && !obj; ++it ) {
590 SALOME_PYQT_DataObjectLight* curentobj =
591 dynamic_cast<SALOME_PYQT_DataObjectLight*>( it.current() );
592 if ( curentobj && curentobj->entry() == entry )