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