Salome HOME
Update copyrights
[modules/gui.git] / src / SALOME_PYQT / SALOME_PYQT_GUI / SALOME_PYQT_Module.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : SALOME_PYQT_Module.cxx
23 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
24
25 #include "SALOME_PYQT_Module.h"
26 #include "SALOME_PYQT_PyModule.h"
27 #include "SalomeApp_Application.h"
28
29 #include <SALOME_LifeCycleCORBA.hxx>
30 #include <Container_init_python.hxx>
31
32 #include <QCoreApplication>
33
34 //
35 // NB: Python requests.
36 // General rule for Python requests created by Python-based GUI modules
37 // (SALOME_PYQT_Module and other ones):
38 // all requests should be executed SYNCHRONOUSLY within the main GUI thread.
39 // However, it is obligatory that ANY Python call is wrapped with a request object,
40 // so that ALL Python API calls are serialized with PyInterp_Dispatcher.
41 //
42 // NB: Library initialization
43 // Since the SalomePyQtGUI library is not imported in Python it's initialization function
44 // should be called manually (and only once) in order to initialize global sip data
45 // and to get C API from sip : sipBuildResult for example
46 //
47
48 #define INIT_FUNCTION PyInit_SalomePyQtGUILight
49 #if defined(SIP_STATIC_MODULE)
50 extern "C" void INIT_FUNCTION();
51 #else
52 PyMODINIT_FUNC INIT_FUNCTION();
53 #endif
54
55 /*!
56   \fn CAM_Module* createModule()
57   \brief Module factory function.
58   \internal
59   
60   Creates an instance of SALOME_PYQT_Module object by request
61   of an application when the module is loaded and initialized.
62
63   \return new module object
64 */
65
66 extern "C" {
67   SALOME_PYQT_EXPORT CAM_Module* createModule()
68   {
69     QCoreApplication* app = QCoreApplication::instance();
70     bool alreadyInitialized = app && app->property( "salome_pyqt_gui_light_initialized" ).toBool();
71
72     if ( !alreadyInitialized ) {
73       PyLockWrapper lck; // GIL acquisition
74       INIT_FUNCTION();
75       if ( app ) app->setProperty( "salome_pyqt_gui_light_initialized", true );
76     }
77
78     return new SALOME_PYQT_Module();
79   }
80 }
81
82 /*!
83   \class SALOME_PYQT_Module
84   \brief This class implements GUI module for CORBA engine-based Python SALOME modules.
85 */
86
87 /*!
88   \brief Constructor
89 */
90 SALOME_PYQT_Module::SALOME_PYQT_Module()
91   : SalomeApp_Module( "noname" ) // name is set explicitly at the module initialization
92 {
93   // initialize helper
94   myHelper = new PyModuleHelper( this );
95 }
96
97 /*!
98   \brief Destructor
99 */
100 SALOME_PYQT_Module::~SALOME_PYQT_Module()
101 {
102   // as myHelper is a QObject, it should be deleted automatically
103 }
104
105 /*!
106   \brief Get module engine IOR
107   
108   This function tries to get engine IOR from the Python module using engineIOR() function.
109   That function can load module engine using appropriate container if required.
110   If this function is not available in Python module, the default implementation
111   is used which loads engine to the default FactoryServer container.
112 */
113 QString SALOME_PYQT_Module::engineIOR() const
114 {
115   // call helper to get IOR from Python module
116   static QString ior;
117
118   if ( ior.isEmpty() ) {
119     // first call helper to get IOR from Python module
120     ior = myHelper->engineIOR();
121   }
122   if ( ior.isEmpty() ) {
123     // if IOR is still not specified, try default implementation
124     // which loads engine to the default FactoryServer container.
125     Engines::EngineComponent_var comp;
126     // temporary solution
127     try {
128       comp = getApp()->lcc()->FindOrLoad_Component( "FactoryServer", name().toLatin1() );
129     }
130     catch (CORBA::Exception&) {
131     }
132     if ( !CORBA::is_nil( comp ) )
133       ior = QString( getApp()->orb()->object_to_string( comp.in() ) );
134   }
135
136   return ior;
137 }
138
139 /*!
140   \brief Initialization of the module.
141   \param app parent application object
142   \sa PyModuleHelper::initialize()
143 */
144 void SALOME_PYQT_Module::initialize( CAM_Application* app )
145 {
146   // call base implementation
147   SalomeApp_Module::initialize( app );
148
149   // ... then call helper
150   myHelper->initialize( app );
151 }
152
153 /*!
154   \brief Activation of the module.
155   \param study parent study
156   \return \c true if activation is successful and \c false otherwise
157   \sa PyModuleHelper::activate()
158 */
159 bool SALOME_PYQT_Module::activateModule( SUIT_Study* study )
160 {
161   // call base implementation and then helper
162   return SalomeApp_Module::activateModule( study ) && myHelper->activate( study );
163 }
164
165 /*!
166   \brief Deactivation of the module.
167   \param study parent study
168   \return \c true if deactivation is successful and \c false otherwise
169   \sa PyModuleHelper::deactivate()
170 */
171 bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* study )
172 {
173   // call helper
174   bool res = myHelper->deactivate( study );
175     
176   // ... then call base implementation
177   return SalomeApp_Module::deactivateModule( study ) && res;
178 }
179
180 /*!
181   \brief Get the dockable windows associated with the module.
182   \param winMap output map of dockable windows in form { <window_type> : <dock_area> }
183   \sa PyModuleHelper::windows()
184 */
185 void SALOME_PYQT_Module::windows( QMap<int, int>& winMap ) const
186 {
187   // get list of dockable windows from helper
188   winMap = myHelper->windows();
189 }
190
191 /*!
192   \brief Define the compatible view windows associated with the module.
193   \param viewList output list of view windows types
194   \sa PyModuleHelper::viewManagers()
195 */
196 void SALOME_PYQT_Module::viewManagers( QStringList& viewList ) const
197 {
198   // get list of view types from helper
199   viewList = myHelper->viewManagers();
200 }
201
202 /*!
203   \brief Process study activation.
204   \sa PyModuleHelper::studyActivated()
205 */
206 void SALOME_PYQT_Module::studyActivated()
207 {
208   // call helper
209   myHelper->studyActivated( application()->activeStudy() );
210 }
211
212 /*!
213   \brief Process context popup menu request.
214   \param context popup menu context (e.g. "ObjectBrowser")
215   \param menu popup menu
216   \param title popup menu title (not used)
217   \sa PyModuleHelper::contextMenu()
218 */
219 void SALOME_PYQT_Module::contextMenuPopup( const QString& context, 
220                                            QMenu*         menu, 
221                                            QString&       /*title*/ )
222 {
223   // call helper
224   myHelper->contextMenu( context, menu );
225 }
226
227 /*!
228   \brief Export preferences for the Python module.
229   \sa PyModuleHelper::createPreferences()
230 */
231 void SALOME_PYQT_Module::createPreferences()
232 {
233   // call helper
234   myHelper->createPreferences();
235 }
236
237 /*!
238   \brief Process module's preferences changing.
239   \param section preference resources section
240   \param parameter preference resources parameter name
241   \sa PyModuleHelper::preferencesChanged()
242 */
243 void SALOME_PYQT_Module::preferencesChanged( const QString& section, const QString& parameter )
244 {
245   // call helper
246   myHelper->preferencesChanged( section, parameter );
247 }
248
249 /*!
250   \brief Called when study is closed
251   \param study study being closed
252   \sa PyModuleHelper::studyClosed()
253 */
254 void SALOME_PYQT_Module::studyClosed( SUIT_Study* study )
255 {
256   // call helper
257   myHelper->modelClosed( study );
258   SalomeApp_Module::studyClosed( study );
259 }
260
261 /*!
262   \brief Test if object \a what can be dragged by the user.
263   \param what data object being tested
264   \return \c true if object can be dragged or \c false otherwise
265   \sa PyModuleHelper::isDraggable()
266 */
267 bool SALOME_PYQT_Module::isDraggable( const SUIT_DataObject* what ) const
268 {
269   // call helper
270   return myHelper->isDraggable( what );
271 }
272
273 /*!
274   \brief Test if drop operation can be done on the \a where object.
275   \param where data object being tested
276   \return \c true if if drop operation is supported by object or \c false otherwise
277   \sa PyModuleHelper::isDropAccepted()
278 */
279 bool SALOME_PYQT_Module::isDropAccepted( const SUIT_DataObject* where ) const
280 {
281   // call helper
282   return myHelper->isDropAccepted( where );
283 }
284
285 /*!
286   \brief Perform drop operation
287   \param what list of data objects being dropped
288   \param where target data object for drop operation
289   \param row line (child item index) where drop operation is performed to
290   \param action current drop action (copy or move)
291   \sa PyModuleHelper::dropObjects()
292 */
293 void SALOME_PYQT_Module::dropObjects( const DataObjectList& what, SUIT_DataObject* where,
294                                       const int row, Qt::DropAction action )
295 {
296   // call helper
297   myHelper->dropObjects( what, where, row, action );
298 }
299