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