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->setObjectName( "pythonConsole" );
1071 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1072 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1073 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1074 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1076 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1077 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1079 else if ( flag == WT_NoteBook )
1081 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1083 _PTR(Study) aStudy = appStudy->studyDS();
1084 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1085 //to receive signal in NoteBook that it's variable was modified
1086 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1087 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1089 wid = getNoteBook();
1090 wid->setObjectName( "noteBook" );
1096 /*!Create preferences.*/
1097 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1099 LightApp_Application::createPreferences(pref);
1104 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1105 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1106 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1107 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1109 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1110 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1112 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1114 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1115 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1116 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1117 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1118 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1119 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1120 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1121 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1122 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1123 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1126 /*!Update desktop title.*/
1127 void SalomeApp_Application::updateDesktopTitle() {
1128 QString aTitle = applicationName();
1129 QString aVer = applicationVersion();
1130 if ( !aVer.isEmpty() )
1131 aTitle += QString( " " ) + aVer;
1133 if ( activeStudy() )
1135 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1136 if ( !sName.isEmpty() ) {
1137 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1139 _PTR(Study) stdDS = study->studyDS();
1141 if ( stdDS->GetProperties()->IsLocked() ) {
1142 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1144 aTitle += QString( " - [%1]" ).arg( sName );
1151 desktop()->setWindowTitle( aTitle );
1154 int SalomeApp_Application::closeChoice( const QString& docName )
1156 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1157 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1158 //tr ("APPCLOSE_UNLOAD"),
1159 tr ("APPCLOSE_CANCEL"), 0 );
1161 int res = CloseCancel;
1164 else if ( answer == 1 )
1166 // else if ( answer == 2 )
1167 // res = CloseUnload;
1172 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1178 if ( activeStudy()->isSaved() )
1180 else if ( !onSaveAsDoc() )
1186 closePermanently = false;
1196 int SalomeApp_Application::openChoice( const QString& aName )
1198 int choice = LightApp_Application::openChoice( aName );
1200 if ( QFileInfo( aName ).exists() ) {
1201 if ( choice == OpenNew ) { // The document isn't already open.
1203 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1204 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1205 if ( aName == QString( lst[i].c_str() ) )
1208 // The document already exists in the study manager.
1209 // Do you want to reload it?
1211 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1212 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1213 if ( answer == SUIT_MessageBox::Yes )
1214 choice = OpenRefresh;
1216 choice = OpenCancel;
1219 } else { // file is not exist on disk
1220 SUIT_MessageBox::warning( desktop(),
1221 QObject::tr("WRN_WARNING"),
1222 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1229 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1232 int choice = aChoice;
1237 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1240 studyMgr()->Close( aStudy );
1245 res = LightApp_Application::openAction( choice, aName );
1253 \brief Get map of the operations which can be performed
1254 on the module activation.
1256 The method should return the map of the kind \c {<id>:<name>}
1257 where \c <id> is an integer identifier of the operation and
1258 \c <name> is a title for the button to be added to the
1259 dialog box. After user selects the required operation by the
1260 clicking the corresponding button in the dialog box, its identifier
1261 is passed to the moduleActionSelected() method to process
1264 \return map of the operations
1265 \sa moduleActionSelected()
1267 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1269 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1271 // rnv commented : implementation of the mono-study in GUI
1272 // opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1274 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1279 \brief Called when the used selectes required operation chosen
1280 from "Activate module" dialog box.
1282 Performs the required operation according to the user choice.
1284 \param id operation identifier
1285 \sa activateModuleActions()
1287 void SalomeApp_Application::moduleActionSelected( const int id )
1293 case NewAndScriptId:
1297 LightApp_Application::moduleActionSelected( id );
1302 /*!Gets CORBA::ORB_var*/
1303 CORBA::ORB_var SalomeApp_Application::orb()
1305 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1306 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1310 /*!Create and return SALOMEDS_StudyManager.*/
1311 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1313 static _PTR(StudyManager) _sm;
1314 if(!_sm) _sm = ClientFactory::StudyManager();
1318 /*!Create and return SALOME_NamingService.*/
1319 SALOME_NamingService* SalomeApp_Application::namingService()
1321 static SALOME_NamingService _ns(orb());
1325 /*!Create and return SALOME_LifeCycleCORBA.*/
1326 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1328 static SALOME_LifeCycleCORBA _lcc( namingService() );
1332 /*!Private SLOT. On preferences.*/
1333 void SalomeApp_Application::onProperties()
1335 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1339 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1342 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1343 int res = aDlg.exec();
1344 if( res==QDialog::Accepted && aDlg.isChanged() )
1345 SB->CommitCommand();
1349 //study->updateCaptions();
1350 updateDesktopTitle();
1354 /*!Insert items in popup, which necessary for current application*/
1355 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1357 LightApp_SelectionMgr* mgr = selectionMgr();
1358 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1359 mgr->setSelectionCacheEnabled( true );
1361 LightApp_Application::contextMenuPopup( type, thePopup, title );
1363 // temporary commented
1364 /*OB_Browser* ob = objectBrowser();
1365 if ( !ob || type != ob->popupClientType() )
1368 // Get selected objects
1369 SALOME_ListIO aList;
1370 mgr->selectedObjects( aList, QString(), false );
1372 // add GUI state commands: restore, rename
1373 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1374 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1375 thePopup->addSeparator();
1376 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1377 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1378 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1379 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1382 // "Delete reference" item should appear only for invalid references
1384 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1385 bool isInvalidRefs = false;
1386 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1387 _PTR(Study) aStudyDS = aStudy->studyDS();
1388 _PTR(SObject) anObj;
1390 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1391 if( it.Value()->hasEntry() )
1393 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1394 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1397 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1398 isInvalidRefs = true;
1401 // Add "Delete reference" item to popup
1402 if ( isInvalidRefs )
1404 thePopup->addSeparator();
1405 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1409 // "Activate module" item should appear only if it's necessary
1410 if ( aList.Extent() == 1 ) {
1412 mgr->selectedObjects( aList );
1414 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1416 // add extra popup menu (defined in XML)
1417 if ( myExtActions.size() > 0 ) {
1418 // Use only first selected object
1419 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1421 _PTR(Study) stdDS = study->studyDS();
1423 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1425 _PTR( GenericAttribute ) anAttr;
1426 std::string auid = "AttributeUserID";
1427 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1428 if ( aSO->FindAttribute( anAttr, auid ) ) {
1429 _PTR(AttributeUserID) aAttrID = anAttr;
1430 QString aId = aAttrID->Value().c_str();
1431 if ( myExtActions.contains( aId ) ) {
1432 thePopup->addAction(myExtActions[aId]);
1440 // check if item is a "GUI state" item (also a first level object)
1441 QString entry( aIObj->getEntry() );
1442 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1443 QString aModuleName( aIObj->getComponentDataType() );
1444 QString aModuleTitle = moduleTitle( aModuleName );
1445 CAM_Module* currentModule = activeModule();
1446 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1447 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1451 mgr->setSelectionCacheEnabled( cacheIsOn );
1454 /*!Update obect browser:
1455 1.if 'updateModels' true, update existing data models;
1456 2. update "non-existing" (not loaded yet) data models;
1457 3. update object browser if it exists */
1458 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1460 // update "non-existing" (not loaded yet) data models
1461 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1464 _PTR(Study) stdDS = study->studyDS();
1467 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1469 _PTR(SComponent) aComponent ( it->Value() );
1471 #ifndef WITH_SALOMEDS_OBSERVER
1472 // with GUI observers this check is not needed anymore
1473 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1474 continue; // skip the magic "Interface Applicative" component
1476 if ( !objectBrowser() )
1477 getWindow( WT_ObjectBrowser );
1478 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1479 objectBrowser()->setAutoUpdate( false );
1480 SalomeApp_DataModel::synchronize( aComponent, study );
1481 objectBrowser()->setAutoUpdate( isAutoUpdate );
1486 // create data objects that correspond to GUI state save points
1487 if ( study ) updateSavePointDataObjects( study );
1489 // update existing data models (already loaded SComponents)
1490 LightApp_Application::updateObjectBrowser( updateModels );
1493 /*!Display Catalog Genenerator dialog */
1494 void SalomeApp_Application::onCatalogGen()
1496 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1500 /*!Display Registry Display dialog */
1501 void SalomeApp_Application::onRegDisplay()
1503 CORBA::ORB_var anOrb = orb();
1504 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1507 regWnd->activateWindow();
1510 /*!find original object by double click on item */
1511 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1513 // Issue 21379: References are supported at LightApp_DataObject level
1514 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1516 if( obj && obj->isReference() )
1518 QString entry = obj->refEntry();
1520 SUIT_DataOwnerPtrList aList;
1521 aList.append( new LightApp_DataOwner( entry ) );
1522 selectionMgr()->setSelected( aList, false );
1524 SUIT_DataBrowser* ob = objectBrowser();
1526 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1527 if ( !aSelectedIndexes.isEmpty() )
1528 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1533 Creates new view manager
1534 \param type - type of view manager
1536 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1538 return createViewManager(type);
1542 /*!Global utility function, returns selected GUI Save point object's ID */
1543 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1545 SALOME_ListIO aList;
1546 selMgr->selectedObjects( aList );
1547 if( aList.Extent() > 0 ) {
1548 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1549 QString entry( aIObj->getEntry() );
1550 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1551 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1553 bool ok; // conversion to integer is ok?
1554 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1555 return ok ? savePoint : -1;
1560 /*!Called on Restore GUI State popup command*/
1561 void SalomeApp_Application::onRestoreGUIState()
1563 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1564 if ( savePoint == -1 )
1566 SalomeApp_VisualState( this ).restoreState( savePoint );
1569 /*!Called on Delete GUI State popup command*/
1570 void SalomeApp_Application::onDeleteGUIState()
1572 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1573 if ( savePoint == -1 )
1575 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1579 study->removeSavePoint( savePoint );
1580 updateSavePointDataObjects( study );
1583 /*!Called on New study operation*/
1584 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1586 LightApp_Application::onStudyCreated( study );
1588 //#ifndef DISABLE_PYCONSOLE
1589 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1590 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1593 loadDockWindowsState();
1595 objectBrowserColumnsVisibility();
1598 /*!Called on Open study operation*/
1599 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1601 LightApp_Application::onStudyOpened( study );
1603 //#ifndef DISABLE_PYCONSOLE
1604 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1605 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1608 loadDockWindowsState();
1610 objectBrowserColumnsVisibility();
1612 // temporary commented
1613 /*if ( objectBrowser() ) {
1614 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1615 objectBrowser()->updateTree( study->root() );
1619 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1620 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1623 SUIT_DataBrowser* ob = objectBrowser();
1624 LightApp_SelectionMgr* selMgr = selectionMgr();
1626 if ( !study || !ob || !selMgr )
1629 // find GUI states root object
1630 SUIT_DataObject* guiRootObj = 0;
1632 study->root()->children( ch );
1633 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1634 for ( ; it != last ; ++it ) {
1635 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1640 std::vector<int> savePoints = study->getSavePoints();
1641 // case 1: no more save points but they existed in study's tree
1642 if ( savePoints.empty() && guiRootObj ) {
1643 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1644 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1645 const bool isAutoUpdate = ob->autoUpdate();
1646 selMgr->clearSelected();
1647 ob->setAutoUpdate(true);
1648 DataObjectList ch = guiRootObj->children();
1649 for( int i = 0; i < ch.size(); i++ )
1652 ob->setAutoUpdate(isAutoUpdate);
1655 // case 2: no more save points but root does not exist either
1656 if ( savePoints.empty() && !guiRootObj )
1658 // case 3: save points but no root for them - create it
1659 if ( !savePoints.empty() && !guiRootObj )
1660 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1661 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1662 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1664 if ( guiRootObj->nextBrother() ) {
1665 study->root()->removeChild(guiRootObj);
1666 study->root()->appendChild(guiRootObj);
1667 //study->root()->dump();
1670 // store data objects in a map id-to-DataObject
1671 QMap<int,SalomeApp_SavePointObject*> mapDO;
1673 guiRootObj->children( ch );
1674 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1675 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1677 mapDO[dobj->getId()] = dobj;
1680 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1681 // if in the map - remove it from map.
1682 for ( int i = 0; i < savePoints.size(); i++ )
1683 if ( !mapDO.contains( savePoints[i] ) )
1684 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1686 mapDO.remove( savePoints[i] );
1688 // delete DataObjects that are still in the map -- their IDs were not found in data model
1689 if( mapDO.size() > 0) {
1690 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1691 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1692 selMgr->clearSelected();
1693 const bool isAutoUpdate = ob->autoUpdate();
1694 ob->setAutoUpdate(true);
1695 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1697 ob->setAutoUpdate(isAutoUpdate);
1701 /*! Check data object */
1702 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1711 Opens other study into active Study. If Study is empty - creates it.
1712 \param theName - name of study
1714 bool SalomeApp_Application::useStudy( const QString& theName )
1717 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1720 res = aStudy->loadDocument( theName );
1721 updateDesktopTitle();
1722 updateCommandsStatus();
1726 /*! Show/hide object browser colums according to preferences */
1727 void SalomeApp_Application::objectBrowserColumnsVisibility()
1729 if ( objectBrowser() )
1730 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1732 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1733 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1737 #ifndef DISABLE_PYCONSOLE
1738 /*! Set SalomeApp_NoteBook pointer */
1739 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1741 myNoteBook = theNoteBook;
1744 /*! Return SalomeApp_NoteBook pointer */
1745 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1752 * Define extra actions defined in module definition XML file.
1753 * Additional popup items sections can be defined by parameter "popupitems".
1754 * Supported attributes:
1755 * title - title of menu item,
1756 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1757 * method - method which has to be called when menu item is selected
1759 * <section name="MODULENAME">
1760 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1762 * <section name="importmed">
1763 * <parameter name="title" value="My menu"/>
1764 * <parameter name="objectid" value="VISU.Result"/>
1765 * <parameter name="method" value="nameOfModuleMethod"/>
1768 void SalomeApp_Application::createExtraActions()
1770 myExtActions.clear();
1771 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1773 QStringList aModules;
1774 modules(aModules, false);
1775 foreach(QString aModile, aModules) {
1776 QString aModName = moduleName(aModile);
1777 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1778 if (!aSectionStr.isNull()) {
1779 QStringList aSections = aSectionStr.split(':');
1780 foreach(QString aSection, aSections) {
1781 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1782 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1783 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1784 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1787 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1788 if (aModuleName.isNull())
1789 aModuleName = aModName;
1791 QAction* aAction = new QAction(aTitle, this);
1793 aData<<aModuleName<<aSlot;
1794 aAction->setData(aData);
1795 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1796 myExtActions[aId] = aAction;
1803 * Called when extra action is selected
1805 void SalomeApp_Application::onExtAction()
1807 QAction* aAction = ::qobject_cast<QAction*>(sender());
1811 QVariant aData = aAction->data();
1812 QStringList aDataList = aData.value<QStringList>();
1813 if (aDataList.size() != 2)
1816 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1817 SALOME_ListIO aListIO;
1818 aSelectionMgr->selectedObjects(aListIO);
1819 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1820 if (aListIO.Extent() < 1)
1822 if (!anIO->hasEntry())
1825 QString aEntry(anIO->getEntry());
1827 QApplication::setOverrideCursor( Qt::WaitCursor );
1828 QString aModuleTitle = moduleTitle(aDataList[0]);
1829 activateModule(aModuleTitle);
1830 QApplication::restoreOverrideCursor();
1832 QCoreApplication::processEvents();
1834 CAM_Module* aModule = activeModule();
1838 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1839 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1843 Checks that an object can be renamed.
1844 \param entry entry of the object
1845 \brief Return \c true if object can be renamed
1847 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1849 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1853 Rename object by entry.
1854 \param entry entry of the object
1855 \param name new name of the object
1856 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1858 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1860 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1862 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1864 if(!aStudy || savePoint == -1)
1867 if ( !name.isNull() && !name.isEmpty() ) {
1868 aStudy->setNameOfSavePoint( savePoint, name );
1869 updateSavePointDataObjects( aStudy );
1871 //Mark study as modified
1878 #ifndef DISABLE_PYCONSOLE
1879 //============================================================================
1880 /*! Function : onUpdateStudy
1881 * Purpose : Slot to update the study.
1883 //============================================================================
1884 void SalomeApp_Application::onUpdateStudy()
1886 QApplication::setOverrideCursor( Qt::WaitCursor );
1888 if( !updateStudy() )
1889 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1891 QApplication::restoreOverrideCursor();
1894 //============================================================================
1895 /*! Function : updateStudy
1896 * Purpose : Update study by dumping the study to Python script and loading it.
1897 * It is used to apply variable modifications done in NoteBook to created objects.
1899 //============================================================================
1900 bool SalomeApp_Application::updateStudy()
1902 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1903 if ( !study || !myNoteBook )
1906 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1907 myNoteBook->setDumpedStudyName( study->studyName() );
1909 _PTR(Study) studyDS = study->studyDS();
1911 // get unique temporary directory name
1912 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1913 if( aTmpDir.isEmpty() )
1916 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1917 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1919 // dump study to the temporary directory
1920 QString aScriptName( "notebook" );
1921 bool toPublish = true;
1922 bool isMultiFile = false;
1923 bool toSaveGUI = true;
1926 _PTR(AttributeParameter) ap;
1927 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1928 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1929 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1930 ip->setDumpPython(studyDS);
1931 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1933 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1935 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1938 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1942 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1943 int anIndex = aList.indexOf( this );
1945 // Disconnect dialog from application desktop in case if:
1946 // 1) Application is not the first application in the session
1947 // 2) Application is the first application in session but not the only.
1948 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1949 if( changeDesktop ) {
1951 SalomeApp_Application* app = this;
1952 if( anIndex > 0 && anIndex < aList.count() )
1953 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1954 else if(anIndex == 0 && aList.count() > 1)
1955 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1960 // creation a new study and restoring will be done in another application
1961 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
1962 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
1965 QString aDumpScript = myNoteBook->getDumpedStudyScript();
1966 QString aStudyName = myNoteBook->getDumpedStudyName();
1967 bool isStudySaved = myNoteBook->isDumpedStudySaved();
1968 // clear a study (delete all objects)
1969 onCloseDoc( false );
1971 if( !changeDesktop ) {
1972 ok = onRestoreStudy( aDumpScript,
1981 //============================================================================
1982 /*! Function : onRestoreStudy
1983 * Purpose : Load the dumped study from Python script
1985 //============================================================================
1986 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
1987 const QString& theStudyName,
1988 bool theIsStudySaved )
1992 // create a new study
1995 // get active application
1996 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
1998 // load study from the temporary directory
1999 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2001 #ifndef DISABLE_PYCONSOLE
2002 PyConsole_Console* pyConsole = app->pythonConsole();
2004 pyConsole->execAndWait( command );
2007 // remove temporary directory
2008 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2009 QString aStudyName = aScriptInfo.baseName();
2010 QDir aDir = aScriptInfo.absoluteDir();
2011 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2012 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2013 ok = aDir.remove( *it ) && ok;
2015 ok = aDir.rmdir( aDir.absolutePath() );
2017 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2019 #ifndef DISABLE_PYCONSOLE
2020 _PTR(Study) aStudyDS = newStudy->studyDS();
2021 app->getNoteBook()->Init( aStudyDS );
2022 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2023 newStudy->Modified();
2024 updateDesktopTitle();
2035 Close the Application
2037 void SalomeApp_Application::afterCloseDoc()
2039 #ifndef DISABLE_PYCONSOLE
2040 // emit signal to restore study from Python script
2042 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2043 myNoteBook->getDumpedStudyName(),
2044 myNoteBook->isDumpedStudySaved() );
2047 LightApp_Application::afterCloseDoc();
2051 Asks to close existing document.
2053 bool SalomeApp_Application::checkExistingDoc() {
2055 if( activeStudy() ) {
2056 int answer = SUIT_MessageBox::question( desktop(),
2057 tr( "APPCLOSE_CAPTION" ),
2058 tr( "STUDYCLOSE_DESCRIPTION" ),
2059 tr( "APPCLOSE_SAVE" ),
2060 tr( "APPCLOSE_CLOSE" ),
2061 tr( "APPCLOSE_CANCEL" ), 0 );
2063 if ( activeStudy()->isSaved() ) {
2066 } else if ( onSaveAsDoc() ) {
2067 if( !closeDoc( false ) ) {
2074 else if( answer == 1 ) {
2076 } else if( answer == 2 ) {
2080 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2082 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2083 if( List.size() > 0 ) {
2084 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_ACTIVEDOC_LOAD" ),
2085 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
2086 if ( answer == SUIT_MessageBox::Yes ) {