1 // Copyright (C) 2007-2013 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.
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>
35 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
36 #include "SalomeApp_Application.h"
37 #include "SalomeApp_Study.h"
38 #include "SalomeApp_DataModel.h"
39 #include "SalomeApp_DataObject.h"
40 #include "SalomeApp_VisualState.h"
41 #include "SalomeApp_StudyPropertiesDlg.h"
42 #include "SalomeApp_LoadStudiesDlg.h"
43 #include "SalomeApp_NoteBook.h"
45 #include "SalomeApp_ExitDlg.h"
47 #include <LightApp_Application.h>
48 #include <LightApp_Module.h>
49 #include <LightApp_Preferences.h>
50 #include <LightApp_SelectionMgr.h>
51 #include <LightApp_NameDlg.h>
52 #include <LightApp_DataOwner.h>
53 #include <LightApp_Displayer.h>
55 #include <CAM_Module.h>
57 #include <SUIT_Tools.h>
58 #include <SUIT_Session.h>
59 #include <SUIT_Desktop.h>
60 #include <SUIT_DataBrowser.h>
61 #include <SUIT_FileDlg.h>
62 #include <SUIT_FileValidator.h>
63 #include <SUIT_MessageBox.h>
64 #include <SUIT_ResourceMgr.h>
65 #include <SUIT_TreeModel.h>
66 #include <SUIT_ViewWindow.h>
67 #include <SUIT_ViewManager.h>
68 #include <SUIT_ViewModel.h>
69 #include <SUIT_OverrideCursor.h>
71 #include <QtxTreeView.h>
73 #include <SALOME_EventFilter.h>
75 // temporary commented
76 //#include <OB_ListItem.h>
78 #include <PyConsole_Console.h>
80 #include <Utils_ORB_INIT.hxx>
81 #include <Utils_SINGLETON.hxx>
82 #include <SALOME_LifeCycleCORBA.hxx>
84 #include <QApplication>
88 #include <QPushButton>
90 #include <QListWidget>
91 #include <QGridLayout>
95 #include <SALOMEDSClient_ClientFactory.hxx>
96 #include <Basics_Utils.hxx>
98 #include <SALOME_ListIO.hxx>
99 #include <SALOME_ListIteratorOfListIO.hxx>
100 #include <SALOME_Prs.h>
103 #include <ToolsGUI_CatalogGeneratorDlg.h>
104 #include <ToolsGUI_RegWidget.h>
108 #include <SALOMEDS_Tool.hxx>
110 /*!Internal class that updates object browser item properties */
111 // temporary commented
112 /*class SalomeApp_Updater : public OB_Updater
115 SalomeApp_Updater() : OB_Updater(){};
116 virtual ~SalomeApp_Updater(){};
117 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
120 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
122 if( !theObj || !theItem )
125 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
129 _PTR(SObject) SObj = SAObj->object();
132 _PTR( GenericAttribute ) anAttr;
135 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
137 _PTR(AttributeSelectable) aAttrSel = anAttr;
138 theItem->setSelectable( aAttrSel->IsSelectable() );
141 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
143 _PTR(AttributeExpandable) aAttrExpand = anAttr;
144 theItem->setExpandable( aAttrExpand->IsExpandable() );
147 //this attribute is not supported in the version of SALOME 3.x
148 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
150 // _PTR(AttributeOpened) aAttrOpen = anAttr;
151 // theItem->setOpen( aAttrOpen->IsOpened() );
155 /*!Create new instance of SalomeApp_Application.*/
156 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
158 return new SalomeApp_Application();
162 SalomeApp_Application::SalomeApp_Application()
163 : LightApp_Application()
165 connect( desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
166 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
167 connect( desktop(), SIGNAL( message( const QString& ) ),
168 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
169 myIsSiman = false; // default
173 *\li Destroy event filter.
175 SalomeApp_Application::~SalomeApp_Application()
177 // Do not destroy. It's a singleton !
178 //SALOME_EventFilter::Destroy();
181 /*!Start application.*/
182 void SalomeApp_Application::start()
184 // process the command line options before start: to createActions in accordance to the options
185 static bool isFirst = true;
193 for (int i = 1; i < qApp->argc(); i++) {
194 QRegExp rxs ("--study-hdf=(.+)");
195 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
196 QString file = rxs.capturedTexts()[1];
197 QFileInfo fi ( file );
198 QString extension = fi.suffix().toLower();
199 if ( extension == "hdf" && fi.exists() )
200 hdffile = fi.absoluteFilePath();
203 QRegExp rxp ("--pyscript=\\[(.+)\\]");
204 QRegExp rxl ("--siman-study=(.+)");
205 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
207 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
208 for (int k = 0; k < dictList.count(); ++k) {
209 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
210 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
211 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
212 pyfiles += rxd.capturedTexts()[m];
218 if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
220 loadStudy = rxl.capturedTexts()[1];
226 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
227 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
229 LightApp_Application::start();
230 SALOME_EventFilter::Init();
232 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
233 onOpenDoc( hdffile );
234 else if ( pyfiles.count() > 0 ) // create new study
236 else if (!loadStudy.isEmpty()) {// load study by name
237 if (onLoadDoc(loadStudy))
238 updateObjectBrowser(true);
241 // import/execute python scripts
242 if ( pyfiles.count() > 0 && activeStudy() ) {
243 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
244 PyConsole_Console* pyConsole = pythonConsole();
245 if ( appStudy && pyConsole ) {
246 _PTR(Study) aStudy = appStudy->studyDS();
247 if ( !aStudy->GetProperties()->IsLocked() ) {
248 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
249 // Path is absolute, script has .py extension
250 for (uint j = 0; j < pyfiles.count(); j++ ) {
251 // Extract scripts and their arguments, if any
252 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
253 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
254 QString script = rxp.capturedTexts()[1];
256 QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
257 for (uint k = 0; k < argList.count(); k++ ) {
258 QString arg = argList[k].trimmed();
259 arg.remove( QRegExp("^[\"]") );
260 arg.remove( QRegExp("[\"]$") );
263 args.remove( QRegExp("[,]$") );
264 if (!args.isEmpty()) {
268 script.remove( QRegExp("^python.*[\\s]+") );
269 QString cmd = script+" "+args;
270 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
271 pyConsole->exec(command);
273 } // 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 //SRN: BugID IPAL9021, add an action "Load"
322 createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
323 resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
324 tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
325 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
326 //SRN: BugID IPAL9021: End
330 // check-in operations for SIMAN study
331 createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
332 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
333 0, desk, false, this, SLOT( onCheckIn() ) );
334 createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
335 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
336 0, desk, false, this, SLOT( onLocalCheckIn() ) );
340 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
342 // "Save GUI State" command is renamed to "Save VISU State" and
343 // creation of menu item is moved to VISU
344 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
346 createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load"
350 // check-in operation for SIMAN study
351 // last argument "5" locates this just after "Save As" but certain constant is bad => insert after the separator
352 createMenu( SimanCheckInId, fileMenu, 5);
353 createMenu( SimanLocalCheckInId, fileMenu, 5);
354 createMenu( separator(), fileMenu, 5 );
357 createMenu( DumpStudyId, fileMenu, 10, -1 );
358 createMenu( separator(), fileMenu, -1, 10, -1 );
359 createMenu( LoadScriptId, fileMenu, 10, -1 );
360 createMenu( separator(), fileMenu, -1, 10, -1 );
361 createMenu( PropertiesId, fileMenu, 10, -1 );
362 createMenu( separator(), fileMenu, -1, 10, -1 );
364 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
365 createMenu( CatalogGenId, toolsMenu, 10, -1 );
366 createMenu( RegDisplayId, toolsMenu, 10, -1 );
367 createMenu( separator(), toolsMenu, -1, 15, -1 );
369 createExtraActions();
371 // import Python module that manages SALOME plugins
373 PyLockWrapper lck; // acquire GIL
374 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
375 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str());
379 // end of SALOME plugins loading
385 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
387 LightApp_Application::setDesktop( desk );
390 connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
391 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
392 connect( desk, SIGNAL( message( const QString& ) ),
393 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
398 \brief Close application.
400 void SalomeApp_Application::onExit()
402 bool killServers = false;
405 if ( exitConfirmation() ) {
406 SalomeApp_ExitDlg dlg( desktop() );
407 result = dlg.exec() == QDialog::Accepted;
408 killServers = dlg.isServersShutdown();
412 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
415 /*!SLOT. Load document.*/
416 void SalomeApp_Application::onLoadDoc()
420 std::vector<std::string> List = studyMgr()->GetOpenStudies();
422 SUIT_Session* aSession = SUIT_Session::session();
423 QList<SUIT_Application*> aAppList = aSession->applications();
425 QStringList unloadedStudies;
427 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
428 studyName = List[ind].c_str();
429 // Add to list only unloaded studies
430 bool isAlreadyOpen = false;
431 QListIterator<SUIT_Application*> it( aAppList );
432 while ( it.hasNext() && !isAlreadyOpen ) {
433 SUIT_Application* aApp = it.next();
434 if( !aApp || !aApp->activeStudy() )
436 if ( aApp->activeStudy()->studyName() == studyName )
437 isAlreadyOpen = true;
440 if ( !isAlreadyOpen )
441 unloadedStudies << studyName;
444 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
445 if ( studyName.isEmpty() )
449 // this code replaces marker of windows drive and path become invalid therefore
450 // defines placed there
451 studyName.replace( QRegExp(":"), "/" );
454 if ( onLoadDoc( studyName ) ) {
456 updateViewManagers();
457 updateObjectBrowser( true );
461 /*!SLOT. Create new study and load script*/
462 void SalomeApp_Application::onNewWithScript()
464 QStringList filtersList;
465 filtersList.append(tr("PYTHON_FILES_FILTER"));
466 filtersList.append(tr("ALL_FILES_FILTER"));
468 QString anInitialPath = "";
469 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
470 anInitialPath = QDir::currentPath();
472 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
474 if ( !aFile.isEmpty() )
478 QString command = QString("execfile(r\"%1\")").arg(aFile);
480 PyConsole_Console* pyConsole = pythonConsole();
483 pyConsole->exec( command );
488 /*!SLOT. Load document with \a aName.*/
489 bool SalomeApp_Application::onLoadDoc( const QString& aName )
492 if ( !activeStudy() ) {
493 // if no study - load in current desktop
494 res = useStudy( aName );
497 // if study exists - load in new desktop. Check: is the same file is loaded?
498 SUIT_Session* aSession = SUIT_Session::session();
499 QList<SUIT_Application*> aAppList = aSession->applications();
500 bool isAlreadyOpen = false;
501 SalomeApp_Application* aApp = 0;
502 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
503 it != aAppList.end() && !isAlreadyOpen; ++it ) {
504 aApp = dynamic_cast<SalomeApp_Application*>( *it );
505 if ( aApp && aApp->activeStudy()->studyName() == aName )
506 isAlreadyOpen = true;
508 if ( !isAlreadyOpen ) {
509 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
511 res = aApp->useStudy( aName );
514 aApp->desktop()->activateWindow();
521 /*!SLOT. Load document with a name, specified in \a aMessage.*/
522 void SalomeApp_Application::onLoadDocMessage(const QString& aMessage)
524 if (aMessage.indexOf("simanCheckoutDone ") == 0) {
526 onLoadDoc(aMessage.section(' ', 1));
528 printf( "****************************************************************\n" );
529 printf( "* Warning: SALOME is built without SIMAN support.\n" );
530 printf( "****************************************************************\n" );
535 /*!SLOT. Copy objects to study maneger from selection maneger..*/
536 void SalomeApp_Application::onCopy()
539 LightApp_SelectionMgr* mgr = selectionMgr();
540 mgr->selectedObjects(list);
542 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
543 if(study == NULL) return;
545 _PTR(Study) stdDS = study->studyDS();
548 SALOME_ListIteratorOfListIO it( list );
551 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
553 studyMgr()->Copy(so);
554 onSelectionChanged();
561 /*!SLOT. Paste objects to study maneger from selection manager.*/
562 void SalomeApp_Application::onPaste()
565 LightApp_SelectionMgr* mgr = selectionMgr();
566 mgr->selectedObjects(list);
568 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
569 if(study == NULL) return;
571 _PTR(Study) stdDS = study->studyDS();
574 if ( stdDS->GetProperties()->IsLocked() ) {
575 SUIT_MessageBox::warning( desktop(),
576 QObject::tr("WRN_WARNING"),
577 QObject::tr("WRN_STUDY_LOCKED") );
581 SALOME_ListIteratorOfListIO it( list );
584 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
586 studyMgr()->Paste(so);
587 updateObjectBrowser( true );
588 updateActions(); //SRN: BugID IPAL9377, case 3
595 /*!Check the application on closing.
596 * \retval true if possible, else false
598 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
600 return LightApp_Application::isPossibleToClose( closePermanently );
603 /*! Check if the study is locked */
604 void SalomeApp_Application::onCloseDoc( bool ask )
606 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
609 _PTR(Study) stdDS = study->studyDS();
610 if(stdDS && stdDS->IsStudyLocked()) {
611 if ( SUIT_MessageBox::question( desktop(),
612 QObject::tr( "WRN_WARNING" ),
613 QObject::tr( "CLOSE_LOCKED_STUDY" ),
614 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
615 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
620 LightApp_Application::onCloseDoc( ask );
623 /*!Sets enable or disable some actions on selection changed.*/
624 void SalomeApp_Application::onSelectionChanged()
627 LightApp_SelectionMgr* mgr = selectionMgr();
628 mgr->selectedObjects(list);
630 bool canCopy = false;
631 bool canPaste = false;
633 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
635 _PTR(Study) stdDS = study->studyDS();
638 SALOME_ListIteratorOfListIO it ( list );
640 if (it.More() && list.Extent() == 1) {
641 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
644 canCopy = studyMgr()->CanCopy(so);
645 canPaste = studyMgr()->CanPaste(so);
651 action(EditCopyId)->setEnabled(canCopy);
652 action(EditPasteId)->setEnabled(canPaste);
655 /*!Delete references.*/
656 void SalomeApp_Application::onDeleteInvalidReferences()
659 LightApp_SelectionMgr* mgr = selectionMgr();
660 mgr->selectedObjects( aList, QString(), false );
662 if( aList.IsEmpty() )
665 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
666 _PTR(Study) aStudyDS = aStudy->studyDS();
667 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
670 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
671 if ( it.Value()->hasEntry() )
673 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
674 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
677 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
678 aStudyBuilder->RemoveReference( aSObject );
680 updateObjectBrowser();
684 void SalomeApp_Application::onOpenWith()
686 QApplication::setOverrideCursor( Qt::WaitCursor );
688 LightApp_SelectionMgr* mgr = selectionMgr();
689 mgr->selectedObjects(aList);
690 if (aList.Extent() != 1)
692 QApplication::restoreOverrideCursor();
695 Handle(SALOME_InteractiveObject) aIObj = aList.First();
696 QString aModuleName(aIObj->getComponentDataType());
697 QString aModuleTitle = moduleTitle(aModuleName);
698 activateModule(aModuleTitle);
699 QApplication::restoreOverrideCursor();
705 SUIT_Study* SalomeApp_Application::createNewStudy()
707 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
709 // Set up processing of major study-related events
710 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
711 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
712 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
713 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
715 //to receive signal in application that NoteBook's variable was modified
716 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
717 this, SIGNAL(notebookVarUpdated(QString)) );
723 Enable/Disable menu items and toolbar buttons. Rebuild menu
725 void SalomeApp_Application::updateCommandsStatus()
727 LightApp_Application::updateCommandsStatus();
730 QAction* a = action( DumpStudyId );
732 a->setEnabled( activeStudy() );
735 a = action( LoadScriptId );
737 a->setEnabled( activeStudy() );
740 a = action( PropertiesId );
742 a->setEnabled( activeStudy() );
744 // Save GUI state menu
745 a = action( SaveGUIStateId );
747 a->setEnabled( activeStudy() );
749 // update state of Copy/Paste menu items
750 onSelectionChanged();
754 \class DumpStudyFileDlg
755 Private class used in Dump Study operation. Consists 2 check boxes:
756 "Publish in study" and "Save GUI parameters"
758 class DumpStudyFileDlg : public SUIT_FileDlg
761 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
763 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
766 QWidget *hB = new QWidget( this );
767 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
768 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
769 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
771 QHBoxLayout *layout = new QHBoxLayout;
772 layout->addWidget(myPublishChk);
773 layout->addWidget(myMultiFileChk);
774 layout->addWidget(mySaveGUIChk);
775 hB->setLayout(layout);
777 QPushButton* pb = new QPushButton(this);
779 int row = grid->rowCount();
780 grid->addWidget( new QLabel("", this), row, 0 );
781 grid->addWidget( hB, row, 1, 1, 3 );
782 grid->addWidget( pb, row, 5 );
787 QCheckBox* myPublishChk;
788 QCheckBox* myMultiFileChk;
789 QCheckBox* mySaveGUIChk;
792 class DumpStudyFileValidator : public SUIT_FileValidator
795 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
796 virtual ~DumpStudyFileValidator() {};
797 virtual bool canSave( const QString& file, bool permissions );
800 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
802 QFileInfo fi( file );
803 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
804 SUIT_MessageBox::critical( parent(),
805 QObject::tr("WRN_WARNING"),
806 QObject::tr("WRN_FILE_NAME_BAD") );
809 return SUIT_FileValidator::canSave( file, permissions);
812 /*!Private SLOT. On dump study.*/
813 void SalomeApp_Application::onDumpStudy( )
815 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
816 if ( !appStudy ) return;
817 _PTR(Study) aStudy = appStudy->studyDS();
819 QStringList aFilters;
820 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
822 bool anIsPublish = true;
823 bool anIsMultiFile = false;
824 bool anIsSaveGUI = true;
826 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
827 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
828 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
829 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
832 DumpStudyFileDlg fd( desktop() );
833 fd.setValidator( new DumpStudyFileValidator( &fd ) );
834 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
835 fd.setFilters( aFilters );
836 fd.myPublishChk->setChecked( anIsPublish );
837 fd.myMultiFileChk->setChecked( anIsMultiFile );
838 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
839 if ( fd.exec() == QDialog::Accepted )
841 QString aFileName = fd.selectedFile();
843 bool toPublish = fd.myPublishChk->isChecked();
844 bool isMultiFile = fd.myMultiFileChk->isChecked();
845 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
847 if ( !aFileName.isEmpty() ) {
848 QFileInfo aFileInfo(aFileName);
849 if( aFileInfo.isDir() ) // IPAL19257
852 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
855 SUIT_OverrideCursor wc;
856 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
859 SUIT_MessageBox::warning( desktop(),
860 QObject::tr("WRN_WARNING"),
861 tr("WRN_DUMP_STUDY_FAILED") );
866 /*!Private SLOT. On load script.*/
867 void SalomeApp_Application::onLoadScript( )
869 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
870 if ( !appStudy ) return;
871 _PTR(Study) aStudy = appStudy->studyDS();
873 if ( aStudy->GetProperties()->IsLocked() ) {
874 SUIT_MessageBox::warning( desktop(),
875 QObject::tr("WRN_WARNING"),
876 QObject::tr("WRN_STUDY_LOCKED") );
880 QStringList filtersList;
881 filtersList.append(tr("PYTHON_FILES_FILTER"));
882 filtersList.append(tr("ALL_FILES_FILTER"));
884 QString anInitialPath = "";
885 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
886 anInitialPath = QDir::currentPath();
889 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
891 SALOMEDSClient_StudyManager* aMgr = studyMgr();
892 aMgr->GetSimanStudy()->StudyId();
893 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
894 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
895 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
899 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
901 if ( !aFile.isEmpty() )
903 QString command = QString("execfile(r\"%1\")").arg(aFile);
905 PyConsole_Console* pyConsole = pythonConsole();
908 pyConsole->exec( command );
912 /*!Private SLOT. On save GUI state.*/
913 void SalomeApp_Application::onSaveGUIState()
915 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
917 SalomeApp_VisualState( this ).storeState();
918 updateSavePointDataObjects( study );
919 updateObjectBrowser();
924 /*!Public SLOT. On SIMAN check in operation.*/
925 void SalomeApp_Application::onCheckIn()
928 setMenuShown(SimanCheckInId, false); // check in may be performed only once
929 setMenuShown(SimanLocalCheckInId, false);
930 SALOMEDSClient_StudyManager* aMgr = studyMgr();
931 aMgr->GetSimanStudy()->CheckIn("");
933 printf( "****************************************************************\n" );
934 printf( "* Warning: SALOME is built without SIMAN support.\n" );
935 printf( "****************************************************************\n" );
939 /*!Public SLOT. On SIMAN local check in operation.*/
940 void SalomeApp_Application::onLocalCheckIn()
943 // get the active module
944 CAM_Module* aModule = activeModule();
945 if (!aModule) return; // there is no active module
947 setMenuShown(SimanCheckInId, false); // check in may be performed only once
948 setMenuShown(SimanLocalCheckInId, false);
949 SALOMEDSClient_StudyManager* aMgr = studyMgr();
950 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
952 printf( "****************************************************************\n" );
953 printf( "* Warning: SALOME is built without SIMAN support.\n" );
954 printf( "****************************************************************\n" );
959 *\retval QString "(*.hdf)"
961 QString SalomeApp_Application::getFileFilter() const
967 QWidget* SalomeApp_Application::createWindow( const int flag )
970 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
972 SUIT_ResourceMgr* resMgr = resourceMgr();
974 if ( flag == WT_ObjectBrowser )
976 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
978 // temporary commented
979 //ob->setUpdater( new SalomeApp_Updater() );
981 #ifdef WITH_SALOMEDS_OBSERVER
982 //do not activate the automatic update of Qt tree through signal/slot
983 ob->setAutoUpdate(false);
984 //activate update of modified objects only
985 ob->setUpdateModified(true);
988 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
991 ValueCol = QObject::tr( "VALUE_COLUMN" ),
992 IORCol = QObject::tr( "IOR_COLUMN" ),
993 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
994 EntryCol = QObject::tr( "ENTRY_COLUMN" );
996 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
997 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
998 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
999 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1000 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1001 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1002 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1003 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1004 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1006 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1007 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1008 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1010 ob->setAutoSizeFirstColumn(autoSizeFirst);
1011 ob->setAutoSizeColumns(autoSize);
1012 ob->setResizeOnExpandItem(resizeOnExpandItem);
1013 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1015 // temporary commented
1017 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1019 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1020 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1021 QString().sprintf( "visibility_column_%d", i ), true ) );
1025 // temporary commented
1027 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1028 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1029 ob->resize( desktop()->width()/3, ob->height() );
1033 else if ( flag == WT_PyConsole )
1035 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1036 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1037 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1038 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1039 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1041 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1042 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1044 else if ( flag == WT_NoteBook )
1046 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1048 _PTR(Study) aStudy = appStudy->studyDS();
1049 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1050 //to receive signal in NoteBook that it's variable was modified
1051 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1052 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1054 wid = getNoteBook();
1059 /*!Create preferences.*/
1060 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1062 LightApp_Application::createPreferences(pref);
1067 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1068 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1069 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1070 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1072 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1073 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1075 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1077 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1078 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1079 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1080 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1081 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1082 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1083 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1084 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1085 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1086 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1089 /*!Update desktop title.*/
1090 void SalomeApp_Application::updateDesktopTitle() {
1091 QString aTitle = applicationName();
1092 QString aVer = applicationVersion();
1093 if ( !aVer.isEmpty() )
1094 aTitle += QString( " " ) + aVer;
1096 if ( activeStudy() )
1098 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1099 if ( !sName.isEmpty() ) {
1100 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1102 _PTR(Study) stdDS = study->studyDS();
1104 if ( stdDS->GetProperties()->IsLocked() ) {
1105 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1107 aTitle += QString( " - [%1]" ).arg( sName );
1114 desktop()->setWindowTitle( aTitle );
1117 int SalomeApp_Application::closeChoice( const QString& docName )
1119 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1120 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1121 tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
1123 int res = CloseCancel;
1126 else if ( answer == 1 )
1128 else if ( answer == 2 )
1134 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1140 if ( activeStudy()->isSaved() )
1142 else if ( !onSaveAsDoc() )
1148 closePermanently = false;
1158 int SalomeApp_Application::openChoice( const QString& aName )
1160 int choice = LightApp_Application::openChoice( aName );
1162 if ( QFileInfo( aName ).exists() ) {
1163 if ( choice == OpenNew ) { // The document isn't already open.
1165 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1166 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1167 if ( aName == QString( lst[i].c_str() ) )
1170 // The document already exists in the study manager.
1171 // Do you want to reload it?
1173 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1174 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1175 if ( answer == SUIT_MessageBox::Yes )
1176 choice = OpenRefresh;
1178 choice = OpenCancel;
1181 } else { // file is not exist on disk
1182 SUIT_MessageBox::warning( desktop(),
1183 QObject::tr("WRN_WARNING"),
1184 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1191 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1194 int choice = aChoice;
1199 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1202 studyMgr()->Close( aStudy );
1207 res = LightApp_Application::openAction( choice, aName );
1215 \brief Get map of the operations which can be performed
1216 on the module activation.
1218 The method should return the map of the kind \c {<id>:<name>}
1219 where \c <id> is an integer identifier of the operation and
1220 \c <name> is a title for the button to be added to the
1221 dialog box. After user selects the required operation by the
1222 clicking the corresponding button in the dialog box, its identifier
1223 is passed to the moduleActionSelected() method to process
1226 \return map of the operations
1227 \sa moduleActionSelected()
1229 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1231 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1232 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1233 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1238 \brief Called when the used selectes required operation chosen
1239 from "Activate module" dialog box.
1241 Performs the required operation according to the user choice.
1243 \param id operation identifier
1244 \sa activateModuleActions()
1246 void SalomeApp_Application::moduleActionSelected( const int id )
1252 case NewAndScriptId:
1256 LightApp_Application::moduleActionSelected( id );
1261 /*!Gets CORBA::ORB_var*/
1262 CORBA::ORB_var SalomeApp_Application::orb()
1264 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1265 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1269 /*!Create and return SALOMEDS_StudyManager.*/
1270 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1272 static _PTR(StudyManager) _sm;
1273 if(!_sm) _sm = ClientFactory::StudyManager();
1277 /*!Create and return SALOME_NamingService.*/
1278 SALOME_NamingService* SalomeApp_Application::namingService()
1280 static SALOME_NamingService _ns(orb());
1284 /*!Create and return SALOME_LifeCycleCORBA.*/
1285 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1287 static SALOME_LifeCycleCORBA _lcc( namingService() );
1291 /*!Private SLOT. On preferences.*/
1292 void SalomeApp_Application::onProperties()
1294 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1298 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1301 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1302 int res = aDlg.exec();
1303 if( res==QDialog::Accepted && aDlg.isChanged() )
1304 SB->CommitCommand();
1308 //study->updateCaptions();
1309 updateDesktopTitle();
1313 /*!Insert items in popup, which necessary for current application*/
1314 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1316 LightApp_SelectionMgr* mgr = selectionMgr();
1317 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1318 mgr->setSelectionCacheEnabled( true );
1320 LightApp_Application::contextMenuPopup( type, thePopup, title );
1322 // temporary commented
1323 /*OB_Browser* ob = objectBrowser();
1324 if ( !ob || type != ob->popupClientType() )
1327 // Get selected objects
1328 SALOME_ListIO aList;
1329 mgr->selectedObjects( aList, QString(), false );
1331 // add GUI state commands: restore, rename
1332 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1333 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1334 thePopup->addSeparator();
1335 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1336 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1337 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1338 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1341 // "Delete reference" item should appear only for invalid references
1343 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1344 bool isInvalidRefs = false;
1345 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1346 _PTR(Study) aStudyDS = aStudy->studyDS();
1347 _PTR(SObject) anObj;
1349 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1350 if( it.Value()->hasEntry() )
1352 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1353 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1356 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1357 isInvalidRefs = true;
1360 // Add "Delete reference" item to popup
1361 if ( isInvalidRefs )
1363 thePopup->addSeparator();
1364 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1368 // "Activate module" item should appear only if it's necessary
1369 if ( aList.Extent() == 1 ) {
1371 mgr->selectedObjects( aList );
1373 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1375 // add extra popup menu (defined in XML)
1376 if ( myExtActions.size() > 0 ) {
1377 // Use only first selected object
1378 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1380 _PTR(Study) stdDS = study->studyDS();
1382 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1384 _PTR( GenericAttribute ) anAttr;
1385 std::string auid = "AttributeUserID";
1386 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1387 if ( aSO->FindAttribute( anAttr, auid ) ) {
1388 _PTR(AttributeUserID) aAttrID = anAttr;
1389 QString aId = aAttrID->Value().c_str();
1390 if ( myExtActions.contains( aId ) ) {
1391 thePopup->addAction(myExtActions[aId]);
1399 // check if item is a "GUI state" item (also a first level object)
1400 QString entry( aIObj->getEntry() );
1401 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1402 QString aModuleName( aIObj->getComponentDataType() );
1403 QString aModuleTitle = moduleTitle( aModuleName );
1404 CAM_Module* currentModule = activeModule();
1405 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1406 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1410 mgr->setSelectionCacheEnabled( cacheIsOn );
1413 /*!Update obect browser:
1414 1.if 'updateModels' true, update existing data models;
1415 2. update "non-existing" (not loaded yet) data models;
1416 3. update object browser if it exists */
1417 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1419 // update "non-existing" (not loaded yet) data models
1420 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1423 _PTR(Study) stdDS = study->studyDS();
1426 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1428 _PTR(SComponent) aComponent ( it->Value() );
1430 #ifndef WITH_SALOMEDS_OBSERVER
1431 // with GUI observers this check is not needed anymore
1432 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1433 continue; // skip the magic "Interface Applicative" component
1435 if ( !objectBrowser() )
1436 getWindow( WT_ObjectBrowser );
1437 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1438 objectBrowser()->setAutoUpdate( false );
1439 SalomeApp_DataModel::synchronize( aComponent, study );
1440 objectBrowser()->setAutoUpdate( isAutoUpdate );
1445 // create data objects that correspond to GUI state save points
1446 if ( study ) updateSavePointDataObjects( study );
1448 // update existing data models (already loaded SComponents)
1449 LightApp_Application::updateObjectBrowser( updateModels );
1452 /*!Display Catalog Genenerator dialog */
1453 void SalomeApp_Application::onCatalogGen()
1455 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1459 /*!Display Registry Display dialog */
1460 void SalomeApp_Application::onRegDisplay()
1462 CORBA::ORB_var anOrb = orb();
1463 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1466 regWnd->activateWindow();
1469 /*!find original object by double click on item */
1470 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1472 // Issue 21379: References are supported at LightApp_DataObject level
1473 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1475 if( obj && obj->isReference() )
1477 QString entry = obj->refEntry();
1479 SUIT_DataOwnerPtrList aList;
1480 aList.append( new LightApp_DataOwner( entry ) );
1481 selectionMgr()->setSelected( aList, false );
1483 SUIT_DataBrowser* ob = objectBrowser();
1485 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1486 if ( !aSelectedIndexes.isEmpty() )
1487 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1492 Creates new view manager
1493 \param type - type of view manager
1495 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1497 return createViewManager(type);
1501 /*!Global utility funciton, returns selected GUI Save point object's ID */
1502 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1504 SALOME_ListIO aList;
1505 selMgr->selectedObjects( aList );
1506 if( aList.Extent() > 0 ) {
1507 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1508 QString entry( aIObj->getEntry() );
1509 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1510 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1512 bool ok; // conversion to integer is ok?
1513 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1514 return ok ? savePoint : -1;
1519 /*!Called on Restore GUI State popup command*/
1520 void SalomeApp_Application::onRestoreGUIState()
1522 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1523 if ( savePoint == -1 )
1525 SalomeApp_VisualState( this ).restoreState( savePoint );
1528 /*!Called on Delete GUI State popup command*/
1529 void SalomeApp_Application::onDeleteGUIState()
1531 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1532 if ( savePoint == -1 )
1534 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1538 study->removeSavePoint( savePoint );
1539 updateSavePointDataObjects( study );
1542 /*!Called on New study operation*/
1543 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1545 LightApp_Application::onStudyCreated( study );
1547 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1548 windowDock( getWindow( WT_ObjectBrowser ) ) );
1550 loadDockWindowsState();
1552 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1553 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1556 objectBrowserColumnsVisibility();
1559 /*!Called on Save study operation*/
1560 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1562 LightApp_Application::onStudySaved( study );
1564 // temporary commented
1565 /*if ( objectBrowser() ) {
1566 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1567 objectBrowser()->updateTree( study->root() );
1571 /*!Called on Open study operation*/
1572 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1574 LightApp_Application::onStudyOpened( study );
1576 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1577 windowDock( getWindow( WT_ObjectBrowser ) ) );
1579 loadDockWindowsState();
1581 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1582 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1584 objectBrowserColumnsVisibility();
1586 // temporary commented
1587 /*if ( objectBrowser() ) {
1588 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1589 objectBrowser()->updateTree( study->root() );
1593 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1594 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1597 SUIT_DataBrowser* ob = objectBrowser();
1598 LightApp_SelectionMgr* selMgr = selectionMgr();
1600 if ( !study || !ob || !selMgr )
1603 // find GUI states root object
1604 SUIT_DataObject* guiRootObj = 0;
1606 study->root()->children( ch );
1607 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1608 for ( ; it != last ; ++it ) {
1609 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1614 std::vector<int> savePoints = study->getSavePoints();
1615 // case 1: no more save points but they existed in study's tree
1616 if ( savePoints.empty() && guiRootObj ) {
1617 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1618 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1619 const bool isAutoUpdate = ob->autoUpdate();
1620 selMgr->clearSelected();
1621 ob->setAutoUpdate(true);
1622 DataObjectList ch = guiRootObj->children();
1623 for( int i = 0; i < ch.size(); i++ )
1626 ob->setAutoUpdate(isAutoUpdate);
1629 // case 2: no more save points but root does not exist either
1630 if ( savePoints.empty() && !guiRootObj )
1632 // case 3: save points but no root for them - create it
1633 if ( !savePoints.empty() && !guiRootObj )
1634 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1635 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1636 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1638 if ( guiRootObj->nextBrother() ) {
1639 study->root()->removeChild(guiRootObj);
1640 study->root()->appendChild(guiRootObj);
1641 //study->root()->dump();
1644 // store data objects in a map id-to-DataObject
1645 QMap<int,SalomeApp_SavePointObject*> mapDO;
1647 guiRootObj->children( ch );
1648 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1649 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1651 mapDO[dobj->getId()] = dobj;
1654 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1655 // if in the map - remove it from map.
1656 for ( int i = 0; i < savePoints.size(); i++ )
1657 if ( !mapDO.contains( savePoints[i] ) )
1658 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1660 mapDO.remove( savePoints[i] );
1662 // delete DataObjects that are still in the map -- their IDs were not found in data model
1663 if( mapDO.size() > 0) {
1664 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1665 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1666 selMgr->clearSelected();
1667 const bool isAutoUpdate = ob->autoUpdate();
1668 ob->setAutoUpdate(true);
1669 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1671 ob->setAutoUpdate(isAutoUpdate);
1675 /*! Check data object */
1676 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1685 Opens other study into active Study. If Study is empty - creates it.
1686 \param theName - name of study
1688 bool SalomeApp_Application::useStudy( const QString& theName )
1691 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1694 res = aStudy->loadDocument( theName );
1695 updateDesktopTitle();
1696 updateCommandsStatus();
1700 /*! Show/hide object browser colums according to preferences */
1701 void SalomeApp_Application::objectBrowserColumnsVisibility()
1703 if ( objectBrowser() )
1704 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1706 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1707 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1711 /*! Set SalomeApp_NoteBook pointer */
1712 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1714 myNoteBook = theNoteBook;
1717 /*! Return SalomeApp_NoteBook pointer */
1718 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1724 * Define extra actions defined in module definition XML file.
1725 * Additional popup items sections can be defined by parameter "popupitems".
1726 * Supported attributes:
1727 * title - title of menu item,
1728 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1729 * method - method which has to be called when menu item is selected
1731 * <section name="MODULENAME">
1732 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1734 * <section name="importmed">
1735 * <parameter name="title" value="My menu"/>
1736 * <parameter name="objectid" value="VISU.Result"/>
1737 * <parameter name="method" value="nameOfModuleMethod"/>
1740 void SalomeApp_Application::createExtraActions()
1742 myExtActions.clear();
1743 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1745 QStringList aModules;
1746 modules(aModules, false);
1747 foreach(QString aModile, aModules) {
1748 QString aModName = moduleName(aModile);
1749 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1750 if (!aSectionStr.isNull()) {
1751 QStringList aSections = aSectionStr.split(':');
1752 foreach(QString aSection, aSections) {
1753 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1754 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1755 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1756 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1759 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1760 if (aModuleName.isNull())
1761 aModuleName = aModName;
1763 QAction* aAction = new QAction(aTitle, this);
1765 aData<<aModuleName<<aSlot;
1766 aAction->setData(aData);
1767 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1768 myExtActions[aId] = aAction;
1775 * Called when extra action is selected
1777 void SalomeApp_Application::onExtAction()
1779 QAction* aAction = ::qobject_cast<QAction*>(sender());
1783 QVariant aData = aAction->data();
1784 QStringList aDataList = aData.value<QStringList>();
1785 if (aDataList.size() != 2)
1788 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1789 SALOME_ListIO aListIO;
1790 aSelectionMgr->selectedObjects(aListIO);
1791 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1792 if (aListIO.Extent() < 1)
1794 if (!anIO->hasEntry())
1797 QString aEntry(anIO->getEntry());
1799 QApplication::setOverrideCursor( Qt::WaitCursor );
1800 QString aModuleTitle = moduleTitle(aDataList[0]);
1801 activateModule(aModuleTitle);
1802 QApplication::restoreOverrideCursor();
1804 QCoreApplication::processEvents();
1806 CAM_Module* aModule = activeModule();
1810 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1811 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1815 * Called when window activated
1817 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
1819 SUIT_DataBrowser* anOB = objectBrowser();
1822 SUIT_DataObject* rootObj = anOB->root();
1826 DataObjectList listObj = rootObj->children( true );
1828 SUIT_ViewModel* vmod = 0;
1829 if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
1830 vmod = vman->getViewModel();
1831 updateVisibilityState( listObj, vmod );
1835 Update visibility state of given objects
1837 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
1838 SUIT_ViewModel* theViewModel )
1840 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1845 SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
1847 if (theList.isEmpty() || !aView || !aStudy)
1850 for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
1851 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
1853 if (!obj || aStudy->isComponent(obj->entry()))
1856 LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
1857 Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
1860 LightApp_Displayer* aDisplayer = anObjModule->displayer();
1862 if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
1863 if(aDisplayer->IsDisplayed(obj->entry(),aView))
1864 anObjState = Qtx::ShownState;
1866 anObjState = Qtx::HiddenState;
1869 aStudy->setVisibilityState( obj->entry(), anObjState );
1875 Called then view manager removed
1877 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
1879 ViewManagerList lst;
1881 if( lst.count() == 1) { // in case if closed last view window
1882 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1884 aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
1889 Checks that an object can be renamed.
1890 \param entry entry of the object
1891 \brief Return \c true if object can be renamed
1893 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1895 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1899 Rename object by entry.
1900 \param entry entry of the object
1901 \param name new name of the object
1902 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1904 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1906 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1908 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1910 if(!aStudy || savePoint == -1)
1913 if ( !name.isNull() && !name.isEmpty() ) {
1914 aStudy->setNameOfSavePoint( savePoint, name );
1915 updateSavePointDataObjects( aStudy );
1917 //Mark study as modified
1925 \return default windows( Object Browser, Python Console )
1926 Adds to map \a aMap.
1928 void SalomeApp_Application::defaultWindows( QMap<int, int>& aMap ) const
1930 LightApp_Application::defaultWindows(aMap);
1931 if ( !aMap.contains( WT_NoteBook ) ) {
1932 if ( !myNoteBook ) {
1933 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1939 Gets current windows.
1940 \param winMap - output current windows map.
1942 void SalomeApp_Application::currentWindows(QMap<int, int>& aMap) const
1944 LightApp_Application::currentWindows( aMap );
1945 if ( !aMap.contains( WT_NoteBook) && myNoteBook )
1946 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1949 //============================================================================
1950 /*! Function : onUpdateStudy
1951 * Purpose : Slot to update the study.
1953 //============================================================================
1954 void SalomeApp_Application::onUpdateStudy()
1956 QApplication::setOverrideCursor( Qt::WaitCursor );
1958 if( !updateStudy() )
1959 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1961 QApplication::restoreOverrideCursor();
1964 //============================================================================
1965 /*! Function : updateStudy
1966 * Purpose : Update study by dumping the study to Python script and loading it.
1967 * It is used to apply variable modifications done in NoteBook to created objects.
1969 //============================================================================
1970 bool SalomeApp_Application::updateStudy()
1972 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1973 if ( !study || !myNoteBook )
1976 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1977 myNoteBook->setDumpedStudyName( study->studyName() );
1979 _PTR(Study) studyDS = study->studyDS();
1981 // get unique temporary directory name
1982 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1983 if( aTmpDir.isEmpty() )
1986 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1987 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1989 // dump study to the temporary directory
1990 QString aScriptName( "notebook" );
1991 bool toPublish = true;
1992 bool isMultiFile = false;
1993 bool toSaveGUI = true;
1996 _PTR(AttributeParameter) ap;
1997 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1998 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1999 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2000 ip->setDumpPython(studyDS);
2001 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2003 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2005 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2008 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2012 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2013 int anIndex = aList.indexOf( this );
2015 // Disconnect dialog from application desktop in case if:
2016 // 1) Application is not the first application in the session
2017 // 2) Application is the first application in session but not the only.
2018 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2019 if( changeDesktop ) {
2021 SalomeApp_Application* app = this;
2022 if( anIndex > 0 && anIndex < aList.count() )
2023 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2024 else if(anIndex == 0 && aList.count() > 1)
2025 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2030 // creation a new study and restoring will be done in another application
2031 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2032 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2035 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2036 QString aStudyName = myNoteBook->getDumpedStudyName();
2037 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2038 // clear a study (delete all objects)
2039 onCloseDoc( false );
2041 if( !changeDesktop ) {
2042 ok = onRestoreStudy( aDumpScript,
2050 //============================================================================
2051 /*! Function : onRestoreStudy
2052 * Purpose : Load the dumped study from Python script
2054 //============================================================================
2055 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2056 const QString& theStudyName,
2057 bool theIsStudySaved )
2061 // create a new study
2064 // get active application
2065 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2067 // load study from the temporary directory
2068 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2070 PyConsole_Console* pyConsole = app->pythonConsole();
2072 pyConsole->execAndWait( command );
2074 // remove temporary directory
2075 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2076 QString aStudyName = aScriptInfo.baseName();
2077 QDir aDir = aScriptInfo.absoluteDir();
2078 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2079 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2080 ok = aDir.remove( *it ) && ok;
2082 ok = aDir.rmdir( aDir.absolutePath() );
2084 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2086 _PTR(Study) aStudyDS = newStudy->studyDS();
2087 app->getNoteBook()->Init( aStudyDS );
2088 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2089 newStudy->Modified();
2090 updateDesktopTitle();
2100 Close the Application
2102 void SalomeApp_Application::afterCloseDoc()
2104 // emit signal to restore study from Python script
2106 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2107 myNoteBook->getDumpedStudyName(),
2108 myNoteBook->isDumpedStudySaved() );
2110 LightApp_Application::afterCloseDoc();