Salome HOME
Merge remote-tracking branch 'origin/vsr/fix_single_study_pb' into pre/fix_single_study
[modules/gui.git] / src / Session / Session_Session_i.cxx
1 // Copyright (C) 2007-2014  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_Session_i.cxx
23 //  Author : Paul RASCLE, EDF
24 //  Module : SALOME
25
26 #include "utilities.h"
27
28 #include "Session_Session_i.hxx"
29
30 #include "SALOME_NamingService.hxx"
31 #include "SALOME_Event.h"
32 #include "SalomeApp_Engine_i.h"
33 #include "SUIT_Session.h"
34 #include "SUIT_Desktop.h"
35 #include "SUIT_Study.h"
36
37 #include "Basics_Utils.hxx"
38
39 #include <QMutex>
40 #include <QWaitCondition>
41
42 // Open CASCADE Includes
43 #include <OSD_SharedLibrary.hxx>
44 #include <OSD_Function.hxx>
45
46 #ifdef WIN32
47 # include <process.h>
48 #else
49 #include <unistd.h>
50 #endif
51
52 /*!
53   constructor
54 */
55 SALOME_Session_i::SALOME_Session_i(int argc,
56                                    char ** argv,
57                                    CORBA::ORB_ptr orb,
58                                    PortableServer::POA_ptr poa,
59                                    QMutex* GUIMutex,
60                                    QWaitCondition* GUILauncher)
61 {
62   _argc = argc ;
63   _argv = argv ;
64   _isGUI = FALSE ;
65   _runningStudies= 0 ;
66   _orb = CORBA::ORB::_duplicate(orb) ;
67   _poa = PortableServer::POA::_duplicate(poa) ;
68   _GUIMutex = GUIMutex;
69   _GUILauncher = GUILauncher;
70   _NS = new SALOME_NamingService(_orb);
71   _isShuttingDown = false;
72   //MESSAGE("constructor end");
73 }
74
75 /*!
76   returns Visu component
77 */
78 Engines::EngineComponent_ptr SALOME_Session_i::GetComponent(const char* theLibraryName)
79 {
80   typedef Engines::EngineComponent_ptr TGetImpl(CORBA::ORB_ptr,
81                                                 PortableServer::POA_ptr,
82                                                 SALOME_NamingService*,QMutex*);
83   OSD_SharedLibrary aSharedLibrary(const_cast<char*>(theLibraryName));
84   if (aSharedLibrary.DlOpen(OSD_RTLD_LAZY)) {
85     if (OSD_Function anOSDFun = aSharedLibrary.DlSymb("GetImpl"))
86       return ((TGetImpl (*)) anOSDFun)(_orb,_poa,_NS,_GUIMutex);
87   }
88   CORBA::Object_var obj = SalomeApp_Engine_i::EngineForComponent(theLibraryName, true);
89   if (!CORBA::is_nil(obj)){
90     Engines::EngineComponent_var anEngine = Engines::EngineComponent::_narrow(obj);
91     return anEngine._retn();
92   }
93   return Engines::EngineComponent::_nil();
94 }
95
96 /*!
97   destructor
98 */
99 SALOME_Session_i::~SALOME_Session_i()
100 {
101   delete _NS;
102   //MESSAGE("destructor end");
103 }
104
105 /*!
106   tries to find the Corba Naming Service and to register the session,
107   gives naming service interface to _IAPPThread
108 */
109 void SALOME_Session_i::NSregister()
110 {
111   CORBA::Object_var obref=_this();
112   SALOME::Session_var pSession = SALOME::Session::_narrow(obref);
113   try
114     {
115       _NS->Register(pSession, "/Kernel/Session");
116     }
117   catch (ServiceUnreachable&)
118     {
119       INFOS("Caught exception: Naming Service Unreachable");
120       exit(1) ;
121     }
122   catch (...)
123     {
124       INFOS("Caught unknown exception from Naming Service");
125     }
126   //MESSAGE("Session registered in Naming Service");
127 }
128
129 /*!
130   Unregister session server from CORBA Naming Service
131 */
132 void SALOME_Session_i::NSunregister()
133 {
134   try
135     {
136       _NS->Destroy_Name("/Kernel/Session");
137     }
138   catch (ServiceUnreachable&)
139     {
140       INFOS("Caught exception: Naming Service Unreachable");
141     }
142   catch (...)
143     {
144       INFOS("Caught unknown exception from Naming Service");
145     }
146 }
147
148 /*!
149   Launches the GUI if there is none.
150   The Corba method is oneway (corba client does'nt wait for GUI completion)
151 */
152 void SALOME_Session_i::GetInterface()
153 {
154   _GUIMutex->lock();
155   _GUIMutex->unlock();
156   if ( !SUIT_Session::session() )
157   {
158     _GUILauncher->wakeAll();
159     MESSAGE("SALOME_Session_i::GetInterface() called, starting GUI...");
160   }
161 }
162
163 /*!
164   Kills the session if there are no active studies nore GUI
165 */
166 class CloseEvent : public SALOME_Event
167 {
168 public:
169   virtual void Execute() {
170     if ( SUIT_Session::session() )
171       SUIT_Session::session()->closeSession( SUIT_Session::DONT_SAVE );
172   }
173 };
174
175 /*!
176   Stop session (close all GUI windows)
177 */
178 void SALOME_Session_i::StopSession()
179 {
180   _GUIMutex->lock();
181   _GUIMutex->unlock();
182   if ( SUIT_Session::session() ) {
183     ProcessVoidEvent( new CloseEvent() );
184   }
185 }
186
187 //! Shutdown session
188 void SALOME_Session_i::Shutdown()
189 {
190   _GUIMutex->lock();
191   bool isBeingShuttingDown = _isShuttingDown;
192   _isShuttingDown = true;
193   _GUIMutex->unlock();
194   if ( !isBeingShuttingDown ) {
195     if ( SUIT_Session::session() ) {
196       ProcessVoidEvent( new CloseEvent() );
197     }
198     else {
199       _GUILauncher->wakeAll();
200     }
201   }
202 }
203
204 /*!
205   Send a SALOME::StatSession structure (see idl) to the client
206   (number of running studies and presence of GUI)
207 */
208 /*class QtLock
209 {
210 public:
211   QtLock() { if ( qApp ) qApp->lock(); }
212   ~QtLock() { if ( qApp ) qApp->unlock(); }
213 };*/
214
215
216 SALOME::StatSession SALOME_Session_i::GetStatSession()
217 {
218   // update Session state
219   _GUIMutex->lock();
220
221   _runningStudies = 0;
222   {
223     //QtLock lock;
224     _isGUI = SUIT_Session::session();
225     if ( _isGUI && SUIT_Session::session()->activeApplication() )
226       _runningStudies = SUIT_Session::session()->activeApplication()->getNbStudies();
227   }
228
229   // getting stat info
230   SALOME::StatSession_var myStats = new SALOME::StatSession ;
231   if (_runningStudies)
232     myStats->state = SALOME::running ;
233   else if (_isShuttingDown)
234     myStats->state = SALOME::shutdown ;
235   else
236     myStats->state = SALOME::asleep ;
237   myStats->runningStudies = _runningStudies ;
238   myStats->activeGUI = _isGUI ;
239
240   _GUIMutex->unlock();
241
242   return myStats._retn() ;
243 }
244
245 CORBA::Long SALOME_Session_i::GetActiveStudyId()
246 {
247   long aStudyId=-1;
248   if ( SUIT_Session::session() && SUIT_Session::session()->activeApplication() ) {
249     if ( SUIT_Session::session()->activeApplication()->activeStudy() ) // mkr : IPAL12128
250       aStudyId = SUIT_Session::session()->activeApplication()->activeStudy()->id();
251   }
252   return aStudyId;
253 }
254
255 CORBA::Long SALOME_Session_i::getPID() {
256   return (CORBA::Long)
257 #ifndef WIN32
258     getpid();
259 #else
260     _getpid();
261 #endif
262 }
263
264 char* SALOME_Session_i::getHostname()
265 {
266   std::string aHostName = Kernel_Utils::GetHostname();
267   return CORBA::string_dup( aHostName.data() );
268 }
269
270 bool SALOME_Session_i::restoreVisualState(CORBA::Long theSavePoint)
271 {
272   class TEvent: public SALOME_Event {
273     int _savePoint;
274   public:
275     TEvent(int savePoint) { _savePoint = savePoint; }
276     virtual void Execute() {
277       SUIT_Study* study = SUIT_Session::session()->activeApplication()->activeStudy();
278       if ( study ) {
279         study->restoreState(_savePoint);
280       }
281     }
282   };
283   
284   if(SUIT_Session::session() && SUIT_Session::session()->activeApplication() ) {
285     SUIT_Study* study = SUIT_Session::session()->activeApplication()->activeStudy();
286     if(!study) SUIT_Session::session()->activeApplication()->createEmptyStudy();      
287     ProcessVoidEvent( new TEvent(theSavePoint) );
288     return true;
289   }
290  
291   return false;
292 }
293
294 void SALOME_Session_i::emitMessage(const char* theMessage)
295 {
296   class TEvent: public SALOME_Event {
297   public:
298     TEvent(const char * msg) {
299       _msg = msg;
300     }
301     virtual void Execute() {
302       SUIT_Session::session()->activeApplication()->desktop()->emitMessage(_msg);
303     }
304   private:
305     const char* _msg;
306   };
307   if ( SUIT_Session::session() ) {
308     if ( SUIT_Session::session()->activeApplication() ) {
309       if ( SUIT_Session::session()->activeApplication()->desktop() ) {
310         ProcessVoidEvent( new TEvent(theMessage) );
311       }
312       else {
313         MESSAGE("try to emit message '"<<theMessage<<"' but there is no desktop");
314       }
315     }
316     else {
317       MESSAGE("try to emit message '"<<theMessage<<"' but there is no application");
318     }
319   }
320   else {
321     MESSAGE("try to emit message '"<<theMessage<<"' but there is no session");
322   }
323 }
324
325 void SALOME_Session_i::emitMessageOneWay(const char* theMessage)
326 {
327   emitMessage(theMessage);
328 }