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 if ( SUIT_Session::session()->applications().count() > 0 ) 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 else if ( message.toLower() == "connect_to_study" ) {
594 LightApp_Application::onDesktopMessage( message );
597 /*!SLOT. Copy objects to study maneger from selection maneger..*/
598 void SalomeApp_Application::onCopy()
601 LightApp_SelectionMgr* mgr = selectionMgr();
602 mgr->selectedObjects(list);
604 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
605 if(study == NULL) return;
607 _PTR(Study) stdDS = study->studyDS();
610 SALOME_ListIteratorOfListIO it( list );
613 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
615 studyMgr()->Copy(so);
616 onSelectionChanged();
623 /*!SLOT. Paste objects to study maneger from selection manager.*/
624 void SalomeApp_Application::onPaste()
627 LightApp_SelectionMgr* mgr = selectionMgr();
628 mgr->selectedObjects(list);
630 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
631 if(study == NULL) return;
633 _PTR(Study) stdDS = study->studyDS();
636 if ( stdDS->GetProperties()->IsLocked() ) {
637 SUIT_MessageBox::warning( desktop(),
638 QObject::tr("WRN_WARNING"),
639 QObject::tr("WRN_STUDY_LOCKED") );
643 SALOME_ListIteratorOfListIO it( list );
646 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
648 studyMgr()->Paste(so);
649 updateObjectBrowser( true );
650 updateActions(); //SRN: BugID IPAL9377, case 3
657 /*!Check the application on closing.
658 * \retval true if possible, else false
660 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
662 return LightApp_Application::isPossibleToClose( closePermanently );
665 /*! Check if the study is locked */
666 void SalomeApp_Application::onCloseDoc( bool ask )
668 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
671 _PTR(Study) stdDS = study->studyDS();
672 if(stdDS && stdDS->IsStudyLocked()) {
673 if ( SUIT_MessageBox::question( desktop(),
674 QObject::tr( "WRN_WARNING" ),
675 QObject::tr( "CLOSE_LOCKED_STUDY" ),
676 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
677 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
681 LightApp_Application::onCloseDoc( ask );
684 /*!Sets enable or disable some actions on selection changed.*/
685 void SalomeApp_Application::onSelectionChanged()
688 LightApp_SelectionMgr* mgr = selectionMgr();
689 mgr->selectedObjects(list);
691 bool canCopy = false;
692 bool canPaste = false;
694 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
697 canCopy = m->canCopy();
698 canPaste = m->canPaste();
701 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
703 _PTR(Study) stdDS = study->studyDS();
706 SALOME_ListIteratorOfListIO it ( list );
708 if (it.More() && list.Extent() == 1) {
709 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
712 canCopy = canCopy || studyMgr()->CanCopy(so);
713 canPaste = canPaste || studyMgr()->CanPaste(so);
719 action(EditCopyId)->setEnabled(canCopy);
720 action(EditPasteId)->setEnabled(canPaste);
723 /*!Delete references.*/
724 void SalomeApp_Application::onDeleteInvalidReferences()
727 LightApp_SelectionMgr* mgr = selectionMgr();
728 mgr->selectedObjects( aList, QString(), false );
730 if( aList.IsEmpty() )
733 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
734 _PTR(Study) aStudyDS = aStudy->studyDS();
735 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
738 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
739 if ( it.Value()->hasEntry() )
741 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
742 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
745 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
746 aStudyBuilder->RemoveReference( aSObject );
748 updateObjectBrowser();
752 void SalomeApp_Application::onOpenWith()
754 QApplication::setOverrideCursor( Qt::WaitCursor );
756 LightApp_SelectionMgr* mgr = selectionMgr();
757 mgr->selectedObjects(aList);
758 if (aList.Extent() != 1)
760 QApplication::restoreOverrideCursor();
763 Handle(SALOME_InteractiveObject) aIObj = aList.First();
764 QString aModuleName(aIObj->getComponentDataType());
765 QString aModuleTitle = moduleTitle(aModuleName);
766 activateModule(aModuleTitle);
767 QApplication::restoreOverrideCursor();
773 SUIT_Study* SalomeApp_Application::createNewStudy()
775 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
777 // Set up processing of major study-related events
778 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
779 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
780 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
781 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
783 #ifndef DISABLE_PYCONSOLE
784 //to receive signal in application that NoteBook's variable was modified
785 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
786 this, SIGNAL(notebookVarUpdated(QString)) );
793 Enable/Disable menu items and toolbar buttons. Rebuild menu
795 void SalomeApp_Application::updateCommandsStatus()
797 LightApp_Application::updateCommandsStatus();
800 QAction* a = action( DumpStudyId );
802 a->setEnabled( activeStudy() );
805 a = action( LoadScriptId );
807 a->setEnabled( pythonConsole() );
810 a = action( PropertiesId );
812 a->setEnabled( activeStudy() );
814 // Save GUI state menu
815 a = action( SaveGUIStateId );
817 a->setEnabled( activeStudy() );
819 // Connect study menu
820 a = action( ConnectId );
822 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
824 // Disconnect study menu
825 a = action( DisconnectId );
827 a->setEnabled( activeStudy() );
829 // update state of Copy/Paste menu items
830 onSelectionChanged();
834 \class DumpStudyFileDlg
835 Private class used in Dump Study operation. Consists 2 check boxes:
836 "Publish in study" and "Save GUI parameters"
838 class DumpStudyFileDlg : public SUIT_FileDlg
841 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
843 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
846 QWidget *hB = new QWidget( this );
847 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
848 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
849 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
851 QHBoxLayout *layout = new QHBoxLayout;
852 layout->addWidget(myPublishChk);
853 layout->addWidget(myMultiFileChk);
854 layout->addWidget(mySaveGUIChk);
855 hB->setLayout(layout);
857 QPushButton* pb = new QPushButton(this);
859 int row = grid->rowCount();
860 grid->addWidget( new QLabel("", this), row, 0 );
861 grid->addWidget( hB, row, 1, 1, 3 );
862 grid->addWidget( pb, row, 5 );
867 QCheckBox* myPublishChk;
868 QCheckBox* myMultiFileChk;
869 QCheckBox* mySaveGUIChk;
872 class DumpStudyFileValidator : public SUIT_FileValidator
875 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
876 virtual ~DumpStudyFileValidator() {};
877 virtual bool canSave( const QString& file, bool permissions );
880 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
882 QFileInfo fi( file );
883 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
884 SUIT_MessageBox::critical( parent(),
885 QObject::tr("WRN_WARNING"),
886 QObject::tr("WRN_FILE_NAME_BAD") );
889 return SUIT_FileValidator::canSave( file, permissions);
892 /*!Private SLOT. On dump study.*/
893 void SalomeApp_Application::onDumpStudy( )
895 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
896 if ( !appStudy ) return;
897 _PTR(Study) aStudy = appStudy->studyDS();
899 QStringList aFilters;
900 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
902 bool anIsPublish = true;
903 bool anIsMultiFile = false;
904 bool anIsSaveGUI = true;
906 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
907 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
908 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
909 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
912 DumpStudyFileDlg fd( desktop() );
913 fd.setValidator( new DumpStudyFileValidator( &fd ) );
914 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
915 fd.setFilters( aFilters );
916 fd.myPublishChk->setChecked( anIsPublish );
917 fd.myMultiFileChk->setChecked( anIsMultiFile );
918 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
919 if ( fd.exec() == QDialog::Accepted )
921 QString aFileName = fd.selectedFile();
923 bool toPublish = fd.myPublishChk->isChecked();
924 bool isMultiFile = fd.myMultiFileChk->isChecked();
925 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
927 if ( !aFileName.isEmpty() ) {
928 QFileInfo aFileInfo(aFileName);
929 if( aFileInfo.isDir() ) // IPAL19257
932 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
935 SUIT_OverrideCursor wc;
936 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
939 SUIT_MessageBox::warning( desktop(),
940 QObject::tr("WRN_WARNING"),
941 tr("WRN_DUMP_STUDY_FAILED") );
946 /*!Private SLOT. On load script.*/
947 void SalomeApp_Application::onLoadScript( )
949 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
951 _PTR(Study) aStudy = appStudy->studyDS();
952 if ( aStudy->GetProperties()->IsLocked() ) {
953 SUIT_MessageBox::warning( desktop(),
954 QObject::tr("WRN_WARNING"),
955 QObject::tr("WRN_STUDY_LOCKED") );
960 QStringList filtersList;
961 filtersList.append(tr("PYTHON_FILES_FILTER"));
962 filtersList.append(tr("ALL_FILES_FILTER"));
964 QString anInitialPath = "";
965 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
966 anInitialPath = QDir::currentPath();
969 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
971 SALOMEDSClient_StudyManager* aMgr = studyMgr();
972 aMgr->GetSimanStudy()->StudyId();
973 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
974 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
975 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
979 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
981 if ( !aFile.isEmpty() )
983 QString command = QString("execfile(r\"%1\")").arg(aFile);
985 #ifndef DISABLE_PYCONSOLE
986 PyConsole_Console* pyConsole = pythonConsole();
989 pyConsole->exec( command );
994 /*!Private SLOT. On save GUI state.*/
995 void SalomeApp_Application::onSaveGUIState()
997 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
999 SalomeApp_VisualState( this ).storeState();
1000 updateSavePointDataObjects( study );
1001 updateObjectBrowser();
1006 /*!Public SLOT. On SIMAN check in operation.*/
1007 void SalomeApp_Application::onCheckIn()
1010 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1011 setMenuShown(SimanLocalCheckInId, false);
1012 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1013 aMgr->GetSimanStudy()->CheckIn("");
1015 printf( "****************************************************************\n" );
1016 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1017 printf( "****************************************************************\n" );
1021 /*!Public SLOT. On SIMAN local check in operation.*/
1022 void SalomeApp_Application::onLocalCheckIn()
1025 // get the active module
1026 CAM_Module* aModule = activeModule();
1027 if (!aModule) return; // there is no active module
1029 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1030 setMenuShown(SimanLocalCheckInId, false);
1031 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1032 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1034 printf( "****************************************************************\n" );
1035 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1036 printf( "****************************************************************\n" );
1040 /*!Gets file filter.
1041 *\retval QString "(*.hdf)"
1043 QString SalomeApp_Application::getFileFilter() const
1049 QWidget* SalomeApp_Application::createWindow( const int flag )
1052 #ifndef DISABLE_PYCONSOLE
1053 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1055 wid = LightApp_Application::createWindow(flag);
1058 SUIT_ResourceMgr* resMgr = resourceMgr();
1060 if ( flag == WT_ObjectBrowser )
1062 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1064 // temporary commented
1065 //ob->setUpdater( new SalomeApp_Updater() );
1067 #ifdef WITH_SALOMEDS_OBSERVER
1068 //do not activate the automatic update of Qt tree through signal/slot
1069 ob->setAutoUpdate(false);
1070 //activate update of modified objects only
1071 ob->setUpdateModified(true);
1074 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1077 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1078 IORCol = QObject::tr( "IOR_COLUMN" ),
1079 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1080 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1082 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1083 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1084 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1085 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1086 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1087 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1088 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1089 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1090 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1092 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1093 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1094 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1096 ob->setAutoSizeFirstColumn(autoSizeFirst);
1097 ob->setAutoSizeColumns(autoSize);
1098 ob->setResizeOnExpandItem(resizeOnExpandItem);
1099 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1101 // temporary commented
1103 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1105 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1106 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1107 QString().sprintf( "visibility_column_%d", i ), true ) );
1111 // temporary commented
1113 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1114 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1115 ob->resize( desktop()->width()/3, ob->height() );
1119 #ifndef DISABLE_PYCONSOLE
1120 else if ( flag == WT_PyConsole )
1122 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1123 pyCons->setObjectName( "pythonConsole" );
1124 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1125 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1126 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1127 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1129 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1130 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1132 else if ( flag == WT_NoteBook )
1134 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1136 _PTR(Study) aStudy = appStudy->studyDS();
1137 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1138 //to receive signal in NoteBook that it's variable was modified
1139 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1140 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1142 wid = getNoteBook();
1143 wid->setObjectName( "noteBook" );
1149 /*!Create preferences.*/
1150 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1152 LightApp_Application::createPreferences(pref);
1157 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1158 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1159 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1160 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1162 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1163 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1165 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1167 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1168 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1169 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1170 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1171 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1172 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1173 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1174 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1175 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1176 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1179 /*!Update desktop title.*/
1180 void SalomeApp_Application::updateDesktopTitle() {
1181 QString aTitle = applicationName();
1182 QString aVer = applicationVersion();
1183 if ( !aVer.isEmpty() )
1184 aTitle += QString( " " ) + aVer;
1186 if ( activeStudy() )
1188 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1189 if ( !sName.isEmpty() ) {
1190 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1192 _PTR(Study) stdDS = study->studyDS();
1194 if ( stdDS->GetProperties()->IsLocked() ) {
1195 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1197 aTitle += QString( " - [%1]" ).arg( sName );
1204 desktop()->setWindowTitle( aTitle );
1207 int SalomeApp_Application::closeChoice( const QString& docName )
1209 QStringList buttons;
1210 QMap<int, int> choices;
1212 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1213 choices.insert( idx++, CloseSave ); // ...
1214 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1215 choices.insert( idx++, CloseDiscard ); // ...
1216 if ( myIsCloseFromExit ) {
1217 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1218 choices.insert( idx++, CloseDisconnectSave ); // ...
1219 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1220 choices.insert( idx++, CloseDisconnect ); // ...
1222 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1223 choices.insert( idx++, CloseCancel ); // ...
1225 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1226 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1227 return choices[answer];
1230 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1236 if ( activeStudy()->isSaved() )
1238 else if ( !onSaveAsDoc() )
1243 case CloseDisconnectSave:
1244 if ( activeStudy()->isSaved() )
1246 else if ( !onSaveAsDoc() )
1248 case CloseDisconnect:
1249 closeActiveDoc( false );
1250 closePermanently = false;
1259 int SalomeApp_Application::openChoice( const QString& aName )
1261 int choice = LightApp_Application::openChoice( aName );
1263 if ( QFileInfo( aName ).exists() ) {
1264 if ( choice == OpenNew ) { // The document isn't already open.
1266 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1267 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1268 if ( aName == QString( lst[i].c_str() ) )
1271 // The document already exists in the study manager.
1272 // Do you want to reload it?
1274 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1275 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1276 if ( answer == SUIT_MessageBox::Yes )
1277 choice = OpenRefresh;
1279 choice = OpenCancel;
1282 } else { // file is not exist on disk
1283 SUIT_MessageBox::warning( desktop(),
1284 QObject::tr("WRN_WARNING"),
1285 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1292 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1295 int choice = aChoice;
1300 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1303 studyMgr()->Close( aStudy );
1308 res = LightApp_Application::openAction( choice, aName );
1316 \brief Get map of the operations which can be performed
1317 on the module activation.
1319 The method should return the map of the kind \c {<id>:<name>}
1320 where \c <id> is an integer identifier of the operation and
1321 \c <name> is a title for the button to be added to the
1322 dialog box. After user selects the required operation by the
1323 clicking the corresponding button in the dialog box, its identifier
1324 is passed to the moduleActionSelected() method to process
1327 \return map of the operations
1328 \sa moduleActionSelected()
1330 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1332 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1334 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1336 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1341 \brief Called when the used selectes required operation chosen
1342 from "Activate module" dialog box.
1344 Performs the required operation according to the user choice.
1346 \param id operation identifier
1347 \sa activateModuleActions()
1349 void SalomeApp_Application::moduleActionSelected( const int id )
1355 case NewAndScriptId:
1359 LightApp_Application::moduleActionSelected( id );
1364 /*!Gets CORBA::ORB_var*/
1365 CORBA::ORB_var SalomeApp_Application::orb()
1367 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1368 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1372 /*!Create and return SALOMEDS_StudyManager.*/
1373 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1375 static _PTR(StudyManager) _sm;
1376 if(!_sm) _sm = ClientFactory::StudyManager();
1380 /*!Create and return SALOME_NamingService.*/
1381 SALOME_NamingService* SalomeApp_Application::namingService()
1383 static SALOME_NamingService _ns(orb());
1387 /*!Create and return SALOME_LifeCycleCORBA.*/
1388 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1390 static SALOME_LifeCycleCORBA _lcc( namingService() );
1394 /*!Private SLOT. On preferences.*/
1395 void SalomeApp_Application::onProperties()
1397 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1401 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1404 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1405 int res = aDlg.exec();
1406 if( res==QDialog::Accepted && aDlg.isChanged() )
1407 SB->CommitCommand();
1411 //study->updateCaptions();
1412 updateDesktopTitle();
1416 /*!Insert items in popup, which necessary for current application*/
1417 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1419 LightApp_SelectionMgr* mgr = selectionMgr();
1420 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1421 mgr->setSelectionCacheEnabled( true );
1423 LightApp_Application::contextMenuPopup( type, thePopup, title );
1425 // temporary commented
1426 /*OB_Browser* ob = objectBrowser();
1427 if ( !ob || type != ob->popupClientType() )
1430 // Get selected objects
1431 SALOME_ListIO aList;
1432 mgr->selectedObjects( aList, QString(), false );
1434 // add GUI state commands: restore, rename
1435 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1436 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1437 thePopup->addSeparator();
1438 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1439 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1440 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1441 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1444 // "Delete reference" item should appear only for invalid references
1446 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1447 bool isInvalidRefs = false;
1448 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1450 _PTR(Study) aStudyDS = aStudy->studyDS();
1451 _PTR(SObject) anObj;
1453 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1455 if( it.Value()->hasEntry() )
1457 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1458 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1461 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1462 isInvalidRefs = true;
1466 // Add "Delete reference" item to popup
1467 if ( isInvalidRefs )
1469 thePopup->addSeparator();
1470 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1474 // "Activate module" item should appear only if it's necessary
1475 if ( aList.Extent() == 1 ) {
1477 mgr->selectedObjects( aList );
1479 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1481 // add extra popup menu (defined in XML)
1482 if ( myExtActions.size() > 0 ) {
1483 // Use only first selected object
1484 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1486 _PTR(Study) stdDS = study->studyDS();
1488 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1490 _PTR( GenericAttribute ) anAttr;
1491 std::string auid = "AttributeUserID";
1492 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1493 if ( aSO->FindAttribute( anAttr, auid ) ) {
1494 _PTR(AttributeUserID) aAttrID = anAttr;
1495 QString aId = aAttrID->Value().c_str();
1496 if ( myExtActions.contains( aId ) ) {
1497 thePopup->addAction(myExtActions[aId]);
1505 // check if item is a "GUI state" item (also a first level object)
1506 QString entry( aIObj->getEntry() );
1507 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1508 QString aModuleName( aIObj->getComponentDataType() );
1509 QString aModuleTitle = moduleTitle( aModuleName );
1510 CAM_Module* currentModule = activeModule();
1511 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1512 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1517 mgr->setSelectionCacheEnabled( cacheIsOn );
1520 /*!Update obect browser:
1521 1.if 'updateModels' true, update existing data models;
1522 2. update "non-existing" (not loaded yet) data models;
1523 3. update object browser if it exists */
1524 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1526 // update "non-existing" (not loaded yet) data models
1527 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1530 _PTR(Study) stdDS = study->studyDS();
1533 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1535 _PTR(SComponent) aComponent ( it->Value() );
1537 #ifndef WITH_SALOMEDS_OBSERVER
1538 // with GUI observers this check is not needed anymore
1539 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1540 continue; // skip the magic "Interface Applicative" component
1542 if ( !objectBrowser() )
1543 getWindow( WT_ObjectBrowser );
1544 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1545 objectBrowser()->setAutoUpdate( false );
1546 SalomeApp_DataModel::synchronize( aComponent, study );
1547 objectBrowser()->setAutoUpdate( isAutoUpdate );
1552 // create data objects that correspond to GUI state save points
1553 if ( study ) updateSavePointDataObjects( study );
1555 // update existing data models (already loaded SComponents)
1556 LightApp_Application::updateObjectBrowser( updateModels );
1559 /*!Display Catalog Genenerator dialog */
1560 void SalomeApp_Application::onCatalogGen()
1562 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1566 /*!Display Registry Display dialog */
1567 void SalomeApp_Application::onRegDisplay()
1569 CORBA::ORB_var anOrb = orb();
1570 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1573 regWnd->activateWindow();
1576 /*!find original object by double click on item */
1577 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1579 // Issue 21379: References are supported at LightApp_DataObject level
1580 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1582 if( obj && obj->isReference() )
1584 QString entry = obj->refEntry();
1586 SUIT_DataOwnerPtrList aList;
1587 aList.append( new LightApp_DataOwner( entry ) );
1588 selectionMgr()->setSelected( aList, false );
1590 SUIT_DataBrowser* ob = objectBrowser();
1592 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1593 if ( !aSelectedIndexes.isEmpty() )
1594 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1599 Creates new view manager
1600 \param type - type of view manager
1602 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1604 return createViewManager(type);
1608 /*!Global utility function, returns selected GUI Save point object's ID */
1609 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1611 SALOME_ListIO aList;
1612 selMgr->selectedObjects( aList );
1613 if( aList.Extent() > 0 ) {
1614 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1615 QString entry( aIObj->getEntry() );
1616 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1617 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1619 bool ok; // conversion to integer is ok?
1620 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1621 return ok ? savePoint : -1;
1626 /*!Called on Restore GUI State popup command*/
1627 void SalomeApp_Application::onRestoreGUIState()
1629 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1630 if ( savePoint == -1 )
1632 SalomeApp_VisualState( this ).restoreState( savePoint );
1635 /*!Called on Delete GUI State popup command*/
1636 void SalomeApp_Application::onDeleteGUIState()
1638 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1639 if ( savePoint == -1 )
1641 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1645 study->removeSavePoint( savePoint );
1646 updateSavePointDataObjects( study );
1649 /*!Called on New study operation*/
1650 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1652 LightApp_Application::onStudyCreated( study );
1654 //#ifndef DISABLE_PYCONSOLE
1655 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1656 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1659 loadDockWindowsState();
1661 objectBrowserColumnsVisibility();
1664 /*!Called on Open study operation*/
1665 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1667 LightApp_Application::onStudyOpened( study );
1669 //#ifndef DISABLE_PYCONSOLE
1670 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1671 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1674 loadDockWindowsState();
1676 objectBrowserColumnsVisibility();
1678 // temporary commented
1679 /*if ( objectBrowser() ) {
1680 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1681 objectBrowser()->updateTree( study->root() );
1685 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1686 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1689 SUIT_DataBrowser* ob = objectBrowser();
1690 LightApp_SelectionMgr* selMgr = selectionMgr();
1692 if ( !study || !ob || !selMgr )
1695 // find GUI states root object
1696 SUIT_DataObject* guiRootObj = 0;
1698 study->root()->children( ch );
1699 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1700 for ( ; it != last ; ++it ) {
1701 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1706 std::vector<int> savePoints = study->getSavePoints();
1707 // case 1: no more save points but they existed in study's tree
1708 if ( savePoints.empty() && guiRootObj ) {
1709 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1710 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1711 const bool isAutoUpdate = ob->autoUpdate();
1712 selMgr->clearSelected();
1713 ob->setAutoUpdate(true);
1714 DataObjectList ch = guiRootObj->children();
1715 for( int i = 0; i < ch.size(); i++ )
1718 ob->setAutoUpdate(isAutoUpdate);
1721 // case 2: no more save points but root does not exist either
1722 if ( savePoints.empty() && !guiRootObj )
1724 // case 3: save points but no root for them - create it
1725 if ( !savePoints.empty() && !guiRootObj )
1726 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1727 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1728 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1730 if ( guiRootObj->nextBrother() ) {
1731 study->root()->removeChild(guiRootObj);
1732 study->root()->appendChild(guiRootObj);
1733 //study->root()->dump();
1736 // store data objects in a map id-to-DataObject
1737 QMap<int,SalomeApp_SavePointObject*> mapDO;
1739 guiRootObj->children( ch );
1740 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1741 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1743 mapDO[dobj->getId()] = dobj;
1746 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1747 // if in the map - remove it from map.
1748 for ( int i = 0; i < savePoints.size(); i++ )
1749 if ( !mapDO.contains( savePoints[i] ) )
1750 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1752 mapDO.remove( savePoints[i] );
1754 // delete DataObjects that are still in the map -- their IDs were not found in data model
1755 if( mapDO.size() > 0) {
1756 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1757 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1758 selMgr->clearSelected();
1759 const bool isAutoUpdate = ob->autoUpdate();
1760 ob->setAutoUpdate(true);
1761 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1763 ob->setAutoUpdate(isAutoUpdate);
1767 /*! Check data object */
1768 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1777 Opens other study into active Study. If Study is empty - creates it.
1778 \param theName - name of study
1780 bool SalomeApp_Application::useStudy( const QString& theName )
1783 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1786 res = aStudy->loadDocument( theName );
1787 updateDesktopTitle();
1788 updateCommandsStatus();
1792 /*! Show/hide object browser colums according to preferences */
1793 void SalomeApp_Application::objectBrowserColumnsVisibility()
1795 if ( objectBrowser() )
1796 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1798 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1799 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1803 #ifndef DISABLE_PYCONSOLE
1804 /*! Set SalomeApp_NoteBook pointer */
1805 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1807 myNoteBook = theNoteBook;
1810 /*! Return SalomeApp_NoteBook pointer */
1811 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1818 * Define extra actions defined in module definition XML file.
1819 * Additional popup items sections can be defined by parameter "popupitems".
1820 * Supported attributes:
1821 * title - title of menu item,
1822 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1823 * method - method which has to be called when menu item is selected
1825 * <section name="MODULENAME">
1826 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1828 * <section name="importmed">
1829 * <parameter name="title" value="My menu"/>
1830 * <parameter name="objectid" value="VISU.Result"/>
1831 * <parameter name="method" value="nameOfModuleMethod"/>
1834 void SalomeApp_Application::createExtraActions()
1836 myExtActions.clear();
1837 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1839 QStringList aModules;
1840 modules(aModules, false);
1841 foreach(QString aModile, aModules) {
1842 QString aModName = moduleName(aModile);
1843 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1844 if (!aSectionStr.isNull()) {
1845 QStringList aSections = aSectionStr.split(':');
1846 foreach(QString aSection, aSections) {
1847 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1848 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1849 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1850 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1853 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1854 if (aModuleName.isNull())
1855 aModuleName = aModName;
1857 QAction* aAction = new QAction(aTitle, this);
1859 aData<<aModuleName<<aSlot;
1860 aAction->setData(aData);
1861 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1862 myExtActions[aId] = aAction;
1869 * Called when extra action is selected
1871 void SalomeApp_Application::onExtAction()
1873 QAction* aAction = ::qobject_cast<QAction*>(sender());
1877 QVariant aData = aAction->data();
1878 QStringList aDataList = aData.value<QStringList>();
1879 if (aDataList.size() != 2)
1882 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1883 SALOME_ListIO aListIO;
1884 aSelectionMgr->selectedObjects(aListIO);
1885 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1886 if (aListIO.Extent() < 1)
1888 if (!anIO->hasEntry())
1891 QString aEntry(anIO->getEntry());
1893 QApplication::setOverrideCursor( Qt::WaitCursor );
1894 QString aModuleTitle = moduleTitle(aDataList[0]);
1895 activateModule(aModuleTitle);
1896 QApplication::restoreOverrideCursor();
1898 QCoreApplication::processEvents();
1900 CAM_Module* aModule = activeModule();
1904 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1905 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1909 Checks that an object can be renamed.
1910 \param entry entry of the object
1911 \brief Return \c true if object can be renamed
1913 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1915 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1919 Rename object by entry.
1920 \param entry entry of the object
1921 \param name new name of the object
1922 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1924 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1926 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1928 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1930 if(!aStudy || savePoint == -1)
1933 if ( !name.isNull() && !name.isEmpty() ) {
1934 aStudy->setNameOfSavePoint( savePoint, name );
1935 updateSavePointDataObjects( aStudy );
1937 //Mark study as modified
1944 #ifndef DISABLE_PYCONSOLE
1945 //============================================================================
1946 /*! Function : onUpdateStudy
1947 * Purpose : Slot to update the study.
1949 //============================================================================
1950 void SalomeApp_Application::onUpdateStudy()
1952 QApplication::setOverrideCursor( Qt::WaitCursor );
1954 if( !updateStudy() )
1955 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1957 QApplication::restoreOverrideCursor();
1960 //============================================================================
1961 /*! Function : updateStudy
1962 * Purpose : Update study by dumping the study to Python script and loading it.
1963 * It is used to apply variable modifications done in NoteBook to created objects.
1965 //============================================================================
1966 bool SalomeApp_Application::updateStudy()
1968 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1969 if ( !study || !myNoteBook )
1972 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1973 myNoteBook->setDumpedStudyName( study->studyName() );
1975 _PTR(Study) studyDS = study->studyDS();
1977 // get unique temporary directory name
1978 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1979 if( aTmpDir.isEmpty() )
1982 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1983 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1985 // dump study to the temporary directory
1986 QString aScriptName( "notebook" );
1987 bool toPublish = true;
1988 bool isMultiFile = false;
1989 bool toSaveGUI = true;
1992 _PTR(AttributeParameter) ap;
1993 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1994 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1995 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1996 ip->setDumpPython(studyDS);
1997 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1999 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2001 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2004 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2008 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2009 int anIndex = aList.indexOf( this );
2011 // Disconnect dialog from application desktop in case if:
2012 // 1) Application is not the first application in the session
2013 // 2) Application is the first application in session but not the only.
2014 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2015 if( changeDesktop ) {
2017 SalomeApp_Application* app = this;
2018 if( anIndex > 0 && anIndex < aList.count() )
2019 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2020 else if(anIndex == 0 && aList.count() > 1)
2021 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2026 // creation a new study and restoring will be done in another application
2027 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2028 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2031 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2032 QString aStudyName = myNoteBook->getDumpedStudyName();
2033 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2034 // clear a study (delete all objects)
2035 onCloseDoc( false );
2037 if( !changeDesktop ) {
2038 ok = onRestoreStudy( aDumpScript,
2047 //============================================================================
2048 /*! Function : onRestoreStudy
2049 * Purpose : Load the dumped study from Python script
2051 //============================================================================
2052 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2053 const QString& theStudyName,
2054 bool theIsStudySaved )
2058 // create a new study
2061 // get active application
2062 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2064 // load study from the temporary directory
2065 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2067 #ifndef DISABLE_PYCONSOLE
2068 PyConsole_Console* pyConsole = app->pythonConsole();
2070 pyConsole->execAndWait( command );
2073 // remove temporary directory
2074 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2075 QString aStudyName = aScriptInfo.baseName();
2076 QDir aDir = aScriptInfo.absoluteDir();
2077 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2078 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2079 ok = aDir.remove( *it ) && ok;
2081 ok = aDir.rmdir( aDir.absolutePath() );
2083 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2085 #ifndef DISABLE_PYCONSOLE
2086 _PTR(Study) aStudyDS = newStudy->studyDS();
2087 app->getNoteBook()->Init( aStudyDS );
2088 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2089 newStudy->Modified();
2090 updateDesktopTitle();
2101 Close the Application
2103 void SalomeApp_Application::afterCloseDoc()
2105 #ifndef DISABLE_PYCONSOLE
2106 // emit signal to restore study from Python script
2108 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2109 myNoteBook->getDumpedStudyName(),
2110 myNoteBook->isDumpedStudySaved() );
2113 LightApp_Application::afterCloseDoc();
2117 Asks to close existing document.
2119 bool SalomeApp_Application::checkExistingDoc()
2121 bool result = LightApp_Application::checkExistingDoc();
2122 if ( result && !activeStudy() ) {
2123 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2125 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2126 if( List.size() > 0 ) {
2127 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2136 #ifndef DISABLE_PYCONSOLE
2138 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2140 return new SalomeApp_PyInterp();
2143 #endif // DISABLE_PYCONSOLE