1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: SalomeApp_Application.cxx
24 // Created: 10/22/2004 3:23:45 PM
25 // Author: Sergey LITONIN
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
32 #ifndef DISABLE_PYCONSOLE
37 #ifndef DISABLE_PYCONSOLE
38 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
39 #include <PyConsole_Console.h>
40 #include "SalomeApp_NoteBook.h"
42 #include "SalomeApp_Application.h"
43 #include "SalomeApp_Study.h"
44 #include "SalomeApp_DataModel.h"
45 #include "SalomeApp_DataObject.h"
46 #include "SalomeApp_VisualState.h"
47 #include "SalomeApp_StudyPropertiesDlg.h"
48 #include "SalomeApp_LoadStudiesDlg.h"
49 #include "SalomeApp_ExitDlg.h"
51 #include <LightApp_Application.h>
52 #include <LightApp_Module.h>
53 #include <LightApp_Preferences.h>
54 #include <LightApp_SelectionMgr.h>
55 #include <LightApp_NameDlg.h>
56 #include <LightApp_DataOwner.h>
58 #include <CAM_Module.h>
60 #include <SUIT_Tools.h>
61 #include <SUIT_Session.h>
62 #include <SUIT_Desktop.h>
63 #include <SUIT_DataBrowser.h>
64 #include <SUIT_FileDlg.h>
65 #include <SUIT_FileValidator.h>
66 #include <SUIT_MessageBox.h>
67 #include <SUIT_ResourceMgr.h>
68 #include <SUIT_TreeModel.h>
69 #include <SUIT_ViewWindow.h>
70 #include <SUIT_ViewManager.h>
71 #include <SUIT_ViewModel.h>
72 #include <SUIT_OverrideCursor.h>
74 #include <QtxTreeView.h>
76 #include <SALOME_EventFilter.h>
78 // temporary commented
79 //#include <OB_ListItem.h>
82 #include <Utils_ORB_INIT.hxx>
83 #include <Utils_SINGLETON.hxx>
84 #include <SALOME_LifeCycleCORBA.hxx>
86 #include <QApplication>
90 #include <QPushButton>
92 #include <QListWidget>
93 #include <QGridLayout>
97 #include <SALOMEDSClient_ClientFactory.hxx>
98 #include <Basics_Utils.hxx>
100 #include <SALOME_ListIO.hxx>
101 #include <SALOME_Prs.h>
104 #include <ToolsGUI_CatalogGeneratorDlg.h>
105 #include <ToolsGUI_RegWidget.h>
109 #include <SALOMEDS_Tool.hxx>
111 /*!Internal class that updates object browser item properties */
112 // temporary commented
113 /*class SalomeApp_Updater : public OB_Updater
116 SalomeApp_Updater() : OB_Updater(){};
117 virtual ~SalomeApp_Updater(){};
118 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
121 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
123 if( !theObj || !theItem )
126 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
130 _PTR(SObject) SObj = SAObj->object();
133 _PTR( GenericAttribute ) anAttr;
136 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
138 _PTR(AttributeSelectable) aAttrSel = anAttr;
139 theItem->setSelectable( aAttrSel->IsSelectable() );
142 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
144 _PTR(AttributeExpandable) aAttrExpand = anAttr;
145 theItem->setExpandable( aAttrExpand->IsExpandable() );
148 //this attribute is not supported in the version of SALOME 3.x
149 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
151 // _PTR(AttributeOpened) aAttrOpen = anAttr;
152 // theItem->setOpen( aAttrOpen->IsOpened() );
156 /*!Create new instance of SalomeApp_Application.*/
157 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
159 return new SalomeApp_Application();
163 SalomeApp_Application::SalomeApp_Application()
164 : LightApp_Application(),
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_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
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() );
804 #ifndef DISABLE_PYCONSOLE
806 a = action( LoadScriptId );
808 a->setEnabled( pythonConsole() );
812 a = action( PropertiesId );
814 a->setEnabled( activeStudy() );
816 // Save GUI state menu
817 a = action( SaveGUIStateId );
819 a->setEnabled( activeStudy() );
821 // Connect study menu
822 a = action( ConnectId );
824 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
826 // Disconnect study menu
827 a = action( DisconnectId );
829 a->setEnabled( activeStudy() );
831 // update state of Copy/Paste menu items
832 onSelectionChanged();
836 \class DumpStudyFileDlg
837 Private class used in Dump Study operation. Consists 2 check boxes:
838 "Publish in study" and "Save GUI parameters"
840 class DumpStudyFileDlg : public SUIT_FileDlg
843 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
845 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
848 QWidget *hB = new QWidget( this );
849 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
850 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
851 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
853 QHBoxLayout *layout = new QHBoxLayout;
854 layout->addWidget(myPublishChk);
855 layout->addWidget(myMultiFileChk);
856 layout->addWidget(mySaveGUIChk);
857 hB->setLayout(layout);
859 QPushButton* pb = new QPushButton(this);
861 int row = grid->rowCount();
862 grid->addWidget( new QLabel("", this), row, 0 );
863 grid->addWidget( hB, row, 1, 1, 3 );
864 grid->addWidget( pb, row, 5 );
869 QCheckBox* myPublishChk;
870 QCheckBox* myMultiFileChk;
871 QCheckBox* mySaveGUIChk;
874 class DumpStudyFileValidator : public SUIT_FileValidator
877 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
878 virtual ~DumpStudyFileValidator() {};
879 virtual bool canSave( const QString& file, bool permissions );
882 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
884 QFileInfo fi( file );
885 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
886 SUIT_MessageBox::critical( parent(),
887 QObject::tr("WRN_WARNING"),
888 QObject::tr("WRN_FILE_NAME_BAD") );
891 return SUIT_FileValidator::canSave( file, permissions);
894 /*!Private SLOT. On dump study.*/
895 void SalomeApp_Application::onDumpStudy( )
897 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
898 if ( !appStudy ) return;
899 _PTR(Study) aStudy = appStudy->studyDS();
901 QStringList aFilters;
902 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
904 bool anIsPublish = true;
905 bool anIsMultiFile = false;
906 bool anIsSaveGUI = true;
908 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
909 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
910 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
911 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
914 DumpStudyFileDlg fd( desktop() );
915 fd.setValidator( new DumpStudyFileValidator( &fd ) );
916 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
917 fd.setFilters( aFilters );
918 fd.myPublishChk->setChecked( anIsPublish );
919 fd.myMultiFileChk->setChecked( anIsMultiFile );
920 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
921 if ( fd.exec() == QDialog::Accepted )
923 QString aFileName = fd.selectedFile();
925 bool toPublish = fd.myPublishChk->isChecked();
926 bool isMultiFile = fd.myMultiFileChk->isChecked();
927 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
929 if ( !aFileName.isEmpty() ) {
930 QFileInfo aFileInfo(aFileName);
931 if( aFileInfo.isDir() ) // IPAL19257
934 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
937 SUIT_OverrideCursor wc;
938 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
941 SUIT_MessageBox::warning( desktop(),
942 QObject::tr("WRN_WARNING"),
943 tr("WRN_DUMP_STUDY_FAILED") );
948 /*!Private SLOT. On load script.*/
949 void SalomeApp_Application::onLoadScript( )
951 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
953 _PTR(Study) aStudy = appStudy->studyDS();
954 if ( aStudy->GetProperties()->IsLocked() ) {
955 SUIT_MessageBox::warning( desktop(),
956 QObject::tr("WRN_WARNING"),
957 QObject::tr("WRN_STUDY_LOCKED") );
962 QStringList filtersList;
963 filtersList.append(tr("PYTHON_FILES_FILTER"));
964 filtersList.append(tr("ALL_FILES_FILTER"));
966 QString anInitialPath = "";
967 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
968 anInitialPath = QDir::currentPath();
971 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
973 SALOMEDSClient_StudyManager* aMgr = studyMgr();
974 aMgr->GetSimanStudy()->StudyId();
975 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
976 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
977 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
981 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
983 if ( !aFile.isEmpty() )
985 QString command = QString("execfile(r\"%1\")").arg(aFile);
987 #ifndef DISABLE_PYCONSOLE
988 PyConsole_Console* pyConsole = pythonConsole();
991 pyConsole->exec( command );
996 /*!Private SLOT. On save GUI state.*/
997 void SalomeApp_Application::onSaveGUIState()
999 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1001 SalomeApp_VisualState( this ).storeState();
1002 updateSavePointDataObjects( study );
1003 updateObjectBrowser();
1008 /*!Public SLOT. On SIMAN check in operation.*/
1009 void SalomeApp_Application::onCheckIn()
1012 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1013 setMenuShown(SimanLocalCheckInId, false);
1014 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1015 aMgr->GetSimanStudy()->CheckIn("");
1017 printf( "****************************************************************\n" );
1018 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1019 printf( "****************************************************************\n" );
1023 /*!Public SLOT. On SIMAN local check in operation.*/
1024 void SalomeApp_Application::onLocalCheckIn()
1027 // get the active module
1028 CAM_Module* aModule = activeModule();
1029 if (!aModule) return; // there is no active module
1031 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1032 setMenuShown(SimanLocalCheckInId, false);
1033 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1034 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1036 printf( "****************************************************************\n" );
1037 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1038 printf( "****************************************************************\n" );
1042 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1043 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1045 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1046 QAction* send = ::qobject_cast<QAction*>( sender() );
1049 QString aWinName = send->data().toString();
1050 if ( theIsVisible && aWinName == "objectBrowser" )
1051 objectBrowserColumnsVisibility();
1054 /*!Gets file filter.
1055 *\retval QString "(*.hdf)"
1057 QString SalomeApp_Application::getFileFilter() const
1063 QWidget* SalomeApp_Application::createWindow( const int flag )
1066 #ifndef DISABLE_PYCONSOLE
1067 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1069 wid = LightApp_Application::createWindow(flag);
1072 SUIT_ResourceMgr* resMgr = resourceMgr();
1074 if ( flag == WT_ObjectBrowser )
1076 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1078 // temporary commented
1079 //ob->setUpdater( new SalomeApp_Updater() );
1081 #ifdef WITH_SALOMEDS_OBSERVER
1082 //do not activate the automatic update of Qt tree through signal/slot
1083 ob->setAutoUpdate(false);
1084 //activate update of modified objects only
1085 ob->setUpdateModified(true);
1088 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1091 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1092 IORCol = QObject::tr( "IOR_COLUMN" ),
1093 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1094 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1096 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1097 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1098 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1099 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1100 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1101 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1102 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1103 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1104 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1106 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1107 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1108 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1110 ob->setAutoSizeFirstColumn(autoSizeFirst);
1111 ob->setAutoSizeColumns(autoSize);
1112 ob->setResizeOnExpandItem(resizeOnExpandItem);
1113 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1115 // temporary commented
1117 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1119 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1120 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1121 QString().sprintf( "visibility_column_%d", i ), true ) );
1125 // temporary commented
1127 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1128 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1129 ob->resize( desktop()->width()/3, ob->height() );
1133 #ifndef DISABLE_PYCONSOLE
1134 else if ( flag == WT_PyConsole )
1136 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1137 pyCons->setObjectName( "pythonConsole" );
1138 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1139 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1140 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1141 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1143 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1144 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1146 else if ( flag == WT_NoteBook )
1148 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1150 _PTR(Study) aStudy = appStudy->studyDS();
1151 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1152 //to receive signal in NoteBook that it's variable was modified
1153 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1154 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1156 wid = getNoteBook();
1157 wid->setObjectName( "noteBook" );
1163 /*!Create preferences.*/
1164 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1166 LightApp_Application::createPreferences(pref);
1171 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1172 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1173 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1174 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1176 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1177 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1179 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1181 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1182 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1183 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1184 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1185 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1186 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1187 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1188 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1189 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1190 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1193 /*!Update desktop title.*/
1194 void SalomeApp_Application::updateDesktopTitle() {
1195 QString aTitle = applicationName();
1196 QString aVer = applicationVersion();
1197 if ( !aVer.isEmpty() )
1198 aTitle += QString( " " ) + aVer;
1200 if ( activeStudy() )
1202 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1203 if ( !sName.isEmpty() ) {
1204 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1206 _PTR(Study) stdDS = study->studyDS();
1208 if ( stdDS->GetProperties()->IsLocked() ) {
1209 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1211 aTitle += QString( " - [%1]" ).arg( sName );
1218 desktop()->setWindowTitle( aTitle );
1221 int SalomeApp_Application::closeChoice( const QString& docName )
1223 QStringList buttons;
1224 QMap<int, int> choices;
1226 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1227 choices.insert( idx++, CloseSave ); // ...
1228 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1229 choices.insert( idx++, CloseDiscard ); // ...
1230 if ( myIsCloseFromExit ) {
1231 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1232 choices.insert( idx++, CloseDisconnectSave ); // ...
1233 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1234 choices.insert( idx++, CloseDisconnect ); // ...
1236 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1237 choices.insert( idx++, CloseCancel ); // ...
1239 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1240 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1241 return choices[answer];
1244 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1250 if ( activeStudy()->isSaved() )
1252 else if ( !onSaveAsDoc() )
1257 case CloseDisconnectSave:
1258 if ( activeStudy()->isSaved() )
1260 else if ( !onSaveAsDoc() )
1262 case CloseDisconnect:
1263 closeActiveDoc( false );
1264 closePermanently = false;
1273 int SalomeApp_Application::openChoice( const QString& aName )
1275 int choice = LightApp_Application::openChoice( aName );
1277 if ( QFileInfo( aName ).exists() ) {
1278 if ( choice == OpenNew ) { // The document isn't already open.
1280 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1281 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1282 if ( aName == QString( lst[i].c_str() ) )
1285 // The document already exists in the study manager.
1286 // Do you want to reload it?
1288 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1289 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1290 if ( answer == SUIT_MessageBox::Yes )
1291 choice = OpenRefresh;
1293 choice = OpenCancel;
1296 } else { // file is not exist on disk
1297 SUIT_MessageBox::warning( desktop(),
1298 QObject::tr("WRN_WARNING"),
1299 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1306 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1309 int choice = aChoice;
1314 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1317 studyMgr()->Close( aStudy );
1322 res = LightApp_Application::openAction( choice, aName );
1330 \brief Get map of the operations which can be performed
1331 on the module activation.
1333 The method should return the map of the kind \c {<id>:<name>}
1334 where \c <id> is an integer identifier of the operation and
1335 \c <name> is a title for the button to be added to the
1336 dialog box. After user selects the required operation by the
1337 clicking the corresponding button in the dialog box, its identifier
1338 is passed to the moduleActionSelected() method to process
1341 \return map of the operations
1342 \sa moduleActionSelected()
1344 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1346 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1348 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1350 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1355 \brief Called when the used selectes required operation chosen
1356 from "Activate module" dialog box.
1358 Performs the required operation according to the user choice.
1360 \param id operation identifier
1361 \sa activateModuleActions()
1363 void SalomeApp_Application::moduleActionSelected( const int id )
1369 case NewAndScriptId:
1373 LightApp_Application::moduleActionSelected( id );
1378 /*!Gets CORBA::ORB_var*/
1379 CORBA::ORB_var SalomeApp_Application::orb()
1381 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1382 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1386 /*!Create and return SALOMEDS_StudyManager.*/
1387 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1389 static _PTR(StudyManager) _sm;
1390 if(!_sm) _sm = ClientFactory::StudyManager();
1394 /*!Create and return SALOME_NamingService.*/
1395 SALOME_NamingService* SalomeApp_Application::namingService()
1397 static SALOME_NamingService _ns(orb());
1401 /*!Create and return SALOME_LifeCycleCORBA.*/
1402 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1404 static SALOME_LifeCycleCORBA _lcc( namingService() );
1408 /*!Private SLOT. On preferences.*/
1409 void SalomeApp_Application::onProperties()
1411 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1415 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1418 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1419 int res = aDlg.exec();
1420 if( res==QDialog::Accepted && aDlg.isChanged() )
1421 SB->CommitCommand();
1425 //study->updateCaptions();
1426 updateDesktopTitle();
1430 /*!Insert items in popup, which necessary for current application*/
1431 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1433 LightApp_SelectionMgr* mgr = selectionMgr();
1434 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1435 mgr->setSelectionCacheEnabled( true );
1437 LightApp_Application::contextMenuPopup( type, thePopup, title );
1439 // temporary commented
1440 /*OB_Browser* ob = objectBrowser();
1441 if ( !ob || type != ob->popupClientType() )
1444 // Get selected objects
1445 SALOME_ListIO aList;
1446 mgr->selectedObjects( aList, QString(), false );
1448 // add GUI state commands: restore, rename
1449 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1450 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1451 thePopup->addSeparator();
1452 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1453 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1454 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1455 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1458 // "Delete reference" item should appear only for invalid references
1460 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1461 bool isInvalidRefs = false;
1462 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1464 _PTR(Study) aStudyDS = aStudy->studyDS();
1465 _PTR(SObject) anObj;
1467 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1469 if( it.Value()->hasEntry() )
1471 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1472 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1475 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1476 isInvalidRefs = true;
1480 // Add "Delete reference" item to popup
1481 if ( isInvalidRefs )
1483 thePopup->addSeparator();
1484 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1488 // "Activate module" item should appear only if it's necessary
1489 if ( aList.Extent() == 1 ) {
1491 mgr->selectedObjects( aList );
1493 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1495 // add extra popup menu (defined in XML)
1496 if ( myExtActions.size() > 0 ) {
1497 // Use only first selected object
1498 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1500 _PTR(Study) stdDS = study->studyDS();
1502 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1504 _PTR( GenericAttribute ) anAttr;
1505 std::string auid = "AttributeUserID";
1506 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1507 if ( aSO->FindAttribute( anAttr, auid ) ) {
1508 _PTR(AttributeUserID) aAttrID = anAttr;
1509 QString aId = aAttrID->Value().c_str();
1510 if ( myExtActions.contains( aId ) ) {
1511 thePopup->addAction(myExtActions[aId]);
1519 // check if item is a "GUI state" item (also a first level object)
1520 QString entry( aIObj->getEntry() );
1521 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1522 QString aModuleName( aIObj->getComponentDataType() );
1523 QString aModuleTitle = moduleTitle( aModuleName );
1524 CAM_Module* currentModule = activeModule();
1525 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1526 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1531 mgr->setSelectionCacheEnabled( cacheIsOn );
1534 /*!Update obect browser:
1535 1.if 'updateModels' true, update existing data models;
1536 2. update "non-existing" (not loaded yet) data models;
1537 3. update object browser if it exists */
1538 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1540 // update "non-existing" (not loaded yet) data models
1541 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1544 _PTR(Study) stdDS = study->studyDS();
1547 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1549 _PTR(SComponent) aComponent ( it->Value() );
1551 #ifndef WITH_SALOMEDS_OBSERVER
1552 // with GUI observers this check is not needed anymore
1553 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1554 continue; // skip the magic "Interface Applicative" component
1556 if ( !objectBrowser() )
1557 getWindow( WT_ObjectBrowser );
1558 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1559 objectBrowser()->setAutoUpdate( false );
1560 SalomeApp_DataModel::synchronize( aComponent, study );
1561 objectBrowser()->setAutoUpdate( isAutoUpdate );
1566 // create data objects that correspond to GUI state save points
1567 if ( study ) updateSavePointDataObjects( study );
1569 // update existing data models (already loaded SComponents)
1570 LightApp_Application::updateObjectBrowser( updateModels );
1573 /*!Display Catalog Genenerator dialog */
1574 void SalomeApp_Application::onCatalogGen()
1576 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1580 /*!Display Registry Display dialog */
1581 void SalomeApp_Application::onRegDisplay()
1583 CORBA::ORB_var anOrb = orb();
1584 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1587 regWnd->activateWindow();
1590 /*!find original object by double click on item */
1591 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1593 // Issue 21379: References are supported at LightApp_DataObject level
1594 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1596 if( obj && obj->isReference() )
1598 QString entry = obj->refEntry();
1600 SUIT_DataOwnerPtrList aList;
1601 aList.append( new LightApp_DataOwner( entry ) );
1602 selectionMgr()->setSelected( aList, false );
1604 SUIT_DataBrowser* ob = objectBrowser();
1606 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1607 if ( !aSelectedIndexes.isEmpty() )
1608 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1613 Creates new view manager
1614 \param type - type of view manager
1616 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1618 return createViewManager(type);
1622 /*!Global utility function, returns selected GUI Save point object's ID */
1623 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1625 SALOME_ListIO aList;
1626 selMgr->selectedObjects( aList );
1627 if( aList.Extent() > 0 ) {
1628 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1629 QString entry( aIObj->getEntry() );
1630 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1631 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1633 bool ok; // conversion to integer is ok?
1634 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1635 return ok ? savePoint : -1;
1640 /*!Called on Restore GUI State popup command*/
1641 void SalomeApp_Application::onRestoreGUIState()
1643 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1644 if ( savePoint == -1 )
1646 SalomeApp_VisualState( this ).restoreState( savePoint );
1649 /*!Called on Delete GUI State popup command*/
1650 void SalomeApp_Application::onDeleteGUIState()
1652 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1653 if ( savePoint == -1 )
1655 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1659 study->removeSavePoint( savePoint );
1660 updateSavePointDataObjects( study );
1663 /*!Called on New study operation*/
1664 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1666 LightApp_Application::onStudyCreated( study );
1668 //#ifndef DISABLE_PYCONSOLE
1669 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1670 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1673 loadDockWindowsState();
1675 objectBrowserColumnsVisibility();
1678 /*!Called on Open study operation*/
1679 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1681 LightApp_Application::onStudyOpened( study );
1683 //#ifndef DISABLE_PYCONSOLE
1684 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1685 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1688 loadDockWindowsState();
1690 objectBrowserColumnsVisibility();
1692 // temporary commented
1693 /*if ( objectBrowser() ) {
1694 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1695 objectBrowser()->updateTree( study->root() );
1699 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1700 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1703 SUIT_DataBrowser* ob = objectBrowser();
1704 LightApp_SelectionMgr* selMgr = selectionMgr();
1706 if ( !study || !ob || !selMgr )
1709 // find GUI states root object
1710 SUIT_DataObject* guiRootObj = 0;
1712 study->root()->children( ch );
1713 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1714 for ( ; it != last ; ++it ) {
1715 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1720 std::vector<int> savePoints = study->getSavePoints();
1721 // case 1: no more save points but they existed in study's tree
1722 if ( savePoints.empty() && guiRootObj ) {
1723 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1724 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1725 const bool isAutoUpdate = ob->autoUpdate();
1726 selMgr->clearSelected();
1727 ob->setAutoUpdate(true);
1728 DataObjectList ch = guiRootObj->children();
1729 for( int i = 0; i < ch.size(); i++ )
1732 ob->setAutoUpdate(isAutoUpdate);
1735 // case 2: no more save points but root does not exist either
1736 if ( savePoints.empty() && !guiRootObj )
1738 // case 3: save points but no root for them - create it
1739 if ( !savePoints.empty() && !guiRootObj )
1740 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1741 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1742 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1744 if ( guiRootObj->nextBrother() ) {
1745 study->root()->removeChild(guiRootObj);
1746 study->root()->appendChild(guiRootObj);
1747 //study->root()->dump();
1750 // store data objects in a map id-to-DataObject
1751 QMap<int,SalomeApp_SavePointObject*> mapDO;
1753 guiRootObj->children( ch );
1754 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1755 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1757 mapDO[dobj->getId()] = dobj;
1760 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1761 // if in the map - remove it from map.
1762 for ( int i = 0; i < savePoints.size(); i++ )
1763 if ( !mapDO.contains( savePoints[i] ) )
1764 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1766 mapDO.remove( savePoints[i] );
1768 // delete DataObjects that are still in the map -- their IDs were not found in data model
1769 if( mapDO.size() > 0) {
1770 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1771 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1772 selMgr->clearSelected();
1773 const bool isAutoUpdate = ob->autoUpdate();
1774 ob->setAutoUpdate(true);
1775 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1777 ob->setAutoUpdate(isAutoUpdate);
1781 /*! Check data object */
1782 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1791 Opens other study into active Study. If Study is empty - creates it.
1792 \param theName - name of study
1794 bool SalomeApp_Application::useStudy( const QString& theName )
1797 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1800 res = aStudy->loadDocument( theName );
1801 updateDesktopTitle();
1802 updateCommandsStatus();
1806 /*! Show/hide object browser colums according to preferences */
1807 void SalomeApp_Application::objectBrowserColumnsVisibility()
1809 if ( objectBrowser() )
1810 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1812 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1813 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1817 #ifndef DISABLE_PYCONSOLE
1818 /*! Set SalomeApp_NoteBook pointer */
1819 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1821 myNoteBook = theNoteBook;
1824 /*! Return SalomeApp_NoteBook pointer */
1825 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1832 * Define extra actions defined in module definition XML file.
1833 * Additional popup items sections can be defined by parameter "popupitems".
1834 * Supported attributes:
1835 * title - title of menu item,
1836 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1837 * method - method which has to be called when menu item is selected
1839 * <section name="MODULENAME">
1840 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1842 * <section name="importmed">
1843 * <parameter name="title" value="My menu"/>
1844 * <parameter name="objectid" value="VISU.Result"/>
1845 * <parameter name="method" value="nameOfModuleMethod"/>
1848 void SalomeApp_Application::createExtraActions()
1850 myExtActions.clear();
1851 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1853 QStringList aModules;
1854 modules(aModules, false);
1855 foreach(QString aModile, aModules) {
1856 QString aModName = moduleName(aModile);
1857 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1858 if (!aSectionStr.isNull()) {
1859 QStringList aSections = aSectionStr.split(':');
1860 foreach(QString aSection, aSections) {
1861 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1862 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1863 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1864 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1867 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1868 if (aModuleName.isNull())
1869 aModuleName = aModName;
1871 QAction* aAction = new QAction(aTitle, this);
1873 aData<<aModuleName<<aSlot;
1874 aAction->setData(aData);
1875 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1876 myExtActions[aId] = aAction;
1883 * Called when extra action is selected
1885 void SalomeApp_Application::onExtAction()
1887 QAction* aAction = ::qobject_cast<QAction*>(sender());
1891 QVariant aData = aAction->data();
1892 QStringList aDataList = aData.value<QStringList>();
1893 if (aDataList.size() != 2)
1896 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1897 SALOME_ListIO aListIO;
1898 aSelectionMgr->selectedObjects(aListIO);
1899 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1900 if (aListIO.Extent() < 1)
1902 if (!anIO->hasEntry())
1905 QString aEntry(anIO->getEntry());
1907 QApplication::setOverrideCursor( Qt::WaitCursor );
1908 QString aModuleTitle = moduleTitle(aDataList[0]);
1909 activateModule(aModuleTitle);
1910 QApplication::restoreOverrideCursor();
1912 QCoreApplication::processEvents();
1914 CAM_Module* aModule = activeModule();
1918 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1919 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1923 Checks that an object can be renamed.
1924 \param entry entry of the object
1925 \brief Return \c true if object can be renamed
1927 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1929 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1933 Rename object by entry.
1934 \param entry entry of the object
1935 \param name new name of the object
1936 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1938 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1940 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1942 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1944 if(!aStudy || savePoint == -1)
1947 if ( !name.isNull() && !name.isEmpty() ) {
1948 aStudy->setNameOfSavePoint( savePoint, name );
1949 updateSavePointDataObjects( aStudy );
1951 //Mark study as modified
1958 #ifndef DISABLE_PYCONSOLE
1959 //============================================================================
1960 /*! Function : onUpdateStudy
1961 * Purpose : Slot to update the study.
1963 //============================================================================
1964 void SalomeApp_Application::onUpdateStudy()
1966 QApplication::setOverrideCursor( Qt::WaitCursor );
1968 if( !updateStudy() )
1969 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1971 QApplication::restoreOverrideCursor();
1974 //============================================================================
1975 /*! Function : updateStudy
1976 * Purpose : Update study by dumping the study to Python script and loading it.
1977 * It is used to apply variable modifications done in NoteBook to created objects.
1979 //============================================================================
1980 bool SalomeApp_Application::updateStudy()
1982 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1983 if ( !study || !myNoteBook )
1986 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1987 myNoteBook->setDumpedStudyName( study->studyName() );
1989 _PTR(Study) studyDS = study->studyDS();
1991 // get unique temporary directory name
1992 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1993 if( aTmpDir.isEmpty() )
1996 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1997 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1999 // dump study to the temporary directory
2000 QString aScriptName( "notebook" );
2001 bool toPublish = true;
2002 bool isMultiFile = false;
2003 bool toSaveGUI = true;
2006 _PTR(AttributeParameter) ap;
2007 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2008 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2009 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2010 ip->setDumpPython(studyDS);
2011 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2013 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2015 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2018 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2022 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2023 int anIndex = aList.indexOf( this );
2025 // Disconnect dialog from application desktop in case if:
2026 // 1) Application is not the first application in the session
2027 // 2) Application is the first application in session but not the only.
2028 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2029 if( changeDesktop ) {
2031 SalomeApp_Application* app = this;
2032 if( anIndex > 0 && anIndex < aList.count() )
2033 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2034 else if(anIndex == 0 && aList.count() > 1)
2035 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2040 // creation a new study and restoring will be done in another application
2041 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2042 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2045 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2046 QString aStudyName = myNoteBook->getDumpedStudyName();
2047 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2048 // clear a study (delete all objects)
2049 onCloseDoc( false );
2051 if( !changeDesktop ) {
2052 ok = onRestoreStudy( aDumpScript,
2061 //============================================================================
2062 /*! Function : onRestoreStudy
2063 * Purpose : Load the dumped study from Python script
2065 //============================================================================
2066 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2067 const QString& theStudyName,
2068 bool theIsStudySaved )
2072 // create a new study
2075 // get active application
2076 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2078 // load study from the temporary directory
2079 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2081 #ifndef DISABLE_PYCONSOLE
2082 PyConsole_Console* pyConsole = app->pythonConsole();
2084 pyConsole->execAndWait( command );
2087 // remove temporary directory
2088 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2089 QString aStudyName = aScriptInfo.baseName();
2090 QDir aDir = aScriptInfo.absoluteDir();
2091 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2092 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2093 ok = aDir.remove( *it ) && ok;
2095 ok = aDir.rmdir( aDir.absolutePath() );
2097 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2099 #ifndef DISABLE_PYCONSOLE
2100 _PTR(Study) aStudyDS = newStudy->studyDS();
2101 app->getNoteBook()->Init( aStudyDS );
2102 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2103 newStudy->Modified();
2104 updateDesktopTitle();
2115 Close the Application
2117 void SalomeApp_Application::afterCloseDoc()
2119 #ifndef DISABLE_PYCONSOLE
2120 // emit signal to restore study from Python script
2122 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2123 myNoteBook->getDumpedStudyName(),
2124 myNoteBook->isDumpedStudySaved() );
2127 LightApp_Application::afterCloseDoc();
2131 Asks to close existing document.
2133 bool SalomeApp_Application::checkExistingDoc()
2135 bool result = LightApp_Application::checkExistingDoc();
2136 if ( result && !activeStudy() ) {
2137 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2139 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2140 if( List.size() > 0 ) {
2141 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2150 #ifndef DISABLE_PYCONSOLE
2152 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2154 return new SalomeApp_PyInterp();
2157 #endif // DISABLE_PYCONSOLE