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