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 = ::qobject_cast<QAction*>( sender() );
1047 QString aWinName = send->data().toString();
1048 if ( theIsVisible && aWinName == "objectBrowser" )
1049 objectBrowserColumnsVisibility();
1052 /*!Gets file filter.
1053 *\retval QString "(*.hdf)"
1055 QString SalomeApp_Application::getFileFilter() const
1061 QWidget* SalomeApp_Application::createWindow( const int flag )
1064 #ifndef DISABLE_PYCONSOLE
1065 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1067 wid = LightApp_Application::createWindow(flag);
1070 SUIT_ResourceMgr* resMgr = resourceMgr();
1072 if ( flag == WT_ObjectBrowser )
1074 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1076 // temporary commented
1077 //ob->setUpdater( new SalomeApp_Updater() );
1079 #ifdef WITH_SALOMEDS_OBSERVER
1080 //do not activate the automatic update of Qt tree through signal/slot
1081 ob->setAutoUpdate(false);
1082 //activate update of modified objects only
1083 ob->setUpdateModified(true);
1086 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1089 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1090 IORCol = QObject::tr( "IOR_COLUMN" ),
1091 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1092 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1094 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1095 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1096 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1097 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1098 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1099 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1100 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1101 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1102 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1104 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1105 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1106 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1108 ob->setAutoSizeFirstColumn(autoSizeFirst);
1109 ob->setAutoSizeColumns(autoSize);
1110 ob->setResizeOnExpandItem(resizeOnExpandItem);
1111 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1113 // temporary commented
1115 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1117 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1118 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1119 QString().sprintf( "visibility_column_%d", i ), true ) );
1123 // temporary commented
1125 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1126 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1127 ob->resize( desktop()->width()/3, ob->height() );
1131 #ifndef DISABLE_PYCONSOLE
1132 else if ( flag == WT_PyConsole )
1134 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1135 pyCons->setObjectName( "pythonConsole" );
1136 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1137 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1138 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1139 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1141 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1142 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1144 else if ( flag == WT_NoteBook )
1146 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1148 _PTR(Study) aStudy = appStudy->studyDS();
1149 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1150 //to receive signal in NoteBook that it's variable was modified
1151 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1152 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1154 wid = getNoteBook();
1155 wid->setObjectName( "noteBook" );
1161 /*!Create preferences.*/
1162 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1164 LightApp_Application::createPreferences(pref);
1169 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1170 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1171 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1172 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1174 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1175 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1177 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1179 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1180 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1181 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1182 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1183 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1184 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1185 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1186 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1187 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1188 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1191 /*!Update desktop title.*/
1192 void SalomeApp_Application::updateDesktopTitle() {
1193 QString aTitle = applicationName();
1194 QString aVer = applicationVersion();
1195 if ( !aVer.isEmpty() )
1196 aTitle += QString( " " ) + aVer;
1198 if ( activeStudy() )
1200 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1201 if ( !sName.isEmpty() ) {
1202 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1204 _PTR(Study) stdDS = study->studyDS();
1206 if ( stdDS->GetProperties()->IsLocked() ) {
1207 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1209 aTitle += QString( " - [%1]" ).arg( sName );
1216 desktop()->setWindowTitle( aTitle );
1219 int SalomeApp_Application::closeChoice( const QString& docName )
1221 QStringList buttons;
1222 QMap<int, int> choices;
1224 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1225 choices.insert( idx++, CloseSave ); // ...
1226 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1227 choices.insert( idx++, CloseDiscard ); // ...
1228 if ( myIsCloseFromExit ) {
1229 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1230 choices.insert( idx++, CloseDisconnectSave ); // ...
1231 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1232 choices.insert( idx++, CloseDisconnect ); // ...
1234 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1235 choices.insert( idx++, CloseCancel ); // ...
1237 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1238 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1239 return choices[answer];
1242 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1248 if ( activeStudy()->isSaved() )
1250 else if ( !onSaveAsDoc() )
1255 case CloseDisconnectSave:
1256 if ( activeStudy()->isSaved() )
1258 else if ( !onSaveAsDoc() )
1260 case CloseDisconnect:
1261 closeActiveDoc( false );
1262 closePermanently = false;
1271 int SalomeApp_Application::openChoice( const QString& aName )
1273 int choice = LightApp_Application::openChoice( aName );
1275 if ( QFileInfo( aName ).exists() ) {
1276 if ( choice == OpenNew ) { // The document isn't already open.
1278 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1279 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1280 if ( aName == QString( lst[i].c_str() ) )
1283 // The document already exists in the study manager.
1284 // Do you want to reload it?
1286 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1287 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1288 if ( answer == SUIT_MessageBox::Yes )
1289 choice = OpenRefresh;
1291 choice = OpenCancel;
1294 } else { // file is not exist on disk
1295 SUIT_MessageBox::warning( desktop(),
1296 QObject::tr("WRN_WARNING"),
1297 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1304 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1307 int choice = aChoice;
1312 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1315 studyMgr()->Close( aStudy );
1320 res = LightApp_Application::openAction( choice, aName );
1328 \brief Get map of the operations which can be performed
1329 on the module activation.
1331 The method should return the map of the kind \c {<id>:<name>}
1332 where \c <id> is an integer identifier of the operation and
1333 \c <name> is a title for the button to be added to the
1334 dialog box. After user selects the required operation by the
1335 clicking the corresponding button in the dialog box, its identifier
1336 is passed to the moduleActionSelected() method to process
1339 \return map of the operations
1340 \sa moduleActionSelected()
1342 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1344 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1346 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1348 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1353 \brief Called when the used selectes required operation chosen
1354 from "Activate module" dialog box.
1356 Performs the required operation according to the user choice.
1358 \param id operation identifier
1359 \sa activateModuleActions()
1361 void SalomeApp_Application::moduleActionSelected( const int id )
1367 case NewAndScriptId:
1371 LightApp_Application::moduleActionSelected( id );
1376 /*!Gets CORBA::ORB_var*/
1377 CORBA::ORB_var SalomeApp_Application::orb()
1379 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1380 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1384 /*!Create and return SALOMEDS_StudyManager.*/
1385 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1387 static _PTR(StudyManager) _sm;
1388 if(!_sm) _sm = ClientFactory::StudyManager();
1392 /*!Create and return SALOME_NamingService.*/
1393 SALOME_NamingService* SalomeApp_Application::namingService()
1395 static SALOME_NamingService _ns(orb());
1399 /*!Create and return SALOME_LifeCycleCORBA.*/
1400 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1402 static SALOME_LifeCycleCORBA _lcc( namingService() );
1406 /*!Private SLOT. On preferences.*/
1407 void SalomeApp_Application::onProperties()
1409 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1413 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1416 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1417 int res = aDlg.exec();
1418 if( res==QDialog::Accepted && aDlg.isChanged() )
1419 SB->CommitCommand();
1423 //study->updateCaptions();
1424 updateDesktopTitle();
1428 /*!Insert items in popup, which necessary for current application*/
1429 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1431 LightApp_SelectionMgr* mgr = selectionMgr();
1432 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1433 mgr->setSelectionCacheEnabled( true );
1435 LightApp_Application::contextMenuPopup( type, thePopup, title );
1437 // temporary commented
1438 /*OB_Browser* ob = objectBrowser();
1439 if ( !ob || type != ob->popupClientType() )
1442 // Get selected objects
1443 SALOME_ListIO aList;
1444 mgr->selectedObjects( aList, QString(), false );
1446 // add GUI state commands: restore, rename
1447 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1448 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1449 thePopup->addSeparator();
1450 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1451 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1452 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1453 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1456 // "Delete reference" item should appear only for invalid references
1458 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1459 bool isInvalidRefs = false;
1460 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1462 _PTR(Study) aStudyDS = aStudy->studyDS();
1463 _PTR(SObject) anObj;
1465 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1467 if( it.Value()->hasEntry() )
1469 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1470 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1473 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1474 isInvalidRefs = true;
1478 // Add "Delete reference" item to popup
1479 if ( isInvalidRefs )
1481 thePopup->addSeparator();
1482 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1486 // "Activate module" item should appear only if it's necessary
1487 if ( aList.Extent() == 1 ) {
1489 mgr->selectedObjects( aList );
1491 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1493 // add extra popup menu (defined in XML)
1494 if ( myExtActions.size() > 0 ) {
1495 // Use only first selected object
1496 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1498 _PTR(Study) stdDS = study->studyDS();
1500 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1502 _PTR( GenericAttribute ) anAttr;
1503 std::string auid = "AttributeUserID";
1504 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1505 if ( aSO->FindAttribute( anAttr, auid ) ) {
1506 _PTR(AttributeUserID) aAttrID = anAttr;
1507 QString aId = aAttrID->Value().c_str();
1508 if ( myExtActions.contains( aId ) ) {
1509 thePopup->addAction(myExtActions[aId]);
1517 // check if item is a "GUI state" item (also a first level object)
1518 QString entry( aIObj->getEntry() );
1519 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1520 QString aModuleName( aIObj->getComponentDataType() );
1521 QString aModuleTitle = moduleTitle( aModuleName );
1522 CAM_Module* currentModule = activeModule();
1523 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1524 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1529 mgr->setSelectionCacheEnabled( cacheIsOn );
1532 /*!Update obect browser:
1533 1.if 'updateModels' true, update existing data models;
1534 2. update "non-existing" (not loaded yet) data models;
1535 3. update object browser if it exists */
1536 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1538 // update "non-existing" (not loaded yet) data models
1539 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1542 _PTR(Study) stdDS = study->studyDS();
1545 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1547 _PTR(SComponent) aComponent ( it->Value() );
1549 #ifndef WITH_SALOMEDS_OBSERVER
1550 // with GUI observers this check is not needed anymore
1551 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1552 continue; // skip the magic "Interface Applicative" component
1554 if ( !objectBrowser() )
1555 getWindow( WT_ObjectBrowser );
1556 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1557 objectBrowser()->setAutoUpdate( false );
1558 SalomeApp_DataModel::synchronize( aComponent, study );
1559 objectBrowser()->setAutoUpdate( isAutoUpdate );
1564 // create data objects that correspond to GUI state save points
1565 if ( study ) updateSavePointDataObjects( study );
1567 // update existing data models (already loaded SComponents)
1568 LightApp_Application::updateObjectBrowser( updateModels );
1571 /*!Display Catalog Genenerator dialog */
1572 void SalomeApp_Application::onCatalogGen()
1574 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1578 /*!Display Registry Display dialog */
1579 void SalomeApp_Application::onRegDisplay()
1581 CORBA::ORB_var anOrb = orb();
1582 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1585 regWnd->activateWindow();
1588 /*!find original object by double click on item */
1589 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1591 // Issue 21379: References are supported at LightApp_DataObject level
1592 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1594 if( obj && obj->isReference() )
1596 QString entry = obj->refEntry();
1598 SUIT_DataOwnerPtrList aList;
1599 aList.append( new LightApp_DataOwner( entry ) );
1600 selectionMgr()->setSelected( aList, false );
1602 SUIT_DataBrowser* ob = objectBrowser();
1604 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1605 if ( !aSelectedIndexes.isEmpty() )
1606 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1611 Creates new view manager
1612 \param type - type of view manager
1614 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1616 return createViewManager(type);
1620 /*!Global utility function, returns selected GUI Save point object's ID */
1621 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1623 SALOME_ListIO aList;
1624 selMgr->selectedObjects( aList );
1625 if( aList.Extent() > 0 ) {
1626 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1627 QString entry( aIObj->getEntry() );
1628 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1629 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1631 bool ok; // conversion to integer is ok?
1632 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1633 return ok ? savePoint : -1;
1638 /*!Called on Restore GUI State popup command*/
1639 void SalomeApp_Application::onRestoreGUIState()
1641 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1642 if ( savePoint == -1 )
1644 SalomeApp_VisualState( this ).restoreState( savePoint );
1647 /*!Called on Delete GUI State popup command*/
1648 void SalomeApp_Application::onDeleteGUIState()
1650 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1651 if ( savePoint == -1 )
1653 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1657 study->removeSavePoint( savePoint );
1658 updateSavePointDataObjects( study );
1661 /*!Called on New study operation*/
1662 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1664 LightApp_Application::onStudyCreated( study );
1666 //#ifndef DISABLE_PYCONSOLE
1667 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1668 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1671 loadDockWindowsState();
1673 objectBrowserColumnsVisibility();
1676 /*!Called on Open study operation*/
1677 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1679 LightApp_Application::onStudyOpened( study );
1681 //#ifndef DISABLE_PYCONSOLE
1682 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1683 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1686 loadDockWindowsState();
1688 objectBrowserColumnsVisibility();
1690 // temporary commented
1691 /*if ( objectBrowser() ) {
1692 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1693 objectBrowser()->updateTree( study->root() );
1697 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1698 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1701 SUIT_DataBrowser* ob = objectBrowser();
1702 LightApp_SelectionMgr* selMgr = selectionMgr();
1704 if ( !study || !ob || !selMgr )
1707 // find GUI states root object
1708 SUIT_DataObject* guiRootObj = 0;
1710 study->root()->children( ch );
1711 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1712 for ( ; it != last ; ++it ) {
1713 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1718 std::vector<int> savePoints = study->getSavePoints();
1719 // case 1: no more save points but they existed in study's tree
1720 if ( savePoints.empty() && guiRootObj ) {
1721 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1722 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1723 const bool isAutoUpdate = ob->autoUpdate();
1724 selMgr->clearSelected();
1725 ob->setAutoUpdate(true);
1726 DataObjectList ch = guiRootObj->children();
1727 for( int i = 0; i < ch.size(); i++ )
1730 ob->setAutoUpdate(isAutoUpdate);
1733 // case 2: no more save points but root does not exist either
1734 if ( savePoints.empty() && !guiRootObj )
1736 // case 3: save points but no root for them - create it
1737 if ( !savePoints.empty() && !guiRootObj )
1738 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1739 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1740 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1742 if ( guiRootObj->nextBrother() ) {
1743 study->root()->removeChild(guiRootObj);
1744 study->root()->appendChild(guiRootObj);
1745 //study->root()->dump();
1748 // store data objects in a map id-to-DataObject
1749 QMap<int,SalomeApp_SavePointObject*> mapDO;
1751 guiRootObj->children( ch );
1752 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1753 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1755 mapDO[dobj->getId()] = dobj;
1758 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1759 // if in the map - remove it from map.
1760 for ( int i = 0; i < savePoints.size(); i++ )
1761 if ( !mapDO.contains( savePoints[i] ) )
1762 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1764 mapDO.remove( savePoints[i] );
1766 // delete DataObjects that are still in the map -- their IDs were not found in data model
1767 if( mapDO.size() > 0) {
1768 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1769 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1770 selMgr->clearSelected();
1771 const bool isAutoUpdate = ob->autoUpdate();
1772 ob->setAutoUpdate(true);
1773 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1775 ob->setAutoUpdate(isAutoUpdate);
1779 /*! Check data object */
1780 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1789 Opens other study into active Study. If Study is empty - creates it.
1790 \param theName - name of study
1792 bool SalomeApp_Application::useStudy( const QString& theName )
1795 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1798 res = aStudy->loadDocument( theName );
1799 updateDesktopTitle();
1800 updateCommandsStatus();
1804 /*! Show/hide object browser colums according to preferences */
1805 void SalomeApp_Application::objectBrowserColumnsVisibility()
1807 if ( objectBrowser() )
1808 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1810 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1811 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1815 #ifndef DISABLE_PYCONSOLE
1816 /*! Set SalomeApp_NoteBook pointer */
1817 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1819 myNoteBook = theNoteBook;
1822 /*! Return SalomeApp_NoteBook pointer */
1823 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1830 * Define extra actions defined in module definition XML file.
1831 * Additional popup items sections can be defined by parameter "popupitems".
1832 * Supported attributes:
1833 * title - title of menu item,
1834 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1835 * method - method which has to be called when menu item is selected
1837 * <section name="MODULENAME">
1838 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1840 * <section name="importmed">
1841 * <parameter name="title" value="My menu"/>
1842 * <parameter name="objectid" value="VISU.Result"/>
1843 * <parameter name="method" value="nameOfModuleMethod"/>
1846 void SalomeApp_Application::createExtraActions()
1848 myExtActions.clear();
1849 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1851 QStringList aModules;
1852 modules(aModules, false);
1853 foreach(QString aModile, aModules) {
1854 QString aModName = moduleName(aModile);
1855 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1856 if (!aSectionStr.isNull()) {
1857 QStringList aSections = aSectionStr.split(':');
1858 foreach(QString aSection, aSections) {
1859 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1860 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1861 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1862 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1865 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1866 if (aModuleName.isNull())
1867 aModuleName = aModName;
1869 QAction* aAction = new QAction(aTitle, this);
1871 aData<<aModuleName<<aSlot;
1872 aAction->setData(aData);
1873 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1874 myExtActions[aId] = aAction;
1881 * Called when extra action is selected
1883 void SalomeApp_Application::onExtAction()
1885 QAction* aAction = ::qobject_cast<QAction*>(sender());
1889 QVariant aData = aAction->data();
1890 QStringList aDataList = aData.value<QStringList>();
1891 if (aDataList.size() != 2)
1894 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1895 SALOME_ListIO aListIO;
1896 aSelectionMgr->selectedObjects(aListIO);
1897 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1898 if (aListIO.Extent() < 1)
1900 if (!anIO->hasEntry())
1903 QString aEntry(anIO->getEntry());
1905 QApplication::setOverrideCursor( Qt::WaitCursor );
1906 QString aModuleTitle = moduleTitle(aDataList[0]);
1907 activateModule(aModuleTitle);
1908 QApplication::restoreOverrideCursor();
1910 QCoreApplication::processEvents();
1912 CAM_Module* aModule = activeModule();
1916 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1917 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1921 Checks that an object can be renamed.
1922 \param entry entry of the object
1923 \brief Return \c true if object can be renamed
1925 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1927 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1931 Rename object by entry.
1932 \param entry entry of the object
1933 \param name new name of the object
1934 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1936 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1938 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1940 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1942 if(!aStudy || savePoint == -1)
1945 if ( !name.isNull() && !name.isEmpty() ) {
1946 aStudy->setNameOfSavePoint( savePoint, name );
1947 updateSavePointDataObjects( aStudy );
1949 //Mark study as modified
1956 #ifndef DISABLE_PYCONSOLE
1957 //============================================================================
1958 /*! Function : onUpdateStudy
1959 * Purpose : Slot to update the study.
1961 //============================================================================
1962 void SalomeApp_Application::onUpdateStudy()
1964 QApplication::setOverrideCursor( Qt::WaitCursor );
1966 if( !updateStudy() )
1967 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1969 QApplication::restoreOverrideCursor();
1972 //============================================================================
1973 /*! Function : updateStudy
1974 * Purpose : Update study by dumping the study to Python script and loading it.
1975 * It is used to apply variable modifications done in NoteBook to created objects.
1977 //============================================================================
1978 bool SalomeApp_Application::updateStudy()
1980 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1981 if ( !study || !myNoteBook )
1984 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1985 myNoteBook->setDumpedStudyName( study->studyName() );
1987 _PTR(Study) studyDS = study->studyDS();
1989 // get unique temporary directory name
1990 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1991 if( aTmpDir.isEmpty() )
1994 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1995 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1997 // dump study to the temporary directory
1998 QString aScriptName( "notebook" );
1999 bool toPublish = true;
2000 bool isMultiFile = false;
2001 bool toSaveGUI = true;
2004 _PTR(AttributeParameter) ap;
2005 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2006 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2007 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2008 ip->setDumpPython(studyDS);
2009 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2011 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2013 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2016 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2020 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2021 int anIndex = aList.indexOf( this );
2023 // Disconnect dialog from application desktop in case if:
2024 // 1) Application is not the first application in the session
2025 // 2) Application is the first application in session but not the only.
2026 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2027 if( changeDesktop ) {
2029 SalomeApp_Application* app = this;
2030 if( anIndex > 0 && anIndex < aList.count() )
2031 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2032 else if(anIndex == 0 && aList.count() > 1)
2033 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2038 // creation a new study and restoring will be done in another application
2039 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2040 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2043 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2044 QString aStudyName = myNoteBook->getDumpedStudyName();
2045 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2046 // clear a study (delete all objects)
2047 onCloseDoc( false );
2049 if( !changeDesktop ) {
2050 ok = onRestoreStudy( aDumpScript,
2059 //============================================================================
2060 /*! Function : onRestoreStudy
2061 * Purpose : Load the dumped study from Python script
2063 //============================================================================
2064 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2065 const QString& theStudyName,
2066 bool theIsStudySaved )
2070 // create a new study
2073 // get active application
2074 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2076 // load study from the temporary directory
2077 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2079 #ifndef DISABLE_PYCONSOLE
2080 PyConsole_Console* pyConsole = app->pythonConsole();
2082 pyConsole->execAndWait( command );
2085 // remove temporary directory
2086 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2087 QString aStudyName = aScriptInfo.baseName();
2088 QDir aDir = aScriptInfo.absoluteDir();
2089 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2090 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2091 ok = aDir.remove( *it ) && ok;
2093 ok = aDir.rmdir( aDir.absolutePath() );
2095 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2097 #ifndef DISABLE_PYCONSOLE
2098 _PTR(Study) aStudyDS = newStudy->studyDS();
2099 app->getNoteBook()->Init( aStudyDS );
2100 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2101 newStudy->Modified();
2102 updateDesktopTitle();
2113 Close the Application
2115 void SalomeApp_Application::afterCloseDoc()
2117 #ifndef DISABLE_PYCONSOLE
2118 // emit signal to restore study from Python script
2120 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2121 myNoteBook->getDumpedStudyName(),
2122 myNoteBook->isDumpedStudySaved() );
2125 LightApp_Application::afterCloseDoc();
2129 Asks to close existing document.
2131 bool SalomeApp_Application::checkExistingDoc()
2133 bool result = LightApp_Application::checkExistingDoc();
2134 if ( result && !activeStudy() ) {
2135 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2137 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2138 if( List.size() > 0 ) {
2139 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2148 #ifndef DISABLE_PYCONSOLE
2150 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2152 return new SalomeApp_PyInterp();
2155 #endif // DISABLE_PYCONSOLE