1 // Copyright (C) 2007-2015 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_Prs.h>
104 #include <ToolsGUI_CatalogGeneratorDlg.h>
105 #include <ToolsGUI_RegWidget.h>
109 #include <SALOMEDS_Tool.hxx>
111 /*!Internal class that updates object browser item properties */
112 // temporary commented
113 /*class SalomeApp_Updater : public OB_Updater
116 SalomeApp_Updater() : OB_Updater(){};
117 virtual ~SalomeApp_Updater(){};
118 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
121 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
123 if( !theObj || !theItem )
126 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
130 _PTR(SObject) SObj = SAObj->object();
133 _PTR( GenericAttribute ) anAttr;
136 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
138 _PTR(AttributeSelectable) aAttrSel = anAttr;
139 theItem->setSelectable( aAttrSel->IsSelectable() );
142 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
144 _PTR(AttributeExpandable) aAttrExpand = anAttr;
145 theItem->setExpandable( aAttrExpand->IsExpandable() );
148 //this attribute is not supported in the version of SALOME 3.x
149 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
151 // _PTR(AttributeOpened) aAttrOpen = anAttr;
152 // theItem->setOpen( aAttrOpen->IsOpened() );
156 /*!Create new instance of SalomeApp_Application.*/
157 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
159 return new SalomeApp_Application();
163 SalomeApp_Application::SalomeApp_Application()
164 : LightApp_Application(),
165 myIsCloseFromExit( false )
170 *\li Destroy event filter.
172 SalomeApp_Application::~SalomeApp_Application()
174 // Do not destroy. It's a singleton !
175 //SALOME_EventFilter::Destroy();
178 QStringList __getArgsList(QString argsString)
180 // Special process if some items of 'args:' list are themselves lists
181 // Note that an item can be a list, but not a list of lists...
182 // So we can have something like this:
183 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
184 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
185 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
186 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
187 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
189 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
194 return argsString.split(",", QString::SkipEmptyParts);
197 /*!Start application.*/
198 void SalomeApp_Application::start()
200 // process the command line options before start: to createActions in accordance to the options
201 static bool isFirst = true;
209 for (int i = 1; i < qApp->argc(); i++) {
210 QRegExp rxs ("--study-hdf=(.+)");
211 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
212 QString file = rxs.capturedTexts()[1];
213 QFileInfo fi ( file );
214 QString extension = fi.suffix().toLower();
215 if ( extension == "hdf" && fi.exists() )
216 hdffile = fi.absoluteFilePath();
219 QRegExp rxp ("--pyscript=\\[(.+)\\]");
220 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
222 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
223 for (int k = 0; k < dictList.count(); ++k) {
224 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
225 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
226 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
227 pyfiles += rxd.capturedTexts()[m];
234 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
235 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
237 LightApp_Application::start();
238 SALOME_EventFilter::Init();
240 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
241 onOpenDoc( hdffile );
242 else if ( pyfiles.count() > 0 ) // create new study
244 else if (!loadStudy.isEmpty()) {// load study by name
245 if (onLoadDoc(loadStudy))
246 updateObjectBrowser(true);
249 #ifndef DISABLE_PYCONSOLE
250 // import/execute python scripts
251 if ( pyfiles.count() > 0 && activeStudy() ) {
252 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
253 PyConsole_Console* pyConsole = pythonConsole();
254 if ( appStudy && pyConsole ) {
255 _PTR(Study) aStudy = appStudy->studyDS();
256 if ( !aStudy->GetProperties()->IsLocked() ) {
257 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
258 // Path is absolute, script has .py extension
259 for (uint j = 0; j < pyfiles.count(); j++ ) {
260 // Extract scripts and their arguments, if any
261 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
262 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
263 QString script = rxp.capturedTexts()[1];
265 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
266 for (uint k = 0; k < argList.count(); k++ ) {
267 QString arg = argList[k].trimmed();
268 arg.remove( QRegExp("^[\"]") );
269 arg.remove( QRegExp("[\"]$") );
272 args.remove( QRegExp("[,]$") );
273 if (!args.isEmpty()) {
277 script.remove( QRegExp("^python.*[\\s]+") );
278 QString cmd = script+" "+args;
279 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
280 pyConsole->exec(command);
282 } // end for loop on pyfiles QStringList
288 LightApp_Application::start();
289 SALOME_EventFilter::Init();
294 void SalomeApp_Application::createActions()
296 LightApp_Application::createActions();
298 SUIT_Desktop* desk = desktop();
301 // "Save GUI State" command is moved to VISU module
302 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
303 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
304 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
307 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
308 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
309 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
312 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
313 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
314 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
317 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
318 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
319 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
321 //! Catalog Generator
322 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
323 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
324 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
327 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
328 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
329 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
331 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
332 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
333 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
335 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
336 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
337 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
340 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
342 // "Save GUI State" command is renamed to "Save VISU State" and
343 // creation of menu item is moved to VISU
344 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
346 createMenu( ConnectId, fileMenu, 5 );
347 createMenu( DisconnectId, fileMenu, 5 );
348 createMenu( separator(), fileMenu, -1, 5 );
350 createMenu( DumpStudyId, fileMenu, 10, -1 );
351 createMenu( LoadScriptId, fileMenu, 10, -1 );
352 createMenu( separator(), fileMenu, -1, 10, -1 );
353 createMenu( PropertiesId, fileMenu, 10, -1 );
354 createMenu( separator(), fileMenu, -1, 10, -1 );
356 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
357 createMenu( CatalogGenId, toolsMenu, 10, -1 );
358 createMenu( RegDisplayId, toolsMenu, 10, -1 );
359 createMenu( separator(), toolsMenu, -1, 15, -1 );
361 createExtraActions();
363 #ifndef DISABLE_PYCONSOLE
364 #ifndef DISABLE_SALOMEOBJECT
365 // import Python module that manages SALOME plugins
367 PyLockWrapper lck; // acquire GIL
368 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
369 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
373 // end of SALOME plugins loading
380 \brief Close application.
382 void SalomeApp_Application::onExit()
384 bool killServers = false;
387 if ( exitConfirmation() ) {
388 SalomeApp_ExitDlg dlg( desktop() );
389 result = dlg.exec() == QDialog::Accepted;
390 killServers = dlg.isServersShutdown();
394 if ( !killServers ) myIsCloseFromExit = true;
395 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
396 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
400 /*!SLOT. Load document.*/
401 void SalomeApp_Application::onLoadDoc()
405 std::vector<std::string> List = studyMgr()->GetOpenStudies();
407 // rnv: According to the single-study approach on the server side
408 // can be only one study. So if it is exists connect to them,
409 // overwise show warning message: "No active study on the server"
412 SUIT_Session* aSession = SUIT_Session::session();
413 QList<SUIT_Application*> aAppList = aSession->applications();
415 QStringList unloadedStudies;
417 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
418 studyName = List[ind].c_str();
419 // Add to list only unloaded studies
420 bool isAlreadyOpen = false;
421 QListIterator<SUIT_Application*> it( aAppList );
422 while ( it.hasNext() && !isAlreadyOpen ) {
423 SUIT_Application* aApp = it.next();
424 if( !aApp || !aApp->activeStudy() )
426 if ( aApp->activeStudy()->studyName() == studyName )
427 isAlreadyOpen = true;
430 if ( !isAlreadyOpen )
431 unloadedStudies << studyName;
433 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
434 if ( studyName.isEmpty() )
438 if(List.size() <= 0) {
439 SUIT_MessageBox::warning( desktop(),
440 QObject::tr("WRN_WARNING"),
441 QObject::tr("WRN_NO_STUDY_ON SERV") );
445 studyName = List[0].c_str();
448 // this code replaces marker of windows drive and path become invalid therefore
449 // defines placed there
450 studyName.replace( QRegExp(":"), "/" );
453 if ( onLoadDoc( studyName ) ) {
455 updateViewManagers();
456 updateObjectBrowser( true );
460 /*!SLOT. Unload document.*/
461 void SalomeApp_Application::onUnloadDoc( bool ask )
464 activeStudy()->abortAllOperations();
465 if ( activeStudy()->isModified() ) {
466 QString docName = activeStudy()->studyName().trimmed();
467 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
468 tr( "DISCONNECT_DESCRIPTION" ),
469 tr( "DISCONNECT_SAVE" ),
470 tr( "DISCONNECT_WO_SAVE" ),
471 tr( "APPCLOSE_CANCEL" ), 0 );
472 if ( answer == 0 ) { // save before unload
473 if ( activeStudy()->isSaved() )
475 else if ( !onSaveAsDoc() )
478 else if ( answer == 2 ) // Cancel
482 closeActiveDoc( false );
485 /*!SLOT. Create new study and load script*/
486 void SalomeApp_Application::onNewWithScript()
488 QStringList filtersList;
489 filtersList.append(tr("PYTHON_FILES_FILTER"));
490 filtersList.append(tr("ALL_FILES_FILTER"));
492 QString anInitialPath = "";
493 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
494 anInitialPath = QDir::currentPath();
496 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
498 if ( !aFile.isEmpty() )
502 QString command = QString("execfile(r\"%1\")").arg(aFile);
504 #ifndef DISABLE_PYCONSOLE
505 PyConsole_Console* pyConsole = pythonConsole();
508 pyConsole->exec( command );
514 /*!SLOT. Load document with \a aName.*/
515 bool SalomeApp_Application::onLoadDoc( const QString& aName )
517 #ifdef SINGLE_DESKTOP
518 if ( !LightApp_Application::closeDoc() )
522 if ( !activeStudy() ) {
523 // if no study - load in current desktop
524 res = useStudy( aName );
527 // if study exists - load in new desktop. Check: is the same file is loaded?
528 SUIT_Session* aSession = SUIT_Session::session();
529 QList<SUIT_Application*> aAppList = aSession->applications();
530 bool isAlreadyOpen = false;
531 SalomeApp_Application* aApp = 0;
532 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
533 it != aAppList.end() && !isAlreadyOpen; ++it ) {
534 aApp = dynamic_cast<SalomeApp_Application*>( *it );
535 if ( aApp && aApp->activeStudy()->studyName() == aName )
536 isAlreadyOpen = true;
538 if ( !isAlreadyOpen ) {
539 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
541 res = aApp->useStudy( aName );
544 aApp->desktop()->activateWindow();
551 /*!SLOT. Parse message for desktop.*/
552 void SalomeApp_Application::onDesktopMessage( const QString& message )
554 if (message.indexOf("studyCreated:") == 0) {
555 // Enable 'Connect' action
556 updateCommandsStatus();
558 else if (message.indexOf("studyClosed:") == 0) {
559 /* message also contains ID of the closed study,
560 but as soon as SALOME is mono-study application for the moment,
561 this ID is not needed now.*/
562 //long aStudyId = message.section(':', 1).toLong();
563 // Disconnect GUI from active study, because it was closed on DS side.
564 closeActiveDoc( false );
565 // Disable 'Connect' action
566 QAction* a = action( ConnectId );
568 a->setEnabled( false );
570 else if ( message.toLower() == "connect_to_study" ) {
573 LightApp_Application::onDesktopMessage( message );
576 /*!SLOT. Copy objects to study maneger from selection maneger..*/
577 void SalomeApp_Application::onCopy()
580 LightApp_SelectionMgr* mgr = selectionMgr();
581 mgr->selectedObjects(list);
583 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
584 if(study == NULL) return;
586 _PTR(Study) stdDS = study->studyDS();
589 SALOME_ListIteratorOfListIO it( list );
592 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
594 studyMgr()->Copy(so);
595 onSelectionChanged();
602 /*!SLOT. Paste objects to study maneger from selection manager.*/
603 void SalomeApp_Application::onPaste()
606 LightApp_SelectionMgr* mgr = selectionMgr();
607 mgr->selectedObjects(list);
609 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
610 if(study == NULL) return;
612 _PTR(Study) stdDS = study->studyDS();
615 if ( stdDS->GetProperties()->IsLocked() ) {
616 SUIT_MessageBox::warning( desktop(),
617 QObject::tr("WRN_WARNING"),
618 QObject::tr("WRN_STUDY_LOCKED") );
622 SALOME_ListIteratorOfListIO it( list );
625 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
627 studyMgr()->Paste(so);
628 updateObjectBrowser( true );
629 updateActions(); //SRN: BugID IPAL9377, case 3
636 /*!Check the application on closing.
637 * \retval true if possible, else false
639 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
641 return LightApp_Application::isPossibleToClose( closePermanently );
644 /*! Check if the study is locked */
645 void SalomeApp_Application::onCloseDoc( bool ask )
647 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
650 _PTR(Study) stdDS = study->studyDS();
651 if(stdDS && stdDS->IsStudyLocked()) {
652 if ( SUIT_MessageBox::question( desktop(),
653 QObject::tr( "WRN_WARNING" ),
654 QObject::tr( "CLOSE_LOCKED_STUDY" ),
655 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
656 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
660 LightApp_Application::onCloseDoc( ask );
663 /*!Sets enable or disable some actions on selection changed.*/
664 void SalomeApp_Application::onSelectionChanged()
667 LightApp_SelectionMgr* mgr = selectionMgr();
668 mgr->selectedObjects(list);
670 bool canCopy = false;
671 bool canPaste = false;
673 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
676 canCopy = m->canCopy();
677 canPaste = m->canPaste();
680 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
682 _PTR(Study) stdDS = study->studyDS();
685 SALOME_ListIteratorOfListIO it ( list );
687 if (it.More() && list.Extent() == 1) {
688 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
691 canCopy = canCopy || studyMgr()->CanCopy(so);
692 canPaste = canPaste || studyMgr()->CanPaste(so);
698 action(EditCopyId)->setEnabled(canCopy);
699 action(EditPasteId)->setEnabled(canPaste);
702 /*!Delete references.*/
703 void SalomeApp_Application::onDeleteInvalidReferences()
706 LightApp_SelectionMgr* mgr = selectionMgr();
707 mgr->selectedObjects( aList, QString(), false );
709 if( aList.IsEmpty() )
712 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
713 _PTR(Study) aStudyDS = aStudy->studyDS();
714 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
717 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
718 if ( it.Value()->hasEntry() )
720 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
721 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
724 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
725 aStudyBuilder->RemoveReference( aSObject );
727 updateObjectBrowser();
731 void SalomeApp_Application::onOpenWith()
733 QApplication::setOverrideCursor( Qt::WaitCursor );
735 LightApp_SelectionMgr* mgr = selectionMgr();
736 mgr->selectedObjects(aList);
737 if (aList.Extent() != 1)
739 QApplication::restoreOverrideCursor();
742 Handle(SALOME_InteractiveObject) aIObj = aList.First();
743 QString aModuleName(aIObj->getComponentDataType());
744 QString aModuleTitle = moduleTitle(aModuleName);
745 activateModule(aModuleTitle);
746 QApplication::restoreOverrideCursor();
752 SUIT_Study* SalomeApp_Application::createNewStudy()
754 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
756 // Set up processing of major study-related events
757 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
758 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
759 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
760 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
762 #ifndef DISABLE_PYCONSOLE
763 //to receive signal in application that NoteBook's variable was modified
764 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
765 this, SIGNAL(notebookVarUpdated(QString)) );
772 Enable/Disable menu items and toolbar buttons. Rebuild menu
774 void SalomeApp_Application::updateCommandsStatus()
776 LightApp_Application::updateCommandsStatus();
779 QAction* a = action( DumpStudyId );
781 a->setEnabled( activeStudy() );
783 #ifndef DISABLE_PYCONSOLE
785 a = action( LoadScriptId );
787 a->setEnabled( pythonConsole() );
791 a = action( PropertiesId );
793 a->setEnabled( activeStudy() );
795 // Save GUI state menu
796 a = action( SaveGUIStateId );
798 a->setEnabled( activeStudy() );
800 // Connect study menu
801 a = action( ConnectId );
803 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
805 // Disconnect study menu
806 a = action( DisconnectId );
808 a->setEnabled( activeStudy() );
810 // update state of Copy/Paste menu items
811 onSelectionChanged();
815 \class DumpStudyFileDlg
816 Private class used in Dump Study operation. Consists 2 check boxes:
817 "Publish in study" and "Save GUI parameters"
819 class DumpStudyFileDlg : public SUIT_FileDlg
822 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
824 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
827 QWidget *hB = new QWidget( this );
828 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
829 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
830 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
832 QHBoxLayout *layout = new QHBoxLayout;
833 layout->addWidget(myPublishChk);
834 layout->addWidget(myMultiFileChk);
835 layout->addWidget(mySaveGUIChk);
836 hB->setLayout(layout);
838 QPushButton* pb = new QPushButton(this);
840 int row = grid->rowCount();
841 grid->addWidget( new QLabel("", this), row, 0 );
842 grid->addWidget( hB, row, 1, 1, 3 );
843 grid->addWidget( pb, row, 5 );
848 QCheckBox* myPublishChk;
849 QCheckBox* myMultiFileChk;
850 QCheckBox* mySaveGUIChk;
853 class DumpStudyFileValidator : public SUIT_FileValidator
856 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
857 virtual ~DumpStudyFileValidator() {};
858 virtual bool canSave( const QString& file, bool permissions );
861 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
863 QFileInfo fi( file );
864 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
865 SUIT_MessageBox::critical( parent(),
866 QObject::tr("WRN_WARNING"),
867 QObject::tr("WRN_FILE_NAME_BAD") );
870 return SUIT_FileValidator::canSave( file, permissions);
873 /*!Private SLOT. On dump study.*/
874 void SalomeApp_Application::onDumpStudy( )
876 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
877 if ( !appStudy ) return;
878 _PTR(Study) aStudy = appStudy->studyDS();
880 QStringList aFilters;
881 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
883 bool anIsPublish = true;
884 bool anIsMultiFile = false;
885 bool anIsSaveGUI = true;
887 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
888 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
889 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
890 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
893 DumpStudyFileDlg fd( desktop() );
894 fd.setValidator( new DumpStudyFileValidator( &fd ) );
895 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
896 fd.setFilters( aFilters );
897 fd.myPublishChk->setChecked( anIsPublish );
898 fd.myMultiFileChk->setChecked( anIsMultiFile );
899 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
900 if ( fd.exec() == QDialog::Accepted )
902 QString aFileName = fd.selectedFile();
904 bool toPublish = fd.myPublishChk->isChecked();
905 bool isMultiFile = fd.myMultiFileChk->isChecked();
906 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
908 if ( !aFileName.isEmpty() ) {
909 QFileInfo aFileInfo(aFileName);
910 if( aFileInfo.isDir() ) // IPAL19257
913 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
916 SUIT_OverrideCursor wc;
917 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
920 SUIT_MessageBox::warning( desktop(),
921 QObject::tr("WRN_WARNING"),
922 tr("WRN_DUMP_STUDY_FAILED") );
927 /*!Private SLOT. On load script.*/
928 void SalomeApp_Application::onLoadScript( )
930 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
932 _PTR(Study) aStudy = appStudy->studyDS();
933 if ( aStudy->GetProperties()->IsLocked() ) {
934 SUIT_MessageBox::warning( desktop(),
935 QObject::tr("WRN_WARNING"),
936 QObject::tr("WRN_STUDY_LOCKED") );
941 QStringList filtersList;
942 filtersList.append(tr("PYTHON_FILES_FILTER"));
943 filtersList.append(tr("ALL_FILES_FILTER"));
945 QString anInitialPath = "";
946 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
947 anInitialPath = QDir::currentPath();
949 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
951 if ( !aFile.isEmpty() )
953 QString command = QString("execfile(r\"%1\")").arg(aFile);
955 #ifndef DISABLE_PYCONSOLE
956 PyConsole_Console* pyConsole = pythonConsole();
959 pyConsole->exec( command );
964 /*!Private SLOT. On save GUI state.*/
965 void SalomeApp_Application::onSaveGUIState()
967 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
969 SalomeApp_VisualState( this ).storeState();
970 updateSavePointDataObjects( study );
971 updateObjectBrowser();
976 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
977 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
979 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
980 QAction* send = ::qobject_cast<QAction*>( sender() );
983 QString aWinName = send->data().toString();
984 if ( theIsVisible && aWinName == "objectBrowser" )
985 objectBrowserColumnsVisibility();
989 *\retval QString "(*.hdf)"
991 QString SalomeApp_Application::getFileFilter() const
997 QWidget* SalomeApp_Application::createWindow( const int flag )
1000 #ifndef DISABLE_PYCONSOLE
1001 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1003 wid = LightApp_Application::createWindow(flag);
1006 SUIT_ResourceMgr* resMgr = resourceMgr();
1008 if ( flag == WT_ObjectBrowser )
1010 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1012 // temporary commented
1013 //ob->setUpdater( new SalomeApp_Updater() );
1015 #ifdef WITH_SALOMEDS_OBSERVER
1016 //do not activate the automatic update of Qt tree through signal/slot
1017 ob->setAutoUpdate(false);
1018 //activate update of modified objects only
1019 ob->setUpdateModified(true);
1022 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1025 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1026 IORCol = QObject::tr( "IOR_COLUMN" ),
1027 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1028 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1030 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1031 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1032 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1033 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1034 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1035 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1036 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1037 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1038 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1040 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1041 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1042 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1044 ob->setAutoSizeFirstColumn(autoSizeFirst);
1045 ob->setAutoSizeColumns(autoSize);
1046 ob->setResizeOnExpandItem(resizeOnExpandItem);
1047 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1049 // temporary commented
1051 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1053 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1054 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1055 QString().sprintf( "visibility_column_%d", i ), true ) );
1059 // temporary commented
1061 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1062 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1063 ob->resize( desktop()->width()/3, ob->height() );
1067 #ifndef DISABLE_PYCONSOLE
1068 else if ( flag == WT_PyConsole )
1070 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1071 pyCons->setObjectName( "pythonConsole" );
1072 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1073 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1074 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1075 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1077 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1078 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1080 else if ( flag == WT_NoteBook )
1082 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1084 _PTR(Study) aStudy = appStudy->studyDS();
1085 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1086 //to receive signal in NoteBook that it's variable was modified
1087 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1088 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1090 wid = getNoteBook();
1091 wid->setObjectName( "noteBook" );
1097 /*!Create preferences.*/
1098 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1100 LightApp_Application::createPreferences(pref);
1105 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1106 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1107 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1108 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1110 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1111 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1113 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1115 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1116 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1117 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1118 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1119 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1120 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1121 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1122 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1123 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1124 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1127 /*!Update desktop title.*/
1128 void SalomeApp_Application::updateDesktopTitle() {
1129 QString aTitle = applicationName();
1130 QString aVer = applicationVersion();
1131 if ( !aVer.isEmpty() )
1132 aTitle += QString( " " ) + aVer;
1134 if ( activeStudy() )
1136 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1137 if ( !sName.isEmpty() ) {
1138 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1140 _PTR(Study) stdDS = study->studyDS();
1142 if ( stdDS->GetProperties()->IsLocked() ) {
1143 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1145 aTitle += QString( " - [%1]" ).arg( sName );
1152 desktop()->setWindowTitle( aTitle );
1155 int SalomeApp_Application::closeChoice( const QString& docName )
1157 QStringList buttons;
1158 QMap<int, int> choices;
1160 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1161 choices.insert( idx++, CloseSave ); // ...
1162 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1163 choices.insert( idx++, CloseDiscard ); // ...
1164 if ( myIsCloseFromExit ) {
1165 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1166 choices.insert( idx++, CloseDisconnectSave ); // ...
1167 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1168 choices.insert( idx++, CloseDisconnect ); // ...
1170 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1171 choices.insert( idx++, CloseCancel ); // ...
1173 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1174 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1175 return choices[answer];
1178 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1184 if ( activeStudy()->isSaved() )
1186 else if ( !onSaveAsDoc() )
1191 case CloseDisconnectSave:
1192 if ( activeStudy()->isSaved() )
1194 else if ( !onSaveAsDoc() )
1196 case CloseDisconnect:
1197 closeActiveDoc( false );
1198 closePermanently = false;
1207 int SalomeApp_Application::openChoice( const QString& aName )
1209 int choice = LightApp_Application::openChoice( aName );
1211 if ( QFileInfo( aName ).exists() ) {
1212 if ( choice == OpenNew ) { // The document isn't already open.
1214 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1215 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1216 if ( aName == QString( lst[i].c_str() ) )
1219 // The document already exists in the study manager.
1220 // Do you want to reload it?
1222 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1223 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1224 if ( answer == SUIT_MessageBox::Yes )
1225 choice = OpenRefresh;
1227 choice = OpenCancel;
1230 } else { // file is not exist on disk
1231 SUIT_MessageBox::warning( desktop(),
1232 QObject::tr("WRN_WARNING"),
1233 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1240 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1243 int choice = aChoice;
1248 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1251 studyMgr()->Close( aStudy );
1256 res = LightApp_Application::openAction( choice, aName );
1264 \brief Get map of the operations which can be performed
1265 on the module activation.
1267 The method should return the map of the kind \c {<id>:<name>}
1268 where \c <id> is an integer identifier of the operation and
1269 \c <name> is a title for the button to be added to the
1270 dialog box. After user selects the required operation by the
1271 clicking the corresponding button in the dialog box, its identifier
1272 is passed to the moduleActionSelected() method to process
1275 \return map of the operations
1276 \sa moduleActionSelected()
1278 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1280 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1282 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1284 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1289 \brief Called when the used selectes required operation chosen
1290 from "Activate module" dialog box.
1292 Performs the required operation according to the user choice.
1294 \param id operation identifier
1295 \sa activateModuleActions()
1297 void SalomeApp_Application::moduleActionSelected( const int id )
1303 case NewAndScriptId:
1307 LightApp_Application::moduleActionSelected( id );
1312 /*!Gets CORBA::ORB_var*/
1313 CORBA::ORB_var SalomeApp_Application::orb()
1315 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1316 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1320 /*!Create and return SALOMEDS_StudyManager.*/
1321 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1323 static _PTR(StudyManager) _sm;
1324 if(!_sm) _sm = ClientFactory::StudyManager();
1328 /*!Create and return SALOME_NamingService.*/
1329 SALOME_NamingService* SalomeApp_Application::namingService()
1331 static SALOME_NamingService _ns(orb());
1335 /*!Create and return SALOME_LifeCycleCORBA.*/
1336 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1338 static SALOME_LifeCycleCORBA _lcc( namingService() );
1342 /*!Private SLOT. On preferences.*/
1343 void SalomeApp_Application::onProperties()
1345 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1349 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1352 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1353 int res = aDlg.exec();
1354 if( res==QDialog::Accepted && aDlg.isChanged() )
1355 SB->CommitCommand();
1359 //study->updateCaptions();
1360 updateDesktopTitle();
1364 /*!Insert items in popup, which necessary for current application*/
1365 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1367 LightApp_SelectionMgr* mgr = selectionMgr();
1368 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1369 mgr->setSelectionCacheEnabled( true );
1371 LightApp_Application::contextMenuPopup( type, thePopup, title );
1373 // temporary commented
1374 /*OB_Browser* ob = objectBrowser();
1375 if ( !ob || type != ob->popupClientType() )
1378 // Get selected objects
1379 SALOME_ListIO aList;
1380 mgr->selectedObjects( aList, QString(), false );
1382 // add GUI state commands: restore, rename
1383 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1384 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1385 thePopup->addSeparator();
1386 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1387 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1388 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1389 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1392 // "Delete reference" item should appear only for invalid references
1394 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1395 bool isInvalidRefs = false;
1396 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1398 _PTR(Study) aStudyDS = aStudy->studyDS();
1399 _PTR(SObject) anObj;
1401 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1403 if( it.Value()->hasEntry() )
1405 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1406 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1409 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1410 isInvalidRefs = true;
1414 // Add "Delete reference" item to popup
1415 if ( isInvalidRefs )
1417 thePopup->addSeparator();
1418 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1422 // "Activate module" item should appear only if it's necessary
1423 if ( aList.Extent() == 1 ) {
1425 mgr->selectedObjects( aList );
1427 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1429 // add extra popup menu (defined in XML)
1430 if ( myExtActions.size() > 0 ) {
1431 // Use only first selected object
1432 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1434 _PTR(Study) stdDS = study->studyDS();
1436 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1438 _PTR( GenericAttribute ) anAttr;
1439 std::string auid = "AttributeUserID";
1440 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1441 if ( aSO->FindAttribute( anAttr, auid ) ) {
1442 _PTR(AttributeUserID) aAttrID = anAttr;
1443 QString aId = aAttrID->Value().c_str();
1444 if ( myExtActions.contains( aId ) ) {
1445 thePopup->addAction(myExtActions[aId]);
1453 // check if item is a "GUI state" item (also a first level object)
1454 QString entry( aIObj->getEntry() );
1455 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1456 QString aModuleName( aIObj->getComponentDataType() );
1457 QString aModuleTitle = moduleTitle( aModuleName );
1458 CAM_Module* currentModule = activeModule();
1459 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1460 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1465 mgr->setSelectionCacheEnabled( cacheIsOn );
1468 /*!Update obect browser:
1469 1.if 'updateModels' true, update existing data models;
1470 2. update "non-existing" (not loaded yet) data models;
1471 3. update object browser if it exists */
1472 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1474 // update "non-existing" (not loaded yet) data models
1475 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1478 _PTR(Study) stdDS = study->studyDS();
1481 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1483 _PTR(SComponent) aComponent ( it->Value() );
1485 #ifndef WITH_SALOMEDS_OBSERVER
1486 // with GUI observers this check is not needed anymore
1487 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1488 continue; // skip the magic "Interface Applicative" component
1490 if ( !objectBrowser() )
1491 getWindow( WT_ObjectBrowser );
1492 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1493 objectBrowser()->setAutoUpdate( false );
1494 SalomeApp_DataModel::synchronize( aComponent, study );
1495 objectBrowser()->setAutoUpdate( isAutoUpdate );
1500 // create data objects that correspond to GUI state save points
1501 if ( study ) updateSavePointDataObjects( study );
1503 // update existing data models (already loaded SComponents)
1504 LightApp_Application::updateObjectBrowser( updateModels );
1507 /*!Display Catalog Genenerator dialog */
1508 void SalomeApp_Application::onCatalogGen()
1510 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1514 /*!Display Registry Display dialog */
1515 void SalomeApp_Application::onRegDisplay()
1517 CORBA::ORB_var anOrb = orb();
1518 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1521 regWnd->activateWindow();
1524 /*!find original object by double click on item */
1525 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1527 // Issue 21379: References are supported at LightApp_DataObject level
1528 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1530 if( obj && obj->isReference() )
1532 QString entry = obj->refEntry();
1534 SUIT_DataOwnerPtrList aList;
1535 aList.append( new LightApp_DataOwner( entry ) );
1536 selectionMgr()->setSelected( aList, false );
1538 SUIT_DataBrowser* ob = objectBrowser();
1540 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1541 if ( !aSelectedIndexes.isEmpty() )
1542 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1547 Creates new view manager
1548 \param type - type of view manager
1550 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1552 return createViewManager(type);
1556 /*!Global utility function, returns selected GUI Save point object's ID */
1557 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1559 SALOME_ListIO aList;
1560 selMgr->selectedObjects( aList );
1561 if( aList.Extent() > 0 ) {
1562 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1563 QString entry( aIObj->getEntry() );
1564 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1565 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1567 bool ok; // conversion to integer is ok?
1568 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1569 return ok ? savePoint : -1;
1574 /*!Called on Restore GUI State popup command*/
1575 void SalomeApp_Application::onRestoreGUIState()
1577 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1578 if ( savePoint == -1 )
1580 SalomeApp_VisualState( this ).restoreState( savePoint );
1583 /*!Called on Delete GUI State popup command*/
1584 void SalomeApp_Application::onDeleteGUIState()
1586 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1587 if ( savePoint == -1 )
1589 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1593 study->removeSavePoint( savePoint );
1594 updateSavePointDataObjects( study );
1597 /*!Called on New study operation*/
1598 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1600 LightApp_Application::onStudyCreated( study );
1602 //#ifndef DISABLE_PYCONSOLE
1603 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1604 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1607 loadDockWindowsState();
1609 objectBrowserColumnsVisibility();
1612 /*!Called on Open study operation*/
1613 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1615 LightApp_Application::onStudyOpened( study );
1617 //#ifndef DISABLE_PYCONSOLE
1618 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1619 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1622 loadDockWindowsState();
1624 objectBrowserColumnsVisibility();
1626 // temporary commented
1627 /*if ( objectBrowser() ) {
1628 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1629 objectBrowser()->updateTree( study->root() );
1633 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1634 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1637 SUIT_DataBrowser* ob = objectBrowser();
1638 LightApp_SelectionMgr* selMgr = selectionMgr();
1640 if ( !study || !ob || !selMgr )
1643 // find GUI states root object
1644 SUIT_DataObject* guiRootObj = 0;
1646 study->root()->children( ch );
1647 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1648 for ( ; it != last ; ++it ) {
1649 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1654 std::vector<int> savePoints = study->getSavePoints();
1655 // case 1: no more save points but they existed in study's tree
1656 if ( savePoints.empty() && guiRootObj ) {
1657 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1658 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1659 const bool isAutoUpdate = ob->autoUpdate();
1660 selMgr->clearSelected();
1661 ob->setAutoUpdate(true);
1662 DataObjectList ch = guiRootObj->children();
1663 for( int i = 0; i < ch.size(); i++ )
1666 ob->setAutoUpdate(isAutoUpdate);
1669 // case 2: no more save points but root does not exist either
1670 if ( savePoints.empty() && !guiRootObj )
1672 // case 3: save points but no root for them - create it
1673 if ( !savePoints.empty() && !guiRootObj )
1674 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1675 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1676 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1678 if ( guiRootObj->nextBrother() ) {
1679 study->root()->removeChild(guiRootObj);
1680 study->root()->appendChild(guiRootObj);
1681 //study->root()->dump();
1684 // store data objects in a map id-to-DataObject
1685 QMap<int,SalomeApp_SavePointObject*> mapDO;
1687 guiRootObj->children( ch );
1688 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1689 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1691 mapDO[dobj->getId()] = dobj;
1694 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1695 // if in the map - remove it from map.
1696 for ( int i = 0; i < savePoints.size(); i++ )
1697 if ( !mapDO.contains( savePoints[i] ) )
1698 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1700 mapDO.remove( savePoints[i] );
1702 // delete DataObjects that are still in the map -- their IDs were not found in data model
1703 if( mapDO.size() > 0) {
1704 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1705 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1706 selMgr->clearSelected();
1707 const bool isAutoUpdate = ob->autoUpdate();
1708 ob->setAutoUpdate(true);
1709 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1711 ob->setAutoUpdate(isAutoUpdate);
1715 /*! Check data object */
1716 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1725 Opens other study into active Study. If Study is empty - creates it.
1726 \param theName - name of study
1728 bool SalomeApp_Application::useStudy( const QString& theName )
1731 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1734 res = aStudy->loadDocument( theName );
1735 updateDesktopTitle();
1736 updateCommandsStatus();
1740 /*! Show/hide object browser colums according to preferences */
1741 void SalomeApp_Application::objectBrowserColumnsVisibility()
1743 if ( objectBrowser() )
1744 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1746 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1747 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1751 #ifndef DISABLE_PYCONSOLE
1752 /*! Set SalomeApp_NoteBook pointer */
1753 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1755 myNoteBook = theNoteBook;
1758 /*! Return SalomeApp_NoteBook pointer */
1759 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1766 * Define extra actions defined in module definition XML file.
1767 * Additional popup items sections can be defined by parameter "popupitems".
1768 * Supported attributes:
1769 * title - title of menu item,
1770 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1771 * method - method which has to be called when menu item is selected
1773 * <section name="MODULENAME">
1774 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1776 * <section name="importmed">
1777 * <parameter name="title" value="My menu"/>
1778 * <parameter name="objectid" value="VISU.Result"/>
1779 * <parameter name="method" value="nameOfModuleMethod"/>
1782 void SalomeApp_Application::createExtraActions()
1784 myExtActions.clear();
1785 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1787 QStringList aModules;
1788 modules(aModules, false);
1789 foreach(QString aModile, aModules) {
1790 QString aModName = moduleName(aModile);
1791 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1792 if (!aSectionStr.isNull()) {
1793 QStringList aSections = aSectionStr.split(':');
1794 foreach(QString aSection, aSections) {
1795 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1796 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1797 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1798 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1801 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1802 if (aModuleName.isNull())
1803 aModuleName = aModName;
1805 QAction* aAction = new QAction(aTitle, this);
1807 aData<<aModuleName<<aSlot;
1808 aAction->setData(aData);
1809 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1810 myExtActions[aId] = aAction;
1817 * Called when extra action is selected
1819 void SalomeApp_Application::onExtAction()
1821 QAction* aAction = ::qobject_cast<QAction*>(sender());
1825 QVariant aData = aAction->data();
1826 QStringList aDataList = aData.value<QStringList>();
1827 if (aDataList.size() != 2)
1830 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1831 SALOME_ListIO aListIO;
1832 aSelectionMgr->selectedObjects(aListIO);
1833 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1834 if (aListIO.Extent() < 1)
1836 if (!anIO->hasEntry())
1839 QString aEntry(anIO->getEntry());
1841 QApplication::setOverrideCursor( Qt::WaitCursor );
1842 QString aModuleTitle = moduleTitle(aDataList[0]);
1843 activateModule(aModuleTitle);
1844 QApplication::restoreOverrideCursor();
1846 QCoreApplication::processEvents();
1848 CAM_Module* aModule = activeModule();
1852 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1853 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1857 Checks that an object can be renamed.
1858 \param entry entry of the object
1859 \brief Return \c true if object can be renamed
1861 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1863 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1867 Rename object by entry.
1868 \param entry entry of the object
1869 \param name new name of the object
1870 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1872 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1874 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1876 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1878 if(!aStudy || savePoint == -1)
1881 if ( !name.isNull() && !name.isEmpty() ) {
1882 aStudy->setNameOfSavePoint( savePoint, name );
1883 updateSavePointDataObjects( aStudy );
1885 //Mark study as modified
1892 #ifndef DISABLE_PYCONSOLE
1893 //============================================================================
1894 /*! Function : onUpdateStudy
1895 * Purpose : Slot to update the study.
1897 //============================================================================
1898 void SalomeApp_Application::onUpdateStudy()
1900 QApplication::setOverrideCursor( Qt::WaitCursor );
1902 if( !updateStudy() )
1903 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1905 QApplication::restoreOverrideCursor();
1908 //============================================================================
1909 /*! Function : updateStudy
1910 * Purpose : Update study by dumping the study to Python script and loading it.
1911 * It is used to apply variable modifications done in NoteBook to created objects.
1913 //============================================================================
1914 bool SalomeApp_Application::updateStudy()
1916 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1917 if ( !study || !myNoteBook )
1920 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1921 myNoteBook->setDumpedStudyName( study->studyName() );
1923 _PTR(Study) studyDS = study->studyDS();
1925 // get unique temporary directory name
1926 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1927 if( aTmpDir.isEmpty() )
1930 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1931 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1933 // dump study to the temporary directory
1934 QString aScriptName( "notebook" );
1935 bool toPublish = true;
1936 bool isMultiFile = false;
1937 bool toSaveGUI = true;
1940 _PTR(AttributeParameter) ap;
1941 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1942 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1943 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1944 ip->setDumpPython(studyDS);
1945 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1947 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1949 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1952 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1956 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1957 int anIndex = aList.indexOf( this );
1959 // Disconnect dialog from application desktop in case if:
1960 // 1) Application is not the first application in the session
1961 // 2) Application is the first application in session but not the only.
1962 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1963 if( changeDesktop ) {
1965 SalomeApp_Application* app = this;
1966 if( anIndex > 0 && anIndex < aList.count() )
1967 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1968 else if(anIndex == 0 && aList.count() > 1)
1969 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1974 // creation a new study and restoring will be done in another application
1975 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
1976 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
1979 QString aDumpScript = myNoteBook->getDumpedStudyScript();
1980 QString aStudyName = myNoteBook->getDumpedStudyName();
1981 bool isStudySaved = myNoteBook->isDumpedStudySaved();
1982 // clear a study (delete all objects)
1983 onCloseDoc( false );
1985 if( !changeDesktop ) {
1986 ok = onRestoreStudy( aDumpScript,
1995 //============================================================================
1996 /*! Function : onRestoreStudy
1997 * Purpose : Load the dumped study from Python script
1999 //============================================================================
2000 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2001 const QString& theStudyName,
2002 bool theIsStudySaved )
2006 // create a new study
2009 // get active application
2010 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2012 // load study from the temporary directory
2013 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2015 #ifndef DISABLE_PYCONSOLE
2016 PyConsole_Console* pyConsole = app->pythonConsole();
2018 pyConsole->execAndWait( command );
2021 // remove temporary directory
2022 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2023 QString aStudyName = aScriptInfo.baseName();
2024 QDir aDir = aScriptInfo.absoluteDir();
2025 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2026 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2027 ok = aDir.remove( *it ) && ok;
2029 ok = aDir.rmdir( aDir.absolutePath() );
2031 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2033 #ifndef DISABLE_PYCONSOLE
2034 _PTR(Study) aStudyDS = newStudy->studyDS();
2035 app->getNoteBook()->Init( aStudyDS );
2036 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2037 newStudy->Modified();
2038 updateDesktopTitle();
2049 Close the Application
2051 void SalomeApp_Application::afterCloseDoc()
2053 #ifndef DISABLE_PYCONSOLE
2054 // emit signal to restore study from Python script
2056 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2057 myNoteBook->getDumpedStudyName(),
2058 myNoteBook->isDumpedStudySaved() );
2061 LightApp_Application::afterCloseDoc();
2065 Asks to close existing document.
2067 bool SalomeApp_Application::checkExistingDoc()
2069 bool result = LightApp_Application::checkExistingDoc();
2070 if ( result && !activeStudy() ) {
2071 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2073 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2074 if( List.size() > 0 ) {
2075 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2084 #ifndef DISABLE_PYCONSOLE
2086 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2088 return new SalomeApp_PyInterp();
2091 #endif // DISABLE_PYCONSOLE