]> SALOME platform Git repositories - modules/gui.git/blob - src/SalomeApp/SalomeApp_Application.cxx
Salome HOME
95465cd4dc788db4b39384b56ba6fc96999931a8
[modules/gui.git] / src / SalomeApp / SalomeApp_Application.cxx
1 // Copyright (C) 2007-2015  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
23 // File:      SalomeApp_Application.cxx
24 // Created:   10/22/2004 3:23:45 PM
25 // Author:    Sergey LITONIN
26
27 #ifdef WIN32
28   // E.A. : On windows with python 2.6, there is a conflict
29   // E.A. : between pymath.h and Standard_math.h which define
30   // E.A. : some same symbols : acosh, asinh, ...
31   #include <Standard_math.hxx>
32   #ifndef DISABLE_PYCONSOLE
33     #include <pymath.h>
34   #endif
35 #endif
36
37 #ifndef DISABLE_PYCONSOLE
38   #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
39   #include <PyConsole_Console.h>
40   #include "SalomeApp_NoteBook.h"
41 #endif
42 #include "SalomeApp_Application.h"
43 #include "SalomeApp_Study.h"
44 #include "SalomeApp_DataModel.h"
45 #include "SalomeApp_DataObject.h"
46 #include "SalomeApp_VisualState.h"
47 #include "SalomeApp_StudyPropertiesDlg.h"
48 #include "SalomeApp_LoadStudiesDlg.h"
49 #include "SalomeApp_ExitDlg.h"
50
51 #include <LightApp_Application.h>
52 #include <LightApp_Module.h>
53 #include <LightApp_Preferences.h>
54 #include <LightApp_SelectionMgr.h>
55 #include <LightApp_NameDlg.h>
56 #include <LightApp_DataOwner.h>
57
58 #include <CAM_Module.h>
59
60 #include <SUIT_Tools.h>
61 #include <SUIT_Session.h>
62 #include <SUIT_Desktop.h>
63 #include <SUIT_DataBrowser.h>
64 #include <SUIT_FileDlg.h>
65 #include <SUIT_FileValidator.h>
66 #include <SUIT_MessageBox.h>
67 #include <SUIT_ResourceMgr.h>
68 #include <SUIT_TreeModel.h>
69 #include <SUIT_ViewWindow.h>
70 #include <SUIT_ViewManager.h>
71 #include <SUIT_ViewModel.h>
72 #include <SUIT_OverrideCursor.h>
73
74 #include <QtxTreeView.h>
75
76 #include <SALOME_EventFilter.h>
77
78 // temporary commented
79 //#include <OB_ListItem.h>
80
81
82 #include <Utils_ORB_INIT.hxx>
83 #include <Utils_SINGLETON.hxx>
84 #include <SALOME_LifeCycleCORBA.hxx>
85
86 #include <QApplication>
87 #include <QAction>
88 #include <QRegExp>
89 #include <QCheckBox>
90 #include <QPushButton>
91 #include <QLabel>
92 #include <QListWidget>
93 #include <QGridLayout>
94 #include <QMenu>
95 #include <QtDebug>
96
97 #include <SALOMEDSClient_ClientFactory.hxx>
98 #include <Basics_Utils.hxx>
99
100 #include <SALOME_ListIO.hxx>
101 #include <SALOME_Prs.h>
102
103
104 #include <ToolsGUI_CatalogGeneratorDlg.h>
105 #include <ToolsGUI_RegWidget.h>
106
107 #include <vector>
108
109 #include <SALOMEDS_Tool.hxx>
110
111 /*!Internal class that updates object browser item properties */
112 // temporary commented
113 /*class SalomeApp_Updater : public OB_Updater
114 {
115 public:
116   SalomeApp_Updater() : OB_Updater(){};
117   virtual ~SalomeApp_Updater(){};
118   virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
119 };
120
121 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
122 {
123   if( !theObj || !theItem )
124     return;
125
126   SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
127   if( !SAObj )
128     return;
129
130   _PTR(SObject) SObj = SAObj->object();
131   if( !SObj )
132     return;
133   _PTR( GenericAttribute ) anAttr;
134
135   // Selectable
136   if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
137   {
138     _PTR(AttributeSelectable) aAttrSel = anAttr;
139     theItem->setSelectable( aAttrSel->IsSelectable() );
140   }
141   // Expandable
142   if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
143   {
144     _PTR(AttributeExpandable) aAttrExpand = anAttr;
145     theItem->setExpandable( aAttrExpand->IsExpandable() );
146   }
147   // Opened
148   //this attribute is not supported in the version of SALOME 3.x
149   //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
150   //{
151   //  _PTR(AttributeOpened) aAttrOpen = anAttr;
152   //  theItem->setOpen( aAttrOpen->IsOpened() );
153   //}
154 }*/
155
156 /*!Create new instance of SalomeApp_Application.*/
157 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
158 {
159   return new SalomeApp_Application();
160 }
161
162 /*!Constructor.*/
163 SalomeApp_Application::SalomeApp_Application()
164   : LightApp_Application(), 
165     myIsSiman( false ),
166     myIsCloseFromExit( false )
167 {
168 }
169
170 /*!Destructor.
171  *\li Destroy event filter.
172  */
173 SalomeApp_Application::~SalomeApp_Application()
174 {
175   // Do not destroy. It's a singleton !
176   //SALOME_EventFilter::Destroy();
177 }
178
179 /*!Start application.*/
180 void SalomeApp_Application::start()
181 {
182   // process the command line options before start: to createActions in accordance to the options
183   static bool isFirst = true;
184   if ( isFirst ) {
185     isFirst = false;
186
187     QString hdffile;
188     QStringList pyfiles;
189     QString loadStudy;
190
191     for (int i = 1; i < qApp->argc(); i++) {
192       QRegExp rxs ("--study-hdf=(.+)");
193       if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
194         QString file = rxs.capturedTexts()[1];
195         QFileInfo fi ( file );
196         QString extension = fi.suffix().toLower();
197         if ( extension == "hdf" && fi.exists() )
198           hdffile = fi.absoluteFilePath();
199       }
200       else {
201         QRegExp rxp ("--pyscript=\\[(.+)\\]");
202         QRegExp rxl ("--siman-study=(.+)");
203         if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
204           // pyscript
205           QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
206           for (int k = 0; k < dictList.count(); ++k) {
207             QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
208             if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
209               for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
210                 pyfiles += rxd.capturedTexts()[m];
211               }
212             }
213           }
214         }
215 #ifdef WITH_SIMANIO
216         if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
217           // siman
218           loadStudy = rxl.capturedTexts()[1];
219           myIsSiman = true;
220         }
221 #endif
222       }
223     }
224     // Here pyfiles elements are: "script_name": [list_of_"arg"s]
225     // For example: "/absolute/path/to/my_script.py": ["1", "2"]
226
227     LightApp_Application::start();
228     SALOME_EventFilter::Init();
229
230     if ( !hdffile.isEmpty() )       // open hdf file given as parameter
231       onOpenDoc( hdffile );
232     else if ( pyfiles.count() > 0 ) // create new study
233       onNewDoc();
234     else if (!loadStudy.isEmpty()) {// load study by name
235       if (onLoadDoc(loadStudy))
236         updateObjectBrowser(true);
237     }
238
239 #ifndef DISABLE_PYCONSOLE
240     // import/execute python scripts
241     if ( pyfiles.count() > 0 && activeStudy() ) {
242       SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
243       PyConsole_Console* pyConsole = pythonConsole();
244       if ( appStudy && pyConsole ) {
245         _PTR(Study) aStudy = appStudy->studyDS();
246         if ( !aStudy->GetProperties()->IsLocked() ) {
247           // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
248           // Path is absolute, script has .py extension
249           for (uint j = 0; j < pyfiles.count(); j++ ) {
250             // Extract scripts and their arguments, if any
251             QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
252             if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
253               QString script = rxp.capturedTexts()[1];
254               QString args = "";
255               QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
256               for (uint k = 0; k < argList.count(); k++ ) {
257                 QString arg = argList[k].trimmed();
258                 arg.remove( QRegExp("^[\"]") );
259                 arg.remove( QRegExp("[\"]$") );
260                 args += arg+",";
261               }
262               args.remove( QRegExp("[,]$") );
263               if (!args.isEmpty()) {
264                 args = "args:"+args;
265               }
266
267               script.remove( QRegExp("^python.*[\\s]+") );
268               QString cmd = script+" "+args;
269               QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
270               pyConsole->exec(command);
271             }
272           } // end for loop on pyfiles QStringList
273         }
274       }
275     }
276 #endif
277   } else {
278     LightApp_Application::start();
279     SALOME_EventFilter::Init();
280   }
281 }
282
283 /*!Create actions:*/
284 void SalomeApp_Application::createActions()
285 {
286   LightApp_Application::createActions();
287
288   SUIT_Desktop* desk = desktop();
289
290   //! Save GUI state
291   // "Save GUI State" command is moved to VISU module
292   //  createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
293   //            tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
294   //            0, desk, false, this, SLOT( onSaveGUIState() ) );
295
296   //! Dump study
297   createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
298                 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
299                 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
300
301   //! Load script
302   createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
303                 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
304                 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
305
306   //! Properties
307   createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
308                 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
309                 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
310
311   //! Catalog Generator
312   createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ),  QIcon(),
313                 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
314                 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
315
316   //! Registry Display
317   createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ),  QIcon(),
318                 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
319                 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
320
321   createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
322                 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
323                 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
324
325   createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
326                 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
327                 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
328
329
330 #ifdef WITH_SIMANIO
331   if (myIsSiman) {
332     // check-in operations for SIMAN study  
333     createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
334                 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
335                 0, desk, false, this, SLOT( onCheckIn() ) );
336     createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
337                 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
338                 0, desk, false, this, SLOT( onLocalCheckIn() ) );
339   }
340 #endif
341
342   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
343
344   // "Save GUI State" command is renamed to "Save VISU State" and
345   // creation of menu item is moved to VISU
346   //  createMenu( SaveGUIStateId, fileMenu, 10, -1 );
347
348   createMenu( ConnectId,    fileMenu, 5 );
349   createMenu( DisconnectId, fileMenu, 5 );
350   createMenu( separator(),  fileMenu, -1, 5 );
351
352 #ifdef WITH_SIMANIO
353   if (myIsSiman) {
354     // check-in operation for SIMAN study
355     // last argument "5" locates this just after "Save As" but certain constant is bad => insert after the separator
356     createMenu( SimanCheckInId, fileMenu, 5);
357     createMenu( SimanLocalCheckInId, fileMenu, 5);
358     createMenu( separator(), fileMenu, 5 );
359   }
360 #endif
361   createMenu( DumpStudyId, fileMenu, 10, -1 );
362   createMenu( LoadScriptId, fileMenu, 10, -1 );
363   createMenu( separator(), fileMenu, -1, 10, -1 );
364   createMenu( PropertiesId, fileMenu, 10, -1 );
365   createMenu( separator(), fileMenu, -1, 10, -1 );
366
367   int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
368   createMenu( CatalogGenId, toolsMenu, 10, -1 );
369   createMenu( RegDisplayId, toolsMenu, 10, -1 );
370   createMenu( separator(), toolsMenu, -1, 15, -1 );
371
372   createExtraActions();
373
374 #ifndef DISABLE_PYCONSOLE
375 #ifndef DISABLE_SALOMEOBJECT
376   // import Python module that manages SALOME plugins
377   {
378     PyLockWrapper lck; // acquire GIL
379     PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
380     PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
381     if ( !res )
382       PyErr_Print();
383   }
384   // end of SALOME plugins loading
385 #endif
386 #endif
387
388 }
389
390 /*!
391   \brief Close application.
392 */
393 void SalomeApp_Application::onExit()
394 {
395   bool killServers = false;
396   bool result = true;
397
398   if ( exitConfirmation() ) {
399     SalomeApp_ExitDlg dlg( desktop() );
400     result = dlg.exec() == QDialog::Accepted;
401     killServers = dlg.isServersShutdown();
402   }
403
404   if ( result ) {
405     if ( !killServers ) myIsCloseFromExit = true;
406     SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
407     if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
408   }
409 }
410
411 /*!SLOT. Load document.*/
412 void SalomeApp_Application::onLoadDoc()
413 {
414   QString studyName;
415
416   std::vector<std::string> List = studyMgr()->GetOpenStudies();
417
418   // rnv: According to the single-study approach on the server side
419   //      can be only one study. So if it is exists connect to them,  
420   //      overwise show warning message: "No active study on the server"
421
422   /*
423   SUIT_Session* aSession = SUIT_Session::session();
424   QList<SUIT_Application*> aAppList = aSession->applications();
425
426   QStringList unloadedStudies;
427
428   for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
429      studyName = List[ind].c_str();
430      // Add to list only unloaded studies
431      bool isAlreadyOpen = false;
432      QListIterator<SUIT_Application*> it( aAppList );
433      while ( it.hasNext() && !isAlreadyOpen ) {
434        SUIT_Application* aApp = it.next();
435        if( !aApp || !aApp->activeStudy() )
436          continue;
437        if ( aApp->activeStudy()->studyName() == studyName )
438          isAlreadyOpen = true;
439      }
440
441      if ( !isAlreadyOpen )
442        unloadedStudies << studyName;
443   }
444   studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
445   if ( studyName.isEmpty() )
446     return;
447   */
448
449   if(List.size() <= 0) {
450     SUIT_MessageBox::warning( desktop(),
451                               QObject::tr("WRN_WARNING"),
452                               QObject::tr("WRN_NO_STUDY_ON SERV") );
453     return;
454   }
455   
456   studyName = List[0].c_str();
457
458 #ifndef WIN32
459   // this code replaces marker of windows drive and path become invalid therefore
460   // defines placed there
461   studyName.replace( QRegExp(":"), "/" );
462 #endif
463
464   if ( onLoadDoc( studyName ) ) {
465     updateWindows();
466     updateViewManagers();
467     updateObjectBrowser( true );
468   }
469 }
470
471 /*!SLOT. Unload document.*/
472 void SalomeApp_Application::onUnloadDoc( bool ask )
473 {
474   if ( ask ) {
475     activeStudy()->abortAllOperations();
476     if ( activeStudy()->isModified() ) {
477       QString docName = activeStudy()->studyName().trimmed();
478       int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
479                                             tr( "DISCONNECT_DESCRIPTION" ),
480                                             tr( "DISCONNECT_SAVE" ), 
481                                             tr( "DISCONNECT_WO_SAVE" ),
482                                             tr( "APPCLOSE_CANCEL" ), 0 );
483       if ( answer == 0 ) { // save before unload
484         if ( activeStudy()->isSaved() )
485           onSaveDoc();
486         else if ( !onSaveAsDoc() )
487           return;
488       }
489       else if ( answer == 2 ) // Cancel
490         return;
491     }
492   }
493   closeActiveDoc( false );
494 }
495
496 /*!SLOT. Create new study and load script*/
497 void SalomeApp_Application::onNewWithScript()
498 {
499   QStringList filtersList;
500   filtersList.append(tr("PYTHON_FILES_FILTER"));
501   filtersList.append(tr("ALL_FILES_FILTER"));
502
503   QString anInitialPath = "";
504   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
505     anInitialPath = QDir::currentPath();
506
507   QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
508
509   if ( !aFile.isEmpty() )
510   {
511     onNewDoc();
512
513     QString command = QString("execfile(r\"%1\")").arg(aFile);
514
515 #ifndef DISABLE_PYCONSOLE
516     PyConsole_Console* pyConsole = pythonConsole();
517
518     if ( pyConsole )
519       pyConsole->exec( command );
520 #endif
521   }
522 }
523
524
525 /*!SLOT. Load document with \a aName.*/
526 bool SalomeApp_Application::onLoadDoc( const QString& aName )
527 {
528 #ifdef SINGLE_DESKTOP
529   if ( !LightApp_Application::closeDoc() )
530     return false;
531 #endif
532   bool res = true;
533   if ( !activeStudy() ) {
534     // if no study - load in current desktop
535     res = useStudy( aName );
536   }
537   else {
538     // if study exists - load in new desktop. Check: is the same file is loaded?
539     SUIT_Session* aSession = SUIT_Session::session();
540     QList<SUIT_Application*> aAppList = aSession->applications();
541     bool isAlreadyOpen = false;
542     SalomeApp_Application* aApp = 0;
543     for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
544           it != aAppList.end() && !isAlreadyOpen; ++it ) {
545       aApp = dynamic_cast<SalomeApp_Application*>( *it );
546       if ( aApp && aApp->activeStudy()->studyName() == aName )
547         isAlreadyOpen = true;
548     }
549     if ( !isAlreadyOpen ) {
550       aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
551       if ( aApp )
552         res = aApp->useStudy( aName );
553     }
554     else {
555       aApp->desktop()->activateWindow();
556     }
557   }
558
559   return res;
560 }
561
562 /*!SLOT. Parse message for desktop.*/
563 void SalomeApp_Application::onDesktopMessage( const QString& message )
564 {
565   if (message.indexOf("simanCheckoutDone ") == 0) {
566 #ifdef WITH_SIMANIO
567     // Load document with a name, specified in aMessage.
568     onLoadDoc(message.section(' ', 1));
569 #else
570     printf( "****************************************************************\n" );
571     printf( "*    Warning: SALOME is built without SIMAN support.\n" );
572     printf( "****************************************************************\n" );
573 #endif
574   }
575   else if (message.indexOf("studyCreated:") == 0) {
576     // Enable 'Connect' action
577     updateCommandsStatus();
578   }
579   else if (message.indexOf("studyClosed:") == 0) {
580     /* message also contains ID of the closed study,
581        but as soon as SALOME is mono-study application for the moment,
582        this ID is not needed now.*/
583     //long aStudyId = message.section(':', 1).toLong();
584     // Disconnect GUI from active study, because it was closed on DS side.
585     closeActiveDoc( false );
586     // Disable 'Connect' action
587     QAction* a = action( ConnectId );
588     if ( a )
589       a->setEnabled( false );
590   }
591   else if ( message.toLower() == "connect_to_study" ) {
592     onLoadDoc();
593   }
594   LightApp_Application::onDesktopMessage( message );
595 }
596
597 /*!SLOT. Copy objects to study maneger from selection maneger..*/
598 void SalomeApp_Application::onCopy()
599 {
600   SALOME_ListIO list;
601   LightApp_SelectionMgr* mgr = selectionMgr();
602   mgr->selectedObjects(list);
603
604   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
605   if(study == NULL) return;
606
607   _PTR(Study) stdDS = study->studyDS();
608   if(!stdDS) return;
609
610   SALOME_ListIteratorOfListIO it( list );
611   if(it.More())
612     {
613       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
614       try {
615         studyMgr()->Copy(so);
616         onSelectionChanged();
617       }
618       catch(...) {
619       }
620     }
621 }
622
623 /*!SLOT. Paste objects to study maneger from selection manager.*/
624 void SalomeApp_Application::onPaste()
625 {
626   SALOME_ListIO list;
627   LightApp_SelectionMgr* mgr = selectionMgr();
628   mgr->selectedObjects(list);
629
630   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
631   if(study == NULL) return;
632
633   _PTR(Study) stdDS = study->studyDS();
634   if(!stdDS) return;
635
636   if ( stdDS->GetProperties()->IsLocked() ) {
637     SUIT_MessageBox::warning( desktop(),
638                               QObject::tr("WRN_WARNING"),
639                               QObject::tr("WRN_STUDY_LOCKED") );
640     return;
641   }
642
643   SALOME_ListIteratorOfListIO it( list );
644   if(it.More())
645     {
646       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
647       try {
648         studyMgr()->Paste(so);
649         updateObjectBrowser( true );
650         updateActions(); //SRN: BugID IPAL9377, case 3
651       }
652       catch(...) {
653       }
654     }
655 }
656
657 /*!Check the application on closing.
658  * \retval true if possible, else false
659  */
660 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
661 {
662   return LightApp_Application::isPossibleToClose( closePermanently );
663 }
664
665 /*! Check if the study is locked */
666 void SalomeApp_Application::onCloseDoc( bool ask )
667 {
668   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
669
670   if (study != NULL) {
671     _PTR(Study) stdDS = study->studyDS();
672     if(stdDS && stdDS->IsStudyLocked()) {
673       if ( SUIT_MessageBox::question( desktop(),
674                                       QObject::tr( "WRN_WARNING" ),
675                                       QObject::tr( "CLOSE_LOCKED_STUDY" ),
676                                       SUIT_MessageBox::Yes | SUIT_MessageBox::No,
677                                       SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
678
679     }
680   }
681   LightApp_Application::onCloseDoc( ask );
682 }
683
684 /*!Sets enable or disable some actions on selection changed.*/
685 void SalomeApp_Application::onSelectionChanged()
686 {
687    SALOME_ListIO list;
688    LightApp_SelectionMgr* mgr = selectionMgr();
689    mgr->selectedObjects(list);
690
691    bool canCopy  = false;
692    bool canPaste = false;
693
694    LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
695
696    if ( m ) {
697      canCopy  = m->canCopy();
698      canPaste = m->canPaste();
699    }
700
701    SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
702    if (study) {
703      _PTR(Study) stdDS = study->studyDS();
704
705      if (stdDS) {
706        SALOME_ListIteratorOfListIO it ( list );
707
708        if (it.More() && list.Extent() == 1) {
709          _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
710
711          if ( so ) {
712            canCopy  = canCopy  || studyMgr()->CanCopy(so);
713            canPaste = canPaste || studyMgr()->CanPaste(so);
714          }
715        }
716      }
717    }
718
719    action(EditCopyId)->setEnabled(canCopy);
720    action(EditPasteId)->setEnabled(canPaste);
721 }
722
723 /*!Delete references.*/
724 void SalomeApp_Application::onDeleteInvalidReferences()
725 {
726   SALOME_ListIO aList;
727   LightApp_SelectionMgr* mgr = selectionMgr();
728   mgr->selectedObjects( aList, QString(), false );
729
730   if( aList.IsEmpty() )
731     return;
732
733   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
734   _PTR(Study) aStudyDS = aStudy->studyDS();
735   _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
736   _PTR(SObject) anObj;
737
738   for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
739     if ( it.Value()->hasEntry() )
740     {
741       _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
742       while( aRefObj && aRefObj->ReferencedObject( anObj ) )
743         aRefObj = anObj;
744
745       if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
746          aStudyBuilder->RemoveReference( aSObject );
747     }
748   updateObjectBrowser();
749 }
750
751 /*!Private SLOT. */
752 void SalomeApp_Application::onOpenWith()
753 {
754   QApplication::setOverrideCursor( Qt::WaitCursor );
755   SALOME_ListIO aList;
756   LightApp_SelectionMgr* mgr = selectionMgr();
757   mgr->selectedObjects(aList);
758   if (aList.Extent() != 1)
759     {
760       QApplication::restoreOverrideCursor();
761       return;
762     }
763   Handle(SALOME_InteractiveObject) aIObj = aList.First();
764   QString aModuleName(aIObj->getComponentDataType());
765   QString aModuleTitle = moduleTitle(aModuleName);
766   activateModule(aModuleTitle);
767   QApplication::restoreOverrideCursor();
768 }
769
770 /*!
771   Creates new study
772 */
773 SUIT_Study* SalomeApp_Application::createNewStudy()
774 {
775   SalomeApp_Study* aStudy = new SalomeApp_Study( this );
776
777   // Set up processing of major study-related events
778   connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
779   connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
780   connect( aStudy, SIGNAL( saved  ( SUIT_Study* ) ), this, SLOT( onStudySaved  ( SUIT_Study* ) ) );
781   connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
782
783 #ifndef DISABLE_PYCONSOLE
784   //to receive signal in application that NoteBook's variable was modified
785   connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
786            this, SIGNAL(notebookVarUpdated(QString)) );
787 #endif
788
789   return aStudy;
790 }
791
792 /*!
793   Enable/Disable menu items and toolbar buttons. Rebuild menu
794 */
795 void SalomeApp_Application::updateCommandsStatus()
796 {
797   LightApp_Application::updateCommandsStatus();
798
799   // Dump study menu
800   QAction* a = action( DumpStudyId );
801   if ( a )
802     a->setEnabled( activeStudy() );
803
804   // Load script menu
805   a = action( LoadScriptId );
806   if( a )
807     a->setEnabled( pythonConsole() );
808
809   // Properties menu
810   a = action( PropertiesId );
811   if( a )
812     a->setEnabled( activeStudy() );
813
814   // Save GUI state menu
815   a = action( SaveGUIStateId );
816   if( a )
817     a->setEnabled( activeStudy() );
818
819   // Connect study menu
820   a = action( ConnectId );
821   if( a )
822     a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
823
824   // Disconnect study menu
825   a = action( DisconnectId );
826   if( a )
827     a->setEnabled( activeStudy() );
828
829   // update state of Copy/Paste menu items
830   onSelectionChanged();
831 }
832
833 /*!
834   \class DumpStudyFileDlg
835   Private class used in Dump Study operation.  Consists 2 check boxes:
836   "Publish in study" and "Save GUI parameters"
837 */
838 class DumpStudyFileDlg : public SUIT_FileDlg
839 {
840 public:
841   DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
842   {
843     QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
844     if ( grid )
845     {
846       QWidget *hB = new QWidget( this );
847       myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
848       myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
849       mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
850
851       QHBoxLayout *layout = new QHBoxLayout;
852       layout->addWidget(myPublishChk);
853       layout->addWidget(myMultiFileChk);
854       layout->addWidget(mySaveGUIChk);
855       hB->setLayout(layout);
856
857       QPushButton* pb = new QPushButton(this);
858
859       int row = grid->rowCount();
860       grid->addWidget( new QLabel("", this), row, 0 );
861       grid->addWidget( hB, row, 1, 1, 3 );
862       grid->addWidget( pb, row, 5 );
863
864       pb->hide();
865     }
866   }
867   QCheckBox* myPublishChk;
868   QCheckBox* myMultiFileChk;
869   QCheckBox* mySaveGUIChk;
870 };
871
872 class DumpStudyFileValidator : public SUIT_FileValidator
873 {
874  public:
875   DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
876   virtual ~DumpStudyFileValidator() {};
877   virtual bool canSave( const QString& file, bool permissions );
878 };
879
880 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
881 {
882   QFileInfo fi( file );
883   if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
884     SUIT_MessageBox::critical( parent(),
885                                QObject::tr("WRN_WARNING"),
886                                QObject::tr("WRN_FILE_NAME_BAD") );
887     return false;
888   }
889   return SUIT_FileValidator::canSave( file, permissions);
890 }
891
892 /*!Private SLOT. On dump study.*/
893 void SalomeApp_Application::onDumpStudy( )
894 {
895   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
896   if ( !appStudy ) return;
897   _PTR(Study) aStudy = appStudy->studyDS();
898
899   QStringList aFilters;
900   aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
901
902   bool anIsPublish = true;
903   bool anIsMultiFile = false;
904   bool anIsSaveGUI = true;
905
906   if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
907     anIsPublish   = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
908     anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
909     anIsSaveGUI   = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
910   }
911
912   DumpStudyFileDlg fd( desktop() );
913   fd.setValidator( new DumpStudyFileValidator( &fd ) );
914   fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
915   fd.setFilters( aFilters );
916   fd.myPublishChk->setChecked( anIsPublish );
917   fd.myMultiFileChk->setChecked( anIsMultiFile );
918   fd.mySaveGUIChk->setChecked( anIsSaveGUI );
919   if ( fd.exec() == QDialog::Accepted )
920   {
921     QString aFileName = fd.selectedFile();
922
923     bool toPublish = fd.myPublishChk->isChecked();
924     bool isMultiFile = fd.myMultiFileChk->isChecked();
925     bool toSaveGUI = fd.mySaveGUIChk->isChecked();
926
927     if ( !aFileName.isEmpty() ) {
928       QFileInfo aFileInfo(aFileName);
929       if( aFileInfo.isDir() ) // IPAL19257
930         return;
931
932       // Issue 21377 - dump study implementation moved to SalomeApp_Study class
933       bool res;
934       {
935         SUIT_OverrideCursor wc;
936         res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
937       }
938       if ( !res )
939         SUIT_MessageBox::warning( desktop(),
940                                   QObject::tr("WRN_WARNING"),
941                                   tr("WRN_DUMP_STUDY_FAILED") );
942     }
943   }
944 }
945
946 /*!Private SLOT. On load script.*/
947 void SalomeApp_Application::onLoadScript( )
948 {
949   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
950   if ( appStudy ) {
951     _PTR(Study) aStudy = appStudy->studyDS();
952     if ( aStudy->GetProperties()->IsLocked() ) {
953       SUIT_MessageBox::warning( desktop(),
954                                 QObject::tr("WRN_WARNING"),
955                                 QObject::tr("WRN_STUDY_LOCKED") );
956       return;
957     }
958   }
959
960   QStringList filtersList;
961   filtersList.append(tr("PYTHON_FILES_FILTER"));
962   filtersList.append(tr("ALL_FILES_FILTER"));
963
964   QString anInitialPath = "";
965   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
966     anInitialPath = QDir::currentPath();
967   
968 #ifdef WITH_SIMANIO
969   // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
970   if (myIsSiman) {
971     SALOMEDSClient_StudyManager* aMgr = studyMgr();
972     aMgr->GetSimanStudy()->StudyId();
973     anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() + 
974       aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
975       aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
976   }
977 #endif
978
979   QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
980
981   if ( !aFile.isEmpty() )
982   {
983     QString command = QString("execfile(r\"%1\")").arg(aFile);
984
985 #ifndef DISABLE_PYCONSOLE
986     PyConsole_Console* pyConsole = pythonConsole();
987
988     if ( pyConsole )
989       pyConsole->exec( command );
990 #endif
991   }
992 }
993
994 /*!Private SLOT. On save GUI state.*/
995 void SalomeApp_Application::onSaveGUIState()
996 {
997   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
998   if ( study ) {
999     SalomeApp_VisualState( this ).storeState();
1000     updateSavePointDataObjects( study );
1001     updateObjectBrowser();
1002   }
1003   updateActions();
1004 }
1005
1006 /*!Public SLOT. On SIMAN check in operation.*/
1007 void SalomeApp_Application::onCheckIn()
1008 {
1009 #ifdef WITH_SIMANIO
1010   setMenuShown(SimanCheckInId, false); // check in may be performed only once
1011   setMenuShown(SimanLocalCheckInId, false);
1012   SALOMEDSClient_StudyManager* aMgr = studyMgr();
1013   aMgr->GetSimanStudy()->CheckIn("");
1014 #else
1015   printf( "****************************************************************\n" );
1016   printf( "*    Warning: SALOME is built without SIMAN support.\n" );
1017   printf( "****************************************************************\n" );
1018 #endif
1019 }
1020
1021 /*!Public SLOT. On SIMAN local check in operation.*/
1022 void SalomeApp_Application::onLocalCheckIn()
1023 {
1024 #ifdef WITH_SIMANIO
1025   // get the active module
1026   CAM_Module* aModule = activeModule();
1027   if (!aModule) return; // there is no active module
1028   
1029   setMenuShown(SimanCheckInId, false); // check in may be performed only once
1030   setMenuShown(SimanLocalCheckInId, false);
1031   SALOMEDSClient_StudyManager* aMgr = studyMgr();
1032   aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1033 #else
1034   printf( "****************************************************************\n" );
1035   printf( "*    Warning: SALOME is built without SIMAN support.\n" );
1036   printf( "****************************************************************\n" );
1037 #endif
1038 }
1039
1040 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1041 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1042 {
1043   LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1044   QAction* send = ::qobject_cast<QAction*>( sender() );
1045   if ( !send )
1046     return;
1047   QString aWinName = send->data().toString();
1048   if ( theIsVisible && aWinName == "objectBrowser" )
1049     objectBrowserColumnsVisibility();
1050 }
1051
1052 /*!Gets file filter.
1053  *\retval QString "(*.hdf)"
1054  */
1055 QString SalomeApp_Application::getFileFilter() const
1056 {
1057   return "(*.hdf)";
1058 }
1059
1060 /*!Create window.*/
1061 QWidget* SalomeApp_Application::createWindow( const int flag )
1062 {
1063   QWidget* wid = 0;
1064 #ifndef DISABLE_PYCONSOLE
1065   if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1066 #else
1067   wid = LightApp_Application::createWindow(flag);
1068 #endif
1069
1070   SUIT_ResourceMgr* resMgr = resourceMgr();
1071
1072   if ( flag == WT_ObjectBrowser )
1073   {
1074     SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1075     if ( ob ) {
1076       // temporary commented
1077       //ob->setUpdater( new SalomeApp_Updater() );
1078
1079 #ifdef WITH_SALOMEDS_OBSERVER
1080       //do not activate the automatic update of Qt tree through signal/slot
1081       ob->setAutoUpdate(false);
1082       //activate update of modified objects only
1083       ob->setUpdateModified(true);
1084 #endif
1085
1086       connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1087
1088       QString
1089         ValueCol = QObject::tr( "VALUE_COLUMN" ),
1090         IORCol = QObject::tr( "IOR_COLUMN" ),
1091         RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1092         EntryCol = QObject::tr( "ENTRY_COLUMN" );
1093
1094       SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1095       treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1096       treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1097       treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1098       treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1099       treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1100       treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1101       treeModel->setAppropriate( IORCol, Qtx::Toggled );
1102       treeModel->setAppropriate( RefCol, Qtx::Toggled );
1103
1104       bool autoSize      = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1105       bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1106       bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1107
1108       ob->setAutoSizeFirstColumn(autoSizeFirst);
1109       ob->setAutoSizeColumns(autoSize);
1110       ob->setResizeOnExpandItem(resizeOnExpandItem);
1111       ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1112
1113       // temporary commented
1114       /*
1115       for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1116       {
1117       ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1118       ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1119                                                     QString().sprintf( "visibility_column_%d", i ), true ) );
1120       }
1121       */
1122
1123       // temporary commented
1124       /*
1125         ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1126         ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1127         ob->resize( desktop()->width()/3, ob->height() );
1128       */
1129     }
1130   }
1131 #ifndef DISABLE_PYCONSOLE
1132   else if ( flag == WT_PyConsole )
1133   {
1134     PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1135     pyCons->setObjectName( "pythonConsole" );
1136     pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1137     pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1138     pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1139     pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1140     wid = pyCons;
1141     //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1142     pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1143   }
1144   else if ( flag == WT_NoteBook )
1145   {
1146     SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1147     if ( appStudy ) {
1148       _PTR(Study) aStudy = appStudy->studyDS();
1149       setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1150       //to receive signal in NoteBook that it's variable was modified
1151       connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1152                getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1153     }
1154     wid = getNoteBook();
1155     wid->setObjectName( "noteBook" );
1156   }
1157 #endif
1158   return wid;
1159 }
1160
1161 /*!Create preferences.*/
1162 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1163 {
1164   LightApp_Application::createPreferences(pref);
1165
1166   if ( !pref )
1167     return;
1168
1169   int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1170   int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1171   int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1172   for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1173   {
1174     pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1175                          LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1176   }
1177   pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1178
1179   // adding preference to LightApp_Application handled preferences..  a bit of hacking with resources..
1180   int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1181   int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1182   pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1183   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1184   pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1185   pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1186   pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1187   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1188   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1189 }
1190
1191 /*!Update desktop title.*/
1192 void SalomeApp_Application::updateDesktopTitle() {
1193   QString aTitle = applicationName();
1194   QString aVer = applicationVersion();
1195   if ( !aVer.isEmpty() )
1196     aTitle += QString( " " ) + aVer;
1197
1198   if ( activeStudy() )
1199   {
1200     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1201     if ( !sName.isEmpty() ) {
1202       SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1203       if ( study ) {
1204         _PTR(Study) stdDS = study->studyDS();
1205         if(stdDS) {
1206           if ( stdDS->GetProperties()->IsLocked() ) {
1207             aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1208           } else {
1209             aTitle += QString( " - [%1]" ).arg( sName );
1210           }
1211         }
1212       }
1213     }
1214   }
1215
1216   desktop()->setWindowTitle( aTitle );
1217 }
1218
1219 int SalomeApp_Application::closeChoice( const QString& docName )
1220 {
1221   QStringList buttons;
1222   QMap<int, int> choices;
1223   int idx = 0;
1224   buttons << tr ("APPCLOSE_SAVE");                // Save & Close
1225   choices.insert( idx++, CloseSave );             // ...
1226   buttons << tr ("APPCLOSE_CLOSE");               // Close w/o saving
1227   choices.insert( idx++, CloseDiscard );          // ...
1228   if ( myIsCloseFromExit ) {
1229     buttons << tr ("APPCLOSE_UNLOAD_SAVE");       // Save & Disconnect
1230     choices.insert( idx++, CloseDisconnectSave );     // ...
1231     buttons << tr ("APPCLOSE_UNLOAD");            // Disconnect
1232     choices.insert( idx++, CloseDisconnect );         // ...
1233   }
1234   buttons << tr ("APPCLOSE_CANCEL");              // Cancel
1235   choices.insert( idx++, CloseCancel );           // ...
1236
1237   int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1238                                           tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1239   return choices[answer];
1240 }
1241
1242 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1243 {
1244   bool res = true;
1245   switch( choice )
1246   {
1247   case CloseSave:
1248     if ( activeStudy()->isSaved() )
1249       onSaveDoc();
1250     else if ( !onSaveAsDoc() )
1251       res = false;
1252     break;
1253   case CloseDiscard:
1254     break;
1255   case CloseDisconnectSave:
1256     if ( activeStudy()->isSaved() )
1257       onSaveDoc();
1258     else if ( !onSaveAsDoc() )
1259       res = false;
1260   case CloseDisconnect:
1261     closeActiveDoc( false );
1262     closePermanently = false;
1263     break;
1264   case CloseCancel:
1265   default:
1266     res = false;
1267   }
1268   return res;
1269 }
1270
1271 int SalomeApp_Application::openChoice( const QString& aName )
1272 {
1273   int choice = LightApp_Application::openChoice( aName );
1274
1275   if ( QFileInfo( aName ).exists() ) {
1276     if ( choice == OpenNew ) { // The document isn't already open.
1277       bool exist = false;
1278       std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1279       for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1280         if ( aName == QString( lst[i].c_str() ) )
1281           exist = true;
1282       }
1283       // The document already exists in the study manager.
1284       // Do you want to reload it?
1285       if ( exist ) {
1286         int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1287                                                 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1288         if ( answer == SUIT_MessageBox::Yes )
1289           choice = OpenRefresh;
1290         else
1291           choice = OpenCancel;
1292       }
1293     }
1294   } else { // file is not exist on disk
1295     SUIT_MessageBox::warning( desktop(),
1296                               QObject::tr("WRN_WARNING"),
1297                               QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1298     return false;
1299   }
1300
1301   return choice;
1302 }
1303
1304 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1305 {
1306   bool res = false;
1307   int choice = aChoice;
1308   switch ( choice )
1309   {
1310   case OpenRefresh:
1311     {
1312       _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1313       if ( aStudy )
1314       {
1315         studyMgr()->Close( aStudy );
1316         choice = OpenNew;
1317       }
1318     }
1319   default:
1320     res = LightApp_Application::openAction( choice, aName );
1321     break;
1322   }
1323
1324   return res;
1325 }
1326
1327 /*!
1328   \brief Get map of the operations which can be performed
1329   on the module activation.
1330
1331   The method should return the map of the kind \c {<id>:<name>}
1332   where \c <id> is an integer identifier of the operation and
1333   \c <name> is a title for the button to be added to the
1334   dialog box. After user selects the required operation by the
1335   clicking the corresponding button in the dialog box, its identifier
1336   is passed to the moduleActionSelected() method to process
1337   the made choice.
1338
1339   \return map of the operations
1340   \sa moduleActionSelected()
1341 */
1342 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1343 {
1344   QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1345
1346   opmap.insert( LoadStudyId,     tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1347
1348   opmap.insert( NewAndScriptId,  tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1349   return opmap;
1350 }
1351
1352 /*!
1353   \brief Called when the used selectes required operation chosen
1354   from "Activate module" dialog box.
1355
1356   Performs the required operation according to the user choice.
1357
1358   \param id operation identifier
1359   \sa activateModuleActions()
1360 */
1361 void SalomeApp_Application::moduleActionSelected( const int id )
1362 {
1363   switch ( id ) {
1364   case LoadStudyId:
1365     onLoadDoc();
1366     break;
1367   case NewAndScriptId:
1368     onNewWithScript();
1369     break;
1370   default:
1371     LightApp_Application::moduleActionSelected( id );
1372     break;
1373   }
1374 }
1375
1376 /*!Gets CORBA::ORB_var*/
1377 CORBA::ORB_var SalomeApp_Application::orb()
1378 {
1379   ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1380   static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1381   return _orb;
1382 }
1383
1384 /*!Create and return SALOMEDS_StudyManager.*/
1385 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1386 {
1387   static _PTR(StudyManager) _sm;
1388   if(!_sm) _sm = ClientFactory::StudyManager();
1389   return _sm.get();
1390 }
1391
1392 /*!Create and return SALOME_NamingService.*/
1393 SALOME_NamingService* SalomeApp_Application::namingService()
1394 {
1395   static SALOME_NamingService _ns(orb());
1396   return &_ns;
1397 }
1398
1399 /*!Create and return SALOME_LifeCycleCORBA.*/
1400 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1401 {
1402   static SALOME_LifeCycleCORBA _lcc( namingService() );
1403   return &_lcc;
1404 }
1405
1406 /*!Private SLOT. On preferences.*/
1407 void SalomeApp_Application::onProperties()
1408 {
1409   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1410   if( !study )
1411     return;
1412
1413   _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1414   SB->NewCommand();
1415
1416   SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1417   int res = aDlg.exec();
1418   if( res==QDialog::Accepted && aDlg.isChanged() )
1419     SB->CommitCommand();
1420   else
1421     SB->AbortCommand();
1422
1423   //study->updateCaptions();
1424   updateDesktopTitle();
1425   updateActions();
1426 }
1427
1428 /*!Insert items in popup, which necessary for current application*/
1429 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1430 {
1431   LightApp_SelectionMgr* mgr = selectionMgr();
1432   bool cacheIsOn = mgr->isSelectionCacheEnabled();
1433   mgr->setSelectionCacheEnabled( true );
1434
1435   LightApp_Application::contextMenuPopup( type, thePopup, title );
1436
1437   // temporary commented
1438   /*OB_Browser* ob = objectBrowser();
1439   if ( !ob || type != ob->popupClientType() )
1440     return;*/
1441
1442   // Get selected objects
1443   SALOME_ListIO aList;
1444   mgr->selectedObjects( aList, QString(), false );
1445
1446   // add GUI state commands: restore, rename
1447   if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1448        QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1449     thePopup->addSeparator();
1450     thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1451     thePopup->addAction( tr( "MEN_RENAME_VS" ),  objectBrowser(),
1452                          SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1453     thePopup->addAction( tr( "MEN_DELETE_VS" ),  this, SLOT( onDeleteGUIState() ) );
1454   }
1455
1456   // "Delete reference" item should appear only for invalid references
1457
1458   // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1459   bool isInvalidRefs = false;
1460   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1461   if ( aStudy ) {
1462     _PTR(Study) aStudyDS = aStudy->studyDS();
1463     _PTR(SObject) anObj;
1464     
1465     for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1466     {
1467       if( it.Value()->hasEntry() )
1468       {
1469         _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1470         while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1471           aRefObj = anObj;
1472         
1473         if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1474           isInvalidRefs = true;
1475       }
1476     }
1477     
1478     // Add "Delete reference" item to popup
1479     if ( isInvalidRefs )
1480     {
1481       thePopup->addSeparator();
1482       thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1483       return;
1484     }
1485
1486     // "Activate module" item should appear only if it's necessary
1487     if ( aList.Extent() == 1 ) {
1488       aList.Clear();
1489       mgr->selectedObjects( aList );
1490       
1491       Handle(SALOME_InteractiveObject) aIObj = aList.First();
1492       
1493       // add extra popup menu (defined in XML)
1494       if ( myExtActions.size() > 0 ) {
1495         // Use only first selected object
1496         SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1497         if ( study ) {
1498           _PTR(Study) stdDS = study->studyDS();
1499           if ( stdDS ) {
1500             _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1501             if ( aSO ) {
1502               _PTR( GenericAttribute ) anAttr;
1503               std::string auid = "AttributeUserID";
1504               auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1505               if ( aSO->FindAttribute( anAttr, auid ) ) {
1506                 _PTR(AttributeUserID) aAttrID = anAttr;
1507                 QString aId = aAttrID->Value().c_str();
1508                 if ( myExtActions.contains( aId ) ) {
1509                   thePopup->addAction(myExtActions[aId]);
1510                 }
1511               }
1512             }
1513           }
1514         }
1515       }
1516       
1517       // check if item is a "GUI state" item (also a first level object)
1518       QString entry( aIObj->getEntry() );
1519       if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1520         QString aModuleName( aIObj->getComponentDataType() );
1521         QString aModuleTitle = moduleTitle( aModuleName );
1522         CAM_Module* currentModule = activeModule();
1523         if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1524           thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1525       }
1526     }
1527   }
1528
1529   mgr->setSelectionCacheEnabled( cacheIsOn );
1530 }
1531
1532 /*!Update obect browser:
1533  1.if 'updateModels' true, update existing data models;
1534  2. update "non-existing" (not loaded yet) data models;
1535  3. update object browser if it exists */
1536 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1537 {
1538   // update "non-existing" (not loaded yet) data models
1539   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1540   if ( study )
1541   {
1542     _PTR(Study) stdDS = study->studyDS();
1543     if( stdDS )
1544     {
1545       for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1546       {
1547         _PTR(SComponent) aComponent ( it->Value() );
1548
1549 #ifndef WITH_SALOMEDS_OBSERVER
1550         // with GUI observers this check is not needed anymore
1551         if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1552           continue; // skip the magic "Interface Applicative" component
1553 #endif
1554         if ( !objectBrowser() )
1555           getWindow( WT_ObjectBrowser );
1556         const bool isAutoUpdate = objectBrowser()->autoUpdate();
1557         objectBrowser()->setAutoUpdate( false );
1558         SalomeApp_DataModel::synchronize( aComponent, study );
1559         objectBrowser()->setAutoUpdate( isAutoUpdate );
1560       }
1561     }
1562   }
1563
1564   // create data objects that correspond to GUI state save points
1565   if ( study ) updateSavePointDataObjects( study );
1566
1567   // update existing data models (already loaded SComponents)
1568   LightApp_Application::updateObjectBrowser( updateModels );
1569 }
1570
1571 /*!Display Catalog Genenerator dialog */
1572 void SalomeApp_Application::onCatalogGen()
1573 {
1574   ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1575   aDlg.exec();
1576 }
1577
1578 /*!Display Registry Display dialog */
1579 void SalomeApp_Application::onRegDisplay()
1580 {
1581   CORBA::ORB_var anOrb = orb();
1582   ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1583   regWnd->show();
1584   regWnd->raise();
1585   regWnd->activateWindow();
1586 }
1587
1588 /*!find original object by double click on item */
1589 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1590 {
1591   // Issue 21379: References are supported at LightApp_DataObject level
1592   LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1593
1594   if( obj && obj->isReference() )
1595   {
1596     QString entry = obj->refEntry();
1597
1598     SUIT_DataOwnerPtrList aList;
1599     aList.append( new LightApp_DataOwner( entry ) );
1600     selectionMgr()->setSelected( aList, false );
1601
1602     SUIT_DataBrowser* ob = objectBrowser();
1603
1604     QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1605     if ( !aSelectedIndexes.isEmpty() )
1606       ob->treeView()->scrollTo( aSelectedIndexes.first() );
1607   }
1608 }
1609
1610 /*!
1611   Creates new view manager
1612   \param type - type of view manager
1613 */
1614 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1615 {
1616   return createViewManager(type);
1617 }
1618
1619
1620 /*!Global utility function, returns selected GUI Save point object's ID */
1621 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1622 {
1623   SALOME_ListIO aList;
1624   selMgr->selectedObjects( aList );
1625   if( aList.Extent() > 0 ) {
1626     Handle(SALOME_InteractiveObject) aIObj = aList.First();
1627     QString entry( aIObj->getEntry() );
1628     QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1629     if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1630       return -1;
1631     bool ok; // conversion to integer is ok?
1632     int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1633     return ok ? savePoint : -1;
1634   }
1635   return -1;
1636 }
1637
1638 /*!Called on Restore GUI State popup command*/
1639 void SalomeApp_Application::onRestoreGUIState()
1640 {
1641   int savePoint = ::getSelectedSavePoint( selectionMgr() );
1642   if ( savePoint == -1 )
1643     return;
1644   SalomeApp_VisualState( this ).restoreState( savePoint );
1645 }
1646
1647 /*!Called on Delete GUI State popup command*/
1648 void SalomeApp_Application::onDeleteGUIState()
1649 {
1650   int savePoint = ::getSelectedSavePoint( selectionMgr() );
1651   if ( savePoint == -1 )
1652     return;
1653   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1654   if ( !study )
1655     return;
1656
1657   study->removeSavePoint( savePoint );
1658   updateSavePointDataObjects( study );
1659 }
1660
1661 /*!Called on New study operation*/
1662 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1663 {
1664   LightApp_Application::onStudyCreated( study );
1665
1666 //#ifndef DISABLE_PYCONSOLE
1667 //  desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1668 //                               windowDock( getWindow( WT_ObjectBrowser ) ) );
1669 //#endif
1670
1671   loadDockWindowsState();
1672
1673   objectBrowserColumnsVisibility();
1674 }
1675
1676 /*!Called on Open study operation*/
1677 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1678 {
1679   LightApp_Application::onStudyOpened( study );
1680
1681 //#ifndef DISABLE_PYCONSOLE
1682 //  desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1683 //                               windowDock( getWindow( WT_ObjectBrowser ) ) );
1684 //#endif
1685
1686   loadDockWindowsState();
1687
1688   objectBrowserColumnsVisibility();
1689
1690   // temporary commented
1691   /*if ( objectBrowser() ) {
1692     updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1693     objectBrowser()->updateTree( study->root() );
1694   }*/
1695 }
1696
1697 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1698 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1699 {
1700
1701   SUIT_DataBrowser* ob = objectBrowser();
1702   LightApp_SelectionMgr* selMgr = selectionMgr();
1703
1704   if ( !study || !ob || !selMgr )
1705     return;
1706
1707   // find GUI states root object
1708   SUIT_DataObject* guiRootObj = 0;
1709   DataObjectList ch;
1710   study->root()->children( ch );
1711   DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1712   for ( ; it != last ; ++it ) {
1713     if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1714       guiRootObj = *it;
1715       break;
1716     }
1717   }
1718   std::vector<int> savePoints = study->getSavePoints();
1719   // case 1: no more save points but they existed in study's tree
1720   if ( savePoints.empty() && guiRootObj ) {
1721     //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1722     //    : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1723     const bool isAutoUpdate = ob->autoUpdate();
1724     selMgr->clearSelected();
1725     ob->setAutoUpdate(true);
1726     DataObjectList ch = guiRootObj->children();
1727     for( int i = 0; i < ch.size(); i++ )
1728       delete ch[i];
1729     delete guiRootObj;
1730     ob->setAutoUpdate(isAutoUpdate);
1731     return;
1732   }
1733   // case 2: no more save points but root does not exist either
1734   if ( savePoints.empty() && !guiRootObj )
1735     return;
1736   // case 3: save points but no root for them - create it
1737   if ( !savePoints.empty() && !guiRootObj )
1738     guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1739   // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1740   // to be always the last one in the tree.  Here we check - if it is not the last one - remove and
1741   // re-create it.
1742   if ( guiRootObj->nextBrother() ) {
1743     study->root()->removeChild(guiRootObj);
1744     study->root()->appendChild(guiRootObj);
1745     //study->root()->dump();
1746   }
1747
1748   // store data objects in a map id-to-DataObject
1749   QMap<int,SalomeApp_SavePointObject*> mapDO;
1750   ch.clear();
1751   guiRootObj->children( ch );
1752   for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1753     SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1754     if ( dobj )
1755       mapDO[dobj->getId()] = dobj;
1756   }
1757
1758   // iterate new save points.  if DataObject with such ID not found in map - create DataObject
1759   // if in the map - remove it from map.
1760   for ( int i = 0; i < savePoints.size(); i++ )
1761     if ( !mapDO.contains( savePoints[i] ) )
1762       new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1763     else
1764       mapDO.remove( savePoints[i] );
1765
1766   // delete DataObjects that are still in the map -- their IDs were not found in data model
1767   if( mapDO.size() > 0) {
1768     //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1769     //    : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1770     selMgr->clearSelected();
1771     const bool isAutoUpdate = ob->autoUpdate();
1772     ob->setAutoUpdate(true);
1773     for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1774       delete it.value();
1775     ob->setAutoUpdate(isAutoUpdate);
1776   }
1777 }
1778
1779 /*! Check data object */
1780 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1781 {
1782   if (theObj)
1783     return true;
1784
1785   return false;
1786 }
1787
1788 /*!
1789   Opens other study into active Study. If Study is empty - creates it.
1790   \param theName - name of study
1791 */
1792 bool SalomeApp_Application::useStudy( const QString& theName )
1793 {
1794   createEmptyStudy();
1795   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1796   bool res = false;
1797   if (aStudy)
1798     res = aStudy->loadDocument( theName );
1799   updateDesktopTitle();
1800   updateCommandsStatus();
1801   return res;
1802 }
1803
1804 /*! Show/hide object browser colums according to preferences */
1805 void SalomeApp_Application::objectBrowserColumnsVisibility()
1806 {
1807   if ( objectBrowser() )
1808     for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1809     {
1810       bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1811       objectBrowser()->treeView()->setColumnHidden( i, !shown );
1812     }
1813 }
1814
1815 #ifndef DISABLE_PYCONSOLE
1816 /*! Set SalomeApp_NoteBook pointer */
1817 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1818 {
1819   myNoteBook = theNoteBook;
1820 }
1821
1822 /*! Return SalomeApp_NoteBook pointer */
1823 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1824 {
1825   return myNoteBook;
1826 }
1827 #endif
1828
1829 /*!
1830  * Define extra actions defined in module definition XML file.
1831  * Additional popup items sections can be defined by parameter "popupitems".
1832  * Supported attributes:
1833  * title - title of menu item,
1834  * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1835  * method - method which has to be called when menu item is selected
1836  * Example:
1837  * <section name="MODULENAME">
1838  *   <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1839  * </section>
1840  * <section name="importmed">
1841  *   <parameter name="title" value="My menu"/>
1842  *   <parameter name="objectid" value="VISU.Result"/>
1843  *   <parameter name="method" value="nameOfModuleMethod"/>
1844  * </section>
1845  */
1846 void SalomeApp_Application::createExtraActions()
1847 {
1848   myExtActions.clear();
1849   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1850
1851   QStringList aModules;
1852   modules(aModules, false);
1853   foreach(QString aModile, aModules) {
1854     QString aModName = moduleName(aModile);
1855     QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1856     if (!aSectionStr.isNull()) {
1857       QStringList aSections = aSectionStr.split(':');
1858       foreach(QString aSection, aSections) {
1859         QString aTitle = resMgr->stringValue(aSection, "title",    QString());
1860         QString aId    = resMgr->stringValue(aSection, "objectid", QString());
1861         QString aSlot  = resMgr->stringValue(aSection, "method",   QString());
1862         if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1863           continue;
1864
1865         QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1866         if (aModuleName.isNull())
1867           aModuleName = aModName;
1868
1869         QAction* aAction = new QAction(aTitle, this);
1870         QStringList aData;
1871         aData<<aModuleName<<aSlot;
1872         aAction->setData(aData);
1873         connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1874         myExtActions[aId] = aAction;
1875       }
1876     }
1877   }
1878 }
1879
1880 /*!
1881  * Called when extra action is selected
1882  */
1883 void SalomeApp_Application::onExtAction()
1884 {
1885   QAction* aAction = ::qobject_cast<QAction*>(sender());
1886   if (!aAction)
1887     return;
1888
1889   QVariant aData = aAction->data();
1890   QStringList aDataList = aData.value<QStringList>();
1891   if (aDataList.size() != 2)
1892     return;
1893
1894   LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1895   SALOME_ListIO aListIO;
1896   aSelectionMgr->selectedObjects(aListIO);
1897   const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1898   if (aListIO.Extent() < 1)
1899     return;
1900   if (!anIO->hasEntry())
1901     return;
1902
1903   QString aEntry(anIO->getEntry());
1904
1905   QApplication::setOverrideCursor( Qt::WaitCursor );
1906   QString aModuleTitle = moduleTitle(aDataList[0]);
1907   activateModule(aModuleTitle);
1908   QApplication::restoreOverrideCursor();
1909
1910   QCoreApplication::processEvents();
1911
1912   CAM_Module* aModule = activeModule();
1913   if (!aModule)
1914     return;
1915
1916   if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1917     printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1918 }
1919
1920 /*!
1921   Checks that an object can be renamed.
1922   \param entry entry of the object
1923   \brief Return \c true if object can be renamed
1924 */
1925 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1926 {
1927   return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1928 }
1929
1930 /*!
1931   Rename object by entry.
1932   \param entry entry of the object
1933   \param name new name of the object
1934   \brief Return \c true if rename operation finished successfully, \c false otherwise.
1935 */
1936 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1937 {
1938   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1939
1940   int savePoint = ::getSelectedSavePoint( selectionMgr() );
1941
1942   if(!aStudy || savePoint == -1)
1943     return false;
1944
1945   if ( !name.isNull() && !name.isEmpty() ) {
1946     aStudy->setNameOfSavePoint( savePoint, name );
1947     updateSavePointDataObjects( aStudy );
1948
1949     //Mark study as modified
1950     aStudy->Modified();
1951     return true;
1952   }
1953   return false;
1954 }
1955
1956 #ifndef DISABLE_PYCONSOLE
1957 //============================================================================
1958 /*! Function : onUpdateStudy
1959  *  Purpose  : Slot to update the study.
1960  */
1961 //============================================================================
1962 void SalomeApp_Application::onUpdateStudy()
1963 {
1964   QApplication::setOverrideCursor( Qt::WaitCursor );
1965
1966   if( !updateStudy() )
1967     SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1968
1969   QApplication::restoreOverrideCursor();
1970 }
1971
1972 //============================================================================
1973 /*! Function : updateStudy
1974  *  Purpose  : Update study by dumping the study to Python script and loading it.
1975  *             It is used to apply variable modifications done in NoteBook to created objects.
1976  */
1977 //============================================================================
1978 bool SalomeApp_Application::updateStudy()
1979 {
1980   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1981   if ( !study || !myNoteBook )
1982     return false;
1983
1984   myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1985   myNoteBook->setDumpedStudyName( study->studyName() );
1986
1987   _PTR(Study) studyDS = study->studyDS();
1988
1989   // get unique temporary directory name
1990   QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1991   if( aTmpDir.isEmpty() )
1992     return false;
1993
1994   if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1995     aTmpDir.remove( aTmpDir.length() - 1, 1 );
1996
1997   // dump study to the temporary directory
1998   QString aScriptName( "notebook" );
1999   bool toPublish = true;
2000   bool isMultiFile = false;
2001   bool toSaveGUI = true;
2002
2003   int savePoint;
2004   _PTR(AttributeParameter) ap;
2005   _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2006   if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2007   if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2008     ip->setDumpPython(studyDS);
2009     savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2010   }
2011   bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2012   if ( toSaveGUI )
2013     study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2014
2015   if( ok )
2016     myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2017   else
2018     return false;
2019
2020   QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2021   int anIndex = aList.indexOf( this );
2022
2023   // Disconnect dialog from application desktop in case if:
2024   // 1) Application is not the first application in the session
2025   // 2) Application is the first application in session but not the only.
2026   bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2027   if( changeDesktop ) {
2028
2029     SalomeApp_Application* app = this;
2030     if( anIndex > 0 && anIndex < aList.count() )
2031       app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2032     else if(anIndex == 0 && aList.count() > 1)
2033       app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2034
2035     if( !app )
2036       return false;
2037
2038     // creation a new study and restoring will be done in another application
2039     connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2040              app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2041   }
2042
2043   QString aDumpScript = myNoteBook->getDumpedStudyScript();
2044   QString aStudyName = myNoteBook->getDumpedStudyName();
2045   bool isStudySaved = myNoteBook->isDumpedStudySaved();
2046   // clear a study (delete all objects)
2047   onCloseDoc( false );
2048
2049   if( !changeDesktop ) {
2050     ok = onRestoreStudy( aDumpScript,
2051                          aStudyName,
2052                          isStudySaved );
2053   }
2054
2055   return ok;
2056 }
2057 #endif
2058
2059 //============================================================================
2060 /*! Function : onRestoreStudy
2061  *  Purpose  : Load the dumped study from Python script
2062  */
2063 //============================================================================
2064 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2065                                             const QString& theStudyName,
2066                                             bool theIsStudySaved )
2067 {
2068   bool ok = true;
2069
2070   // create a new study
2071   onNewDoc();
2072
2073   // get active application
2074   SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2075
2076   // load study from the temporary directory
2077   QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2078
2079 #ifndef DISABLE_PYCONSOLE
2080   PyConsole_Console* pyConsole = app->pythonConsole();
2081   if ( pyConsole )
2082     pyConsole->execAndWait( command );
2083 #endif
2084
2085   // remove temporary directory
2086   QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2087   QString aStudyName = aScriptInfo.baseName();
2088   QDir aDir = aScriptInfo.absoluteDir();
2089   QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2090   for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2091     ok = aDir.remove( *it ) && ok;
2092   if( ok )
2093     ok = aDir.rmdir( aDir.absolutePath() );
2094
2095   if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2096   {
2097 #ifndef DISABLE_PYCONSOLE
2098     _PTR(Study) aStudyDS = newStudy->studyDS();
2099     app->getNoteBook()->Init( aStudyDS );
2100     newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2101     newStudy->Modified();
2102     updateDesktopTitle();
2103     updateActions();
2104 #endif
2105   }
2106   else
2107     ok = false;
2108
2109   return ok;
2110 }
2111
2112 /*!
2113   Close the Application
2114 */
2115 void SalomeApp_Application::afterCloseDoc()
2116 {
2117 #ifndef DISABLE_PYCONSOLE
2118   // emit signal to restore study from Python script
2119   if ( myNoteBook ) {
2120     emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2121                             myNoteBook->getDumpedStudyName(),
2122                             myNoteBook->isDumpedStudySaved() );
2123   }
2124 #endif
2125   LightApp_Application::afterCloseDoc();
2126 }
2127
2128 /*
2129   Asks to close existing document.
2130 */
2131 bool SalomeApp_Application::checkExistingDoc()
2132 {
2133   bool result = LightApp_Application::checkExistingDoc();
2134   if ( result && !activeStudy() ) {
2135     SALOMEDSClient_StudyManager* aMgr = studyMgr();
2136     if ( aMgr ) {
2137       std::vector<std::string> List = studyMgr()->GetOpenStudies();
2138       if( List.size() > 0 ) {
2139         SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2140         result = false;
2141       }
2142     }
2143   }
2144   return result;
2145 }
2146
2147
2148 #ifndef DISABLE_PYCONSOLE
2149
2150 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2151 {
2152   return new SalomeApp_PyInterp();
2153 }
2154
2155 #endif // DISABLE_PYCONSOLE