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
372 PyGILState_STATE gstate = PyGILState_Ensure();
373 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
374 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());
377 PyGILState_Release(gstate);
378 // end of SALOME plugins loading
384 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
386 LightApp_Application::setDesktop( desk );
389 connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
390 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
391 connect( desk, SIGNAL( message( const QString& ) ),
392 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
397 \brief Close application.
399 void SalomeApp_Application::onExit()
401 bool killServers = false;
404 if ( exitConfirmation() ) {
405 SalomeApp_ExitDlg dlg( desktop() );
406 result = dlg.exec() == QDialog::Accepted;
407 killServers = dlg.isServersShutdown();
411 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
414 /*!SLOT. Load document.*/
415 void SalomeApp_Application::onLoadDoc()
419 std::vector<std::string> List = studyMgr()->GetOpenStudies();
421 SUIT_Session* aSession = SUIT_Session::session();
422 QList<SUIT_Application*> aAppList = aSession->applications();
424 QStringList unloadedStudies;
426 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
427 studyName = List[ind].c_str();
428 // Add to list only unloaded studies
429 bool isAlreadyOpen = false;
430 QListIterator<SUIT_Application*> it( aAppList );
431 while ( it.hasNext() && !isAlreadyOpen ) {
432 SUIT_Application* aApp = it.next();
433 if( !aApp || !aApp->activeStudy() )
435 if ( aApp->activeStudy()->studyName() == studyName )
436 isAlreadyOpen = true;
439 if ( !isAlreadyOpen )
440 unloadedStudies << studyName;
443 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
444 if ( studyName.isEmpty() )
448 // this code replaces marker of windows drive and path become invalid therefore
449 // defines placed there
450 studyName.replace( QRegExp(":"), "/" );
453 if ( onLoadDoc( studyName ) ) {
455 updateViewManagers();
456 updateObjectBrowser( true );
460 /*!SLOT. Create new study and load script*/
461 void SalomeApp_Application::onNewWithScript()
463 QStringList filtersList;
464 filtersList.append(tr("PYTHON_FILES_FILTER"));
465 filtersList.append(tr("ALL_FILES_FILTER"));
467 QString anInitialPath = "";
468 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
469 anInitialPath = QDir::currentPath();
471 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
473 if ( !aFile.isEmpty() )
477 QString command = QString("execfile(r\"%1\")").arg(aFile);
479 PyConsole_Console* pyConsole = pythonConsole();
482 pyConsole->exec( command );
487 /*!SLOT. Load document with \a aName.*/
488 bool SalomeApp_Application::onLoadDoc( const QString& aName )
491 if ( !activeStudy() ) {
492 // if no study - load in current desktop
493 res = useStudy( aName );
496 // if study exists - load in new desktop. Check: is the same file is loaded?
497 SUIT_Session* aSession = SUIT_Session::session();
498 QList<SUIT_Application*> aAppList = aSession->applications();
499 bool isAlreadyOpen = false;
500 SalomeApp_Application* aApp = 0;
501 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
502 it != aAppList.end() && !isAlreadyOpen; ++it ) {
503 aApp = dynamic_cast<SalomeApp_Application*>( *it );
504 if ( aApp && aApp->activeStudy()->studyName() == aName )
505 isAlreadyOpen = true;
507 if ( !isAlreadyOpen ) {
508 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
510 res = aApp->useStudy( aName );
513 aApp->desktop()->activateWindow();
520 /*!SLOT. Load document with a name, specified in \a aMessage.*/
521 void SalomeApp_Application::onLoadDocMessage(const QString& aMessage)
523 if (aMessage.indexOf("simanCheckoutDone ") == 0) {
525 onLoadDoc(aMessage.section(' ', 1));
527 printf( "****************************************************************\n" );
528 printf( "* Warning: SALOME is built without SIMAN support.\n" );
529 printf( "****************************************************************\n" );
534 /*!SLOT. Copy objects to study maneger from selection maneger..*/
535 void SalomeApp_Application::onCopy()
538 LightApp_SelectionMgr* mgr = selectionMgr();
539 mgr->selectedObjects(list);
541 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
542 if(study == NULL) return;
544 _PTR(Study) stdDS = study->studyDS();
547 SALOME_ListIteratorOfListIO it( list );
550 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
552 studyMgr()->Copy(so);
553 onSelectionChanged();
560 /*!SLOT. Paste objects to study maneger from selection manager.*/
561 void SalomeApp_Application::onPaste()
564 LightApp_SelectionMgr* mgr = selectionMgr();
565 mgr->selectedObjects(list);
567 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
568 if(study == NULL) return;
570 _PTR(Study) stdDS = study->studyDS();
573 if ( stdDS->GetProperties()->IsLocked() ) {
574 SUIT_MessageBox::warning( desktop(),
575 QObject::tr("WRN_WARNING"),
576 QObject::tr("WRN_STUDY_LOCKED") );
580 SALOME_ListIteratorOfListIO it( list );
583 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
585 studyMgr()->Paste(so);
586 updateObjectBrowser( true );
587 updateActions(); //SRN: BugID IPAL9377, case 3
594 /*!Check the application on closing.
595 * \retval true if possible, else false
597 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
599 return LightApp_Application::isPossibleToClose( closePermanently );
602 /*! Check if the study is locked */
603 void SalomeApp_Application::onCloseDoc( bool ask )
605 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
608 _PTR(Study) stdDS = study->studyDS();
609 if(stdDS && stdDS->IsStudyLocked()) {
610 if ( SUIT_MessageBox::question( desktop(),
611 QObject::tr( "WRN_WARNING" ),
612 QObject::tr( "CLOSE_LOCKED_STUDY" ),
613 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
614 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
619 LightApp_Application::onCloseDoc( ask );
622 /*!Sets enable or disable some actions on selection changed.*/
623 void SalomeApp_Application::onSelectionChanged()
626 LightApp_SelectionMgr* mgr = selectionMgr();
627 mgr->selectedObjects(list);
629 bool canCopy = false;
630 bool canPaste = false;
632 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
634 _PTR(Study) stdDS = study->studyDS();
637 SALOME_ListIteratorOfListIO it ( list );
639 if (it.More() && list.Extent() == 1) {
640 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
643 canCopy = studyMgr()->CanCopy(so);
644 canPaste = studyMgr()->CanPaste(so);
650 action(EditCopyId)->setEnabled(canCopy);
651 action(EditPasteId)->setEnabled(canPaste);
654 /*!Delete references.*/
655 void SalomeApp_Application::onDeleteInvalidReferences()
658 LightApp_SelectionMgr* mgr = selectionMgr();
659 mgr->selectedObjects( aList, QString(), false );
661 if( aList.IsEmpty() )
664 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
665 _PTR(Study) aStudyDS = aStudy->studyDS();
666 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
669 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
670 if ( it.Value()->hasEntry() )
672 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
673 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
676 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
677 aStudyBuilder->RemoveReference( aSObject );
679 updateObjectBrowser();
683 void SalomeApp_Application::onOpenWith()
685 QApplication::setOverrideCursor( Qt::WaitCursor );
687 LightApp_SelectionMgr* mgr = selectionMgr();
688 mgr->selectedObjects(aList);
689 if (aList.Extent() != 1)
691 QApplication::restoreOverrideCursor();
694 Handle(SALOME_InteractiveObject) aIObj = aList.First();
695 QString aModuleName(aIObj->getComponentDataType());
696 QString aModuleTitle = moduleTitle(aModuleName);
697 activateModule(aModuleTitle);
698 QApplication::restoreOverrideCursor();
704 SUIT_Study* SalomeApp_Application::createNewStudy()
706 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
708 // Set up processing of major study-related events
709 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
710 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
711 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
712 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
714 //to receive signal in application that NoteBook's variable was modified
715 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
716 this, SIGNAL(notebookVarUpdated(QString)) );
722 Enable/Disable menu items and toolbar buttons. Rebuild menu
724 void SalomeApp_Application::updateCommandsStatus()
726 LightApp_Application::updateCommandsStatus();
729 QAction* a = action( DumpStudyId );
731 a->setEnabled( activeStudy() );
734 a = action( LoadScriptId );
736 a->setEnabled( activeStudy() );
739 a = action( PropertiesId );
741 a->setEnabled( activeStudy() );
743 // Save GUI state menu
744 a = action( SaveGUIStateId );
746 a->setEnabled( activeStudy() );
748 // update state of Copy/Paste menu items
749 onSelectionChanged();
753 \class DumpStudyFileDlg
754 Private class used in Dump Study operation. Consists 2 check boxes:
755 "Publish in study" and "Save GUI parameters"
757 class DumpStudyFileDlg : public SUIT_FileDlg
760 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
762 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
765 QWidget *hB = new QWidget( this );
766 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
767 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
768 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
770 QHBoxLayout *layout = new QHBoxLayout;
771 layout->addWidget(myPublishChk);
772 layout->addWidget(myMultiFileChk);
773 layout->addWidget(mySaveGUIChk);
774 hB->setLayout(layout);
776 QPushButton* pb = new QPushButton(this);
778 int row = grid->rowCount();
779 grid->addWidget( new QLabel("", this), row, 0 );
780 grid->addWidget( hB, row, 1, 1, 3 );
781 grid->addWidget( pb, row, 5 );
786 QCheckBox* myPublishChk;
787 QCheckBox* myMultiFileChk;
788 QCheckBox* mySaveGUIChk;
791 class DumpStudyFileValidator : public SUIT_FileValidator
794 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
795 virtual ~DumpStudyFileValidator() {};
796 virtual bool canSave( const QString& file, bool permissions );
799 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
801 QFileInfo fi( file );
802 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
803 SUIT_MessageBox::critical( parent(),
804 QObject::tr("WRN_WARNING"),
805 QObject::tr("WRN_FILE_NAME_BAD") );
808 return SUIT_FileValidator::canSave( file, permissions);
811 /*!Private SLOT. On dump study.*/
812 void SalomeApp_Application::onDumpStudy( )
814 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
815 if ( !appStudy ) return;
816 _PTR(Study) aStudy = appStudy->studyDS();
818 QStringList aFilters;
819 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
821 bool anIsPublish = true;
822 bool anIsMultiFile = false;
823 bool anIsSaveGUI = true;
825 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
826 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
827 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
828 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
831 DumpStudyFileDlg fd( desktop() );
832 fd.setValidator( new DumpStudyFileValidator( &fd ) );
833 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
834 fd.setFilters( aFilters );
835 fd.myPublishChk->setChecked( anIsPublish );
836 fd.myMultiFileChk->setChecked( anIsMultiFile );
837 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
838 if ( fd.exec() == QDialog::Accepted )
840 QString aFileName = fd.selectedFile();
842 bool toPublish = fd.myPublishChk->isChecked();
843 bool isMultiFile = fd.myMultiFileChk->isChecked();
844 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
846 if ( !aFileName.isEmpty() ) {
847 QFileInfo aFileInfo(aFileName);
848 if( aFileInfo.isDir() ) // IPAL19257
851 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
854 SUIT_OverrideCursor wc;
855 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
858 SUIT_MessageBox::warning( desktop(),
859 QObject::tr("WRN_WARNING"),
860 tr("WRN_DUMP_STUDY_FAILED") );
865 /*!Private SLOT. On load script.*/
866 void SalomeApp_Application::onLoadScript( )
868 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
869 if ( !appStudy ) return;
870 _PTR(Study) aStudy = appStudy->studyDS();
872 if ( aStudy->GetProperties()->IsLocked() ) {
873 SUIT_MessageBox::warning( desktop(),
874 QObject::tr("WRN_WARNING"),
875 QObject::tr("WRN_STUDY_LOCKED") );
879 QStringList filtersList;
880 filtersList.append(tr("PYTHON_FILES_FILTER"));
881 filtersList.append(tr("ALL_FILES_FILTER"));
883 QString anInitialPath = "";
884 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
885 anInitialPath = QDir::currentPath();
888 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
890 SALOMEDSClient_StudyManager* aMgr = studyMgr();
891 aMgr->GetSimanStudy()->StudyId();
892 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
893 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
894 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
898 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
900 if ( !aFile.isEmpty() )
902 QString command = QString("execfile(r\"%1\")").arg(aFile);
904 PyConsole_Console* pyConsole = pythonConsole();
907 pyConsole->exec( command );
911 /*!Private SLOT. On save GUI state.*/
912 void SalomeApp_Application::onSaveGUIState()
914 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
916 SalomeApp_VisualState( this ).storeState();
917 updateSavePointDataObjects( study );
918 updateObjectBrowser();
923 /*!Public SLOT. On SIMAN check in operation.*/
924 void SalomeApp_Application::onCheckIn()
927 setMenuShown(SimanCheckInId, false); // check in may be performed only once
928 setMenuShown(SimanLocalCheckInId, false);
929 SALOMEDSClient_StudyManager* aMgr = studyMgr();
930 aMgr->GetSimanStudy()->CheckIn("");
932 printf( "****************************************************************\n" );
933 printf( "* Warning: SALOME is built without SIMAN support.\n" );
934 printf( "****************************************************************\n" );
938 /*!Public SLOT. On SIMAN local check in operation.*/
939 void SalomeApp_Application::onLocalCheckIn()
942 // get the active module
943 CAM_Module* aModule = activeModule();
944 if (!aModule) return; // there is no active module
946 setMenuShown(SimanCheckInId, false); // check in may be performed only once
947 setMenuShown(SimanLocalCheckInId, false);
948 SALOMEDSClient_StudyManager* aMgr = studyMgr();
949 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
951 printf( "****************************************************************\n" );
952 printf( "* Warning: SALOME is built without SIMAN support.\n" );
953 printf( "****************************************************************\n" );
958 *\retval QString "(*.hdf)"
960 QString SalomeApp_Application::getFileFilter() const
966 QWidget* SalomeApp_Application::createWindow( const int flag )
969 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
971 SUIT_ResourceMgr* resMgr = resourceMgr();
973 if ( flag == WT_ObjectBrowser )
975 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
977 // temporary commented
978 //ob->setUpdater( new SalomeApp_Updater() );
980 #ifdef WITH_SALOMEDS_OBSERVER
981 //do not activate the automatic update of Qt tree through signal/slot
982 ob->setAutoUpdate(false);
983 //activate update of modified objects only
984 ob->setUpdateModified(true);
987 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
990 ValueCol = QObject::tr( "VALUE_COLUMN" ),
991 IORCol = QObject::tr( "IOR_COLUMN" ),
992 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
993 EntryCol = QObject::tr( "ENTRY_COLUMN" );
995 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
996 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
997 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
998 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
999 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1000 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1001 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1002 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1003 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1005 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1006 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1007 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1009 ob->setAutoSizeFirstColumn(autoSizeFirst);
1010 ob->setAutoSizeColumns(autoSize);
1011 ob->setResizeOnExpandItem(resizeOnExpandItem);
1012 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1014 // temporary commented
1016 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1018 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1019 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1020 QString().sprintf( "visibility_column_%d", i ), true ) );
1024 // temporary commented
1026 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1027 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1028 ob->resize( desktop()->width()/3, ob->height() );
1032 else if ( flag == WT_PyConsole )
1034 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1035 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1036 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1037 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1038 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1040 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1041 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1043 else if ( flag == WT_NoteBook )
1045 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1047 _PTR(Study) aStudy = appStudy->studyDS();
1048 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1049 //to receive signal in NoteBook that it's variable was modified
1050 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1051 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1053 wid = getNoteBook();
1058 /*!Create preferences.*/
1059 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1061 LightApp_Application::createPreferences(pref);
1066 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1067 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1068 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1069 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1071 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1072 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1074 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1076 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1077 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1078 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1079 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1080 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1081 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1082 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1083 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1084 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1085 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1088 /*!Update desktop title.*/
1089 void SalomeApp_Application::updateDesktopTitle() {
1090 QString aTitle = applicationName();
1091 QString aVer = applicationVersion();
1092 if ( !aVer.isEmpty() )
1093 aTitle += QString( " " ) + aVer;
1095 if ( activeStudy() )
1097 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1098 if ( !sName.isEmpty() ) {
1099 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1101 _PTR(Study) stdDS = study->studyDS();
1103 if ( stdDS->GetProperties()->IsLocked() ) {
1104 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1106 aTitle += QString( " - [%1]" ).arg( sName );
1113 desktop()->setWindowTitle( aTitle );
1116 int SalomeApp_Application::closeChoice( const QString& docName )
1118 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1119 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1120 tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
1122 int res = CloseCancel;
1125 else if ( answer == 1 )
1127 else if ( answer == 2 )
1133 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1139 if ( activeStudy()->isSaved() )
1141 else if ( !onSaveAsDoc() )
1147 closePermanently = false;
1157 int SalomeApp_Application::openChoice( const QString& aName )
1159 int choice = LightApp_Application::openChoice( aName );
1161 if ( QFileInfo( aName ).exists() ) {
1162 if ( choice == OpenNew ) { // The document isn't already open.
1164 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1165 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1166 if ( aName == QString( lst[i].c_str() ) )
1169 // The document already exists in the study manager.
1170 // Do you want to reload it?
1172 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1173 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1174 if ( answer == SUIT_MessageBox::Yes )
1175 choice = OpenRefresh;
1177 choice = OpenCancel;
1180 } else { // file is not exist on disk
1181 SUIT_MessageBox::warning( desktop(),
1182 QObject::tr("WRN_WARNING"),
1183 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1190 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1193 int choice = aChoice;
1198 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1201 studyMgr()->Close( aStudy );
1206 res = LightApp_Application::openAction( choice, aName );
1214 \brief Get map of the operations which can be performed
1215 on the module activation.
1217 The method should return the map of the kind \c {<id>:<name>}
1218 where \c <id> is an integer identifier of the operation and
1219 \c <name> is a title for the button to be added to the
1220 dialog box. After user selects the required operation by the
1221 clicking the corresponding button in the dialog box, its identifier
1222 is passed to the moduleActionSelected() method to process
1225 \return map of the operations
1226 \sa moduleActionSelected()
1228 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1230 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1231 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1232 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1237 \brief Called when the used selectes required operation chosen
1238 from "Activate module" dialog box.
1240 Performs the required operation according to the user choice.
1242 \param id operation identifier
1243 \sa activateModuleActions()
1245 void SalomeApp_Application::moduleActionSelected( const int id )
1251 case NewAndScriptId:
1255 LightApp_Application::moduleActionSelected( id );
1260 /*!Gets CORBA::ORB_var*/
1261 CORBA::ORB_var SalomeApp_Application::orb()
1263 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1264 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1268 /*!Create and return SALOMEDS_StudyManager.*/
1269 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1271 static _PTR(StudyManager) _sm;
1272 if(!_sm) _sm = ClientFactory::StudyManager();
1276 /*!Create and return SALOME_NamingService.*/
1277 SALOME_NamingService* SalomeApp_Application::namingService()
1279 static SALOME_NamingService _ns(orb());
1283 /*!Create and return SALOME_LifeCycleCORBA.*/
1284 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1286 static SALOME_LifeCycleCORBA _lcc( namingService() );
1290 /*!Private SLOT. On preferences.*/
1291 void SalomeApp_Application::onProperties()
1293 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1297 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1300 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1301 int res = aDlg.exec();
1302 if( res==QDialog::Accepted && aDlg.isChanged() )
1303 SB->CommitCommand();
1307 //study->updateCaptions();
1308 updateDesktopTitle();
1312 /*!Insert items in popup, which necessary for current application*/
1313 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1315 LightApp_SelectionMgr* mgr = selectionMgr();
1316 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1317 mgr->setSelectionCacheEnabled( true );
1319 LightApp_Application::contextMenuPopup( type, thePopup, title );
1321 // temporary commented
1322 /*OB_Browser* ob = objectBrowser();
1323 if ( !ob || type != ob->popupClientType() )
1326 // Get selected objects
1327 SALOME_ListIO aList;
1328 mgr->selectedObjects( aList, QString(), false );
1330 // add GUI state commands: restore, rename
1331 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1332 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1333 thePopup->addSeparator();
1334 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1335 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1336 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1337 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1340 // "Delete reference" item should appear only for invalid references
1342 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1343 bool isInvalidRefs = false;
1344 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1345 _PTR(Study) aStudyDS = aStudy->studyDS();
1346 _PTR(SObject) anObj;
1348 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1349 if( it.Value()->hasEntry() )
1351 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1352 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1355 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1356 isInvalidRefs = true;
1359 // Add "Delete reference" item to popup
1360 if ( isInvalidRefs )
1362 thePopup->addSeparator();
1363 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1367 // "Activate module" item should appear only if it's necessary
1368 if ( aList.Extent() == 1 ) {
1370 mgr->selectedObjects( aList );
1372 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1374 // add extra popup menu (defined in XML)
1375 if ( myExtActions.size() > 0 ) {
1376 // Use only first selected object
1377 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1379 _PTR(Study) stdDS = study->studyDS();
1381 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1383 _PTR( GenericAttribute ) anAttr;
1384 std::string auid = "AttributeUserID";
1385 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1386 if ( aSO->FindAttribute( anAttr, auid ) ) {
1387 _PTR(AttributeUserID) aAttrID = anAttr;
1388 QString aId = aAttrID->Value().c_str();
1389 if ( myExtActions.contains( aId ) ) {
1390 thePopup->addAction(myExtActions[aId]);
1398 // check if item is a "GUI state" item (also a first level object)
1399 QString entry( aIObj->getEntry() );
1400 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1401 QString aModuleName( aIObj->getComponentDataType() );
1402 QString aModuleTitle = moduleTitle( aModuleName );
1403 CAM_Module* currentModule = activeModule();
1404 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1405 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1409 mgr->setSelectionCacheEnabled( cacheIsOn );
1412 /*!Update obect browser:
1413 1.if 'updateModels' true, update existing data models;
1414 2. update "non-existing" (not loaded yet) data models;
1415 3. update object browser if it exists */
1416 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1418 // update "non-existing" (not loaded yet) data models
1419 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1422 _PTR(Study) stdDS = study->studyDS();
1425 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1427 _PTR(SComponent) aComponent ( it->Value() );
1429 #ifndef WITH_SALOMEDS_OBSERVER
1430 // with GUI observers this check is not needed anymore
1431 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1432 continue; // skip the magic "Interface Applicative" component
1434 if ( !objectBrowser() )
1435 getWindow( WT_ObjectBrowser );
1436 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1437 objectBrowser()->setAutoUpdate( false );
1438 SalomeApp_DataModel::synchronize( aComponent, study );
1439 objectBrowser()->setAutoUpdate( isAutoUpdate );
1444 // create data objects that correspond to GUI state save points
1445 if ( study ) updateSavePointDataObjects( study );
1447 // update existing data models (already loaded SComponents)
1448 LightApp_Application::updateObjectBrowser( updateModels );
1451 /*!Display Catalog Genenerator dialog */
1452 void SalomeApp_Application::onCatalogGen()
1454 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1458 /*!Display Registry Display dialog */
1459 void SalomeApp_Application::onRegDisplay()
1461 CORBA::ORB_var anOrb = orb();
1462 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1465 regWnd->activateWindow();
1468 /*!find original object by double click on item */
1469 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1471 // Issue 21379: References are supported at LightApp_DataObject level
1472 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1474 if( obj && obj->isReference() )
1476 QString entry = obj->refEntry();
1478 SUIT_DataOwnerPtrList aList;
1479 aList.append( new LightApp_DataOwner( entry ) );
1480 selectionMgr()->setSelected( aList, false );
1482 SUIT_DataBrowser* ob = objectBrowser();
1484 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1485 if ( !aSelectedIndexes.isEmpty() )
1486 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1491 Creates new view manager
1492 \param type - type of view manager
1494 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1496 return createViewManager(type);
1500 /*!Global utility funciton, returns selected GUI Save point object's ID */
1501 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1503 SALOME_ListIO aList;
1504 selMgr->selectedObjects( aList );
1505 if( aList.Extent() > 0 ) {
1506 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1507 QString entry( aIObj->getEntry() );
1508 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1509 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1511 bool ok; // conversion to integer is ok?
1512 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1513 return ok ? savePoint : -1;
1518 /*!Called on Restore GUI State popup command*/
1519 void SalomeApp_Application::onRestoreGUIState()
1521 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1522 if ( savePoint == -1 )
1524 SalomeApp_VisualState( this ).restoreState( savePoint );
1527 /*!Called on Delete GUI State popup command*/
1528 void SalomeApp_Application::onDeleteGUIState()
1530 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1531 if ( savePoint == -1 )
1533 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1537 study->removeSavePoint( savePoint );
1538 updateSavePointDataObjects( study );
1541 /*!Called on New study operation*/
1542 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1544 LightApp_Application::onStudyCreated( study );
1546 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1547 windowDock( getWindow( WT_ObjectBrowser ) ) );
1549 loadDockWindowsState();
1551 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1552 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1555 objectBrowserColumnsVisibility();
1558 /*!Called on Save study operation*/
1559 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1561 LightApp_Application::onStudySaved( study );
1563 // temporary commented
1564 /*if ( objectBrowser() ) {
1565 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1566 objectBrowser()->updateTree( study->root() );
1570 /*!Called on Open study operation*/
1571 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1573 LightApp_Application::onStudyOpened( study );
1575 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1576 windowDock( getWindow( WT_ObjectBrowser ) ) );
1578 loadDockWindowsState();
1580 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1581 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1583 objectBrowserColumnsVisibility();
1585 // temporary commented
1586 /*if ( objectBrowser() ) {
1587 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1588 objectBrowser()->updateTree( study->root() );
1592 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1593 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1596 SUIT_DataBrowser* ob = objectBrowser();
1597 LightApp_SelectionMgr* selMgr = selectionMgr();
1599 if ( !study || !ob || !selMgr )
1602 // find GUI states root object
1603 SUIT_DataObject* guiRootObj = 0;
1605 study->root()->children( ch );
1606 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1607 for ( ; it != last ; ++it ) {
1608 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1613 std::vector<int> savePoints = study->getSavePoints();
1614 // case 1: no more save points but they existed in study's tree
1615 if ( savePoints.empty() && guiRootObj ) {
1616 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1617 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1618 const bool isAutoUpdate = ob->autoUpdate();
1619 selMgr->clearSelected();
1620 ob->setAutoUpdate(true);
1621 DataObjectList ch = guiRootObj->children();
1622 for( int i = 0; i < ch.size(); i++ )
1625 ob->setAutoUpdate(isAutoUpdate);
1628 // case 2: no more save points but root does not exist either
1629 if ( savePoints.empty() && !guiRootObj )
1631 // case 3: save points but no root for them - create it
1632 if ( !savePoints.empty() && !guiRootObj )
1633 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1634 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1635 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1637 if ( guiRootObj->nextBrother() ) {
1638 study->root()->removeChild(guiRootObj);
1639 study->root()->appendChild(guiRootObj);
1640 //study->root()->dump();
1643 // store data objects in a map id-to-DataObject
1644 QMap<int,SalomeApp_SavePointObject*> mapDO;
1646 guiRootObj->children( ch );
1647 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1648 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1650 mapDO[dobj->getId()] = dobj;
1653 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1654 // if in the map - remove it from map.
1655 for ( int i = 0; i < savePoints.size(); i++ )
1656 if ( !mapDO.contains( savePoints[i] ) )
1657 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1659 mapDO.remove( savePoints[i] );
1661 // delete DataObjects that are still in the map -- their IDs were not found in data model
1662 if( mapDO.size() > 0) {
1663 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1664 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1665 selMgr->clearSelected();
1666 const bool isAutoUpdate = ob->autoUpdate();
1667 ob->setAutoUpdate(true);
1668 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1670 ob->setAutoUpdate(isAutoUpdate);
1674 /*! Check data object */
1675 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1684 Opens other study into active Study. If Study is empty - creates it.
1685 \param theName - name of study
1687 bool SalomeApp_Application::useStudy( const QString& theName )
1690 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1693 res = aStudy->loadDocument( theName );
1694 updateDesktopTitle();
1695 updateCommandsStatus();
1699 /*! Show/hide object browser colums according to preferences */
1700 void SalomeApp_Application::objectBrowserColumnsVisibility()
1702 if ( objectBrowser() )
1703 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1705 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1706 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1710 /*! Set SalomeApp_NoteBook pointer */
1711 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1713 myNoteBook = theNoteBook;
1716 /*! Return SalomeApp_NoteBook pointer */
1717 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1723 * Define extra actions defined in module definition XML file.
1724 * Additional popup items sections can be defined by parameter "popupitems".
1725 * Supported attributes:
1726 * title - title of menu item,
1727 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1728 * method - method which has to be called when menu item is selected
1730 * <section name="MODULENAME">
1731 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1733 * <section name="importmed">
1734 * <parameter name="title" value="My menu"/>
1735 * <parameter name="objectid" value="VISU.Result"/>
1736 * <parameter name="method" value="nameOfModuleMethod"/>
1739 void SalomeApp_Application::createExtraActions()
1741 myExtActions.clear();
1742 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1744 QStringList aModules;
1745 modules(aModules, false);
1746 foreach(QString aModile, aModules) {
1747 QString aModName = moduleName(aModile);
1748 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1749 if (!aSectionStr.isNull()) {
1750 QStringList aSections = aSectionStr.split(':');
1751 foreach(QString aSection, aSections) {
1752 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1753 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1754 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1755 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1758 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1759 if (aModuleName.isNull())
1760 aModuleName = aModName;
1762 QAction* aAction = new QAction(aTitle, this);
1764 aData<<aModuleName<<aSlot;
1765 aAction->setData(aData);
1766 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1767 myExtActions[aId] = aAction;
1774 * Called when extra action is selected
1776 void SalomeApp_Application::onExtAction()
1778 QAction* aAction = ::qobject_cast<QAction*>(sender());
1782 QVariant aData = aAction->data();
1783 QStringList aDataList = aData.value<QStringList>();
1784 if (aDataList.size() != 2)
1787 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1788 SALOME_ListIO aListIO;
1789 aSelectionMgr->selectedObjects(aListIO);
1790 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1791 if (aListIO.Extent() < 1)
1793 if (!anIO->hasEntry())
1796 QString aEntry(anIO->getEntry());
1798 QApplication::setOverrideCursor( Qt::WaitCursor );
1799 QString aModuleTitle = moduleTitle(aDataList[0]);
1800 activateModule(aModuleTitle);
1801 QApplication::restoreOverrideCursor();
1803 QCoreApplication::processEvents();
1805 CAM_Module* aModule = activeModule();
1809 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1810 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1814 * Called when window activated
1816 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
1818 SUIT_DataBrowser* anOB = objectBrowser();
1821 SUIT_DataObject* rootObj = anOB->root();
1825 DataObjectList listObj = rootObj->children( true );
1827 SUIT_ViewModel* vmod = 0;
1828 if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
1829 vmod = vman->getViewModel();
1830 updateVisibilityState( listObj, vmod );
1834 Update visibility state of given objects
1836 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
1837 SUIT_ViewModel* theViewModel )
1839 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1844 SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
1846 if (theList.isEmpty() || !aView || !aStudy)
1849 for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
1850 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
1852 if (!obj || aStudy->isComponent(obj->entry()))
1855 LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
1856 Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
1859 LightApp_Displayer* aDisplayer = anObjModule->displayer();
1861 if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
1862 if(aDisplayer->IsDisplayed(obj->entry(),aView))
1863 anObjState = Qtx::ShownState;
1865 anObjState = Qtx::HiddenState;
1868 aStudy->setVisibilityState( obj->entry(), anObjState );
1874 Called then view manager removed
1876 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
1878 ViewManagerList lst;
1880 if( lst.count() == 1) { // in case if closed last view window
1881 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1883 aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
1888 Checks that an object can be renamed.
1889 \param entry entry of the object
1890 \brief Return \c true if object can be renamed
1892 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1894 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1898 Rename object by entry.
1899 \param entry entry of the object
1900 \param name new name of the object
1901 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1903 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1905 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1907 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1909 if(!aStudy || savePoint == -1)
1912 if ( !name.isNull() && !name.isEmpty() ) {
1913 aStudy->setNameOfSavePoint( savePoint, name );
1914 updateSavePointDataObjects( aStudy );
1916 //Mark study as modified
1924 \return default windows( Object Browser, Python Console )
1925 Adds to map \a aMap.
1927 void SalomeApp_Application::defaultWindows( QMap<int, int>& aMap ) const
1929 LightApp_Application::defaultWindows(aMap);
1930 if ( !aMap.contains( WT_NoteBook ) ) {
1931 if ( !myNoteBook ) {
1932 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1938 Gets current windows.
1939 \param winMap - output current windows map.
1941 void SalomeApp_Application::currentWindows(QMap<int, int>& aMap) const
1943 LightApp_Application::currentWindows( aMap );
1944 if ( !aMap.contains( WT_NoteBook) && myNoteBook )
1945 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1948 //============================================================================
1949 /*! Function : onUpdateStudy
1950 * Purpose : Slot to update the study.
1952 //============================================================================
1953 void SalomeApp_Application::onUpdateStudy()
1955 QApplication::setOverrideCursor( Qt::WaitCursor );
1957 if( !updateStudy() )
1958 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1960 QApplication::restoreOverrideCursor();
1963 //============================================================================
1964 /*! Function : updateStudy
1965 * Purpose : Update study by dumping the study to Python script and loading it.
1966 * It is used to apply variable modifications done in NoteBook to created objects.
1968 //============================================================================
1969 bool SalomeApp_Application::updateStudy()
1971 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1972 if ( !study || !myNoteBook )
1975 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1976 myNoteBook->setDumpedStudyName( study->studyName() );
1978 _PTR(Study) studyDS = study->studyDS();
1980 // get unique temporary directory name
1981 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1982 if( aTmpDir.isEmpty() )
1985 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1986 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1988 // dump study to the temporary directory
1989 QString aScriptName( "notebook" );
1990 bool toPublish = true;
1991 bool isMultiFile = false;
1992 bool toSaveGUI = true;
1995 _PTR(AttributeParameter) ap;
1996 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1997 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1998 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1999 ip->setDumpPython(studyDS);
2000 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2002 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2004 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2007 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2011 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2012 int anIndex = aList.indexOf( this );
2014 // Disconnect dialog from application desktop in case if:
2015 // 1) Application is not the first application in the session
2016 // 2) Application is the first application in session but not the only.
2017 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2018 if( changeDesktop ) {
2020 SalomeApp_Application* app = this;
2021 if( anIndex > 0 && anIndex < aList.count() )
2022 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2023 else if(anIndex == 0 && aList.count() > 1)
2024 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2029 // creation a new study and restoring will be done in another application
2030 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2031 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2034 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2035 QString aStudyName = myNoteBook->getDumpedStudyName();
2036 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2037 // clear a study (delete all objects)
2038 onCloseDoc( false );
2040 if( !changeDesktop ) {
2041 ok = onRestoreStudy( aDumpScript,
2049 //============================================================================
2050 /*! Function : onRestoreStudy
2051 * Purpose : Load the dumped study from Python script
2053 //============================================================================
2054 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2055 const QString& theStudyName,
2056 bool theIsStudySaved )
2060 // create a new study
2063 // get active application
2064 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2066 // load study from the temporary directory
2067 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2069 PyConsole_Console* pyConsole = app->pythonConsole();
2071 pyConsole->execAndWait( command );
2073 // remove temporary directory
2074 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2075 QString aStudyName = aScriptInfo.baseName();
2076 QDir aDir = aScriptInfo.absoluteDir();
2077 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2078 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2079 ok = aDir.remove( *it ) && ok;
2081 ok = aDir.rmdir( aDir.absolutePath() );
2083 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2085 _PTR(Study) aStudyDS = newStudy->studyDS();
2086 app->getNoteBook()->Init( aStudyDS );
2087 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2088 newStudy->Modified();
2089 updateDesktopTitle();
2099 Close the Application
2101 void SalomeApp_Application::afterCloseDoc()
2103 // emit signal to restore study from Python script
2105 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2106 myNoteBook->getDumpedStudyName(),
2107 myNoteBook->isDumpedStudySaved() );
2109 LightApp_Application::afterCloseDoc();