]> SALOME platform Git repositories - modules/gui.git/blob - src/SalomeApp/SalomeApp_Application.cxx
Salome HOME
2c66cbdd71240e1ab49431ff7a4cfaf214c34239
[modules/gui.git] / src / SalomeApp / SalomeApp_Application.cxx
1 //  Copyright (C) 2007-2008  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 // File:      SalomeApp_Application.cxx
23 // Created:   10/22/2004 3:23:45 PM
24 // Author:    Sergey LITONIN
25 //
26 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
27 #include "SalomeApp_Application.h"
28 #include "SalomeApp_Study.h"
29 #include "SalomeApp_DataModel.h"
30 #include "SalomeApp_DataObject.h"
31 #include "SalomeApp_VisualState.h"
32 #include "SalomeApp_StudyPropertiesDlg.h"
33 #include "SalomeApp_LoadStudiesDlg.h"
34 #include "SalomeApp_NoteBookDlg.h"
35
36 #include "SalomeApp_ExitDlg.h"
37
38 #include <LightApp_Application.h>
39 #include <LightApp_Preferences.h>
40 #include <LightApp_SelectionMgr.h>
41 #include <LightApp_NameDlg.h>
42 #include <LightApp_DataOwner.h>
43
44 #include <CAM_Module.h>
45
46 #include <SUIT_Tools.h>
47 #include <SUIT_Session.h>
48 #include <SUIT_Desktop.h>
49 #include <SUIT_DataBrowser.h>
50 #include <SUIT_FileDlg.h>
51 #include <SUIT_FileValidator.h>
52 #include <SUIT_MessageBox.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SUIT_TreeModel.h>
55
56 #include <QtxTreeView.h>
57
58 #include <SALOME_EventFilter.h>
59
60 // temporary commented
61 //#include <OB_ListItem.h>
62
63 #include <PyConsole_Console.h>
64
65 #include <Utils_ORB_INIT.hxx>
66 #include <Utils_SINGLETON.hxx>
67 #include <SALOME_LifeCycleCORBA.hxx>
68
69 #include <QApplication>
70 #include <QAction>
71 #include <QRegExp>
72 #include <QCheckBox>
73 #include <QPushButton>
74 #include <QLabel>
75 #include <QListWidget>
76 #include <QGridLayout>
77 #include <QMenu>
78
79 #include <SALOMEDSClient_ClientFactory.hxx>
80
81 #include <SALOME_ListIteratorOfListIO.hxx>
82 #include <SALOME_ListIO.hxx>
83
84 #include <ToolsGUI_CatalogGeneratorDlg.h>
85 #include <ToolsGUI_RegWidget.h>
86
87 #include <vector>
88
89 /*!Internal class that updates object browser item properties */
90 // temporary commented
91 /*class SalomeApp_Updater : public OB_Updater
92 {
93 public:
94   SalomeApp_Updater() : OB_Updater(){};
95   virtual ~SalomeApp_Updater(){};
96   virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
97 };
98
99 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
100 {
101   if( !theObj || !theItem )
102     return;
103
104   SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
105   if( !SAObj )
106     return;
107
108   _PTR(SObject) SObj = SAObj->object();
109   if( !SObj )
110     return;
111   _PTR( GenericAttribute ) anAttr;
112
113   // Selectable
114   if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
115   {
116     _PTR(AttributeSelectable) aAttrSel = anAttr;
117     theItem->setSelectable( aAttrSel->IsSelectable() );
118   }
119   // Expandable
120   if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
121   {
122     _PTR(AttributeExpandable) aAttrExpand = anAttr;
123     theItem->setExpandable( aAttrExpand->IsExpandable() );
124   }
125   // Opened
126   //this attribute is not supported in the version of SALOME 3.x
127   //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
128   //{
129   //  _PTR(AttributeOpened) aAttrOpen = anAttr;
130   //  theItem->setOpen( aAttrOpen->IsOpened() );
131   //}
132 }*/
133
134 /*!Create new instance of SalomeApp_Application.*/
135 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
136 {
137   return new SalomeApp_Application();
138 }
139
140 /*!Constructor.*/
141 SalomeApp_Application::SalomeApp_Application()
142   : LightApp_Application()
143 {
144   connect( desktop(), SIGNAL( message( const QString& ) ),
145            this,      SLOT( onDesktopMessage( const QString& ) ) );
146   setNoteBook(0);
147 }
148
149 /*!Destructor.
150  *\li Destroy event filter.
151  */
152 SalomeApp_Application::~SalomeApp_Application()
153 {
154   // Do not destroy. It's a singleton !
155   //SALOME_EventFilter::Destroy();
156 }
157
158 /*!Start application.*/
159 void SalomeApp_Application::start()
160 {
161   LightApp_Application::start();
162
163   SALOME_EventFilter::Init();
164
165   static bool isFirst = true;
166   if ( isFirst ) {
167     isFirst = false;
168
169     QString hdffile;
170     QStringList pyfiles;
171
172     for (int i = 1; i < qApp->argc(); i++) {
173       QRegExp rxs ("--study-hdf=(.+)");
174       if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
175         QString file = rxs.capturedTexts()[1];
176         QFileInfo fi ( file );
177         QString extension = fi.suffix().toLower();
178         if ( extension == "hdf" && fi.exists() )
179           hdffile = fi.absoluteFilePath();
180       }
181       else {
182         QRegExp rxp ("--pyscript=(.+)");
183         if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
184           QStringList files = rxp.capturedTexts()[1].split(",",QString::SkipEmptyParts);
185           pyfiles += files;
186         }
187       }
188     }
189
190     if ( !hdffile.isEmpty() )       // open hdf file given as parameter
191       onOpenDoc( hdffile );
192     else if ( pyfiles.count() > 0 ) // create new study
193       onNewDoc();
194
195     // import/execute python scripts
196     if ( pyfiles.count() > 0 && activeStudy() ) {
197       SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
198       if ( appStudy ) {
199         _PTR(Study) aStudy = appStudy->studyDS();
200         if ( !aStudy->GetProperties()->IsLocked() ) {
201           for (uint j = 0; j < pyfiles.count(); j++ ) {
202             QFileInfo fi ( pyfiles[j] );
203             PyConsole_Console* pyConsole = pythonConsole();
204             if ( pyConsole ) {
205               QString extension = fi.suffix().toLower();
206               if ( fi.exists() ) {
207                 // execute python script
208                 QString command = QString( "execfile(\"%1\")" ).arg( fi.absoluteFilePath() );
209                 pyConsole->exec( command );
210               }
211               else {
212                 // import python module
213                 QString command = QString( "import %1" ).arg( pyfiles[j] );
214                 if ( extension == "py" )
215                   command = QString( "import %1" ).arg( fi.completeBaseName() );
216                 pyConsole->exec( command );
217               }
218             }
219           }
220         }
221       }
222     }
223   }
224 }
225
226 /*!Create actions:*/
227 void SalomeApp_Application::createActions()
228 {
229   LightApp_Application::createActions();
230
231   SUIT_Desktop* desk = desktop();
232
233   //! Save GUI state
234   // "Save GUI State" command is moved to VISU module
235   //  createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
236   //            tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
237   //            0, desk, false, this, SLOT( onSaveGUIState() ) );
238
239   //! Dump study
240   createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
241                 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
242                 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
243
244   //! NoteBook
245   createAction(NoteBookId, tr( "TOT_DESK_FILE_NOTEBOOK" ), QIcon(),
246                tr( "MEN_DESK_FILE_NOTEBOOK" ), tr( "PRP_DESK_FILE_NOTEBOOK" ),
247                Qt::CTRL+Qt::Key_K, desk, false, this, SLOT(onNoteBook()));
248
249   //! Load script
250   createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
251                 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
252                 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
253
254   //! Properties
255   createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
256                 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
257                 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
258
259   //! Catalog Generator
260   createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ),  QIcon(),
261                 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
262                 Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
263
264   //! Registry Display
265   createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ),  QIcon(),
266                 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
267                 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
268
269   //SRN: BugID IPAL9021, add an action "Load"
270   createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
271                 resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
272                 tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
273                 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
274   //SRN: BugID IPAL9021: End
275
276
277   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
278
279   // "Save GUI State" command is renamed to "Save VISU State" and
280   // creation of menu item is moved to VISU
281   //  createMenu( SaveGUIStateId, fileMenu, 10, -1 );
282
283   createMenu( FileLoadId,   fileMenu, 0 );  //SRN: BugID IPAL9021, add a menu item "Load"
284
285   createMenu( DumpStudyId, fileMenu, 10, -1 );
286   createMenu( NoteBookId, fileMenu, 10, -1 );
287   createMenu( separator(), fileMenu, -1, 10, -1 );
288   createMenu( LoadScriptId, fileMenu, 10, -1 );
289   createMenu( separator(), fileMenu, -1, 10, -1 );
290   createMenu( PropertiesId, fileMenu, 10, -1 );
291   createMenu( separator(), fileMenu, -1, 10, -1 );
292
293   int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
294   createMenu( CatalogGenId, toolsMenu, 10, -1 );
295   createMenu( RegDisplayId, toolsMenu, 10, -1 );
296   createMenu( separator(), toolsMenu, -1, 15, -1 );
297 }
298
299 /*!
300   \brief Close application.
301 */
302 void SalomeApp_Application::onExit()
303 {
304   bool killServers = false;
305   bool result = true;
306
307   if ( exitConfirmation() ) {
308     SalomeApp_ExitDlg dlg( desktop() );
309     result = dlg.exec() == QDialog::Accepted;
310     killServers = dlg.isServersShutdown();
311   }
312
313   if ( result )
314     SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
315 }
316
317 /*!SLOT. Load document.*/
318 void SalomeApp_Application::onLoadDoc()
319 {
320   QString studyName;
321
322   std::vector<std::string> List = studyMgr()->GetOpenStudies();
323
324   SUIT_Session* aSession = SUIT_Session::session();
325   QList<SUIT_Application*> aAppList = aSession->applications();
326
327   QStringList unloadedStudies;
328
329   for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
330      studyName = List[ind].c_str();
331      // Add to list only unloaded studies
332      bool isAlreadyOpen = false;
333      QListIterator<SUIT_Application*> it( aAppList );
334      while ( it.hasNext() && !isAlreadyOpen ) {
335        SUIT_Application* aApp = it.next();
336        if( !aApp || !aApp->activeStudy() )
337          continue;
338        if ( aApp->activeStudy()->studyName() == studyName )
339          isAlreadyOpen = true;
340      }
341
342      if ( !isAlreadyOpen )
343        unloadedStudies << studyName;
344   }
345
346   studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
347   if ( studyName.isEmpty() )
348     return;
349
350 #ifndef WIN32
351   // this code replaces marker of windows drive and path become invalid therefore
352   // defines placed there
353   studyName.replace( QRegExp(":"), "/" );
354 #endif
355
356   if ( onLoadDoc( studyName ) ) {
357     updateWindows();
358     updateViewManagers();
359     updateObjectBrowser( true );
360   }
361 }
362
363 /*!SLOT. Load document with \a aName.*/
364 bool SalomeApp_Application::onLoadDoc( const QString& aName )
365 {
366   bool res = true;
367   if ( !activeStudy() ) {
368     // if no study - load in current desktop
369     res = useStudy( aName );
370   }
371   else {
372     // if study exists - load in new desktop. Check: is the same file is loaded?
373     SUIT_Session* aSession = SUIT_Session::session();
374     QList<SUIT_Application*> aAppList = aSession->applications();
375     bool isAlreadyOpen = false;
376     SalomeApp_Application* aApp = 0;
377     for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
378           it != aAppList.end() && !isAlreadyOpen; ++it ) {
379       aApp = dynamic_cast<SalomeApp_Application*>( *it );
380       if ( aApp && aApp->activeStudy()->studyName() == aName )
381         isAlreadyOpen = true;
382     }
383     if ( !isAlreadyOpen ) {
384       aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
385       if ( aApp )
386         res = aApp->useStudy( aName );
387     }
388     else {
389       aApp->desktop()->activateWindow();
390     }
391   }
392
393   return res;
394 }
395
396 /*!SLOT. Copy objects to study maneger from selection maneger..*/
397 void SalomeApp_Application::onCopy()
398 {
399   SALOME_ListIO list;
400   LightApp_SelectionMgr* mgr = selectionMgr();
401   mgr->selectedObjects(list);
402
403   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
404   if(study == NULL) return;
405
406   _PTR(Study) stdDS = study->studyDS();
407   if(!stdDS) return;
408
409   SALOME_ListIteratorOfListIO it( list );
410   if(it.More())
411     {
412       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
413       try {
414         studyMgr()->Copy(so);
415         onSelectionChanged();
416       }
417       catch(...) {
418       }
419     }
420 }
421
422 /*!SLOT. Paste objects to study maneger from selection manager.*/
423 void SalomeApp_Application::onPaste()
424 {
425   SALOME_ListIO list;
426   LightApp_SelectionMgr* mgr = selectionMgr();
427   mgr->selectedObjects(list);
428
429   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
430   if(study == NULL) return;
431
432   _PTR(Study) stdDS = study->studyDS();
433   if(!stdDS) return;
434
435   if ( stdDS->GetProperties()->IsLocked() ) {
436     SUIT_MessageBox::warning( desktop(),
437                               QObject::tr("WRN_WARNING"),
438                               QObject::tr("WRN_STUDY_LOCKED") );
439     return;
440   }
441
442   SALOME_ListIteratorOfListIO it( list );
443   if(it.More())
444     {
445       _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
446       try {
447         studyMgr()->Paste(so);
448         updateObjectBrowser( true );
449         updateActions(); //SRN: BugID IPAL9377, case 3
450       }
451       catch(...) {
452       }
453     }
454 }
455
456 /*!Check the application on closing.
457  * \retval true if possible, else false
458  */
459 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
460 {
461   return LightApp_Application::isPossibleToClose( closePermanently );
462 }
463
464 /*! Check if the study is locked */
465 void SalomeApp_Application::onCloseDoc( bool ask )
466 {
467   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
468
469   if (study != NULL) {
470     _PTR(Study) stdDS = study->studyDS();
471     if(stdDS && stdDS->IsStudyLocked()) {
472       if ( SUIT_MessageBox::question( desktop(),
473                                       QObject::tr( "WRN_WARNING" ),
474                                       QObject::tr( "CLOSE_LOCKED_STUDY" ),
475                                       SUIT_MessageBox::Yes | SUIT_MessageBox::No,
476                                       SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
477
478     }
479   }
480
481   LightApp_Application::onCloseDoc( ask );
482   if(myNoteBook && myNoteBook->isVisible())
483      myNoteBook->hide();
484 }
485
486 /*!Sets enable or disable some actions on selection changed.*/
487 void SalomeApp_Application::onSelectionChanged()
488 {
489    SALOME_ListIO list;
490    LightApp_SelectionMgr* mgr = selectionMgr();
491    mgr->selectedObjects(list);
492
493    bool canCopy  = false;
494    bool canPaste = false;
495
496    SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
497    if (study != NULL) {
498      _PTR(Study) stdDS = study->studyDS();
499
500      if (stdDS) {
501        SALOME_ListIteratorOfListIO it ( list );
502
503        if (it.More() && list.Extent() == 1) {
504          _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
505
506          if ( so ) {
507              canCopy = studyMgr()->CanCopy(so);
508              canPaste = studyMgr()->CanPaste(so);
509          }
510        }
511      }
512    }
513
514    action(EditCopyId)->setEnabled(canCopy);
515    action(EditPasteId)->setEnabled(canPaste);
516 }
517
518 /*!Delete references.*/
519 void SalomeApp_Application::onDeleteInvalidReferences()
520 {
521   SALOME_ListIO aList;
522   LightApp_SelectionMgr* mgr = selectionMgr();
523   mgr->selectedObjects( aList, QString(), false );
524
525   if( aList.IsEmpty() )
526     return;
527
528   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
529   _PTR(Study) aStudyDS = aStudy->studyDS();
530   _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
531   _PTR(SObject) anObj;
532
533   for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
534     if ( it.Value()->hasEntry() )
535     {
536       _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
537       while( aRefObj && aRefObj->ReferencedObject( anObj ) )
538         aRefObj = anObj;
539
540       if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
541          aStudyBuilder->RemoveReference( aSObject );
542     }
543   updateObjectBrowser();
544 }
545
546 /*!Private SLOT. */
547 void SalomeApp_Application::onOpenWith()
548 {
549   QApplication::setOverrideCursor( Qt::WaitCursor );
550   SALOME_ListIO aList;
551   LightApp_SelectionMgr* mgr = selectionMgr();
552   mgr->selectedObjects(aList);
553   if (aList.Extent() != 1)
554     {
555       QApplication::restoreOverrideCursor();
556       return;
557     }
558   Handle(SALOME_InteractiveObject) aIObj = aList.First();
559   QString aModuleName(aIObj->getComponentDataType());
560   QString aModuleTitle = moduleTitle(aModuleName);
561   activateModule(aModuleTitle);
562   QApplication::restoreOverrideCursor();
563 }
564
565 /*!
566   Creates new study
567 */
568 SUIT_Study* SalomeApp_Application::createNewStudy()
569 {
570   SalomeApp_Study* aStudy = new SalomeApp_Study( this );
571
572   // Set up processing of major study-related events
573   connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
574   connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
575   connect( aStudy, SIGNAL( saved  ( SUIT_Study* ) ), this, SLOT( onStudySaved  ( SUIT_Study* ) ) );
576   connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
577
578   return aStudy;
579 }
580
581 /*!
582   Enable/Disable menu items and toolbar buttons. Rebuild menu
583 */
584 void SalomeApp_Application::updateCommandsStatus()
585 {
586   LightApp_Application::updateCommandsStatus();
587
588   // Dump study menu
589   QAction* a = action( DumpStudyId );
590   if ( a )
591     a->setEnabled( activeStudy() );
592
593   // Note Book
594   a = action(NoteBookId);
595   if( a )
596     a->setEnabled( activeStudy() );
597   
598   // Load script menu
599   a = action( LoadScriptId );
600   if ( a )
601     a->setEnabled( activeStudy() );
602
603   // Properties menu
604   a = action( PropertiesId );
605   if( a )
606     a->setEnabled( activeStudy() );
607
608   // Save GUI state menu
609   a = action( SaveGUIStateId );
610   if( a )
611     a->setEnabled( activeStudy() );
612
613   // update state of Copy/Paste menu items
614   onSelectionChanged();
615 }
616
617 /*!
618   \class DumpStudyFileDlg
619   Private class used in Dump Study operation.  Consists 2 check boxes:
620   "Publish in study" and "Save GUI parameters"
621 */
622 class DumpStudyFileDlg : public SUIT_FileDlg
623 {
624 public:
625   DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
626   {
627     QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
628     if ( grid )
629     {
630       QWidget *hB = new QWidget( this );
631       myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
632       mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
633
634       QHBoxLayout *layout = new QHBoxLayout;
635       layout->addWidget(myPublishChk);
636       layout->addWidget(mySaveGUIChk);
637       hB->setLayout(layout);
638
639       QPushButton* pb = new QPushButton(this);
640
641       int row = grid->rowCount();
642       grid->addWidget( new QLabel("", this), row, 0 );
643       grid->addWidget( hB, row, 1, 1, 3 );
644       grid->addWidget( pb, row, 5 );
645
646       pb->hide();
647     }
648   }
649   QCheckBox* myPublishChk;
650   QCheckBox* mySaveGUIChk;
651 };
652
653 class DumpStudyFileValidator : public SUIT_FileValidator
654 {
655  public:
656   DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
657   virtual ~DumpStudyFileValidator() {};
658   virtual bool canSave( const QString& file, bool permissions );
659 };
660
661 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
662 {
663   QFileInfo fi( file );
664   QString name = fi.fileName(); 
665   
666   if ( name.indexOf( QRegExp("[-!?#*&]") ) >= 0 ) {
667     SUIT_MessageBox::critical( parent(),
668                                QObject::tr("WRN_WARNING"),
669                                QObject::tr("WRN_FILE_NAME_BAD") );
670     return false;
671   }
672   return SUIT_FileValidator::canSave( file, permissions);
673 }
674
675 /*!Private SLOT. On dump study.*/
676 void SalomeApp_Application::onDumpStudy( )
677 {
678   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
679   if ( !appStudy ) return;
680   _PTR(Study) aStudy = appStudy->studyDS();
681
682   QStringList aFilters;
683   aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
684
685   DumpStudyFileDlg fd( desktop() );
686   fd.setValidator( new DumpStudyFileValidator( &fd ) );
687   fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
688   fd.setFilters( aFilters );
689   fd.myPublishChk->setChecked( true );
690   fd.mySaveGUIChk->setChecked( true );
691   if ( fd.exec() == QDialog::Accepted )
692   {
693     QString aFileName = fd.selectedFile();
694     
695     bool toPublish = fd.myPublishChk->isChecked();
696     bool toSaveGUI = fd.mySaveGUIChk->isChecked();
697     
698     if ( !aFileName.isEmpty() ) {
699       QFileInfo aFileInfo(aFileName);
700       if( aFileInfo.isDir() ) // IPAL19257
701         return;
702
703       int savePoint;
704       _PTR(AttributeParameter) ap;
705       _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
706       if(ip->isDumpPython(appStudy->studyDS())) ip->setDumpPython(appStudy->studyDS()); //Unset DumpPython flag.
707       if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
708         ip->setDumpPython(appStudy->studyDS());
709         savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
710       }
711       bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toStdString(),
712                                     aFileInfo.baseName().toStdString(), toPublish);
713       if ( toSaveGUI )
714         appStudy->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
715       if ( !res )
716         SUIT_MessageBox::warning( desktop(),
717                                   QObject::tr("WRN_WARNING"),
718                                   tr("WRN_DUMP_STUDY_FAILED") );
719     }
720   }
721 }
722
723 /*!Private SLOT. On NoteBook*/
724 void SalomeApp_Application::onNoteBook()
725 {
726   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
727   if ( appStudy ) {
728     _PTR(Study) aStudy = appStudy->studyDS();
729     if(!myNoteBook) {
730       myNoteBook = new SalomeApp_NoteBookDlg(desktop(),aStudy);
731     }
732     else if(!myNoteBook->isVisible()){
733       myNoteBook->Init(aStudy);
734       myNoteBook->adjustSize();
735       myNoteBook->move((int)(desktop()->x() + desktop()->width()/2  - myNoteBook->frameGeometry().width()/2),
736                        (int)(desktop()->y() + desktop()->height()/2 - myNoteBook->frameGeometry().height()/2));
737     }
738     myNoteBook->show();
739   }
740 }
741
742 /*!Private SLOT. On load script.*/
743 void SalomeApp_Application::onLoadScript( )
744 {
745   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
746   if ( !appStudy ) return;
747   _PTR(Study) aStudy = appStudy->studyDS();
748
749   if ( aStudy->GetProperties()->IsLocked() ) {
750     SUIT_MessageBox::warning( desktop(),
751                               QObject::tr("WRN_WARNING"),
752                               QObject::tr("WRN_STUDY_LOCKED") );
753     return;
754   }
755
756   QStringList filtersList;
757   filtersList.append(tr("PYTHON_FILES_FILTER"));
758   filtersList.append(tr("ALL_FILES_FILTER"));
759   
760   QString anInitialPath = "";
761   if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
762     anInitialPath = QDir::currentPath();
763
764   QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
765
766   if ( !aFile.isEmpty() )
767   {
768     QString command = QString("execfile(\"%1\")").arg(aFile);
769
770     PyConsole_Console* pyConsole = pythonConsole();
771
772     if ( pyConsole )
773       pyConsole->exec( command );
774   }
775 }
776
777 /*!Private SLOT. On save GUI state.*/
778 void SalomeApp_Application::onSaveGUIState()
779 {
780   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
781   if ( study ) {
782     SalomeApp_VisualState( this ).storeState();
783     updateSavePointDataObjects( study );
784     // temporary commented
785     //objectBrowser()->updateTree( study->root() );
786   }
787   updateActions();
788 }
789
790 /*!Gets file filter.
791  *\retval QString "(*.hdf)"
792  */
793 QString SalomeApp_Application::getFileFilter() const
794 {
795   return "(*.hdf)";
796 }
797
798 /*!Create window.*/
799 QWidget* SalomeApp_Application::createWindow( const int flag )
800 {
801   QWidget* wid = 0;
802   if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
803
804   SUIT_ResourceMgr* resMgr = resourceMgr();
805
806   if ( flag == WT_ObjectBrowser )
807   {
808     SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
809     if ( ob ) {
810       // temporary commented
811       //ob->setUpdater( new SalomeApp_Updater() );
812
813       connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
814
815       QString
816         ValueCol = QObject::tr( "VALUE_COLUMN" ),
817         IORCol = QObject::tr( "IOR_COLUMN" ),
818         RefCol = QObject::tr( "REFENTRY_COLUMN" ),
819         EntryCol = QObject::tr( "ENTRY_COLUMN" );
820
821       SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
822       treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
823       treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
824       treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
825       treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
826       treeModel->setAppropriate( EntryCol, Qtx::Toggled );
827       treeModel->setAppropriate( ValueCol, Qtx::Toggled );
828       treeModel->setAppropriate( IORCol, Qtx::Toggled );
829       treeModel->setAppropriate( RefCol, Qtx::Toggled );
830
831       bool autoSize      = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
832       bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
833       bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
834
835       ob->setAutoSizeFirstColumn(autoSizeFirst);
836       ob->setAutoSizeColumns(autoSize);
837       ob->setResizeOnExpandItem(resizeOnExpandItem);
838
839       // temporary commented
840       /*
841       for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
842       {
843       ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
844       ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
845                                                     QString().sprintf( "visibility_column_%d", i ), true ) );
846       }
847       */
848
849       // temporary commented
850       /*
851         ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
852         ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
853         ob->resize( desktop()->width()/3, ob->height() );
854       */
855     }
856   }
857   else if ( flag == WT_PyConsole )
858   {
859     PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new SalomeApp_PyInterp() );
860     pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
861     wid = pyCons;
862     pyCons->resize( pyCons->width(), desktop()->height()/4 );
863     pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
864   }
865   return wid;
866 }
867
868 /*!Create preferences.*/
869 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
870 {
871   LightApp_Application::createPreferences(pref);
872
873   if ( !pref )
874     return;
875
876   int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
877   int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
878   int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
879   for ( int i = SalomeApp_DataObject::EntryId; i <= SalomeApp_DataObject::RefEntryId; i++ )
880   {
881     pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-1 ).toLatin1() ), defCols,
882                          LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i ) );
883   }
884   pref->setItemProperty( "orientation", Qt::Vertical, defCols );
885
886   // adding preference to LightApp_Application handled preferences..  a bit of hacking with resources..
887   int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
888   int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
889   pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
890 }
891
892 /*!Update desktop title.*/
893 void SalomeApp_Application::updateDesktopTitle() {
894   QString aTitle = applicationName();
895   QString aVer = applicationVersion();
896   if ( !aVer.isEmpty() )
897     aTitle += QString( " " ) + aVer;
898
899   if ( activeStudy() )
900   {
901     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
902     if ( !sName.isEmpty() ) {
903       SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
904       if ( study ) {
905         _PTR(Study) stdDS = study->studyDS();
906         if(stdDS) {
907           if ( stdDS->GetProperties()->IsLocked() ) {
908             aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
909           } else {
910             aTitle += QString( " - [%1]" ).arg( sName );
911           }
912         }
913       }
914     }
915   }
916
917   desktop()->setWindowTitle( aTitle );
918 }
919
920 int SalomeApp_Application::closeChoice( const QString& docName )
921 {
922   int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
923                                           tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
924                                           tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
925
926   int res = CloseCancel;
927   if ( answer == 0 )
928     res = CloseSave;
929   else if ( answer == 1 )
930     res = CloseDiscard;
931   else if ( answer == 2 )
932     res = CloseUnload;
933
934   return res;
935 }
936
937 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
938 {
939   bool res = true;
940   switch( choice )
941   {
942   case CloseSave:
943     if ( activeStudy()->isSaved() )
944       onSaveDoc();
945     else if ( !onSaveAsDoc() )
946       res = false;
947     break;
948   case CloseDiscard:
949     break;
950   case CloseUnload:
951     closePermanently = false;
952     break;
953   case CloseCancel:
954   default:
955     res = false;
956   }
957
958   return res;
959 }
960
961 int SalomeApp_Application::openChoice( const QString& aName )
962 {
963   int choice = LightApp_Application::openChoice( aName );
964
965   if ( choice == OpenNew ) // The document isn't already open.
966   {
967     bool exist = false;
968     std::vector<std::string> lst = studyMgr()->GetOpenStudies();
969     for ( uint i = 0; i < lst.size() && !exist; i++ )
970     {
971       if ( aName == QString( lst[i].c_str() ) )
972         exist = true;
973     }
974
975     // The document already exists in the study manager.
976     // Do you want to reload it?
977     if ( exist )
978     {
979       int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
980                                               SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
981       if ( answer == SUIT_MessageBox::Yes )
982         choice = OpenRefresh;
983       else
984         choice = OpenCancel;
985     }
986   }
987
988   return choice;
989 }
990
991 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
992 {
993   bool res = false;
994   int choice = aChoice;
995   switch ( choice )
996   {
997   case OpenRefresh:
998     {
999       _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1000       if ( aStudy )
1001       {
1002         studyMgr()->Close( aStudy );
1003         choice = OpenNew;
1004       }
1005     }
1006   default:
1007     res = LightApp_Application::openAction( choice, aName );
1008     break;
1009   }
1010
1011   return res;
1012 }
1013
1014 /*!
1015   \brief Get map of the operations which can be performed
1016   on the module activation.
1017
1018   The method should return the map of the kind \c {<id>:<name>}
1019   where \c <id> is an integer identifier of the operation and
1020   \c <name> is a title for the button to be added to the
1021   dialog box. After user selects the required operation by the
1022   clicking the corresponding button in the dialog box, its identifier
1023   is passed to the moduleActionSelected() method to process
1024   the made choice.
1025
1026   \return map of the operations
1027   \sa moduleActionSelected()
1028 */
1029 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1030 {
1031   QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1032   opmap.insert( LoadStudyId,  tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1033   return opmap;
1034 }
1035
1036 /*!
1037   \brief Called when the used selectes required operation chosen
1038   from "Activate module" dialog box.
1039
1040   Performs the required operation according to the user choice.
1041
1042   \param id operation identifier
1043   \sa activateModuleActions()
1044 */
1045 void SalomeApp_Application::moduleActionSelected( const int id )
1046 {
1047   if ( id == LoadStudyId )
1048     onLoadDoc();
1049   else
1050     LightApp_Application::moduleActionSelected( id );
1051 }
1052
1053 /*!Gets CORBA::ORB_var*/
1054 CORBA::ORB_var SalomeApp_Application::orb()
1055 {
1056   ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1057   static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1058   return _orb;
1059 }
1060
1061 /*!Create and return SALOMEDS_StudyManager.*/
1062 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1063 {
1064   static _PTR(StudyManager) _sm;
1065   if(!_sm) _sm = ClientFactory::StudyManager();
1066   return _sm.get();
1067 }
1068
1069 /*!Create and return SALOME_NamingService.*/
1070 SALOME_NamingService* SalomeApp_Application::namingService()
1071 {
1072   static SALOME_NamingService* _ns = new SALOME_NamingService( orb() );
1073   return _ns;
1074 }
1075
1076 /*!Create and return SALOME_LifeCycleCORBA.*/
1077 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1078 {
1079   static SALOME_LifeCycleCORBA* _lcc = new SALOME_LifeCycleCORBA( namingService() );
1080   return _lcc;
1081 }
1082
1083 /*!Return default engine IOR for light modules*/
1084 QString SalomeApp_Application::defaultEngineIOR()
1085 {
1086   /// Look for a default module engine (needed for CORBAless modules to use SALOMEDS persistence)
1087   QString anIOR( "" );
1088   CORBA::Object_ptr anEngine = namingService()->Resolve( "/SalomeAppEngine" );
1089   if ( !CORBA::is_nil( anEngine ) )
1090   {
1091     CORBA::String_var objStr = orb()->object_to_string( anEngine );
1092     anIOR = QString( objStr.in() );
1093   }
1094   return anIOR;
1095 }
1096
1097 /*!Private SLOT. On preferences.*/
1098 void SalomeApp_Application::onProperties()
1099 {
1100   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1101   if( !study )
1102     return;
1103
1104   _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1105   SB->NewCommand();
1106
1107   SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1108   int res = aDlg.exec();
1109   if( res==QDialog::Accepted && aDlg.isChanged() )
1110     SB->CommitCommand();
1111   else
1112     SB->AbortCommand();
1113
1114   //study->updateCaptions();
1115   updateDesktopTitle();
1116   updateActions();
1117 }
1118
1119 /*!Insert items in popup, which necessary for current application*/
1120 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1121 {
1122   LightApp_Application::contextMenuPopup( type, thePopup, title );
1123
1124   // temporary commented
1125   /*OB_Browser* ob = objectBrowser();
1126   if ( !ob || type != ob->popupClientType() )
1127     return;*/
1128
1129   // Get selected objects
1130   SALOME_ListIO aList;
1131   LightApp_SelectionMgr* mgr = selectionMgr();
1132   mgr->selectedObjects( aList, QString(), false );
1133
1134   // add GUI state commands: restore, rename
1135   if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1136        QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1137     thePopup->addSeparator();
1138     thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1139     thePopup->addAction( tr( "MEN_RENAME_VS" ),  this, SLOT( onRenameGUIState() ) );
1140     thePopup->addAction( tr( "MEN_DELETE_VS" ),  this, SLOT( onDeleteGUIState() ) );
1141   }
1142
1143   // "Delete reference" item should appear only for invalid references
1144
1145   // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1146   bool isInvalidRefs = false;
1147   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1148   _PTR(Study) aStudyDS = aStudy->studyDS();
1149   _PTR(SObject) anObj;
1150
1151   for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1152     if( it.Value()->hasEntry() )
1153     {
1154       _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1155       while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1156         aRefObj = anObj;
1157
1158       if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1159         isInvalidRefs = true;
1160     }
1161
1162   // Add "Delete reference" item to popup
1163   if ( isInvalidRefs )
1164   {
1165     thePopup->addSeparator();
1166     thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1167     return;
1168   }
1169
1170   aList.Clear();
1171   mgr->selectedObjects( aList );
1172
1173   // "Activate module" item should appear only if it's necessary
1174   if (aList.Extent() != 1)
1175     return;
1176   Handle(SALOME_InteractiveObject) aIObj = aList.First();
1177   // check if item is a "GUI state" item (also a first level object)
1178   QString entry( aIObj->getEntry() );
1179   if ( entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) )
1180     return;
1181   QString aModuleName(aIObj->getComponentDataType());
1182   QString aModuleTitle = moduleTitle(aModuleName);
1183   CAM_Module* currentModule = activeModule();
1184   if (currentModule && currentModule->moduleName() == aModuleTitle)
1185     return;
1186   if ( !aModuleTitle.isEmpty() )
1187     thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1188 }
1189
1190 /*!Update obect browser:
1191  1.if 'updateModels' true, update existing data models;
1192  2. update "non-existing" (not loaded yet) data models;
1193  3. update object browser if it exists */
1194 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1195 {
1196   // update "non-existing" (not loaded yet) data models
1197   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1198   if ( study )
1199   {
1200     _PTR(Study) stdDS = study->studyDS();
1201     if( stdDS )
1202     {
1203       for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1204       {
1205         _PTR(SComponent) aComponent ( it->Value() );
1206
1207         if ( aComponent->ComponentDataType() == "Interface Applicative" )
1208           continue; // skip the magic "Interface Applicative" component
1209
1210         getWindow( WT_ObjectBrowser );
1211         const bool isAutoUpdate = objectBrowser()->autoUpdate();
1212         objectBrowser()->setAutoUpdate( false );
1213         SalomeApp_DataModel::synchronize( aComponent, study );
1214         objectBrowser()->setAutoUpdate( isAutoUpdate );
1215       }
1216     }
1217   }
1218
1219   // create data objects that correspond to GUI state save points
1220   if ( study ) updateSavePointDataObjects( study );
1221
1222   // update existing data models (already loaded SComponents)
1223   LightApp_Application::updateObjectBrowser( updateModels );
1224 }
1225
1226 /*!Display Catalog Genenerator dialog */
1227 void SalomeApp_Application::onCatalogGen()
1228 {
1229   ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1230   aDlg.exec();
1231 }
1232
1233 /*!Display Registry Display dialog */
1234 void SalomeApp_Application::onRegDisplay()
1235 {
1236   CORBA::ORB_var anOrb = orb();
1237   ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1238   regWnd->show();
1239   regWnd->raise();
1240   regWnd->activateWindow();
1241 }
1242
1243 /*!find original object by double click on item */
1244 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1245 {
1246   SalomeApp_DataObject* obj = dynamic_cast<SalomeApp_DataObject*>( theObj );
1247   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1248
1249   if( study && obj )
1250   {
1251     QString entry = obj->entry();
1252     _PTR(SObject) sobj = study->studyDS()->FindObjectID( entry.toStdString() ), ref;
1253
1254     if( sobj && sobj->ReferencedObject( ref ) )
1255     {
1256       entry = ref->GetID().c_str();
1257       
1258       SUIT_DataOwnerPtrList aList;
1259       aList.append( new LightApp_DataOwner( entry ) );
1260       selectionMgr()->setSelected( aList, false );
1261
1262       SUIT_DataBrowser* ob = objectBrowser();
1263       
1264       QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1265       if ( !aSelectedIndexes.isEmpty() )
1266         ob->treeView()->scrollTo( aSelectedIndexes.first() );
1267     }
1268   }
1269 }
1270
1271 /*!
1272   Creates new view manager
1273   \param type - type of view manager
1274 */
1275 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1276 {
1277   return createViewManager(type);
1278 }
1279
1280
1281 /*!Global utility funciton, returns selected GUI Save point object's ID */
1282 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1283 {
1284   SALOME_ListIO aList;
1285   selMgr->selectedObjects( aList );
1286   Handle(SALOME_InteractiveObject) aIObj = aList.First();
1287   QString entry( aIObj->getEntry() );
1288   QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1289   if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1290     return -1;
1291   bool ok; // conversion to integer is ok?
1292   int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1293   return ok ? savePoint : -1;
1294 }
1295
1296 /*!Called on Restore GUI State popup command*/
1297 void SalomeApp_Application::onRestoreGUIState()
1298 {
1299   int savePoint = ::getSelectedSavePoint( selectionMgr() );
1300   if ( savePoint == -1 )
1301     return;
1302   SalomeApp_VisualState( this ).restoreState( savePoint );
1303 }
1304
1305 /*!Called on Rename GUI State popup command*/
1306 void SalomeApp_Application::onRenameGUIState()
1307 {
1308   int savePoint = ::getSelectedSavePoint( selectionMgr() );
1309   if ( savePoint == -1 )
1310     return;
1311   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1312   if ( !study )
1313     return;
1314
1315   QString newName = LightApp_NameDlg::getName( desktop(), study->getNameOfSavePoint( savePoint ) );
1316   if ( !newName.isNull() && !newName.isEmpty() ) {
1317     study->setNameOfSavePoint( savePoint, newName );
1318     updateSavePointDataObjects( study );
1319     // temporary commented
1320     //objectBrowser()->updateTree( study->root() );
1321   }
1322 }
1323
1324
1325 /*!Called on Delete GUI State popup command*/
1326 void SalomeApp_Application::onDeleteGUIState()
1327 {
1328   int savePoint = ::getSelectedSavePoint( selectionMgr() );
1329   if ( savePoint == -1 )
1330     return;
1331   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1332   if ( !study )
1333     return;
1334
1335   study->removeSavePoint( savePoint );
1336   updateSavePointDataObjects( study );
1337 }
1338
1339 /*!Called on New study operation*/
1340 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1341 {
1342   LightApp_Application::onStudyCreated( study );
1343
1344   objectBrowserColumnsVisibility();
1345 }
1346
1347 /*!Called on Save study operation*/
1348 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1349 {
1350   LightApp_Application::onStudySaved( study );
1351
1352   // temporary commented
1353   /*if ( objectBrowser() ) {
1354     updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1355     objectBrowser()->updateTree( study->root() );
1356   }*/
1357 }
1358
1359 /*!Called on Open study operation*/
1360 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1361 {
1362   LightApp_Application::onStudyOpened( study );
1363
1364   objectBrowserColumnsVisibility();
1365
1366   // temporary commented
1367   /*if ( objectBrowser() ) {
1368     updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1369     objectBrowser()->updateTree( study->root() );
1370   }*/
1371 }
1372
1373 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1374 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1375 {
1376   // temporary commented
1377   //OB_Browser* ob = objectBrowser();
1378
1379   if ( !study /*|| !ob */) // temporary commented
1380     return;
1381
1382   // find GUI states root object
1383   SUIT_DataObject* guiRootObj = 0;
1384   DataObjectList ch;
1385   study->root()->children( ch );
1386   DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1387   for ( ; it != last ; ++it ) {
1388     if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1389       guiRootObj = *it;
1390       break;
1391     }
1392   }
1393   std::vector<int> savePoints = study->getSavePoints();
1394   // case 1: no more save points but they existed in study's tree
1395   if ( savePoints.empty() && guiRootObj ) {
1396     delete guiRootObj;
1397     return;
1398   }
1399   // case 2: no more save points but root does not exist either
1400   if ( savePoints.empty() && !guiRootObj )
1401     return;
1402   // case 3: save points but no root for them - create it
1403   if ( !savePoints.empty() && !guiRootObj )
1404     guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1405   // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1406   // to be always the last one in the tree.  Here we check - if it is not the last one - remove and
1407   // re-create it.
1408   if ( guiRootObj->nextBrother() ) {
1409     study->root()->removeChild(guiRootObj);
1410     study->root()->appendChild(guiRootObj);
1411     //study->root()->dump();
1412   }
1413
1414   // store data objects in a map id-to-DataObject
1415   QMap<int,SalomeApp_SavePointObject*> mapDO;
1416   ch.clear();
1417   guiRootObj->children( ch );
1418   for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1419     SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1420     if ( dobj )
1421       mapDO[dobj->getId()] = dobj;
1422   }
1423
1424   // iterate new save points.  if DataObject with such ID not found in map - create DataObject
1425   // if in the map - remove it from map.
1426   for ( int i = 0; i < savePoints.size(); i++ )
1427     if ( !mapDO.contains( savePoints[i] ) )
1428       new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1429     else
1430       mapDO.remove( savePoints[i] );
1431
1432   // delete DataObjects that are still in the map -- their IDs were not found in data model
1433   for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1434     delete it.value();
1435 }
1436
1437 /*! Check data object */
1438 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1439 {
1440   if (theObj)
1441     return true;
1442
1443   return false;
1444 }
1445
1446 /*! Process standard messages from desktop */
1447 void SalomeApp_Application::onDesktopMessage( const QString& message )
1448 {
1449   // update object browser
1450   if ( message.toLower() == "updateobjectbrowser" ||
1451        message.toLower() == "updateobjbrowser" )
1452     updateObjectBrowser();
1453 }
1454
1455 /*!
1456   Opens other study into active Study. If Study is empty - creates it.
1457   \param theName - name of study
1458 */
1459 bool SalomeApp_Application::useStudy( const QString& theName )
1460 {
1461   createEmptyStudy();
1462   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1463   bool res = false;
1464   if (aStudy)
1465     res = aStudy->loadDocument( theName );
1466   updateDesktopTitle();
1467   updateCommandsStatus();
1468   return res;
1469 }
1470
1471 /*! Show/hide object browser colums according to preferences */
1472 void SalomeApp_Application::objectBrowserColumnsVisibility()
1473 {
1474   if ( objectBrowser() )
1475     for ( int i = SalomeApp_DataObject::EntryId; i <= SalomeApp_DataObject::RefEntryId; i++ )
1476     {
1477       bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i ), true );
1478       objectBrowser()->treeView()->setColumnHidden( i, !shown );
1479     }
1480 }
1481
1482 /*! Set SalomeApp_NoteBookDlg pointer */
1483 void SalomeApp_Application::setNoteBook(SalomeApp_NoteBookDlg* theNoteBook){
1484   myNoteBook = theNoteBook;
1485 }
1486
1487 /*! Return SalomeApp_NoteBookDlg pointer */
1488 SalomeApp_NoteBookDlg* SalomeApp_Application::getNoteBook() const
1489 {
1490   return myNoteBook;
1491 }
1492