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_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(),
166 myIsCloseFromExit( false )
171 *\li Destroy event filter.
173 SalomeApp_Application::~SalomeApp_Application()
175 // Do not destroy. It's a singleton !
176 //SALOME_EventFilter::Destroy();
179 /*!Start application.*/
180 void SalomeApp_Application::start()
182 // process the command line options before start: to createActions in accordance to the options
183 static bool isFirst = true;
191 for (int i = 1; i < qApp->argc(); i++) {
192 QRegExp rxs ("--study-hdf=(.+)");
193 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
194 QString file = rxs.capturedTexts()[1];
195 QFileInfo fi ( file );
196 QString extension = fi.suffix().toLower();
197 if ( extension == "hdf" && fi.exists() )
198 hdffile = fi.absoluteFilePath();
201 QRegExp rxp ("--pyscript=\\[(.+)\\]");
202 QRegExp rxl ("--siman-study=(.+)");
203 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
205 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
206 for (int k = 0; k < dictList.count(); ++k) {
207 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
208 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
209 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
210 pyfiles += rxd.capturedTexts()[m];
216 if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
218 loadStudy = rxl.capturedTexts()[1];
224 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
225 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
227 LightApp_Application::start();
228 SALOME_EventFilter::Init();
230 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
231 onOpenDoc( hdffile );
232 else if ( pyfiles.count() > 0 ) // create new study
234 else if (!loadStudy.isEmpty()) {// load study by name
235 if (onLoadDoc(loadStudy))
236 updateObjectBrowser(true);
239 #ifndef DISABLE_PYCONSOLE
240 // import/execute python scripts
241 if ( pyfiles.count() > 0 && activeStudy() ) {
242 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
243 PyConsole_Console* pyConsole = pythonConsole();
244 if ( appStudy && pyConsole ) {
245 _PTR(Study) aStudy = appStudy->studyDS();
246 if ( !aStudy->GetProperties()->IsLocked() ) {
247 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
248 // Path is absolute, script has .py extension
249 for (uint j = 0; j < pyfiles.count(); j++ ) {
250 // Extract scripts and their arguments, if any
251 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
252 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
253 QString script = rxp.capturedTexts()[1];
255 QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
256 for (uint k = 0; k < argList.count(); k++ ) {
257 QString arg = argList[k].trimmed();
258 arg.remove( QRegExp("^[\"]") );
259 arg.remove( QRegExp("[\"]$") );
262 args.remove( QRegExp("[,]$") );
263 if (!args.isEmpty()) {
267 script.remove( QRegExp("^python.*[\\s]+") );
268 QString cmd = script+" "+args;
269 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
270 pyConsole->exec(command);
272 } // end for loop on pyfiles QStringList
278 LightApp_Application::start();
279 SALOME_EventFilter::Init();
284 void SalomeApp_Application::createActions()
286 LightApp_Application::createActions();
288 SUIT_Desktop* desk = desktop();
291 // "Save GUI State" command is moved to VISU module
292 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
293 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
294 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
297 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
298 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
299 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
302 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
303 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
304 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
307 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
308 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
309 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
311 //! Catalog Generator
312 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
313 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
314 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
317 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
318 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
319 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
321 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
322 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
323 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
325 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
326 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
327 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
332 // check-in operations for SIMAN study
333 createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
334 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
335 0, desk, false, this, SLOT( onCheckIn() ) );
336 createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
337 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
338 0, desk, false, this, SLOT( onLocalCheckIn() ) );
342 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
344 // "Save GUI State" command is renamed to "Save VISU State" and
345 // creation of menu item is moved to VISU
346 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
348 createMenu( ConnectId, fileMenu, 5 );
349 createMenu( DisconnectId, fileMenu, 5 );
350 createMenu( separator(), fileMenu, -1, 5 );
354 // check-in operation for SIMAN study
355 // last argument "5" locates this just after "Save As" but certain constant is bad => insert after the separator
356 createMenu( SimanCheckInId, fileMenu, 5);
357 createMenu( SimanLocalCheckInId, fileMenu, 5);
358 createMenu( separator(), fileMenu, 5 );
361 createMenu( DumpStudyId, fileMenu, 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
391 \brief Close application.
393 void SalomeApp_Application::onExit()
395 bool killServers = false;
398 if ( exitConfirmation() ) {
399 SalomeApp_ExitDlg dlg( desktop() );
400 result = dlg.exec() == QDialog::Accepted;
401 killServers = dlg.isServersShutdown();
405 if ( !killServers ) myIsCloseFromExit = true;
406 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
407 myIsCloseFromExit = false;
411 /*!SLOT. Load document.*/
412 void SalomeApp_Application::onLoadDoc()
416 std::vector<std::string> List = studyMgr()->GetOpenStudies();
418 // rnv: According to the single-study approach on the server side
419 // can be only one study. So if it is exists connect to them,
420 // overwise show warning message: "No active study on the server"
423 SUIT_Session* aSession = SUIT_Session::session();
424 QList<SUIT_Application*> aAppList = aSession->applications();
426 QStringList unloadedStudies;
428 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
429 studyName = List[ind].c_str();
430 // Add to list only unloaded studies
431 bool isAlreadyOpen = false;
432 QListIterator<SUIT_Application*> it( aAppList );
433 while ( it.hasNext() && !isAlreadyOpen ) {
434 SUIT_Application* aApp = it.next();
435 if( !aApp || !aApp->activeStudy() )
437 if ( aApp->activeStudy()->studyName() == studyName )
438 isAlreadyOpen = true;
441 if ( !isAlreadyOpen )
442 unloadedStudies << studyName;
444 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
445 if ( studyName.isEmpty() )
449 if(List.size() <= 0) {
450 SUIT_MessageBox::warning( desktop(),
451 QObject::tr("WRN_WARNING"),
452 QObject::tr("WRN_NO_STUDY_ON SERV") );
456 studyName = List[0].c_str();
459 // this code replaces marker of windows drive and path become invalid therefore
460 // defines placed there
461 studyName.replace( QRegExp(":"), "/" );
464 if ( onLoadDoc( studyName ) ) {
466 updateViewManagers();
467 updateObjectBrowser( true );
471 /*!SLOT. Unload document.*/
472 void SalomeApp_Application::onUnloadDoc( bool ask )
475 activeStudy()->abortAllOperations();
476 if ( activeStudy()->isModified() ) {
477 QString docName = activeStudy()->studyName().trimmed();
478 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
479 tr( "DISCONNECT_DESCRIPTION" ),
480 tr( "DISCONNECT_SAVE" ),
481 tr( "DISCONNECT_WO_SAVE" ),
482 tr( "APPCLOSE_CANCEL" ), 0 );
483 if ( answer == 0 ) { // save before unload
484 if ( activeStudy()->isSaved() )
486 else if ( !onSaveAsDoc() )
489 else if ( answer == 2 ) // Cancel
493 closeActiveDoc( false );
496 /*!SLOT. Create new study and load script*/
497 void SalomeApp_Application::onNewWithScript()
499 QStringList filtersList;
500 filtersList.append(tr("PYTHON_FILES_FILTER"));
501 filtersList.append(tr("ALL_FILES_FILTER"));
503 QString anInitialPath = "";
504 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
505 anInitialPath = QDir::currentPath();
507 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
509 if ( !aFile.isEmpty() )
513 QString command = QString("execfile(r\"%1\")").arg(aFile);
515 #ifndef DISABLE_PYCONSOLE
516 PyConsole_Console* pyConsole = pythonConsole();
519 pyConsole->exec( command );
525 /*!SLOT. Load document with \a aName.*/
526 bool SalomeApp_Application::onLoadDoc( const QString& aName )
528 #ifdef SINGLE_DESKTOP
529 if ( !LightApp_Application::closeDoc() )
533 if ( !activeStudy() ) {
534 // if no study - load in current desktop
535 res = useStudy( aName );
538 // if study exists - load in new desktop. Check: is the same file is loaded?
539 SUIT_Session* aSession = SUIT_Session::session();
540 QList<SUIT_Application*> aAppList = aSession->applications();
541 bool isAlreadyOpen = false;
542 SalomeApp_Application* aApp = 0;
543 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
544 it != aAppList.end() && !isAlreadyOpen; ++it ) {
545 aApp = dynamic_cast<SalomeApp_Application*>( *it );
546 if ( aApp && aApp->activeStudy()->studyName() == aName )
547 isAlreadyOpen = true;
549 if ( !isAlreadyOpen ) {
550 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
552 res = aApp->useStudy( aName );
555 aApp->desktop()->activateWindow();
562 /*!SLOT. Parse message for desktop.*/
563 void SalomeApp_Application::onDesktopMessage( const QString& message )
565 if (message.indexOf("simanCheckoutDone ") == 0) {
567 // Load document with a name, specified in aMessage.
568 onLoadDoc(message.section(' ', 1));
570 printf( "****************************************************************\n" );
571 printf( "* Warning: SALOME is built without SIMAN support.\n" );
572 printf( "****************************************************************\n" );
575 else if (message.indexOf("studyCreated:") == 0) {
576 // Enable 'Connect' action
577 updateCommandsStatus();
579 else if (message.indexOf("studyClosed:") == 0) {
580 /* message also contains ID of the closed study,
581 but as soon as SALOME is mono-study application for the moment,
582 this ID is not needed now.*/
583 //long aStudyId = message.section(':', 1).toLong();
584 // Disconnect GUI from active study, because it was closed on DS side.
585 closeActiveDoc( false );
586 // Disable 'Connect' action
587 QAction* a = action( ConnectId );
589 a->setEnabled( false );
591 LightApp_Application::onDesktopMessage( message );
594 /*!SLOT. Copy objects to study maneger from selection maneger..*/
595 void SalomeApp_Application::onCopy()
598 LightApp_SelectionMgr* mgr = selectionMgr();
599 mgr->selectedObjects(list);
601 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
602 if(study == NULL) return;
604 _PTR(Study) stdDS = study->studyDS();
607 SALOME_ListIteratorOfListIO it( list );
610 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
612 studyMgr()->Copy(so);
613 onSelectionChanged();
620 /*!SLOT. Paste objects to study maneger from selection manager.*/
621 void SalomeApp_Application::onPaste()
624 LightApp_SelectionMgr* mgr = selectionMgr();
625 mgr->selectedObjects(list);
627 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
628 if(study == NULL) return;
630 _PTR(Study) stdDS = study->studyDS();
633 if ( stdDS->GetProperties()->IsLocked() ) {
634 SUIT_MessageBox::warning( desktop(),
635 QObject::tr("WRN_WARNING"),
636 QObject::tr("WRN_STUDY_LOCKED") );
640 SALOME_ListIteratorOfListIO it( list );
643 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
645 studyMgr()->Paste(so);
646 updateObjectBrowser( true );
647 updateActions(); //SRN: BugID IPAL9377, case 3
654 /*!Check the application on closing.
655 * \retval true if possible, else false
657 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
659 return LightApp_Application::isPossibleToClose( closePermanently );
662 /*! Check if the study is locked */
663 void SalomeApp_Application::onCloseDoc( bool ask )
665 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
668 _PTR(Study) stdDS = study->studyDS();
669 if(stdDS && stdDS->IsStudyLocked()) {
670 if ( SUIT_MessageBox::question( desktop(),
671 QObject::tr( "WRN_WARNING" ),
672 QObject::tr( "CLOSE_LOCKED_STUDY" ),
673 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
674 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
678 LightApp_Application::onCloseDoc( ask );
681 /*!Sets enable or disable some actions on selection changed.*/
682 void SalomeApp_Application::onSelectionChanged()
685 LightApp_SelectionMgr* mgr = selectionMgr();
686 mgr->selectedObjects(list);
688 bool canCopy = false;
689 bool canPaste = false;
691 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
693 _PTR(Study) stdDS = study->studyDS();
696 SALOME_ListIteratorOfListIO it ( list );
698 if (it.More() && list.Extent() == 1) {
699 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
702 canCopy = studyMgr()->CanCopy(so);
703 canPaste = studyMgr()->CanPaste(so);
709 action(EditCopyId)->setEnabled(canCopy);
710 action(EditPasteId)->setEnabled(canPaste);
713 /*!Delete references.*/
714 void SalomeApp_Application::onDeleteInvalidReferences()
717 LightApp_SelectionMgr* mgr = selectionMgr();
718 mgr->selectedObjects( aList, QString(), false );
720 if( aList.IsEmpty() )
723 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
724 _PTR(Study) aStudyDS = aStudy->studyDS();
725 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
728 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
729 if ( it.Value()->hasEntry() )
731 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
732 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
735 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
736 aStudyBuilder->RemoveReference( aSObject );
738 updateObjectBrowser();
742 void SalomeApp_Application::onOpenWith()
744 QApplication::setOverrideCursor( Qt::WaitCursor );
746 LightApp_SelectionMgr* mgr = selectionMgr();
747 mgr->selectedObjects(aList);
748 if (aList.Extent() != 1)
750 QApplication::restoreOverrideCursor();
753 Handle(SALOME_InteractiveObject) aIObj = aList.First();
754 QString aModuleName(aIObj->getComponentDataType());
755 QString aModuleTitle = moduleTitle(aModuleName);
756 activateModule(aModuleTitle);
757 QApplication::restoreOverrideCursor();
763 SUIT_Study* SalomeApp_Application::createNewStudy()
765 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
767 // Set up processing of major study-related events
768 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
769 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
770 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
771 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
773 #ifndef DISABLE_PYCONSOLE
774 //to receive signal in application that NoteBook's variable was modified
775 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
776 this, SIGNAL(notebookVarUpdated(QString)) );
783 Enable/Disable menu items and toolbar buttons. Rebuild menu
785 void SalomeApp_Application::updateCommandsStatus()
787 LightApp_Application::updateCommandsStatus();
790 QAction* a = action( DumpStudyId );
792 a->setEnabled( activeStudy() );
795 a = action( LoadScriptId );
797 a->setEnabled( pythonConsole() );
800 a = action( PropertiesId );
802 a->setEnabled( activeStudy() );
804 // Save GUI state menu
805 a = action( SaveGUIStateId );
807 a->setEnabled( activeStudy() );
809 // Connect study menu
810 a = action( ConnectId );
812 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
814 // Disconnect study menu
815 a = action( DisconnectId );
817 a->setEnabled( activeStudy() );
819 // update state of Copy/Paste menu items
820 onSelectionChanged();
824 \class DumpStudyFileDlg
825 Private class used in Dump Study operation. Consists 2 check boxes:
826 "Publish in study" and "Save GUI parameters"
828 class DumpStudyFileDlg : public SUIT_FileDlg
831 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
833 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
836 QWidget *hB = new QWidget( this );
837 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
838 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
839 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
841 QHBoxLayout *layout = new QHBoxLayout;
842 layout->addWidget(myPublishChk);
843 layout->addWidget(myMultiFileChk);
844 layout->addWidget(mySaveGUIChk);
845 hB->setLayout(layout);
847 QPushButton* pb = new QPushButton(this);
849 int row = grid->rowCount();
850 grid->addWidget( new QLabel("", this), row, 0 );
851 grid->addWidget( hB, row, 1, 1, 3 );
852 grid->addWidget( pb, row, 5 );
857 QCheckBox* myPublishChk;
858 QCheckBox* myMultiFileChk;
859 QCheckBox* mySaveGUIChk;
862 class DumpStudyFileValidator : public SUIT_FileValidator
865 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
866 virtual ~DumpStudyFileValidator() {};
867 virtual bool canSave( const QString& file, bool permissions );
870 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
872 QFileInfo fi( file );
873 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
874 SUIT_MessageBox::critical( parent(),
875 QObject::tr("WRN_WARNING"),
876 QObject::tr("WRN_FILE_NAME_BAD") );
879 return SUIT_FileValidator::canSave( file, permissions);
882 /*!Private SLOT. On dump study.*/
883 void SalomeApp_Application::onDumpStudy( )
885 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
886 if ( !appStudy ) return;
887 _PTR(Study) aStudy = appStudy->studyDS();
889 QStringList aFilters;
890 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
892 bool anIsPublish = true;
893 bool anIsMultiFile = false;
894 bool anIsSaveGUI = true;
896 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
897 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
898 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
899 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
902 DumpStudyFileDlg fd( desktop() );
903 fd.setValidator( new DumpStudyFileValidator( &fd ) );
904 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
905 fd.setFilters( aFilters );
906 fd.myPublishChk->setChecked( anIsPublish );
907 fd.myMultiFileChk->setChecked( anIsMultiFile );
908 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
909 if ( fd.exec() == QDialog::Accepted )
911 QString aFileName = fd.selectedFile();
913 bool toPublish = fd.myPublishChk->isChecked();
914 bool isMultiFile = fd.myMultiFileChk->isChecked();
915 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
917 if ( !aFileName.isEmpty() ) {
918 QFileInfo aFileInfo(aFileName);
919 if( aFileInfo.isDir() ) // IPAL19257
922 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
925 SUIT_OverrideCursor wc;
926 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
929 SUIT_MessageBox::warning( desktop(),
930 QObject::tr("WRN_WARNING"),
931 tr("WRN_DUMP_STUDY_FAILED") );
936 /*!Private SLOT. On load script.*/
937 void SalomeApp_Application::onLoadScript( )
939 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
941 _PTR(Study) aStudy = appStudy->studyDS();
942 if ( aStudy->GetProperties()->IsLocked() ) {
943 SUIT_MessageBox::warning( desktop(),
944 QObject::tr("WRN_WARNING"),
945 QObject::tr("WRN_STUDY_LOCKED") );
950 QStringList filtersList;
951 filtersList.append(tr("PYTHON_FILES_FILTER"));
952 filtersList.append(tr("ALL_FILES_FILTER"));
954 QString anInitialPath = "";
955 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
956 anInitialPath = QDir::currentPath();
959 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
961 SALOMEDSClient_StudyManager* aMgr = studyMgr();
962 aMgr->GetSimanStudy()->StudyId();
963 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
964 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
965 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
969 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
971 if ( !aFile.isEmpty() )
973 QString command = QString("execfile(r\"%1\")").arg(aFile);
975 #ifndef DISABLE_PYCONSOLE
976 PyConsole_Console* pyConsole = pythonConsole();
979 pyConsole->exec( command );
984 /*!Private SLOT. On save GUI state.*/
985 void SalomeApp_Application::onSaveGUIState()
987 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
989 SalomeApp_VisualState( this ).storeState();
990 updateSavePointDataObjects( study );
991 updateObjectBrowser();
996 /*!Public SLOT. On SIMAN check in operation.*/
997 void SalomeApp_Application::onCheckIn()
1000 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1001 setMenuShown(SimanLocalCheckInId, false);
1002 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1003 aMgr->GetSimanStudy()->CheckIn("");
1005 printf( "****************************************************************\n" );
1006 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1007 printf( "****************************************************************\n" );
1011 /*!Public SLOT. On SIMAN local check in operation.*/
1012 void SalomeApp_Application::onLocalCheckIn()
1015 // get the active module
1016 CAM_Module* aModule = activeModule();
1017 if (!aModule) return; // there is no active module
1019 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1020 setMenuShown(SimanLocalCheckInId, false);
1021 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1022 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1024 printf( "****************************************************************\n" );
1025 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1026 printf( "****************************************************************\n" );
1030 /*!Gets file filter.
1031 *\retval QString "(*.hdf)"
1033 QString SalomeApp_Application::getFileFilter() const
1039 QWidget* SalomeApp_Application::createWindow( const int flag )
1042 #ifndef DISABLE_PYCONSOLE
1043 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1045 wid = LightApp_Application::createWindow(flag);
1048 SUIT_ResourceMgr* resMgr = resourceMgr();
1050 if ( flag == WT_ObjectBrowser )
1052 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1054 // temporary commented
1055 //ob->setUpdater( new SalomeApp_Updater() );
1057 #ifdef WITH_SALOMEDS_OBSERVER
1058 //do not activate the automatic update of Qt tree through signal/slot
1059 ob->setAutoUpdate(false);
1060 //activate update of modified objects only
1061 ob->setUpdateModified(true);
1064 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1067 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1068 IORCol = QObject::tr( "IOR_COLUMN" ),
1069 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1070 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1072 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1073 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1074 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1075 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1076 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1077 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1078 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1079 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1080 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1082 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1083 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1084 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1086 ob->setAutoSizeFirstColumn(autoSizeFirst);
1087 ob->setAutoSizeColumns(autoSize);
1088 ob->setResizeOnExpandItem(resizeOnExpandItem);
1089 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1091 // temporary commented
1093 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1095 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1096 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1097 QString().sprintf( "visibility_column_%d", i ), true ) );
1101 // temporary commented
1103 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1104 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1105 ob->resize( desktop()->width()/3, ob->height() );
1109 #ifndef DISABLE_PYCONSOLE
1110 else if ( flag == WT_PyConsole )
1112 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1113 pyCons->setObjectName( "pythonConsole" );
1114 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1115 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1116 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1117 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1119 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1120 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1122 else if ( flag == WT_NoteBook )
1124 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1126 _PTR(Study) aStudy = appStudy->studyDS();
1127 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1128 //to receive signal in NoteBook that it's variable was modified
1129 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1130 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1132 wid = getNoteBook();
1133 wid->setObjectName( "noteBook" );
1139 /*!Create preferences.*/
1140 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1142 LightApp_Application::createPreferences(pref);
1147 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1148 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1149 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1150 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1152 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1153 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1155 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1157 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1158 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1159 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1160 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1161 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1162 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1163 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1164 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1165 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1166 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1169 /*!Update desktop title.*/
1170 void SalomeApp_Application::updateDesktopTitle() {
1171 QString aTitle = applicationName();
1172 QString aVer = applicationVersion();
1173 if ( !aVer.isEmpty() )
1174 aTitle += QString( " " ) + aVer;
1176 if ( activeStudy() )
1178 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1179 if ( !sName.isEmpty() ) {
1180 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1182 _PTR(Study) stdDS = study->studyDS();
1184 if ( stdDS->GetProperties()->IsLocked() ) {
1185 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1187 aTitle += QString( " - [%1]" ).arg( sName );
1194 desktop()->setWindowTitle( aTitle );
1197 int SalomeApp_Application::closeChoice( const QString& docName )
1199 QStringList buttons;
1200 QMap<int, int> choices;
1202 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1203 choices.insert( idx++, CloseSave ); // ...
1204 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1205 choices.insert( idx++, CloseDiscard ); // ...
1206 if ( myIsCloseFromExit ) {
1207 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1208 choices.insert( idx++, CloseDisconnectSave ); // ...
1209 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1210 choices.insert( idx++, CloseDisconnect ); // ...
1212 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1213 choices.insert( idx++, CloseCancel ); // ...
1215 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1216 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1217 return choices[answer];
1220 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1226 if ( activeStudy()->isSaved() )
1228 else if ( !onSaveAsDoc() )
1233 case CloseDisconnectSave:
1234 if ( activeStudy()->isSaved() )
1236 else if ( !onSaveAsDoc() )
1238 case CloseDisconnect:
1239 closeActiveDoc( false );
1240 closePermanently = false;
1249 int SalomeApp_Application::openChoice( const QString& aName )
1251 int choice = LightApp_Application::openChoice( aName );
1253 if ( QFileInfo( aName ).exists() ) {
1254 if ( choice == OpenNew ) { // The document isn't already open.
1256 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1257 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1258 if ( aName == QString( lst[i].c_str() ) )
1261 // The document already exists in the study manager.
1262 // Do you want to reload it?
1264 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1265 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1266 if ( answer == SUIT_MessageBox::Yes )
1267 choice = OpenRefresh;
1269 choice = OpenCancel;
1272 } else { // file is not exist on disk
1273 SUIT_MessageBox::warning( desktop(),
1274 QObject::tr("WRN_WARNING"),
1275 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1282 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1285 int choice = aChoice;
1290 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1293 studyMgr()->Close( aStudy );
1298 res = LightApp_Application::openAction( choice, aName );
1306 \brief Get map of the operations which can be performed
1307 on the module activation.
1309 The method should return the map of the kind \c {<id>:<name>}
1310 where \c <id> is an integer identifier of the operation and
1311 \c <name> is a title for the button to be added to the
1312 dialog box. After user selects the required operation by the
1313 clicking the corresponding button in the dialog box, its identifier
1314 is passed to the moduleActionSelected() method to process
1317 \return map of the operations
1318 \sa moduleActionSelected()
1320 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1322 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1324 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1326 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1331 \brief Called when the used selectes required operation chosen
1332 from "Activate module" dialog box.
1334 Performs the required operation according to the user choice.
1336 \param id operation identifier
1337 \sa activateModuleActions()
1339 void SalomeApp_Application::moduleActionSelected( const int id )
1345 case NewAndScriptId:
1349 LightApp_Application::moduleActionSelected( id );
1354 /*!Gets CORBA::ORB_var*/
1355 CORBA::ORB_var SalomeApp_Application::orb()
1357 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1358 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1362 /*!Create and return SALOMEDS_StudyManager.*/
1363 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1365 static _PTR(StudyManager) _sm;
1366 if(!_sm) _sm = ClientFactory::StudyManager();
1370 /*!Create and return SALOME_NamingService.*/
1371 SALOME_NamingService* SalomeApp_Application::namingService()
1373 static SALOME_NamingService _ns(orb());
1377 /*!Create and return SALOME_LifeCycleCORBA.*/
1378 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1380 static SALOME_LifeCycleCORBA _lcc( namingService() );
1384 /*!Private SLOT. On preferences.*/
1385 void SalomeApp_Application::onProperties()
1387 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1391 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1394 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1395 int res = aDlg.exec();
1396 if( res==QDialog::Accepted && aDlg.isChanged() )
1397 SB->CommitCommand();
1401 //study->updateCaptions();
1402 updateDesktopTitle();
1406 /*!Insert items in popup, which necessary for current application*/
1407 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1409 LightApp_SelectionMgr* mgr = selectionMgr();
1410 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1411 mgr->setSelectionCacheEnabled( true );
1413 LightApp_Application::contextMenuPopup( type, thePopup, title );
1415 // temporary commented
1416 /*OB_Browser* ob = objectBrowser();
1417 if ( !ob || type != ob->popupClientType() )
1420 // Get selected objects
1421 SALOME_ListIO aList;
1422 mgr->selectedObjects( aList, QString(), false );
1424 // add GUI state commands: restore, rename
1425 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1426 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1427 thePopup->addSeparator();
1428 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1429 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1430 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1431 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1434 // "Delete reference" item should appear only for invalid references
1436 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1437 bool isInvalidRefs = false;
1438 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1440 _PTR(Study) aStudyDS = aStudy->studyDS();
1441 _PTR(SObject) anObj;
1443 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1445 if( it.Value()->hasEntry() )
1447 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1448 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1451 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1452 isInvalidRefs = true;
1456 // Add "Delete reference" item to popup
1457 if ( isInvalidRefs )
1459 thePopup->addSeparator();
1460 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1464 // "Activate module" item should appear only if it's necessary
1465 if ( aList.Extent() == 1 ) {
1467 mgr->selectedObjects( aList );
1469 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1471 // add extra popup menu (defined in XML)
1472 if ( myExtActions.size() > 0 ) {
1473 // Use only first selected object
1474 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1476 _PTR(Study) stdDS = study->studyDS();
1478 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1480 _PTR( GenericAttribute ) anAttr;
1481 std::string auid = "AttributeUserID";
1482 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1483 if ( aSO->FindAttribute( anAttr, auid ) ) {
1484 _PTR(AttributeUserID) aAttrID = anAttr;
1485 QString aId = aAttrID->Value().c_str();
1486 if ( myExtActions.contains( aId ) ) {
1487 thePopup->addAction(myExtActions[aId]);
1495 // check if item is a "GUI state" item (also a first level object)
1496 QString entry( aIObj->getEntry() );
1497 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1498 QString aModuleName( aIObj->getComponentDataType() );
1499 QString aModuleTitle = moduleTitle( aModuleName );
1500 CAM_Module* currentModule = activeModule();
1501 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1502 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1507 mgr->setSelectionCacheEnabled( cacheIsOn );
1510 /*!Update obect browser:
1511 1.if 'updateModels' true, update existing data models;
1512 2. update "non-existing" (not loaded yet) data models;
1513 3. update object browser if it exists */
1514 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1516 // update "non-existing" (not loaded yet) data models
1517 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1520 _PTR(Study) stdDS = study->studyDS();
1523 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1525 _PTR(SComponent) aComponent ( it->Value() );
1527 #ifndef WITH_SALOMEDS_OBSERVER
1528 // with GUI observers this check is not needed anymore
1529 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1530 continue; // skip the magic "Interface Applicative" component
1532 if ( !objectBrowser() )
1533 getWindow( WT_ObjectBrowser );
1534 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1535 objectBrowser()->setAutoUpdate( false );
1536 SalomeApp_DataModel::synchronize( aComponent, study );
1537 objectBrowser()->setAutoUpdate( isAutoUpdate );
1542 // create data objects that correspond to GUI state save points
1543 if ( study ) updateSavePointDataObjects( study );
1545 // update existing data models (already loaded SComponents)
1546 LightApp_Application::updateObjectBrowser( updateModels );
1549 /*!Display Catalog Genenerator dialog */
1550 void SalomeApp_Application::onCatalogGen()
1552 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1556 /*!Display Registry Display dialog */
1557 void SalomeApp_Application::onRegDisplay()
1559 CORBA::ORB_var anOrb = orb();
1560 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1563 regWnd->activateWindow();
1566 /*!find original object by double click on item */
1567 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1569 // Issue 21379: References are supported at LightApp_DataObject level
1570 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1572 if( obj && obj->isReference() )
1574 QString entry = obj->refEntry();
1576 SUIT_DataOwnerPtrList aList;
1577 aList.append( new LightApp_DataOwner( entry ) );
1578 selectionMgr()->setSelected( aList, false );
1580 SUIT_DataBrowser* ob = objectBrowser();
1582 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1583 if ( !aSelectedIndexes.isEmpty() )
1584 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1589 Creates new view manager
1590 \param type - type of view manager
1592 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1594 return createViewManager(type);
1598 /*!Global utility function, returns selected GUI Save point object's ID */
1599 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1601 SALOME_ListIO aList;
1602 selMgr->selectedObjects( aList );
1603 if( aList.Extent() > 0 ) {
1604 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1605 QString entry( aIObj->getEntry() );
1606 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1607 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1609 bool ok; // conversion to integer is ok?
1610 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1611 return ok ? savePoint : -1;
1616 /*!Called on Restore GUI State popup command*/
1617 void SalomeApp_Application::onRestoreGUIState()
1619 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1620 if ( savePoint == -1 )
1622 SalomeApp_VisualState( this ).restoreState( savePoint );
1625 /*!Called on Delete GUI State popup command*/
1626 void SalomeApp_Application::onDeleteGUIState()
1628 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1629 if ( savePoint == -1 )
1631 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1635 study->removeSavePoint( savePoint );
1636 updateSavePointDataObjects( study );
1639 /*!Called on New study operation*/
1640 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1642 LightApp_Application::onStudyCreated( study );
1644 //#ifndef DISABLE_PYCONSOLE
1645 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1646 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1649 loadDockWindowsState();
1651 objectBrowserColumnsVisibility();
1654 /*!Called on Open study operation*/
1655 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1657 LightApp_Application::onStudyOpened( study );
1659 //#ifndef DISABLE_PYCONSOLE
1660 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1661 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1664 loadDockWindowsState();
1666 objectBrowserColumnsVisibility();
1668 // temporary commented
1669 /*if ( objectBrowser() ) {
1670 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1671 objectBrowser()->updateTree( study->root() );
1675 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1676 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1679 SUIT_DataBrowser* ob = objectBrowser();
1680 LightApp_SelectionMgr* selMgr = selectionMgr();
1682 if ( !study || !ob || !selMgr )
1685 // find GUI states root object
1686 SUIT_DataObject* guiRootObj = 0;
1688 study->root()->children( ch );
1689 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1690 for ( ; it != last ; ++it ) {
1691 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1696 std::vector<int> savePoints = study->getSavePoints();
1697 // case 1: no more save points but they existed in study's tree
1698 if ( savePoints.empty() && guiRootObj ) {
1699 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1700 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1701 const bool isAutoUpdate = ob->autoUpdate();
1702 selMgr->clearSelected();
1703 ob->setAutoUpdate(true);
1704 DataObjectList ch = guiRootObj->children();
1705 for( int i = 0; i < ch.size(); i++ )
1708 ob->setAutoUpdate(isAutoUpdate);
1711 // case 2: no more save points but root does not exist either
1712 if ( savePoints.empty() && !guiRootObj )
1714 // case 3: save points but no root for them - create it
1715 if ( !savePoints.empty() && !guiRootObj )
1716 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1717 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1718 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1720 if ( guiRootObj->nextBrother() ) {
1721 study->root()->removeChild(guiRootObj);
1722 study->root()->appendChild(guiRootObj);
1723 //study->root()->dump();
1726 // store data objects in a map id-to-DataObject
1727 QMap<int,SalomeApp_SavePointObject*> mapDO;
1729 guiRootObj->children( ch );
1730 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1731 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1733 mapDO[dobj->getId()] = dobj;
1736 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1737 // if in the map - remove it from map.
1738 for ( int i = 0; i < savePoints.size(); i++ )
1739 if ( !mapDO.contains( savePoints[i] ) )
1740 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1742 mapDO.remove( savePoints[i] );
1744 // delete DataObjects that are still in the map -- their IDs were not found in data model
1745 if( mapDO.size() > 0) {
1746 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1747 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1748 selMgr->clearSelected();
1749 const bool isAutoUpdate = ob->autoUpdate();
1750 ob->setAutoUpdate(true);
1751 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1753 ob->setAutoUpdate(isAutoUpdate);
1757 /*! Check data object */
1758 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1767 Opens other study into active Study. If Study is empty - creates it.
1768 \param theName - name of study
1770 bool SalomeApp_Application::useStudy( const QString& theName )
1773 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1776 res = aStudy->loadDocument( theName );
1777 updateDesktopTitle();
1778 updateCommandsStatus();
1782 /*! Show/hide object browser colums according to preferences */
1783 void SalomeApp_Application::objectBrowserColumnsVisibility()
1785 if ( objectBrowser() )
1786 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1788 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1789 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1793 #ifndef DISABLE_PYCONSOLE
1794 /*! Set SalomeApp_NoteBook pointer */
1795 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1797 myNoteBook = theNoteBook;
1800 /*! Return SalomeApp_NoteBook pointer */
1801 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1808 * Define extra actions defined in module definition XML file.
1809 * Additional popup items sections can be defined by parameter "popupitems".
1810 * Supported attributes:
1811 * title - title of menu item,
1812 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1813 * method - method which has to be called when menu item is selected
1815 * <section name="MODULENAME">
1816 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1818 * <section name="importmed">
1819 * <parameter name="title" value="My menu"/>
1820 * <parameter name="objectid" value="VISU.Result"/>
1821 * <parameter name="method" value="nameOfModuleMethod"/>
1824 void SalomeApp_Application::createExtraActions()
1826 myExtActions.clear();
1827 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1829 QStringList aModules;
1830 modules(aModules, false);
1831 foreach(QString aModile, aModules) {
1832 QString aModName = moduleName(aModile);
1833 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1834 if (!aSectionStr.isNull()) {
1835 QStringList aSections = aSectionStr.split(':');
1836 foreach(QString aSection, aSections) {
1837 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1838 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1839 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1840 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1843 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1844 if (aModuleName.isNull())
1845 aModuleName = aModName;
1847 QAction* aAction = new QAction(aTitle, this);
1849 aData<<aModuleName<<aSlot;
1850 aAction->setData(aData);
1851 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1852 myExtActions[aId] = aAction;
1859 * Called when extra action is selected
1861 void SalomeApp_Application::onExtAction()
1863 QAction* aAction = ::qobject_cast<QAction*>(sender());
1867 QVariant aData = aAction->data();
1868 QStringList aDataList = aData.value<QStringList>();
1869 if (aDataList.size() != 2)
1872 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1873 SALOME_ListIO aListIO;
1874 aSelectionMgr->selectedObjects(aListIO);
1875 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1876 if (aListIO.Extent() < 1)
1878 if (!anIO->hasEntry())
1881 QString aEntry(anIO->getEntry());
1883 QApplication::setOverrideCursor( Qt::WaitCursor );
1884 QString aModuleTitle = moduleTitle(aDataList[0]);
1885 activateModule(aModuleTitle);
1886 QApplication::restoreOverrideCursor();
1888 QCoreApplication::processEvents();
1890 CAM_Module* aModule = activeModule();
1894 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1895 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1899 Checks that an object can be renamed.
1900 \param entry entry of the object
1901 \brief Return \c true if object can be renamed
1903 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1905 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1909 Rename object by entry.
1910 \param entry entry of the object
1911 \param name new name of the object
1912 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1914 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1916 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1918 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1920 if(!aStudy || savePoint == -1)
1923 if ( !name.isNull() && !name.isEmpty() ) {
1924 aStudy->setNameOfSavePoint( savePoint, name );
1925 updateSavePointDataObjects( aStudy );
1927 //Mark study as modified
1934 #ifndef DISABLE_PYCONSOLE
1935 //============================================================================
1936 /*! Function : onUpdateStudy
1937 * Purpose : Slot to update the study.
1939 //============================================================================
1940 void SalomeApp_Application::onUpdateStudy()
1942 QApplication::setOverrideCursor( Qt::WaitCursor );
1944 if( !updateStudy() )
1945 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1947 QApplication::restoreOverrideCursor();
1950 //============================================================================
1951 /*! Function : updateStudy
1952 * Purpose : Update study by dumping the study to Python script and loading it.
1953 * It is used to apply variable modifications done in NoteBook to created objects.
1955 //============================================================================
1956 bool SalomeApp_Application::updateStudy()
1958 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1959 if ( !study || !myNoteBook )
1962 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1963 myNoteBook->setDumpedStudyName( study->studyName() );
1965 _PTR(Study) studyDS = study->studyDS();
1967 // get unique temporary directory name
1968 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1969 if( aTmpDir.isEmpty() )
1972 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1973 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1975 // dump study to the temporary directory
1976 QString aScriptName( "notebook" );
1977 bool toPublish = true;
1978 bool isMultiFile = false;
1979 bool toSaveGUI = true;
1982 _PTR(AttributeParameter) ap;
1983 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1984 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1985 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1986 ip->setDumpPython(studyDS);
1987 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1989 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1991 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1994 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1998 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1999 int anIndex = aList.indexOf( this );
2001 // Disconnect dialog from application desktop in case if:
2002 // 1) Application is not the first application in the session
2003 // 2) Application is the first application in session but not the only.
2004 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2005 if( changeDesktop ) {
2007 SalomeApp_Application* app = this;
2008 if( anIndex > 0 && anIndex < aList.count() )
2009 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2010 else if(anIndex == 0 && aList.count() > 1)
2011 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2016 // creation a new study and restoring will be done in another application
2017 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2018 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2021 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2022 QString aStudyName = myNoteBook->getDumpedStudyName();
2023 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2024 // clear a study (delete all objects)
2025 onCloseDoc( false );
2027 if( !changeDesktop ) {
2028 ok = onRestoreStudy( aDumpScript,
2037 //============================================================================
2038 /*! Function : onRestoreStudy
2039 * Purpose : Load the dumped study from Python script
2041 //============================================================================
2042 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2043 const QString& theStudyName,
2044 bool theIsStudySaved )
2048 // create a new study
2051 // get active application
2052 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2054 // load study from the temporary directory
2055 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2057 #ifndef DISABLE_PYCONSOLE
2058 PyConsole_Console* pyConsole = app->pythonConsole();
2060 pyConsole->execAndWait( command );
2063 // remove temporary directory
2064 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2065 QString aStudyName = aScriptInfo.baseName();
2066 QDir aDir = aScriptInfo.absoluteDir();
2067 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2068 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2069 ok = aDir.remove( *it ) && ok;
2071 ok = aDir.rmdir( aDir.absolutePath() );
2073 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2075 #ifndef DISABLE_PYCONSOLE
2076 _PTR(Study) aStudyDS = newStudy->studyDS();
2077 app->getNoteBook()->Init( aStudyDS );
2078 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2079 newStudy->Modified();
2080 updateDesktopTitle();
2091 Close the Application
2093 void SalomeApp_Application::afterCloseDoc()
2095 #ifndef DISABLE_PYCONSOLE
2096 // emit signal to restore study from Python script
2098 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2099 myNoteBook->getDumpedStudyName(),
2100 myNoteBook->isDumpedStudySaved() );
2103 LightApp_Application::afterCloseDoc();
2107 Asks to close existing document.
2109 bool SalomeApp_Application::checkExistingDoc()
2111 bool result = LightApp_Application::checkExistingDoc();
2112 if ( result && !activeStudy() ) {
2113 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2115 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2116 if( List.size() > 0 ) {
2117 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));