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