Salome HOME
Merge from V6_main 01/04/2013
[modules/gui.git] / src / SALOME_PYQT / SALOME_PYQT_GUI / SALOME_PYQT_Module.cxx
1 // Copyright (C) 2007-2013  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.
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 //
33 // NB: Python requests.
34 // General rule for Python requests created by Python-based GUI modules
35 // (SALOME_PYQT_Module and other ones):
36 // all requests should be executed SYNCHRONOUSLY within the main GUI thread.
37 // However, it is obligatory that ANY Python call is wrapped with a request object,
38 // so that ALL Python API calls are serialized with PyInterp_Dispatcher.
39 //
40 // NB: Library initialization
41 // Since the SalomePyQtGUI library is not imported in Python it's initialization function
42 // should be called manually (and only once) in order to initialize global sip data
43 // and to get C API from sip : sipBuildResult for example
44 //
45
46 #define INIT_FUNCTION initSalomePyQtGUILight
47 #if defined(SIP_STATIC_MODULE)
48 extern "C" void INIT_FUNCTION();
49 #else
50 PyMODINIT_FUNC INIT_FUNCTION();
51 #endif
52
53 /*!
54   \fn CAM_Module* createModule()
55   \brief Module factory function.
56   \internal
57   
58   Creates an instance of SALOME_PYQT_Module object by request
59   of an application when the module is loaded and initialized.
60
61   \return new module object
62 */
63
64 extern "C" {
65   SALOME_PYQT_EXPORT CAM_Module* createModule()
66   {
67     static bool alreadyInitialized = false;
68
69     if ( !alreadyInitialized ) {
70       // call only once (see comment above) !
71       PyEval_RestoreThread( KERNEL_PYTHON::_gtstate);
72       INIT_FUNCTION();
73       PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate);
74       alreadyInitialized = !alreadyInitialized;
75     }
76
77     return new SALOME_PYQT_Module();
78   }
79 }
80
81 /*!
82   \class SALOME_PYQT_Module
83   \brief This class implements GUI module for CORBA engine-based Python SALOME modules.
84 */
85
86 /*!
87   \brief Constructor
88 */
89 SALOME_PYQT_Module::SALOME_PYQT_Module()
90   : SalomeApp_Module( "noname" ) // name is set explicitly at the module initialization
91 {
92   // initialize helper
93   myHelper = new PyModuleHelper( this );
94 }
95
96 /*!
97   \brief Destructor
98 */
99 SALOME_PYQT_Module::~SALOME_PYQT_Module()
100 {
101   // as myHelper is a QObject, it should be deleted automatically
102 }
103
104 /*!
105   \brief Get module engine IOR
106   
107   This function tries to get engine IOR from the Python module using engineIOR() function.
108   That function can load module engine using appropriate container if required.
109   If this function is not available in Python module, the default implementation
110   is used which loads engine to the default FactoryServerPy container.
111 */
112 QString SALOME_PYQT_Module::engineIOR() const
113 {
114   // call helper to get IOR from Python module
115   static QString ior;
116
117   if ( ior.isEmpty() ) {
118     // first call helper to get IOR from Python module
119     ior = myHelper->engineIOR();
120   }
121   if ( ior.isEmpty() ) {
122     // if IOR is still not specified, try default implementation
123     // which loads engine to the default FactoryServerPy container.
124     Engines::EngineComponent_var comp;
125     // temporary solution
126     try {
127       comp = getApp()->lcc()->FindOrLoad_Component( "FactoryServerPy", name().toLatin1() );
128     }
129     catch (CORBA::Exception&) {
130     }
131     if ( !CORBA::is_nil( comp ) )
132       ior = QString( getApp()->orb()->object_to_string( comp.in() ) );
133   }
134
135   return ior;
136 }
137
138 /*!
139   \brief Initialization of the module.
140   \param app parent application object
141   \sa PyModuleHelper::initialize()
142 */
143 void SALOME_PYQT_Module::initialize( CAM_Application* app )
144 {
145   // call base implementation
146   SalomeApp_Module::initialize( app );
147
148   // ... then call helper
149   myHelper->initialize( app );
150 }
151
152 /*!
153   \brief Activation of the module.
154   \param study parent study
155   \return \c true if activation is successful and \c false otherwise
156   \sa PyModuleHelper::activate()
157 */
158 bool SALOME_PYQT_Module::activateModule( SUIT_Study* study )
159 {
160   // call base implementation and then helper
161   return SalomeApp_Module::activateModule( study ) && myHelper->activate( study );
162 }
163
164 /*!
165   \brief Deactivation of the module.
166   \param study parent study
167   \return \c true if deactivation is successful and \c false otherwise
168   \sa PyModuleHelper::deactivate()
169 */
170 bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* study )
171 {
172   // call helper
173   bool res = myHelper->deactivate( study );
174     
175   // ... then call base implementation
176   return SalomeApp_Module::deactivateModule( study ) && res;
177 }
178
179 /*!
180   \brief Get the dockable windows associated with the module.
181   \param winMap output map of dockable windows in form { <window_type> : <dock_area> }
182   \sa PyModuleHelper::windows()
183 */
184 void SALOME_PYQT_Module::windows( QMap<int, int>& winMap ) const
185 {
186   // get list of dockable windows from helper
187   winMap = myHelper->windows();
188 }
189
190 /*!
191   \brief Define the compatible view windows associated with the module.
192   \param viewList output list of view windows types
193   \sa PyModuleHelper::viewManagers()
194 */
195 void SALOME_PYQT_Module::viewManagers( QStringList& viewList ) const
196 {
197   // get list of view types from helper
198   viewList = myHelper->viewManagers();
199 }
200
201 /*!
202   \brief Process study activation.
203   \sa PyModuleHelper::studyActivated()
204 */
205 void SALOME_PYQT_Module::studyActivated()
206 {
207   // call helper
208   myHelper->studyActivated( application()->activeStudy() );
209 }
210
211 /*!
212   \brief Process context popup menu request.
213   \param context popup menu context (e.g. "ObjectBrowser")
214   \param menu popup menu
215   \param title popup menu title (not used)
216   \sa PyModuleHelper::contextMenu()
217 */
218 void SALOME_PYQT_Module::contextMenuPopup( const QString& context, 
219                                            QMenu*         menu, 
220                                            QString&       /*title*/ )
221 {
222   // call helper
223   myHelper->contextMenu( context, menu );
224 }
225
226 /*!
227   \brief Export preferences for the Python module.
228   \sa PyModuleHelper::createPreferences()
229 */
230 void SALOME_PYQT_Module::createPreferences()
231 {
232   // call helper
233   myHelper->createPreferences();
234 }
235
236 /*!
237   \brief Process module's preferences changing.
238   \param section preference resources section
239   \param parameter preference resources parameter name
240   \sa PyModuleHelper::preferencesChanged()
241 */
242 void SALOME_PYQT_Module::preferencesChanged( const QString& section, const QString& parameter )
243 {
244   // call helper
245   myHelper->preferencesChanged( section, parameter );
246 }
247
248 /*!
249   \brief Test if object \a what can be dragged by the user.
250   \param what data object being tested
251   \return \c true if object can be dragged or \c false otherwise
252   \sa PyModuleHelper::isDraggable()
253 */
254 bool SALOME_PYQT_Module::isDraggable( const SUIT_DataObject* what ) const
255 {
256   // call helper
257   return myHelper->isDraggable( what );
258 }
259
260 /*!
261   \brief Test if drop operation can be done on the \a where object.
262   \param where data object being tested
263   \return \c true if if drop operation is supported by object or \c false otherwise
264   \sa PyModuleHelper::isDropAccepted()
265 */
266 bool SALOME_PYQT_Module::isDropAccepted( const SUIT_DataObject* where ) const
267 {
268   // call helper
269   return myHelper->isDropAccepted( where );
270 }
271
272 /*!
273   \brief Perform drop operation
274   \param what list of data objects being dropped
275   \param where target data object for drop operation
276   \param row line (child item index) where drop operation is performed to
277   \param action current drop action (copy or move)
278   \sa PyModuleHelper::dropObjects()
279 */
280 void SALOME_PYQT_Module::dropObjects( const DataObjectList& what, SUIT_DataObject* where,
281                                       const int row, Qt::DropAction action )
282 {
283   // call helper
284   myHelper->dropObjects( what, where, row, action );
285 }
286