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() );
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 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1041 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1043 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1044 QAction* send = (QAction*)sender();
1045 QString aWinName = send->data().toString();
1046 if ( theIsVisible && aWinName == "objectBrowser" )
1047 objectBrowserColumnsVisibility();
1050 /*!Gets file filter.
1051 *\retval QString "(*.hdf)"
1053 QString SalomeApp_Application::getFileFilter() const
1059 QWidget* SalomeApp_Application::createWindow( const int flag )
1062 #ifndef DISABLE_PYCONSOLE
1063 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1065 wid = LightApp_Application::createWindow(flag);
1068 SUIT_ResourceMgr* resMgr = resourceMgr();
1070 if ( flag == WT_ObjectBrowser )
1072 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1074 // temporary commented
1075 //ob->setUpdater( new SalomeApp_Updater() );
1077 #ifdef WITH_SALOMEDS_OBSERVER
1078 //do not activate the automatic update of Qt tree through signal/slot
1079 ob->setAutoUpdate(false);
1080 //activate update of modified objects only
1081 ob->setUpdateModified(true);
1084 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1087 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1088 IORCol = QObject::tr( "IOR_COLUMN" ),
1089 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1090 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1092 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1093 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1094 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1095 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1096 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1097 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1098 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1099 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1100 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1102 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1103 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1104 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1106 ob->setAutoSizeFirstColumn(autoSizeFirst);
1107 ob->setAutoSizeColumns(autoSize);
1108 ob->setResizeOnExpandItem(resizeOnExpandItem);
1109 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1111 // temporary commented
1113 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1115 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1116 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1117 QString().sprintf( "visibility_column_%d", i ), true ) );
1121 // temporary commented
1123 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1124 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1125 ob->resize( desktop()->width()/3, ob->height() );
1129 #ifndef DISABLE_PYCONSOLE
1130 else if ( flag == WT_PyConsole )
1132 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1133 pyCons->setObjectName( "pythonConsole" );
1134 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1135 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1136 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1137 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1139 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1140 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1142 else if ( flag == WT_NoteBook )
1144 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1146 _PTR(Study) aStudy = appStudy->studyDS();
1147 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1148 //to receive signal in NoteBook that it's variable was modified
1149 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1150 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1152 wid = getNoteBook();
1153 wid->setObjectName( "noteBook" );
1159 /*!Create preferences.*/
1160 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1162 LightApp_Application::createPreferences(pref);
1167 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1168 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1169 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1170 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1172 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1173 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1175 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1177 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1178 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1179 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1180 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1181 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1182 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1183 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1184 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1185 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1186 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1189 /*!Update desktop title.*/
1190 void SalomeApp_Application::updateDesktopTitle() {
1191 QString aTitle = applicationName();
1192 QString aVer = applicationVersion();
1193 if ( !aVer.isEmpty() )
1194 aTitle += QString( " " ) + aVer;
1196 if ( activeStudy() )
1198 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1199 if ( !sName.isEmpty() ) {
1200 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1202 _PTR(Study) stdDS = study->studyDS();
1204 if ( stdDS->GetProperties()->IsLocked() ) {
1205 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1207 aTitle += QString( " - [%1]" ).arg( sName );
1214 desktop()->setWindowTitle( aTitle );
1217 int SalomeApp_Application::closeChoice( const QString& docName )
1219 QStringList buttons;
1220 QMap<int, int> choices;
1222 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1223 choices.insert( idx++, CloseSave ); // ...
1224 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1225 choices.insert( idx++, CloseDiscard ); // ...
1226 if ( myIsCloseFromExit ) {
1227 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1228 choices.insert( idx++, CloseDisconnectSave ); // ...
1229 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1230 choices.insert( idx++, CloseDisconnect ); // ...
1232 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1233 choices.insert( idx++, CloseCancel ); // ...
1235 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1236 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1237 return choices[answer];
1240 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1246 if ( activeStudy()->isSaved() )
1248 else if ( !onSaveAsDoc() )
1253 case CloseDisconnectSave:
1254 if ( activeStudy()->isSaved() )
1256 else if ( !onSaveAsDoc() )
1258 case CloseDisconnect:
1259 closeActiveDoc( false );
1260 closePermanently = false;
1269 int SalomeApp_Application::openChoice( const QString& aName )
1271 int choice = LightApp_Application::openChoice( aName );
1273 if ( QFileInfo( aName ).exists() ) {
1274 if ( choice == OpenNew ) { // The document isn't already open.
1276 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1277 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1278 if ( aName == QString( lst[i].c_str() ) )
1281 // The document already exists in the study manager.
1282 // Do you want to reload it?
1284 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1285 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1286 if ( answer == SUIT_MessageBox::Yes )
1287 choice = OpenRefresh;
1289 choice = OpenCancel;
1292 } else { // file is not exist on disk
1293 SUIT_MessageBox::warning( desktop(),
1294 QObject::tr("WRN_WARNING"),
1295 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1302 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1305 int choice = aChoice;
1310 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1313 studyMgr()->Close( aStudy );
1318 res = LightApp_Application::openAction( choice, aName );
1326 \brief Get map of the operations which can be performed
1327 on the module activation.
1329 The method should return the map of the kind \c {<id>:<name>}
1330 where \c <id> is an integer identifier of the operation and
1331 \c <name> is a title for the button to be added to the
1332 dialog box. After user selects the required operation by the
1333 clicking the corresponding button in the dialog box, its identifier
1334 is passed to the moduleActionSelected() method to process
1337 \return map of the operations
1338 \sa moduleActionSelected()
1340 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1342 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1344 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1346 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1351 \brief Called when the used selectes required operation chosen
1352 from "Activate module" dialog box.
1354 Performs the required operation according to the user choice.
1356 \param id operation identifier
1357 \sa activateModuleActions()
1359 void SalomeApp_Application::moduleActionSelected( const int id )
1365 case NewAndScriptId:
1369 LightApp_Application::moduleActionSelected( id );
1374 /*!Gets CORBA::ORB_var*/
1375 CORBA::ORB_var SalomeApp_Application::orb()
1377 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1378 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1382 /*!Create and return SALOMEDS_StudyManager.*/
1383 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1385 static _PTR(StudyManager) _sm;
1386 if(!_sm) _sm = ClientFactory::StudyManager();
1390 /*!Create and return SALOME_NamingService.*/
1391 SALOME_NamingService* SalomeApp_Application::namingService()
1393 static SALOME_NamingService _ns(orb());
1397 /*!Create and return SALOME_LifeCycleCORBA.*/
1398 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1400 static SALOME_LifeCycleCORBA _lcc( namingService() );
1404 /*!Private SLOT. On preferences.*/
1405 void SalomeApp_Application::onProperties()
1407 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1411 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1414 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1415 int res = aDlg.exec();
1416 if( res==QDialog::Accepted && aDlg.isChanged() )
1417 SB->CommitCommand();
1421 //study->updateCaptions();
1422 updateDesktopTitle();
1426 /*!Insert items in popup, which necessary for current application*/
1427 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1429 LightApp_SelectionMgr* mgr = selectionMgr();
1430 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1431 mgr->setSelectionCacheEnabled( true );
1433 LightApp_Application::contextMenuPopup( type, thePopup, title );
1435 // temporary commented
1436 /*OB_Browser* ob = objectBrowser();
1437 if ( !ob || type != ob->popupClientType() )
1440 // Get selected objects
1441 SALOME_ListIO aList;
1442 mgr->selectedObjects( aList, QString(), false );
1444 // add GUI state commands: restore, rename
1445 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1446 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1447 thePopup->addSeparator();
1448 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1449 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1450 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1451 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1454 // "Delete reference" item should appear only for invalid references
1456 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1457 bool isInvalidRefs = false;
1458 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1460 _PTR(Study) aStudyDS = aStudy->studyDS();
1461 _PTR(SObject) anObj;
1463 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1465 if( it.Value()->hasEntry() )
1467 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1468 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1471 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1472 isInvalidRefs = true;
1476 // Add "Delete reference" item to popup
1477 if ( isInvalidRefs )
1479 thePopup->addSeparator();
1480 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1484 // "Activate module" item should appear only if it's necessary
1485 if ( aList.Extent() == 1 ) {
1487 mgr->selectedObjects( aList );
1489 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1491 // add extra popup menu (defined in XML)
1492 if ( myExtActions.size() > 0 ) {
1493 // Use only first selected object
1494 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1496 _PTR(Study) stdDS = study->studyDS();
1498 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1500 _PTR( GenericAttribute ) anAttr;
1501 std::string auid = "AttributeUserID";
1502 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1503 if ( aSO->FindAttribute( anAttr, auid ) ) {
1504 _PTR(AttributeUserID) aAttrID = anAttr;
1505 QString aId = aAttrID->Value().c_str();
1506 if ( myExtActions.contains( aId ) ) {
1507 thePopup->addAction(myExtActions[aId]);
1515 // check if item is a "GUI state" item (also a first level object)
1516 QString entry( aIObj->getEntry() );
1517 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1518 QString aModuleName( aIObj->getComponentDataType() );
1519 QString aModuleTitle = moduleTitle( aModuleName );
1520 CAM_Module* currentModule = activeModule();
1521 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1522 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1527 mgr->setSelectionCacheEnabled( cacheIsOn );
1530 /*!Update obect browser:
1531 1.if 'updateModels' true, update existing data models;
1532 2. update "non-existing" (not loaded yet) data models;
1533 3. update object browser if it exists */
1534 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1536 // update "non-existing" (not loaded yet) data models
1537 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1540 _PTR(Study) stdDS = study->studyDS();
1543 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1545 _PTR(SComponent) aComponent ( it->Value() );
1547 #ifndef WITH_SALOMEDS_OBSERVER
1548 // with GUI observers this check is not needed anymore
1549 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1550 continue; // skip the magic "Interface Applicative" component
1552 if ( !objectBrowser() )
1553 getWindow( WT_ObjectBrowser );
1554 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1555 objectBrowser()->setAutoUpdate( false );
1556 SalomeApp_DataModel::synchronize( aComponent, study );
1557 objectBrowser()->setAutoUpdate( isAutoUpdate );
1562 // create data objects that correspond to GUI state save points
1563 if ( study ) updateSavePointDataObjects( study );
1565 // update existing data models (already loaded SComponents)
1566 LightApp_Application::updateObjectBrowser( updateModels );
1569 /*!Display Catalog Genenerator dialog */
1570 void SalomeApp_Application::onCatalogGen()
1572 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1576 /*!Display Registry Display dialog */
1577 void SalomeApp_Application::onRegDisplay()
1579 CORBA::ORB_var anOrb = orb();
1580 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1583 regWnd->activateWindow();
1586 /*!find original object by double click on item */
1587 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1589 // Issue 21379: References are supported at LightApp_DataObject level
1590 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1592 if( obj && obj->isReference() )
1594 QString entry = obj->refEntry();
1596 SUIT_DataOwnerPtrList aList;
1597 aList.append( new LightApp_DataOwner( entry ) );
1598 selectionMgr()->setSelected( aList, false );
1600 SUIT_DataBrowser* ob = objectBrowser();
1602 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1603 if ( !aSelectedIndexes.isEmpty() )
1604 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1609 Creates new view manager
1610 \param type - type of view manager
1612 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1614 return createViewManager(type);
1618 /*!Global utility function, returns selected GUI Save point object's ID */
1619 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1621 SALOME_ListIO aList;
1622 selMgr->selectedObjects( aList );
1623 if( aList.Extent() > 0 ) {
1624 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1625 QString entry( aIObj->getEntry() );
1626 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1627 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1629 bool ok; // conversion to integer is ok?
1630 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1631 return ok ? savePoint : -1;
1636 /*!Called on Restore GUI State popup command*/
1637 void SalomeApp_Application::onRestoreGUIState()
1639 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1640 if ( savePoint == -1 )
1642 SalomeApp_VisualState( this ).restoreState( savePoint );
1645 /*!Called on Delete GUI State popup command*/
1646 void SalomeApp_Application::onDeleteGUIState()
1648 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1649 if ( savePoint == -1 )
1651 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1655 study->removeSavePoint( savePoint );
1656 updateSavePointDataObjects( study );
1659 /*!Called on New study operation*/
1660 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1662 LightApp_Application::onStudyCreated( study );
1664 //#ifndef DISABLE_PYCONSOLE
1665 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1666 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1669 loadDockWindowsState();
1671 objectBrowserColumnsVisibility();
1674 /*!Called on Open study operation*/
1675 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1677 LightApp_Application::onStudyOpened( study );
1679 //#ifndef DISABLE_PYCONSOLE
1680 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1681 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1684 loadDockWindowsState();
1686 objectBrowserColumnsVisibility();
1688 // temporary commented
1689 /*if ( objectBrowser() ) {
1690 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1691 objectBrowser()->updateTree( study->root() );
1695 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1696 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1699 SUIT_DataBrowser* ob = objectBrowser();
1700 LightApp_SelectionMgr* selMgr = selectionMgr();
1702 if ( !study || !ob || !selMgr )
1705 // find GUI states root object
1706 SUIT_DataObject* guiRootObj = 0;
1708 study->root()->children( ch );
1709 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1710 for ( ; it != last ; ++it ) {
1711 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1716 std::vector<int> savePoints = study->getSavePoints();
1717 // case 1: no more save points but they existed in study's tree
1718 if ( savePoints.empty() && guiRootObj ) {
1719 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1720 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1721 const bool isAutoUpdate = ob->autoUpdate();
1722 selMgr->clearSelected();
1723 ob->setAutoUpdate(true);
1724 DataObjectList ch = guiRootObj->children();
1725 for( int i = 0; i < ch.size(); i++ )
1728 ob->setAutoUpdate(isAutoUpdate);
1731 // case 2: no more save points but root does not exist either
1732 if ( savePoints.empty() && !guiRootObj )
1734 // case 3: save points but no root for them - create it
1735 if ( !savePoints.empty() && !guiRootObj )
1736 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1737 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1738 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1740 if ( guiRootObj->nextBrother() ) {
1741 study->root()->removeChild(guiRootObj);
1742 study->root()->appendChild(guiRootObj);
1743 //study->root()->dump();
1746 // store data objects in a map id-to-DataObject
1747 QMap<int,SalomeApp_SavePointObject*> mapDO;
1749 guiRootObj->children( ch );
1750 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1751 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1753 mapDO[dobj->getId()] = dobj;
1756 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1757 // if in the map - remove it from map.
1758 for ( int i = 0; i < savePoints.size(); i++ )
1759 if ( !mapDO.contains( savePoints[i] ) )
1760 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1762 mapDO.remove( savePoints[i] );
1764 // delete DataObjects that are still in the map -- their IDs were not found in data model
1765 if( mapDO.size() > 0) {
1766 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1767 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1768 selMgr->clearSelected();
1769 const bool isAutoUpdate = ob->autoUpdate();
1770 ob->setAutoUpdate(true);
1771 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1773 ob->setAutoUpdate(isAutoUpdate);
1777 /*! Check data object */
1778 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1787 Opens other study into active Study. If Study is empty - creates it.
1788 \param theName - name of study
1790 bool SalomeApp_Application::useStudy( const QString& theName )
1793 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1796 res = aStudy->loadDocument( theName );
1797 updateDesktopTitle();
1798 updateCommandsStatus();
1802 /*! Show/hide object browser colums according to preferences */
1803 void SalomeApp_Application::objectBrowserColumnsVisibility()
1805 if ( objectBrowser() )
1806 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1808 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1809 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1813 #ifndef DISABLE_PYCONSOLE
1814 /*! Set SalomeApp_NoteBook pointer */
1815 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1817 myNoteBook = theNoteBook;
1820 /*! Return SalomeApp_NoteBook pointer */
1821 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1828 * Define extra actions defined in module definition XML file.
1829 * Additional popup items sections can be defined by parameter "popupitems".
1830 * Supported attributes:
1831 * title - title of menu item,
1832 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1833 * method - method which has to be called when menu item is selected
1835 * <section name="MODULENAME">
1836 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1838 * <section name="importmed">
1839 * <parameter name="title" value="My menu"/>
1840 * <parameter name="objectid" value="VISU.Result"/>
1841 * <parameter name="method" value="nameOfModuleMethod"/>
1844 void SalomeApp_Application::createExtraActions()
1846 myExtActions.clear();
1847 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1849 QStringList aModules;
1850 modules(aModules, false);
1851 foreach(QString aModile, aModules) {
1852 QString aModName = moduleName(aModile);
1853 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1854 if (!aSectionStr.isNull()) {
1855 QStringList aSections = aSectionStr.split(':');
1856 foreach(QString aSection, aSections) {
1857 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1858 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1859 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1860 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1863 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1864 if (aModuleName.isNull())
1865 aModuleName = aModName;
1867 QAction* aAction = new QAction(aTitle, this);
1869 aData<<aModuleName<<aSlot;
1870 aAction->setData(aData);
1871 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1872 myExtActions[aId] = aAction;
1879 * Called when extra action is selected
1881 void SalomeApp_Application::onExtAction()
1883 QAction* aAction = ::qobject_cast<QAction*>(sender());
1887 QVariant aData = aAction->data();
1888 QStringList aDataList = aData.value<QStringList>();
1889 if (aDataList.size() != 2)
1892 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1893 SALOME_ListIO aListIO;
1894 aSelectionMgr->selectedObjects(aListIO);
1895 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1896 if (aListIO.Extent() < 1)
1898 if (!anIO->hasEntry())
1901 QString aEntry(anIO->getEntry());
1903 QApplication::setOverrideCursor( Qt::WaitCursor );
1904 QString aModuleTitle = moduleTitle(aDataList[0]);
1905 activateModule(aModuleTitle);
1906 QApplication::restoreOverrideCursor();
1908 QCoreApplication::processEvents();
1910 CAM_Module* aModule = activeModule();
1914 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1915 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1919 Checks that an object can be renamed.
1920 \param entry entry of the object
1921 \brief Return \c true if object can be renamed
1923 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1925 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1929 Rename object by entry.
1930 \param entry entry of the object
1931 \param name new name of the object
1932 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1934 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1936 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1938 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1940 if(!aStudy || savePoint == -1)
1943 if ( !name.isNull() && !name.isEmpty() ) {
1944 aStudy->setNameOfSavePoint( savePoint, name );
1945 updateSavePointDataObjects( aStudy );
1947 //Mark study as modified
1954 #ifndef DISABLE_PYCONSOLE
1955 //============================================================================
1956 /*! Function : onUpdateStudy
1957 * Purpose : Slot to update the study.
1959 //============================================================================
1960 void SalomeApp_Application::onUpdateStudy()
1962 QApplication::setOverrideCursor( Qt::WaitCursor );
1964 if( !updateStudy() )
1965 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1967 QApplication::restoreOverrideCursor();
1970 //============================================================================
1971 /*! Function : updateStudy
1972 * Purpose : Update study by dumping the study to Python script and loading it.
1973 * It is used to apply variable modifications done in NoteBook to created objects.
1975 //============================================================================
1976 bool SalomeApp_Application::updateStudy()
1978 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1979 if ( !study || !myNoteBook )
1982 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1983 myNoteBook->setDumpedStudyName( study->studyName() );
1985 _PTR(Study) studyDS = study->studyDS();
1987 // get unique temporary directory name
1988 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1989 if( aTmpDir.isEmpty() )
1992 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1993 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1995 // dump study to the temporary directory
1996 QString aScriptName( "notebook" );
1997 bool toPublish = true;
1998 bool isMultiFile = false;
1999 bool toSaveGUI = true;
2002 _PTR(AttributeParameter) ap;
2003 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2004 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2005 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2006 ip->setDumpPython(studyDS);
2007 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2009 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2011 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2014 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2018 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2019 int anIndex = aList.indexOf( this );
2021 // Disconnect dialog from application desktop in case if:
2022 // 1) Application is not the first application in the session
2023 // 2) Application is the first application in session but not the only.
2024 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2025 if( changeDesktop ) {
2027 SalomeApp_Application* app = this;
2028 if( anIndex > 0 && anIndex < aList.count() )
2029 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2030 else if(anIndex == 0 && aList.count() > 1)
2031 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2036 // creation a new study and restoring will be done in another application
2037 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2038 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2041 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2042 QString aStudyName = myNoteBook->getDumpedStudyName();
2043 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2044 // clear a study (delete all objects)
2045 onCloseDoc( false );
2047 if( !changeDesktop ) {
2048 ok = onRestoreStudy( aDumpScript,
2057 //============================================================================
2058 /*! Function : onRestoreStudy
2059 * Purpose : Load the dumped study from Python script
2061 //============================================================================
2062 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2063 const QString& theStudyName,
2064 bool theIsStudySaved )
2068 // create a new study
2071 // get active application
2072 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2074 // load study from the temporary directory
2075 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2077 #ifndef DISABLE_PYCONSOLE
2078 PyConsole_Console* pyConsole = app->pythonConsole();
2080 pyConsole->execAndWait( command );
2083 // remove temporary directory
2084 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2085 QString aStudyName = aScriptInfo.baseName();
2086 QDir aDir = aScriptInfo.absoluteDir();
2087 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2088 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2089 ok = aDir.remove( *it ) && ok;
2091 ok = aDir.rmdir( aDir.absolutePath() );
2093 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2095 #ifndef DISABLE_PYCONSOLE
2096 _PTR(Study) aStudyDS = newStudy->studyDS();
2097 app->getNoteBook()->Init( aStudyDS );
2098 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2099 newStudy->Modified();
2100 updateDesktopTitle();
2111 Close the Application
2113 void SalomeApp_Application::afterCloseDoc()
2115 #ifndef DISABLE_PYCONSOLE
2116 // emit signal to restore study from Python script
2118 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2119 myNoteBook->getDumpedStudyName(),
2120 myNoteBook->isDumpedStudySaved() );
2123 LightApp_Application::afterCloseDoc();
2127 Asks to close existing document.
2129 bool SalomeApp_Application::checkExistingDoc()
2131 bool result = LightApp_Application::checkExistingDoc();
2132 if ( result && !activeStudy() ) {
2133 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2135 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2136 if( List.size() > 0 ) {
2137 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2146 #ifndef DISABLE_PYCONSOLE
2148 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2150 return new SalomeApp_PyInterp();
2153 #endif // DISABLE_PYCONSOLE