1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: SalomeApp_Application.cxx
24 // Created: 10/22/2004 3:23:45 PM
25 // Author: Sergey LITONIN
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
32 #ifndef DISABLE_PYCONSOLE
37 #ifndef DISABLE_PYCONSOLE
38 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
39 #include <PyConsole_Console.h>
40 #include "SalomeApp_NoteBook.h"
42 #include "SalomeApp_Application.h"
43 #include "SalomeApp_Study.h"
44 #include "SalomeApp_DataModel.h"
45 #include "SalomeApp_DataObject.h"
46 #include "SalomeApp_VisualState.h"
47 #include "SalomeApp_StudyPropertiesDlg.h"
48 #include "SalomeApp_LoadStudiesDlg.h"
49 #include "SalomeApp_ExitDlg.h"
51 #include <LightApp_Application.h>
52 #include <LightApp_Module.h>
53 #include <LightApp_Preferences.h>
54 #include <LightApp_SelectionMgr.h>
55 #include <LightApp_NameDlg.h>
56 #include <LightApp_DataOwner.h>
58 #include <CAM_Module.h>
60 #include <SUIT_Tools.h>
61 #include <SUIT_Session.h>
62 #include <SUIT_Desktop.h>
63 #include <SUIT_DataBrowser.h>
64 #include <SUIT_FileDlg.h>
65 #include <SUIT_FileValidator.h>
66 #include <SUIT_MessageBox.h>
67 #include <SUIT_ResourceMgr.h>
68 #include <SUIT_TreeModel.h>
69 #include <SUIT_ViewWindow.h>
70 #include <SUIT_ViewManager.h>
71 #include <SUIT_ViewModel.h>
72 #include <SUIT_OverrideCursor.h>
74 #include <QtxTreeView.h>
76 #include <SALOME_EventFilter.h>
78 // temporary commented
79 //#include <OB_ListItem.h>
82 #include <Utils_ORB_INIT.hxx>
83 #include <Utils_SINGLETON.hxx>
84 #include <SALOME_LifeCycleCORBA.hxx>
86 #include <QApplication>
90 #include <QPushButton>
92 #include <QListWidget>
93 #include <QGridLayout>
97 #include <SALOMEDSClient_ClientFactory.hxx>
98 #include <Basics_Utils.hxx>
100 #include <SALOME_ListIO.hxx>
101 #include <SALOME_ListIteratorOfListIO.hxx>
102 #include <SALOME_Prs.h>
105 #include <ToolsGUI_CatalogGeneratorDlg.h>
106 #include <ToolsGUI_RegWidget.h>
110 #include <SALOMEDS_Tool.hxx>
112 /*!Internal class that updates object browser item properties */
113 // temporary commented
114 /*class SalomeApp_Updater : public OB_Updater
117 SalomeApp_Updater() : OB_Updater(){};
118 virtual ~SalomeApp_Updater(){};
119 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
122 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
124 if( !theObj || !theItem )
127 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
131 _PTR(SObject) SObj = SAObj->object();
134 _PTR( GenericAttribute ) anAttr;
137 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
139 _PTR(AttributeSelectable) aAttrSel = anAttr;
140 theItem->setSelectable( aAttrSel->IsSelectable() );
143 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
145 _PTR(AttributeExpandable) aAttrExpand = anAttr;
146 theItem->setExpandable( aAttrExpand->IsExpandable() );
149 //this attribute is not supported in the version of SALOME 3.x
150 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
152 // _PTR(AttributeOpened) aAttrOpen = anAttr;
153 // theItem->setOpen( aAttrOpen->IsOpened() );
157 /*!Create new instance of SalomeApp_Application.*/
158 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
160 return new SalomeApp_Application();
164 SalomeApp_Application::SalomeApp_Application()
165 : LightApp_Application()
167 connect( desktop(), SIGNAL( message( const QString& ) ),
168 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
169 myIsSiman = false; // default
173 *\li Destroy event filter.
175 SalomeApp_Application::~SalomeApp_Application()
177 // Do not destroy. It's a singleton !
178 //SALOME_EventFilter::Destroy();
181 /*!Start application.*/
182 void SalomeApp_Application::start()
184 // process the command line options before start: to createActions in accordance to the options
185 static bool isFirst = true;
193 for (int i = 1; i < qApp->argc(); i++) {
194 QRegExp rxs ("--study-hdf=(.+)");
195 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
196 QString file = rxs.capturedTexts()[1];
197 QFileInfo fi ( file );
198 QString extension = fi.suffix().toLower();
199 if ( extension == "hdf" && fi.exists() )
200 hdffile = fi.absoluteFilePath();
203 QRegExp rxp ("--pyscript=\\[(.+)\\]");
204 QRegExp rxl ("--siman-study=(.+)");
205 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
207 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
208 for (int k = 0; k < dictList.count(); ++k) {
209 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
210 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
211 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
212 pyfiles += rxd.capturedTexts()[m];
218 if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
220 loadStudy = rxl.capturedTexts()[1];
226 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
227 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
229 LightApp_Application::start();
230 SALOME_EventFilter::Init();
232 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
233 onOpenDoc( hdffile );
234 else if ( pyfiles.count() > 0 ) // create new study
236 else if (!loadStudy.isEmpty()) {// load study by name
237 if (onLoadDoc(loadStudy))
238 updateObjectBrowser(true);
241 #ifndef DISABLE_PYCONSOLE
242 // import/execute python scripts
243 if ( pyfiles.count() > 0 && activeStudy() ) {
244 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
245 PyConsole_Console* pyConsole = pythonConsole();
246 if ( appStudy && pyConsole ) {
247 _PTR(Study) aStudy = appStudy->studyDS();
248 if ( !aStudy->GetProperties()->IsLocked() ) {
249 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
250 // Path is absolute, script has .py extension
251 for (uint j = 0; j < pyfiles.count(); j++ ) {
252 // Extract scripts and their arguments, if any
253 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
254 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
255 QString script = rxp.capturedTexts()[1];
257 QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
258 for (uint k = 0; k < argList.count(); k++ ) {
259 QString arg = argList[k].trimmed();
260 arg.remove( QRegExp("^[\"]") );
261 arg.remove( QRegExp("[\"]$") );
264 args.remove( QRegExp("[,]$") );
265 if (!args.isEmpty()) {
269 script.remove( QRegExp("^python.*[\\s]+") );
270 QString cmd = script+" "+args;
271 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
272 pyConsole->exec(command);
274 } // end for loop on pyfiles QStringList
280 LightApp_Application::start();
281 SALOME_EventFilter::Init();
286 void SalomeApp_Application::createActions()
288 LightApp_Application::createActions();
290 SUIT_Desktop* desk = desktop();
293 // "Save GUI State" command is moved to VISU module
294 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
295 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
296 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
299 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
300 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
301 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
304 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
305 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
306 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
309 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
310 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
311 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
313 //! Catalog Generator
314 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
315 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
316 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
319 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
320 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
321 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
323 //rnv commented : implementation of the mono-study in GUI
325 //createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
326 // resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
327 // tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
328 // Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
333 // check-in operations for SIMAN study
334 createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
335 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
336 0, desk, false, this, SLOT( onCheckIn() ) );
337 createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
338 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
339 0, desk, false, this, SLOT( onLocalCheckIn() ) );
343 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
345 // "Save GUI State" command is renamed to "Save VISU State" and
346 // creation of menu item is moved to VISU
347 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
349 // createMenu( FileLoadId, fileMenu, 0 );
353 // check-in operation for SIMAN study
354 // last argument "5" locates this just after "Save As" but certain constant is bad => insert after the separator
355 createMenu( SimanCheckInId, fileMenu, 5);
356 createMenu( SimanLocalCheckInId, fileMenu, 5);
357 createMenu( separator(), fileMenu, 5 );
360 createMenu( DumpStudyId, fileMenu, 10, -1 );
361 createMenu( separator(), fileMenu, -1, 10, -1 );
362 createMenu( LoadScriptId, fileMenu, 10, -1 );
363 createMenu( separator(), fileMenu, -1, 10, -1 );
364 createMenu( PropertiesId, fileMenu, 10, -1 );
365 createMenu( separator(), fileMenu, -1, 10, -1 );
367 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
368 createMenu( CatalogGenId, toolsMenu, 10, -1 );
369 createMenu( RegDisplayId, toolsMenu, 10, -1 );
370 createMenu( separator(), toolsMenu, -1, 15, -1 );
372 createExtraActions();
374 #ifndef DISABLE_PYCONSOLE
375 #ifndef DISABLE_SALOMEOBJECT
376 // import Python module that manages SALOME plugins
378 PyLockWrapper lck; // acquire GIL
379 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
380 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str());
384 // end of SALOME plugins loading
392 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
394 LightApp_Application::setDesktop( desk );
397 connect( desk, SIGNAL( message( const QString& ) ),
398 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
403 \brief Close application.
405 void SalomeApp_Application::onExit()
407 bool killServers = false;
410 if ( exitConfirmation() ) {
411 SalomeApp_ExitDlg dlg( desktop() );
412 result = dlg.exec() == QDialog::Accepted;
413 killServers = dlg.isServersShutdown();
417 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
420 /*!SLOT. Load document.*/
421 void SalomeApp_Application::onLoadDoc()
425 std::vector<std::string> List = studyMgr()->GetOpenStudies();
427 // rnv: According to the single-study approach on the server side
428 // can be only one study. So if it is exists connect to them,
429 // overwise show warning message: "No active study on the server"
432 SUIT_Session* aSession = SUIT_Session::session();
433 QList<SUIT_Application*> aAppList = aSession->applications();
435 QStringList unloadedStudies;
437 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
438 studyName = List[ind].c_str();
439 // Add to list only unloaded studies
440 bool isAlreadyOpen = false;
441 QListIterator<SUIT_Application*> it( aAppList );
442 while ( it.hasNext() && !isAlreadyOpen ) {
443 SUIT_Application* aApp = it.next();
444 if( !aApp || !aApp->activeStudy() )
446 if ( aApp->activeStudy()->studyName() == studyName )
447 isAlreadyOpen = true;
450 if ( !isAlreadyOpen )
451 unloadedStudies << studyName;
453 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
454 if ( studyName.isEmpty() )
458 if(List.size() <= 0) {
459 SUIT_MessageBox::warning( desktop(),
460 QObject::tr("WRN_WARNING"),
461 QObject::tr("WRN_NO_STUDY_ON SERV") );
465 studyName = List[0].c_str();
468 // this code replaces marker of windows drive and path become invalid therefore
469 // defines placed there
470 studyName.replace( QRegExp(":"), "/" );
473 if ( onLoadDoc( studyName ) ) {
475 updateViewManagers();
476 updateObjectBrowser( true );
480 /*!SLOT. Create new study and load script*/
481 void SalomeApp_Application::onNewWithScript()
483 QStringList filtersList;
484 filtersList.append(tr("PYTHON_FILES_FILTER"));
485 filtersList.append(tr("ALL_FILES_FILTER"));
487 QString anInitialPath = "";
488 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
489 anInitialPath = QDir::currentPath();
491 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
493 if ( !aFile.isEmpty() )
497 QString command = QString("execfile(r\"%1\")").arg(aFile);
499 #ifndef DISABLE_PYCONSOLE
500 PyConsole_Console* pyConsole = pythonConsole();
503 pyConsole->exec( command );
509 /*!SLOT. Load document with \a aName.*/
510 bool SalomeApp_Application::onLoadDoc( const QString& aName )
512 #ifdef SINGLE_DESKTOP
513 if ( !LightApp_Application::closeDoc() )
517 if ( !activeStudy() ) {
518 // if no study - load in current desktop
519 res = useStudy( aName );
522 // if study exists - load in new desktop. Check: is the same file is loaded?
523 SUIT_Session* aSession = SUIT_Session::session();
524 QList<SUIT_Application*> aAppList = aSession->applications();
525 bool isAlreadyOpen = false;
526 SalomeApp_Application* aApp = 0;
527 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
528 it != aAppList.end() && !isAlreadyOpen; ++it ) {
529 aApp = dynamic_cast<SalomeApp_Application*>( *it );
530 if ( aApp && aApp->activeStudy()->studyName() == aName )
531 isAlreadyOpen = true;
533 if ( !isAlreadyOpen ) {
534 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
536 res = aApp->useStudy( aName );
539 aApp->desktop()->activateWindow();
546 /*!SLOT. Load document with a name, specified in \a aMessage.*/
547 void SalomeApp_Application::onLoadDocMessage(const QString& aMessage)
549 if (aMessage.indexOf("simanCheckoutDone ") == 0) {
551 onLoadDoc(aMessage.section(' ', 1));
553 printf( "****************************************************************\n" );
554 printf( "* Warning: SALOME is built without SIMAN support.\n" );
555 printf( "****************************************************************\n" );
560 /*!SLOT. Copy objects to study maneger from selection maneger..*/
561 void SalomeApp_Application::onCopy()
564 LightApp_SelectionMgr* mgr = selectionMgr();
565 mgr->selectedObjects(list);
567 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
568 if(study == NULL) return;
570 _PTR(Study) stdDS = study->studyDS();
573 SALOME_ListIteratorOfListIO it( list );
576 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
578 studyMgr()->Copy(so);
579 onSelectionChanged();
586 /*!SLOT. Paste objects to study maneger from selection manager.*/
587 void SalomeApp_Application::onPaste()
590 LightApp_SelectionMgr* mgr = selectionMgr();
591 mgr->selectedObjects(list);
593 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
594 if(study == NULL) return;
596 _PTR(Study) stdDS = study->studyDS();
599 if ( stdDS->GetProperties()->IsLocked() ) {
600 SUIT_MessageBox::warning( desktop(),
601 QObject::tr("WRN_WARNING"),
602 QObject::tr("WRN_STUDY_LOCKED") );
606 SALOME_ListIteratorOfListIO it( list );
609 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
611 studyMgr()->Paste(so);
612 updateObjectBrowser( true );
613 updateActions(); //SRN: BugID IPAL9377, case 3
620 /*!Check the application on closing.
621 * \retval true if possible, else false
623 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
625 return LightApp_Application::isPossibleToClose( closePermanently );
628 /*! Check if the study is locked */
629 void SalomeApp_Application::onCloseDoc( bool ask )
631 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
634 _PTR(Study) stdDS = study->studyDS();
635 if(stdDS && stdDS->IsStudyLocked()) {
636 if ( SUIT_MessageBox::question( desktop(),
637 QObject::tr( "WRN_WARNING" ),
638 QObject::tr( "CLOSE_LOCKED_STUDY" ),
639 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
640 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
645 LightApp_Application::onCloseDoc( ask );
648 /*!Sets enable or disable some actions on selection changed.*/
649 void SalomeApp_Application::onSelectionChanged()
652 LightApp_SelectionMgr* mgr = selectionMgr();
653 mgr->selectedObjects(list);
655 bool canCopy = false;
656 bool canPaste = false;
658 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
660 _PTR(Study) stdDS = study->studyDS();
663 SALOME_ListIteratorOfListIO it ( list );
665 if (it.More() && list.Extent() == 1) {
666 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
669 canCopy = studyMgr()->CanCopy(so);
670 canPaste = studyMgr()->CanPaste(so);
676 action(EditCopyId)->setEnabled(canCopy);
677 action(EditPasteId)->setEnabled(canPaste);
680 /*!Delete references.*/
681 void SalomeApp_Application::onDeleteInvalidReferences()
684 LightApp_SelectionMgr* mgr = selectionMgr();
685 mgr->selectedObjects( aList, QString(), false );
687 if( aList.IsEmpty() )
690 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
691 _PTR(Study) aStudyDS = aStudy->studyDS();
692 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
695 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
696 if ( it.Value()->hasEntry() )
698 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
699 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
702 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
703 aStudyBuilder->RemoveReference( aSObject );
705 updateObjectBrowser();
709 void SalomeApp_Application::onOpenWith()
711 QApplication::setOverrideCursor( Qt::WaitCursor );
713 LightApp_SelectionMgr* mgr = selectionMgr();
714 mgr->selectedObjects(aList);
715 if (aList.Extent() != 1)
717 QApplication::restoreOverrideCursor();
720 Handle(SALOME_InteractiveObject) aIObj = aList.First();
721 QString aModuleName(aIObj->getComponentDataType());
722 QString aModuleTitle = moduleTitle(aModuleName);
723 activateModule(aModuleTitle);
724 QApplication::restoreOverrideCursor();
730 SUIT_Study* SalomeApp_Application::createNewStudy()
732 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
734 // Set up processing of major study-related events
735 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
736 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
737 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
738 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
740 #ifndef DISABLE_PYCONSOLE
741 //to receive signal in application that NoteBook's variable was modified
742 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
743 this, SIGNAL(notebookVarUpdated(QString)) );
750 Enable/Disable menu items and toolbar buttons. Rebuild menu
752 void SalomeApp_Application::updateCommandsStatus()
754 LightApp_Application::updateCommandsStatus();
757 QAction* a = action( DumpStudyId );
759 a->setEnabled( activeStudy() );
762 a = action( LoadScriptId );
764 a->setEnabled( activeStudy() );
767 a = action( PropertiesId );
769 a->setEnabled( activeStudy() );
771 // Save GUI state menu
772 a = action( SaveGUIStateId );
774 a->setEnabled( activeStudy() );
776 // update state of Copy/Paste menu items
777 onSelectionChanged();
781 \class DumpStudyFileDlg
782 Private class used in Dump Study operation. Consists 2 check boxes:
783 "Publish in study" and "Save GUI parameters"
785 class DumpStudyFileDlg : public SUIT_FileDlg
788 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
790 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
793 QWidget *hB = new QWidget( this );
794 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
795 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
796 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
798 QHBoxLayout *layout = new QHBoxLayout;
799 layout->addWidget(myPublishChk);
800 layout->addWidget(myMultiFileChk);
801 layout->addWidget(mySaveGUIChk);
802 hB->setLayout(layout);
804 QPushButton* pb = new QPushButton(this);
806 int row = grid->rowCount();
807 grid->addWidget( new QLabel("", this), row, 0 );
808 grid->addWidget( hB, row, 1, 1, 3 );
809 grid->addWidget( pb, row, 5 );
814 QCheckBox* myPublishChk;
815 QCheckBox* myMultiFileChk;
816 QCheckBox* mySaveGUIChk;
819 class DumpStudyFileValidator : public SUIT_FileValidator
822 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
823 virtual ~DumpStudyFileValidator() {};
824 virtual bool canSave( const QString& file, bool permissions );
827 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
829 QFileInfo fi( file );
830 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
831 SUIT_MessageBox::critical( parent(),
832 QObject::tr("WRN_WARNING"),
833 QObject::tr("WRN_FILE_NAME_BAD") );
836 return SUIT_FileValidator::canSave( file, permissions);
839 /*!Private SLOT. On dump study.*/
840 void SalomeApp_Application::onDumpStudy( )
842 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
843 if ( !appStudy ) return;
844 _PTR(Study) aStudy = appStudy->studyDS();
846 QStringList aFilters;
847 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
849 bool anIsPublish = true;
850 bool anIsMultiFile = false;
851 bool anIsSaveGUI = true;
853 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
854 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
855 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
856 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
859 DumpStudyFileDlg fd( desktop() );
860 fd.setValidator( new DumpStudyFileValidator( &fd ) );
861 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
862 fd.setFilters( aFilters );
863 fd.myPublishChk->setChecked( anIsPublish );
864 fd.myMultiFileChk->setChecked( anIsMultiFile );
865 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
866 if ( fd.exec() == QDialog::Accepted )
868 QString aFileName = fd.selectedFile();
870 bool toPublish = fd.myPublishChk->isChecked();
871 bool isMultiFile = fd.myMultiFileChk->isChecked();
872 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
874 if ( !aFileName.isEmpty() ) {
875 QFileInfo aFileInfo(aFileName);
876 if( aFileInfo.isDir() ) // IPAL19257
879 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
882 SUIT_OverrideCursor wc;
883 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
886 SUIT_MessageBox::warning( desktop(),
887 QObject::tr("WRN_WARNING"),
888 tr("WRN_DUMP_STUDY_FAILED") );
893 /*!Private SLOT. On load script.*/
894 void SalomeApp_Application::onLoadScript( )
896 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
897 if ( !appStudy ) return;
898 _PTR(Study) aStudy = appStudy->studyDS();
900 if ( aStudy->GetProperties()->IsLocked() ) {
901 SUIT_MessageBox::warning( desktop(),
902 QObject::tr("WRN_WARNING"),
903 QObject::tr("WRN_STUDY_LOCKED") );
907 QStringList filtersList;
908 filtersList.append(tr("PYTHON_FILES_FILTER"));
909 filtersList.append(tr("ALL_FILES_FILTER"));
911 QString anInitialPath = "";
912 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
913 anInitialPath = QDir::currentPath();
916 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
918 SALOMEDSClient_StudyManager* aMgr = studyMgr();
919 aMgr->GetSimanStudy()->StudyId();
920 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
921 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
922 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
926 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
928 if ( !aFile.isEmpty() )
930 QString command = QString("execfile(r\"%1\")").arg(aFile);
932 #ifndef DISABLE_PYCONSOLE
933 PyConsole_Console* pyConsole = pythonConsole();
936 pyConsole->exec( command );
941 /*!Private SLOT. On save GUI state.*/
942 void SalomeApp_Application::onSaveGUIState()
944 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
946 SalomeApp_VisualState( this ).storeState();
947 updateSavePointDataObjects( study );
948 updateObjectBrowser();
953 /*!Public SLOT. On SIMAN check in operation.*/
954 void SalomeApp_Application::onCheckIn()
957 setMenuShown(SimanCheckInId, false); // check in may be performed only once
958 setMenuShown(SimanLocalCheckInId, false);
959 SALOMEDSClient_StudyManager* aMgr = studyMgr();
960 aMgr->GetSimanStudy()->CheckIn("");
962 printf( "****************************************************************\n" );
963 printf( "* Warning: SALOME is built without SIMAN support.\n" );
964 printf( "****************************************************************\n" );
968 /*!Public SLOT. On SIMAN local check in operation.*/
969 void SalomeApp_Application::onLocalCheckIn()
972 // get the active module
973 CAM_Module* aModule = activeModule();
974 if (!aModule) return; // there is no active module
976 setMenuShown(SimanCheckInId, false); // check in may be performed only once
977 setMenuShown(SimanLocalCheckInId, false);
978 SALOMEDSClient_StudyManager* aMgr = studyMgr();
979 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
981 printf( "****************************************************************\n" );
982 printf( "* Warning: SALOME is built without SIMAN support.\n" );
983 printf( "****************************************************************\n" );
988 *\retval QString "(*.hdf)"
990 QString SalomeApp_Application::getFileFilter() const
996 QWidget* SalomeApp_Application::createWindow( const int flag )
999 #ifndef DISABLE_PYCONSOLE
1000 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1002 wid = LightApp_Application::createWindow(flag);
1005 SUIT_ResourceMgr* resMgr = resourceMgr();
1007 if ( flag == WT_ObjectBrowser )
1009 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1011 // temporary commented
1012 //ob->setUpdater( new SalomeApp_Updater() );
1014 #ifdef WITH_SALOMEDS_OBSERVER
1015 //do not activate the automatic update of Qt tree through signal/slot
1016 ob->setAutoUpdate(false);
1017 //activate update of modified objects only
1018 ob->setUpdateModified(true);
1021 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1024 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1025 IORCol = QObject::tr( "IOR_COLUMN" ),
1026 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1027 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1029 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1030 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1031 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1032 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1033 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1034 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1035 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1036 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1037 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1039 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1040 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1041 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1043 ob->setAutoSizeFirstColumn(autoSizeFirst);
1044 ob->setAutoSizeColumns(autoSize);
1045 ob->setResizeOnExpandItem(resizeOnExpandItem);
1046 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1048 // temporary commented
1050 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1052 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1053 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1054 QString().sprintf( "visibility_column_%d", i ), true ) );
1058 // temporary commented
1060 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1061 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1062 ob->resize( desktop()->width()/3, ob->height() );
1066 #ifndef DISABLE_PYCONSOLE
1067 else if ( flag == WT_PyConsole )
1069 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1070 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1071 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1072 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1073 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1075 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1076 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1078 else if ( flag == WT_NoteBook )
1080 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1082 _PTR(Study) aStudy = appStudy->studyDS();
1083 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1084 //to receive signal in NoteBook that it's variable was modified
1085 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1086 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1088 wid = getNoteBook();
1094 /*!Create preferences.*/
1095 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1097 LightApp_Application::createPreferences(pref);
1102 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1103 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1104 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1105 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1107 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1108 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1110 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1112 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1113 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1114 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1115 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1116 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1117 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1118 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1119 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1120 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1121 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1124 /*!Update desktop title.*/
1125 void SalomeApp_Application::updateDesktopTitle() {
1126 QString aTitle = applicationName();
1127 QString aVer = applicationVersion();
1128 if ( !aVer.isEmpty() )
1129 aTitle += QString( " " ) + aVer;
1131 if ( activeStudy() )
1133 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1134 if ( !sName.isEmpty() ) {
1135 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1137 _PTR(Study) stdDS = study->studyDS();
1139 if ( stdDS->GetProperties()->IsLocked() ) {
1140 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1142 aTitle += QString( " - [%1]" ).arg( sName );
1149 desktop()->setWindowTitle( aTitle );
1152 int SalomeApp_Application::closeChoice( const QString& docName )
1154 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1155 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1156 //tr ("APPCLOSE_UNLOAD"),
1157 tr ("APPCLOSE_CANCEL"), 0 );
1159 int res = CloseCancel;
1162 else if ( answer == 1 )
1164 // else if ( answer == 2 )
1165 // res = CloseUnload;
1170 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1176 if ( activeStudy()->isSaved() )
1178 else if ( !onSaveAsDoc() )
1184 closePermanently = false;
1194 int SalomeApp_Application::openChoice( const QString& aName )
1196 int choice = LightApp_Application::openChoice( aName );
1198 if ( QFileInfo( aName ).exists() ) {
1199 if ( choice == OpenNew ) { // The document isn't already open.
1201 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1202 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1203 if ( aName == QString( lst[i].c_str() ) )
1206 // The document already exists in the study manager.
1207 // Do you want to reload it?
1209 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1210 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1211 if ( answer == SUIT_MessageBox::Yes )
1212 choice = OpenRefresh;
1214 choice = OpenCancel;
1217 } else { // file is not exist on disk
1218 SUIT_MessageBox::warning( desktop(),
1219 QObject::tr("WRN_WARNING"),
1220 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1227 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1230 int choice = aChoice;
1235 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1238 studyMgr()->Close( aStudy );
1243 res = LightApp_Application::openAction( choice, aName );
1251 \brief Get map of the operations which can be performed
1252 on the module activation.
1254 The method should return the map of the kind \c {<id>:<name>}
1255 where \c <id> is an integer identifier of the operation and
1256 \c <name> is a title for the button to be added to the
1257 dialog box. After user selects the required operation by the
1258 clicking the corresponding button in the dialog box, its identifier
1259 is passed to the moduleActionSelected() method to process
1262 \return map of the operations
1263 \sa moduleActionSelected()
1265 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1267 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1269 // rnv commented : implementation of the mono-study in GUI
1270 // opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1272 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1277 \brief Called when the used selectes required operation chosen
1278 from "Activate module" dialog box.
1280 Performs the required operation according to the user choice.
1282 \param id operation identifier
1283 \sa activateModuleActions()
1285 void SalomeApp_Application::moduleActionSelected( const int id )
1291 case NewAndScriptId:
1295 LightApp_Application::moduleActionSelected( id );
1300 /*!Gets CORBA::ORB_var*/
1301 CORBA::ORB_var SalomeApp_Application::orb()
1303 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1304 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1308 /*!Create and return SALOMEDS_StudyManager.*/
1309 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1311 static _PTR(StudyManager) _sm;
1312 if(!_sm) _sm = ClientFactory::StudyManager();
1316 /*!Create and return SALOME_NamingService.*/
1317 SALOME_NamingService* SalomeApp_Application::namingService()
1319 static SALOME_NamingService _ns(orb());
1323 /*!Create and return SALOME_LifeCycleCORBA.*/
1324 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1326 static SALOME_LifeCycleCORBA _lcc( namingService() );
1330 /*!Private SLOT. On preferences.*/
1331 void SalomeApp_Application::onProperties()
1333 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1337 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1340 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1341 int res = aDlg.exec();
1342 if( res==QDialog::Accepted && aDlg.isChanged() )
1343 SB->CommitCommand();
1347 //study->updateCaptions();
1348 updateDesktopTitle();
1352 /*!Insert items in popup, which necessary for current application*/
1353 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1355 LightApp_SelectionMgr* mgr = selectionMgr();
1356 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1357 mgr->setSelectionCacheEnabled( true );
1359 LightApp_Application::contextMenuPopup( type, thePopup, title );
1361 // temporary commented
1362 /*OB_Browser* ob = objectBrowser();
1363 if ( !ob || type != ob->popupClientType() )
1366 // Get selected objects
1367 SALOME_ListIO aList;
1368 mgr->selectedObjects( aList, QString(), false );
1370 // add GUI state commands: restore, rename
1371 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1372 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1373 thePopup->addSeparator();
1374 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1375 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1376 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1377 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1380 // "Delete reference" item should appear only for invalid references
1382 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1383 bool isInvalidRefs = false;
1384 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1385 _PTR(Study) aStudyDS = aStudy->studyDS();
1386 _PTR(SObject) anObj;
1388 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1389 if( it.Value()->hasEntry() )
1391 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1392 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1395 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1396 isInvalidRefs = true;
1399 // Add "Delete reference" item to popup
1400 if ( isInvalidRefs )
1402 thePopup->addSeparator();
1403 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1407 // "Activate module" item should appear only if it's necessary
1408 if ( aList.Extent() == 1 ) {
1410 mgr->selectedObjects( aList );
1412 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1414 // add extra popup menu (defined in XML)
1415 if ( myExtActions.size() > 0 ) {
1416 // Use only first selected object
1417 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1419 _PTR(Study) stdDS = study->studyDS();
1421 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1423 _PTR( GenericAttribute ) anAttr;
1424 std::string auid = "AttributeUserID";
1425 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1426 if ( aSO->FindAttribute( anAttr, auid ) ) {
1427 _PTR(AttributeUserID) aAttrID = anAttr;
1428 QString aId = aAttrID->Value().c_str();
1429 if ( myExtActions.contains( aId ) ) {
1430 thePopup->addAction(myExtActions[aId]);
1438 // check if item is a "GUI state" item (also a first level object)
1439 QString entry( aIObj->getEntry() );
1440 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1441 QString aModuleName( aIObj->getComponentDataType() );
1442 QString aModuleTitle = moduleTitle( aModuleName );
1443 CAM_Module* currentModule = activeModule();
1444 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1445 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1449 mgr->setSelectionCacheEnabled( cacheIsOn );
1452 /*!Update obect browser:
1453 1.if 'updateModels' true, update existing data models;
1454 2. update "non-existing" (not loaded yet) data models;
1455 3. update object browser if it exists */
1456 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1458 // update "non-existing" (not loaded yet) data models
1459 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1462 _PTR(Study) stdDS = study->studyDS();
1465 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1467 _PTR(SComponent) aComponent ( it->Value() );
1469 #ifndef WITH_SALOMEDS_OBSERVER
1470 // with GUI observers this check is not needed anymore
1471 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1472 continue; // skip the magic "Interface Applicative" component
1474 if ( !objectBrowser() )
1475 getWindow( WT_ObjectBrowser );
1476 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1477 objectBrowser()->setAutoUpdate( false );
1478 SalomeApp_DataModel::synchronize( aComponent, study );
1479 objectBrowser()->setAutoUpdate( isAutoUpdate );
1484 // create data objects that correspond to GUI state save points
1485 if ( study ) updateSavePointDataObjects( study );
1487 // update existing data models (already loaded SComponents)
1488 LightApp_Application::updateObjectBrowser( updateModels );
1491 /*!Display Catalog Genenerator dialog */
1492 void SalomeApp_Application::onCatalogGen()
1494 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1498 /*!Display Registry Display dialog */
1499 void SalomeApp_Application::onRegDisplay()
1501 CORBA::ORB_var anOrb = orb();
1502 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1505 regWnd->activateWindow();
1508 /*!find original object by double click on item */
1509 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1511 // Issue 21379: References are supported at LightApp_DataObject level
1512 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1514 if( obj && obj->isReference() )
1516 QString entry = obj->refEntry();
1518 SUIT_DataOwnerPtrList aList;
1519 aList.append( new LightApp_DataOwner( entry ) );
1520 selectionMgr()->setSelected( aList, false );
1522 SUIT_DataBrowser* ob = objectBrowser();
1524 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1525 if ( !aSelectedIndexes.isEmpty() )
1526 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1531 Creates new view manager
1532 \param type - type of view manager
1534 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1536 return createViewManager(type);
1540 /*!Global utility function, returns selected GUI Save point object's ID */
1541 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1543 SALOME_ListIO aList;
1544 selMgr->selectedObjects( aList );
1545 if( aList.Extent() > 0 ) {
1546 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1547 QString entry( aIObj->getEntry() );
1548 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1549 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1551 bool ok; // conversion to integer is ok?
1552 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1553 return ok ? savePoint : -1;
1558 /*!Called on Restore GUI State popup command*/
1559 void SalomeApp_Application::onRestoreGUIState()
1561 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1562 if ( savePoint == -1 )
1564 SalomeApp_VisualState( this ).restoreState( savePoint );
1567 /*!Called on Delete GUI State popup command*/
1568 void SalomeApp_Application::onDeleteGUIState()
1570 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1571 if ( savePoint == -1 )
1573 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1577 study->removeSavePoint( savePoint );
1578 updateSavePointDataObjects( study );
1581 /*!Called on New study operation*/
1582 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1584 LightApp_Application::onStudyCreated( study );
1586 //#ifndef DISABLE_PYCONSOLE
1587 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1588 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1591 loadDockWindowsState();
1593 objectBrowserColumnsVisibility();
1596 /*!Called on Open study operation*/
1597 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1599 LightApp_Application::onStudyOpened( study );
1601 //#ifndef DISABLE_PYCONSOLE
1602 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1603 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1606 loadDockWindowsState();
1608 objectBrowserColumnsVisibility();
1610 // temporary commented
1611 /*if ( objectBrowser() ) {
1612 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1613 objectBrowser()->updateTree( study->root() );
1617 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1618 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1621 SUIT_DataBrowser* ob = objectBrowser();
1622 LightApp_SelectionMgr* selMgr = selectionMgr();
1624 if ( !study || !ob || !selMgr )
1627 // find GUI states root object
1628 SUIT_DataObject* guiRootObj = 0;
1630 study->root()->children( ch );
1631 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1632 for ( ; it != last ; ++it ) {
1633 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1638 std::vector<int> savePoints = study->getSavePoints();
1639 // case 1: no more save points but they existed in study's tree
1640 if ( savePoints.empty() && guiRootObj ) {
1641 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1642 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1643 const bool isAutoUpdate = ob->autoUpdate();
1644 selMgr->clearSelected();
1645 ob->setAutoUpdate(true);
1646 DataObjectList ch = guiRootObj->children();
1647 for( int i = 0; i < ch.size(); i++ )
1650 ob->setAutoUpdate(isAutoUpdate);
1653 // case 2: no more save points but root does not exist either
1654 if ( savePoints.empty() && !guiRootObj )
1656 // case 3: save points but no root for them - create it
1657 if ( !savePoints.empty() && !guiRootObj )
1658 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1659 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1660 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1662 if ( guiRootObj->nextBrother() ) {
1663 study->root()->removeChild(guiRootObj);
1664 study->root()->appendChild(guiRootObj);
1665 //study->root()->dump();
1668 // store data objects in a map id-to-DataObject
1669 QMap<int,SalomeApp_SavePointObject*> mapDO;
1671 guiRootObj->children( ch );
1672 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1673 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1675 mapDO[dobj->getId()] = dobj;
1678 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1679 // if in the map - remove it from map.
1680 for ( int i = 0; i < savePoints.size(); i++ )
1681 if ( !mapDO.contains( savePoints[i] ) )
1682 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1684 mapDO.remove( savePoints[i] );
1686 // delete DataObjects that are still in the map -- their IDs were not found in data model
1687 if( mapDO.size() > 0) {
1688 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1689 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1690 selMgr->clearSelected();
1691 const bool isAutoUpdate = ob->autoUpdate();
1692 ob->setAutoUpdate(true);
1693 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1695 ob->setAutoUpdate(isAutoUpdate);
1699 /*! Check data object */
1700 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1709 Opens other study into active Study. If Study is empty - creates it.
1710 \param theName - name of study
1712 bool SalomeApp_Application::useStudy( const QString& theName )
1715 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1718 res = aStudy->loadDocument( theName );
1719 updateDesktopTitle();
1720 updateCommandsStatus();
1724 /*! Show/hide object browser colums according to preferences */
1725 void SalomeApp_Application::objectBrowserColumnsVisibility()
1727 if ( objectBrowser() )
1728 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1730 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1731 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1735 #ifndef DISABLE_PYCONSOLE
1736 /*! Set SalomeApp_NoteBook pointer */
1737 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1739 myNoteBook = theNoteBook;
1742 /*! Return SalomeApp_NoteBook pointer */
1743 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1750 * Define extra actions defined in module definition XML file.
1751 * Additional popup items sections can be defined by parameter "popupitems".
1752 * Supported attributes:
1753 * title - title of menu item,
1754 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1755 * method - method which has to be called when menu item is selected
1757 * <section name="MODULENAME">
1758 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1760 * <section name="importmed">
1761 * <parameter name="title" value="My menu"/>
1762 * <parameter name="objectid" value="VISU.Result"/>
1763 * <parameter name="method" value="nameOfModuleMethod"/>
1766 void SalomeApp_Application::createExtraActions()
1768 myExtActions.clear();
1769 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1771 QStringList aModules;
1772 modules(aModules, false);
1773 foreach(QString aModile, aModules) {
1774 QString aModName = moduleName(aModile);
1775 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1776 if (!aSectionStr.isNull()) {
1777 QStringList aSections = aSectionStr.split(':');
1778 foreach(QString aSection, aSections) {
1779 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1780 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1781 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1782 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1785 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1786 if (aModuleName.isNull())
1787 aModuleName = aModName;
1789 QAction* aAction = new QAction(aTitle, this);
1791 aData<<aModuleName<<aSlot;
1792 aAction->setData(aData);
1793 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1794 myExtActions[aId] = aAction;
1801 * Called when extra action is selected
1803 void SalomeApp_Application::onExtAction()
1805 QAction* aAction = ::qobject_cast<QAction*>(sender());
1809 QVariant aData = aAction->data();
1810 QStringList aDataList = aData.value<QStringList>();
1811 if (aDataList.size() != 2)
1814 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1815 SALOME_ListIO aListIO;
1816 aSelectionMgr->selectedObjects(aListIO);
1817 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1818 if (aListIO.Extent() < 1)
1820 if (!anIO->hasEntry())
1823 QString aEntry(anIO->getEntry());
1825 QApplication::setOverrideCursor( Qt::WaitCursor );
1826 QString aModuleTitle = moduleTitle(aDataList[0]);
1827 activateModule(aModuleTitle);
1828 QApplication::restoreOverrideCursor();
1830 QCoreApplication::processEvents();
1832 CAM_Module* aModule = activeModule();
1836 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1837 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1841 Checks that an object can be renamed.
1842 \param entry entry of the object
1843 \brief Return \c true if object can be renamed
1845 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1847 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1851 Rename object by entry.
1852 \param entry entry of the object
1853 \param name new name of the object
1854 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1856 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1858 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1860 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1862 if(!aStudy || savePoint == -1)
1865 if ( !name.isNull() && !name.isEmpty() ) {
1866 aStudy->setNameOfSavePoint( savePoint, name );
1867 updateSavePointDataObjects( aStudy );
1869 //Mark study as modified
1876 #ifndef DISABLE_PYCONSOLE
1877 //============================================================================
1878 /*! Function : onUpdateStudy
1879 * Purpose : Slot to update the study.
1881 //============================================================================
1882 void SalomeApp_Application::onUpdateStudy()
1884 QApplication::setOverrideCursor( Qt::WaitCursor );
1886 if( !updateStudy() )
1887 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1889 QApplication::restoreOverrideCursor();
1892 //============================================================================
1893 /*! Function : updateStudy
1894 * Purpose : Update study by dumping the study to Python script and loading it.
1895 * It is used to apply variable modifications done in NoteBook to created objects.
1897 //============================================================================
1898 bool SalomeApp_Application::updateStudy()
1900 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1901 if ( !study || !myNoteBook )
1904 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1905 myNoteBook->setDumpedStudyName( study->studyName() );
1907 _PTR(Study) studyDS = study->studyDS();
1909 // get unique temporary directory name
1910 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1911 if( aTmpDir.isEmpty() )
1914 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1915 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1917 // dump study to the temporary directory
1918 QString aScriptName( "notebook" );
1919 bool toPublish = true;
1920 bool isMultiFile = false;
1921 bool toSaveGUI = true;
1924 _PTR(AttributeParameter) ap;
1925 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1926 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1927 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1928 ip->setDumpPython(studyDS);
1929 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1931 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1933 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1936 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1940 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1941 int anIndex = aList.indexOf( this );
1943 // Disconnect dialog from application desktop in case if:
1944 // 1) Application is not the first application in the session
1945 // 2) Application is the first application in session but not the only.
1946 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1947 if( changeDesktop ) {
1949 SalomeApp_Application* app = this;
1950 if( anIndex > 0 && anIndex < aList.count() )
1951 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1952 else if(anIndex == 0 && aList.count() > 1)
1953 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1958 // creation a new study and restoring will be done in another application
1959 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
1960 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
1963 QString aDumpScript = myNoteBook->getDumpedStudyScript();
1964 QString aStudyName = myNoteBook->getDumpedStudyName();
1965 bool isStudySaved = myNoteBook->isDumpedStudySaved();
1966 // clear a study (delete all objects)
1967 onCloseDoc( false );
1969 if( !changeDesktop ) {
1970 ok = onRestoreStudy( aDumpScript,
1979 //============================================================================
1980 /*! Function : onRestoreStudy
1981 * Purpose : Load the dumped study from Python script
1983 //============================================================================
1984 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
1985 const QString& theStudyName,
1986 bool theIsStudySaved )
1990 // create a new study
1993 // get active application
1994 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
1996 // load study from the temporary directory
1997 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
1999 #ifndef DISABLE_PYCONSOLE
2000 PyConsole_Console* pyConsole = app->pythonConsole();
2002 pyConsole->execAndWait( command );
2005 // remove temporary directory
2006 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2007 QString aStudyName = aScriptInfo.baseName();
2008 QDir aDir = aScriptInfo.absoluteDir();
2009 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2010 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2011 ok = aDir.remove( *it ) && ok;
2013 ok = aDir.rmdir( aDir.absolutePath() );
2015 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2017 #ifndef DISABLE_PYCONSOLE
2018 _PTR(Study) aStudyDS = newStudy->studyDS();
2019 app->getNoteBook()->Init( aStudyDS );
2020 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2021 newStudy->Modified();
2022 updateDesktopTitle();
2033 Close the Application
2035 void SalomeApp_Application::afterCloseDoc()
2037 #ifndef DISABLE_PYCONSOLE
2038 // emit signal to restore study from Python script
2040 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2041 myNoteBook->getDumpedStudyName(),
2042 myNoteBook->isDumpedStudySaved() );
2045 LightApp_Application::afterCloseDoc();
2049 Asks to close existing document.
2051 bool SalomeApp_Application::checkExistingDoc() {
2053 if( activeStudy() ) {
2054 int answer = SUIT_MessageBox::question( desktop(),
2055 tr( "APPCLOSE_CAPTION" ),
2056 tr( "STUDYCLOSE_DESCRIPTION" ),
2057 tr( "APPCLOSE_SAVE" ),
2058 tr( "APPCLOSE_CLOSE" ),
2059 tr( "APPCLOSE_CANCEL" ), 0 );
2061 if ( activeStudy()->isSaved() ) {
2064 } else if ( onSaveAsDoc() ) {
2065 if( !closeDoc( false ) ) {
2072 else if( answer == 1 ) {
2074 } else if( answer == 2 ) {
2078 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2080 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2081 if( List.size() > 0 ) {
2082 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_ACTIVEDOC_LOAD" ),
2083 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
2084 if ( answer == SUIT_MessageBox::Yes ) {