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 )
491 #ifdef SINGLE_DESKTOP
492 if ( !LightApp_Application::closeDoc() )
496 if ( !activeStudy() ) {
497 // if no study - load in current desktop
498 res = useStudy( aName );
501 // if study exists - load in new desktop. Check: is the same file is loaded?
502 SUIT_Session* aSession = SUIT_Session::session();
503 QList<SUIT_Application*> aAppList = aSession->applications();
504 bool isAlreadyOpen = false;
505 SalomeApp_Application* aApp = 0;
506 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
507 it != aAppList.end() && !isAlreadyOpen; ++it ) {
508 aApp = dynamic_cast<SalomeApp_Application*>( *it );
509 if ( aApp && aApp->activeStudy()->studyName() == aName )
510 isAlreadyOpen = true;
512 if ( !isAlreadyOpen ) {
513 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
515 res = aApp->useStudy( aName );
518 aApp->desktop()->activateWindow();
525 /*!SLOT. Load document with a name, specified in \a aMessage.*/
526 void SalomeApp_Application::onLoadDocMessage(const QString& aMessage)
528 if (aMessage.indexOf("simanCheckoutDone ") == 0) {
530 onLoadDoc(aMessage.section(' ', 1));
532 printf( "****************************************************************\n" );
533 printf( "* Warning: SALOME is built without SIMAN support.\n" );
534 printf( "****************************************************************\n" );
539 /*!SLOT. Copy objects to study maneger from selection maneger..*/
540 void SalomeApp_Application::onCopy()
543 LightApp_SelectionMgr* mgr = selectionMgr();
544 mgr->selectedObjects(list);
546 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
547 if(study == NULL) return;
549 _PTR(Study) stdDS = study->studyDS();
552 SALOME_ListIteratorOfListIO it( list );
555 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
557 studyMgr()->Copy(so);
558 onSelectionChanged();
565 /*!SLOT. Paste objects to study maneger from selection manager.*/
566 void SalomeApp_Application::onPaste()
569 LightApp_SelectionMgr* mgr = selectionMgr();
570 mgr->selectedObjects(list);
572 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
573 if(study == NULL) return;
575 _PTR(Study) stdDS = study->studyDS();
578 if ( stdDS->GetProperties()->IsLocked() ) {
579 SUIT_MessageBox::warning( desktop(),
580 QObject::tr("WRN_WARNING"),
581 QObject::tr("WRN_STUDY_LOCKED") );
585 SALOME_ListIteratorOfListIO it( list );
588 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
590 studyMgr()->Paste(so);
591 updateObjectBrowser( true );
592 updateActions(); //SRN: BugID IPAL9377, case 3
599 /*!Check the application on closing.
600 * \retval true if possible, else false
602 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
604 return LightApp_Application::isPossibleToClose( closePermanently );
607 /*! Check if the study is locked */
608 void SalomeApp_Application::onCloseDoc( bool ask )
610 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
613 _PTR(Study) stdDS = study->studyDS();
614 if(stdDS && stdDS->IsStudyLocked()) {
615 if ( SUIT_MessageBox::question( desktop(),
616 QObject::tr( "WRN_WARNING" ),
617 QObject::tr( "CLOSE_LOCKED_STUDY" ),
618 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
619 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
624 LightApp_Application::onCloseDoc( ask );
627 /*!Sets enable or disable some actions on selection changed.*/
628 void SalomeApp_Application::onSelectionChanged()
631 LightApp_SelectionMgr* mgr = selectionMgr();
632 mgr->selectedObjects(list);
634 bool canCopy = false;
635 bool canPaste = false;
637 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
639 _PTR(Study) stdDS = study->studyDS();
642 SALOME_ListIteratorOfListIO it ( list );
644 if (it.More() && list.Extent() == 1) {
645 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
648 canCopy = studyMgr()->CanCopy(so);
649 canPaste = studyMgr()->CanPaste(so);
655 action(EditCopyId)->setEnabled(canCopy);
656 action(EditPasteId)->setEnabled(canPaste);
659 /*!Delete references.*/
660 void SalomeApp_Application::onDeleteInvalidReferences()
663 LightApp_SelectionMgr* mgr = selectionMgr();
664 mgr->selectedObjects( aList, QString(), false );
666 if( aList.IsEmpty() )
669 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
670 _PTR(Study) aStudyDS = aStudy->studyDS();
671 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
674 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
675 if ( it.Value()->hasEntry() )
677 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
678 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
681 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
682 aStudyBuilder->RemoveReference( aSObject );
684 updateObjectBrowser();
688 void SalomeApp_Application::onOpenWith()
690 QApplication::setOverrideCursor( Qt::WaitCursor );
692 LightApp_SelectionMgr* mgr = selectionMgr();
693 mgr->selectedObjects(aList);
694 if (aList.Extent() != 1)
696 QApplication::restoreOverrideCursor();
699 Handle(SALOME_InteractiveObject) aIObj = aList.First();
700 QString aModuleName(aIObj->getComponentDataType());
701 QString aModuleTitle = moduleTitle(aModuleName);
702 activateModule(aModuleTitle);
703 QApplication::restoreOverrideCursor();
709 SUIT_Study* SalomeApp_Application::createNewStudy()
711 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
713 // Set up processing of major study-related events
714 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
715 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
716 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
717 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
719 //to receive signal in application that NoteBook's variable was modified
720 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
721 this, SIGNAL(notebookVarUpdated(QString)) );
727 Enable/Disable menu items and toolbar buttons. Rebuild menu
729 void SalomeApp_Application::updateCommandsStatus()
731 LightApp_Application::updateCommandsStatus();
734 QAction* a = action( DumpStudyId );
736 a->setEnabled( activeStudy() );
739 a = action( LoadScriptId );
741 a->setEnabled( activeStudy() );
744 a = action( PropertiesId );
746 a->setEnabled( activeStudy() );
748 // Save GUI state menu
749 a = action( SaveGUIStateId );
751 a->setEnabled( activeStudy() );
753 // update state of Copy/Paste menu items
754 onSelectionChanged();
758 \class DumpStudyFileDlg
759 Private class used in Dump Study operation. Consists 2 check boxes:
760 "Publish in study" and "Save GUI parameters"
762 class DumpStudyFileDlg : public SUIT_FileDlg
765 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
767 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
770 QWidget *hB = new QWidget( this );
771 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
772 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
773 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
775 QHBoxLayout *layout = new QHBoxLayout;
776 layout->addWidget(myPublishChk);
777 layout->addWidget(myMultiFileChk);
778 layout->addWidget(mySaveGUIChk);
779 hB->setLayout(layout);
781 QPushButton* pb = new QPushButton(this);
783 int row = grid->rowCount();
784 grid->addWidget( new QLabel("", this), row, 0 );
785 grid->addWidget( hB, row, 1, 1, 3 );
786 grid->addWidget( pb, row, 5 );
791 QCheckBox* myPublishChk;
792 QCheckBox* myMultiFileChk;
793 QCheckBox* mySaveGUIChk;
796 class DumpStudyFileValidator : public SUIT_FileValidator
799 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
800 virtual ~DumpStudyFileValidator() {};
801 virtual bool canSave( const QString& file, bool permissions );
804 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
806 QFileInfo fi( file );
807 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
808 SUIT_MessageBox::critical( parent(),
809 QObject::tr("WRN_WARNING"),
810 QObject::tr("WRN_FILE_NAME_BAD") );
813 return SUIT_FileValidator::canSave( file, permissions);
816 /*!Private SLOT. On dump study.*/
817 void SalomeApp_Application::onDumpStudy( )
819 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
820 if ( !appStudy ) return;
821 _PTR(Study) aStudy = appStudy->studyDS();
823 QStringList aFilters;
824 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
826 bool anIsPublish = true;
827 bool anIsMultiFile = false;
828 bool anIsSaveGUI = true;
830 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
831 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
832 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
833 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
836 DumpStudyFileDlg fd( desktop() );
837 fd.setValidator( new DumpStudyFileValidator( &fd ) );
838 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
839 fd.setFilters( aFilters );
840 fd.myPublishChk->setChecked( anIsPublish );
841 fd.myMultiFileChk->setChecked( anIsMultiFile );
842 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
843 if ( fd.exec() == QDialog::Accepted )
845 QString aFileName = fd.selectedFile();
847 bool toPublish = fd.myPublishChk->isChecked();
848 bool isMultiFile = fd.myMultiFileChk->isChecked();
849 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
851 if ( !aFileName.isEmpty() ) {
852 QFileInfo aFileInfo(aFileName);
853 if( aFileInfo.isDir() ) // IPAL19257
856 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
859 SUIT_OverrideCursor wc;
860 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
863 SUIT_MessageBox::warning( desktop(),
864 QObject::tr("WRN_WARNING"),
865 tr("WRN_DUMP_STUDY_FAILED") );
870 /*!Private SLOT. On load script.*/
871 void SalomeApp_Application::onLoadScript( )
873 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
874 if ( !appStudy ) return;
875 _PTR(Study) aStudy = appStudy->studyDS();
877 if ( aStudy->GetProperties()->IsLocked() ) {
878 SUIT_MessageBox::warning( desktop(),
879 QObject::tr("WRN_WARNING"),
880 QObject::tr("WRN_STUDY_LOCKED") );
884 QStringList filtersList;
885 filtersList.append(tr("PYTHON_FILES_FILTER"));
886 filtersList.append(tr("ALL_FILES_FILTER"));
888 QString anInitialPath = "";
889 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
890 anInitialPath = QDir::currentPath();
893 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
895 SALOMEDSClient_StudyManager* aMgr = studyMgr();
896 aMgr->GetSimanStudy()->StudyId();
897 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
898 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
899 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
903 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
905 if ( !aFile.isEmpty() )
907 QString command = QString("execfile(r\"%1\")").arg(aFile);
909 PyConsole_Console* pyConsole = pythonConsole();
912 pyConsole->exec( command );
916 /*!Private SLOT. On save GUI state.*/
917 void SalomeApp_Application::onSaveGUIState()
919 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
921 SalomeApp_VisualState( this ).storeState();
922 updateSavePointDataObjects( study );
923 updateObjectBrowser();
928 /*!Public SLOT. On SIMAN check in operation.*/
929 void SalomeApp_Application::onCheckIn()
932 setMenuShown(SimanCheckInId, false); // check in may be performed only once
933 setMenuShown(SimanLocalCheckInId, false);
934 SALOMEDSClient_StudyManager* aMgr = studyMgr();
935 aMgr->GetSimanStudy()->CheckIn("");
937 printf( "****************************************************************\n" );
938 printf( "* Warning: SALOME is built without SIMAN support.\n" );
939 printf( "****************************************************************\n" );
943 /*!Public SLOT. On SIMAN local check in operation.*/
944 void SalomeApp_Application::onLocalCheckIn()
947 // get the active module
948 CAM_Module* aModule = activeModule();
949 if (!aModule) return; // there is no active module
951 setMenuShown(SimanCheckInId, false); // check in may be performed only once
952 setMenuShown(SimanLocalCheckInId, false);
953 SALOMEDSClient_StudyManager* aMgr = studyMgr();
954 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
956 printf( "****************************************************************\n" );
957 printf( "* Warning: SALOME is built without SIMAN support.\n" );
958 printf( "****************************************************************\n" );
963 *\retval QString "(*.hdf)"
965 QString SalomeApp_Application::getFileFilter() const
971 QWidget* SalomeApp_Application::createWindow( const int flag )
974 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
976 SUIT_ResourceMgr* resMgr = resourceMgr();
978 if ( flag == WT_ObjectBrowser )
980 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
982 // temporary commented
983 //ob->setUpdater( new SalomeApp_Updater() );
985 #ifdef WITH_SALOMEDS_OBSERVER
986 //do not activate the automatic update of Qt tree through signal/slot
987 ob->setAutoUpdate(false);
988 //activate update of modified objects only
989 ob->setUpdateModified(true);
992 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
995 ValueCol = QObject::tr( "VALUE_COLUMN" ),
996 IORCol = QObject::tr( "IOR_COLUMN" ),
997 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
998 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1000 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1001 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1002 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1003 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1004 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1005 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1006 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1007 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1008 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1010 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1011 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1012 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1014 ob->setAutoSizeFirstColumn(autoSizeFirst);
1015 ob->setAutoSizeColumns(autoSize);
1016 ob->setResizeOnExpandItem(resizeOnExpandItem);
1017 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1019 // temporary commented
1021 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1023 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1024 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1025 QString().sprintf( "visibility_column_%d", i ), true ) );
1029 // temporary commented
1031 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1032 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1033 ob->resize( desktop()->width()/3, ob->height() );
1037 else if ( flag == WT_PyConsole )
1039 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1040 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1041 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1042 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1043 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1045 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1046 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1048 else if ( flag == WT_NoteBook )
1050 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1052 _PTR(Study) aStudy = appStudy->studyDS();
1053 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1054 //to receive signal in NoteBook that it's variable was modified
1055 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1056 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1058 wid = getNoteBook();
1063 /*!Create preferences.*/
1064 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1066 LightApp_Application::createPreferences(pref);
1071 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1072 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1073 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1074 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1076 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1077 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1079 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1081 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1082 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1083 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1084 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1085 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1086 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1087 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1088 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1089 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1090 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1093 /*!Update desktop title.*/
1094 void SalomeApp_Application::updateDesktopTitle() {
1095 QString aTitle = applicationName();
1096 QString aVer = applicationVersion();
1097 if ( !aVer.isEmpty() )
1098 aTitle += QString( " " ) + aVer;
1100 if ( activeStudy() )
1102 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1103 if ( !sName.isEmpty() ) {
1104 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1106 _PTR(Study) stdDS = study->studyDS();
1108 if ( stdDS->GetProperties()->IsLocked() ) {
1109 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1111 aTitle += QString( " - [%1]" ).arg( sName );
1118 desktop()->setWindowTitle( aTitle );
1121 int SalomeApp_Application::closeChoice( const QString& docName )
1123 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1124 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1125 tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
1127 int res = CloseCancel;
1130 else if ( answer == 1 )
1132 else if ( answer == 2 )
1138 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1144 if ( activeStudy()->isSaved() )
1146 else if ( !onSaveAsDoc() )
1152 closePermanently = false;
1162 int SalomeApp_Application::openChoice( const QString& aName )
1164 int choice = LightApp_Application::openChoice( aName );
1166 if ( QFileInfo( aName ).exists() ) {
1167 if ( choice == OpenNew ) { // The document isn't already open.
1169 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1170 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1171 if ( aName == QString( lst[i].c_str() ) )
1174 // The document already exists in the study manager.
1175 // Do you want to reload it?
1177 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1178 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1179 if ( answer == SUIT_MessageBox::Yes )
1180 choice = OpenRefresh;
1182 choice = OpenCancel;
1185 } else { // file is not exist on disk
1186 SUIT_MessageBox::warning( desktop(),
1187 QObject::tr("WRN_WARNING"),
1188 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1195 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1198 int choice = aChoice;
1203 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1206 studyMgr()->Close( aStudy );
1211 res = LightApp_Application::openAction( choice, aName );
1219 \brief Get map of the operations which can be performed
1220 on the module activation.
1222 The method should return the map of the kind \c {<id>:<name>}
1223 where \c <id> is an integer identifier of the operation and
1224 \c <name> is a title for the button to be added to the
1225 dialog box. After user selects the required operation by the
1226 clicking the corresponding button in the dialog box, its identifier
1227 is passed to the moduleActionSelected() method to process
1230 \return map of the operations
1231 \sa moduleActionSelected()
1233 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1235 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1236 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1237 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1242 \brief Called when the used selectes required operation chosen
1243 from "Activate module" dialog box.
1245 Performs the required operation according to the user choice.
1247 \param id operation identifier
1248 \sa activateModuleActions()
1250 void SalomeApp_Application::moduleActionSelected( const int id )
1256 case NewAndScriptId:
1260 LightApp_Application::moduleActionSelected( id );
1265 /*!Gets CORBA::ORB_var*/
1266 CORBA::ORB_var SalomeApp_Application::orb()
1268 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1269 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1273 /*!Create and return SALOMEDS_StudyManager.*/
1274 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1276 static _PTR(StudyManager) _sm;
1277 if(!_sm) _sm = ClientFactory::StudyManager();
1281 /*!Create and return SALOME_NamingService.*/
1282 SALOME_NamingService* SalomeApp_Application::namingService()
1284 static SALOME_NamingService _ns(orb());
1288 /*!Create and return SALOME_LifeCycleCORBA.*/
1289 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1291 static SALOME_LifeCycleCORBA _lcc( namingService() );
1295 /*!Private SLOT. On preferences.*/
1296 void SalomeApp_Application::onProperties()
1298 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1302 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1305 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1306 int res = aDlg.exec();
1307 if( res==QDialog::Accepted && aDlg.isChanged() )
1308 SB->CommitCommand();
1312 //study->updateCaptions();
1313 updateDesktopTitle();
1317 /*!Insert items in popup, which necessary for current application*/
1318 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1320 LightApp_SelectionMgr* mgr = selectionMgr();
1321 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1322 mgr->setSelectionCacheEnabled( true );
1324 LightApp_Application::contextMenuPopup( type, thePopup, title );
1326 // temporary commented
1327 /*OB_Browser* ob = objectBrowser();
1328 if ( !ob || type != ob->popupClientType() )
1331 // Get selected objects
1332 SALOME_ListIO aList;
1333 mgr->selectedObjects( aList, QString(), false );
1335 // add GUI state commands: restore, rename
1336 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1337 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1338 thePopup->addSeparator();
1339 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1340 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1341 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1342 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1345 // "Delete reference" item should appear only for invalid references
1347 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1348 bool isInvalidRefs = false;
1349 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1350 _PTR(Study) aStudyDS = aStudy->studyDS();
1351 _PTR(SObject) anObj;
1353 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1354 if( it.Value()->hasEntry() )
1356 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1357 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1360 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1361 isInvalidRefs = true;
1364 // Add "Delete reference" item to popup
1365 if ( isInvalidRefs )
1367 thePopup->addSeparator();
1368 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1372 // "Activate module" item should appear only if it's necessary
1373 if ( aList.Extent() == 1 ) {
1375 mgr->selectedObjects( aList );
1377 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1379 // add extra popup menu (defined in XML)
1380 if ( myExtActions.size() > 0 ) {
1381 // Use only first selected object
1382 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1384 _PTR(Study) stdDS = study->studyDS();
1386 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1388 _PTR( GenericAttribute ) anAttr;
1389 std::string auid = "AttributeUserID";
1390 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1391 if ( aSO->FindAttribute( anAttr, auid ) ) {
1392 _PTR(AttributeUserID) aAttrID = anAttr;
1393 QString aId = aAttrID->Value().c_str();
1394 if ( myExtActions.contains( aId ) ) {
1395 thePopup->addAction(myExtActions[aId]);
1403 // check if item is a "GUI state" item (also a first level object)
1404 QString entry( aIObj->getEntry() );
1405 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1406 QString aModuleName( aIObj->getComponentDataType() );
1407 QString aModuleTitle = moduleTitle( aModuleName );
1408 CAM_Module* currentModule = activeModule();
1409 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1410 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1414 mgr->setSelectionCacheEnabled( cacheIsOn );
1417 /*!Update obect browser:
1418 1.if 'updateModels' true, update existing data models;
1419 2. update "non-existing" (not loaded yet) data models;
1420 3. update object browser if it exists */
1421 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1423 // update "non-existing" (not loaded yet) data models
1424 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1427 _PTR(Study) stdDS = study->studyDS();
1430 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1432 _PTR(SComponent) aComponent ( it->Value() );
1434 #ifndef WITH_SALOMEDS_OBSERVER
1435 // with GUI observers this check is not needed anymore
1436 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1437 continue; // skip the magic "Interface Applicative" component
1439 if ( !objectBrowser() )
1440 getWindow( WT_ObjectBrowser );
1441 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1442 objectBrowser()->setAutoUpdate( false );
1443 SalomeApp_DataModel::synchronize( aComponent, study );
1444 objectBrowser()->setAutoUpdate( isAutoUpdate );
1449 // create data objects that correspond to GUI state save points
1450 if ( study ) updateSavePointDataObjects( study );
1452 // update existing data models (already loaded SComponents)
1453 LightApp_Application::updateObjectBrowser( updateModels );
1456 /*!Display Catalog Genenerator dialog */
1457 void SalomeApp_Application::onCatalogGen()
1459 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1463 /*!Display Registry Display dialog */
1464 void SalomeApp_Application::onRegDisplay()
1466 CORBA::ORB_var anOrb = orb();
1467 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1470 regWnd->activateWindow();
1473 /*!find original object by double click on item */
1474 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1476 // Issue 21379: References are supported at LightApp_DataObject level
1477 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1479 if( obj && obj->isReference() )
1481 QString entry = obj->refEntry();
1483 SUIT_DataOwnerPtrList aList;
1484 aList.append( new LightApp_DataOwner( entry ) );
1485 selectionMgr()->setSelected( aList, false );
1487 SUIT_DataBrowser* ob = objectBrowser();
1489 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1490 if ( !aSelectedIndexes.isEmpty() )
1491 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1496 Creates new view manager
1497 \param type - type of view manager
1499 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1501 return createViewManager(type);
1505 /*!Global utility funciton, returns selected GUI Save point object's ID */
1506 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1508 SALOME_ListIO aList;
1509 selMgr->selectedObjects( aList );
1510 if( aList.Extent() > 0 ) {
1511 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1512 QString entry( aIObj->getEntry() );
1513 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1514 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1516 bool ok; // conversion to integer is ok?
1517 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1518 return ok ? savePoint : -1;
1523 /*!Called on Restore GUI State popup command*/
1524 void SalomeApp_Application::onRestoreGUIState()
1526 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1527 if ( savePoint == -1 )
1529 SalomeApp_VisualState( this ).restoreState( savePoint );
1532 /*!Called on Delete GUI State popup command*/
1533 void SalomeApp_Application::onDeleteGUIState()
1535 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1536 if ( savePoint == -1 )
1538 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1542 study->removeSavePoint( savePoint );
1543 updateSavePointDataObjects( study );
1546 /*!Called on New study operation*/
1547 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1549 LightApp_Application::onStudyCreated( study );
1551 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1552 windowDock( getWindow( WT_ObjectBrowser ) ) );
1554 loadDockWindowsState();
1556 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1557 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1560 objectBrowserColumnsVisibility();
1563 /*!Called on Save study operation*/
1564 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1566 LightApp_Application::onStudySaved( study );
1568 // temporary commented
1569 /*if ( objectBrowser() ) {
1570 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1571 objectBrowser()->updateTree( study->root() );
1575 /*!Called on Open study operation*/
1576 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1578 LightApp_Application::onStudyOpened( study );
1580 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1581 windowDock( getWindow( WT_ObjectBrowser ) ) );
1583 loadDockWindowsState();
1585 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1586 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1588 objectBrowserColumnsVisibility();
1590 // temporary commented
1591 /*if ( objectBrowser() ) {
1592 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1593 objectBrowser()->updateTree( study->root() );
1597 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1598 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1601 SUIT_DataBrowser* ob = objectBrowser();
1602 LightApp_SelectionMgr* selMgr = selectionMgr();
1604 if ( !study || !ob || !selMgr )
1607 // find GUI states root object
1608 SUIT_DataObject* guiRootObj = 0;
1610 study->root()->children( ch );
1611 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1612 for ( ; it != last ; ++it ) {
1613 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1618 std::vector<int> savePoints = study->getSavePoints();
1619 // case 1: no more save points but they existed in study's tree
1620 if ( savePoints.empty() && guiRootObj ) {
1621 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1622 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1623 const bool isAutoUpdate = ob->autoUpdate();
1624 selMgr->clearSelected();
1625 ob->setAutoUpdate(true);
1626 DataObjectList ch = guiRootObj->children();
1627 for( int i = 0; i < ch.size(); i++ )
1630 ob->setAutoUpdate(isAutoUpdate);
1633 // case 2: no more save points but root does not exist either
1634 if ( savePoints.empty() && !guiRootObj )
1636 // case 3: save points but no root for them - create it
1637 if ( !savePoints.empty() && !guiRootObj )
1638 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1639 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1640 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1642 if ( guiRootObj->nextBrother() ) {
1643 study->root()->removeChild(guiRootObj);
1644 study->root()->appendChild(guiRootObj);
1645 //study->root()->dump();
1648 // store data objects in a map id-to-DataObject
1649 QMap<int,SalomeApp_SavePointObject*> mapDO;
1651 guiRootObj->children( ch );
1652 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1653 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1655 mapDO[dobj->getId()] = dobj;
1658 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1659 // if in the map - remove it from map.
1660 for ( int i = 0; i < savePoints.size(); i++ )
1661 if ( !mapDO.contains( savePoints[i] ) )
1662 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1664 mapDO.remove( savePoints[i] );
1666 // delete DataObjects that are still in the map -- their IDs were not found in data model
1667 if( mapDO.size() > 0) {
1668 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1669 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1670 selMgr->clearSelected();
1671 const bool isAutoUpdate = ob->autoUpdate();
1672 ob->setAutoUpdate(true);
1673 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1675 ob->setAutoUpdate(isAutoUpdate);
1679 /*! Check data object */
1680 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1689 Opens other study into active Study. If Study is empty - creates it.
1690 \param theName - name of study
1692 bool SalomeApp_Application::useStudy( const QString& theName )
1695 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1698 res = aStudy->loadDocument( theName );
1699 updateDesktopTitle();
1700 updateCommandsStatus();
1704 /*! Show/hide object browser colums according to preferences */
1705 void SalomeApp_Application::objectBrowserColumnsVisibility()
1707 if ( objectBrowser() )
1708 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1710 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1711 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1715 /*! Set SalomeApp_NoteBook pointer */
1716 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1718 myNoteBook = theNoteBook;
1721 /*! Return SalomeApp_NoteBook pointer */
1722 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1728 * Define extra actions defined in module definition XML file.
1729 * Additional popup items sections can be defined by parameter "popupitems".
1730 * Supported attributes:
1731 * title - title of menu item,
1732 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1733 * method - method which has to be called when menu item is selected
1735 * <section name="MODULENAME">
1736 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1738 * <section name="importmed">
1739 * <parameter name="title" value="My menu"/>
1740 * <parameter name="objectid" value="VISU.Result"/>
1741 * <parameter name="method" value="nameOfModuleMethod"/>
1744 void SalomeApp_Application::createExtraActions()
1746 myExtActions.clear();
1747 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1749 QStringList aModules;
1750 modules(aModules, false);
1751 foreach(QString aModile, aModules) {
1752 QString aModName = moduleName(aModile);
1753 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1754 if (!aSectionStr.isNull()) {
1755 QStringList aSections = aSectionStr.split(':');
1756 foreach(QString aSection, aSections) {
1757 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1758 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1759 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1760 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1763 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1764 if (aModuleName.isNull())
1765 aModuleName = aModName;
1767 QAction* aAction = new QAction(aTitle, this);
1769 aData<<aModuleName<<aSlot;
1770 aAction->setData(aData);
1771 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1772 myExtActions[aId] = aAction;
1779 * Called when extra action is selected
1781 void SalomeApp_Application::onExtAction()
1783 QAction* aAction = ::qobject_cast<QAction*>(sender());
1787 QVariant aData = aAction->data();
1788 QStringList aDataList = aData.value<QStringList>();
1789 if (aDataList.size() != 2)
1792 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1793 SALOME_ListIO aListIO;
1794 aSelectionMgr->selectedObjects(aListIO);
1795 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1796 if (aListIO.Extent() < 1)
1798 if (!anIO->hasEntry())
1801 QString aEntry(anIO->getEntry());
1803 QApplication::setOverrideCursor( Qt::WaitCursor );
1804 QString aModuleTitle = moduleTitle(aDataList[0]);
1805 activateModule(aModuleTitle);
1806 QApplication::restoreOverrideCursor();
1808 QCoreApplication::processEvents();
1810 CAM_Module* aModule = activeModule();
1814 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1815 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1819 * Called when window activated
1821 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
1823 SUIT_DataBrowser* anOB = objectBrowser();
1826 SUIT_DataObject* rootObj = anOB->root();
1830 DataObjectList listObj = rootObj->children( true );
1832 SUIT_ViewModel* vmod = 0;
1833 if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
1834 vmod = vman->getViewModel();
1835 updateVisibilityState( listObj, vmod );
1839 Update visibility state of given objects
1841 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
1842 SUIT_ViewModel* theViewModel )
1844 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1849 SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
1851 if (theList.isEmpty() || !aView || !aStudy)
1854 for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
1855 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
1857 if (!obj || aStudy->isComponent(obj->entry()))
1860 LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
1861 Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
1864 LightApp_Displayer* aDisplayer = anObjModule->displayer();
1866 if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
1867 if(aDisplayer->IsDisplayed(obj->entry(),aView))
1868 anObjState = Qtx::ShownState;
1870 anObjState = Qtx::HiddenState;
1873 aStudy->setVisibilityState( obj->entry(), anObjState );
1879 Called then view manager removed
1881 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
1883 ViewManagerList lst;
1885 if( lst.count() == 1) { // in case if closed last view window
1886 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1888 aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
1893 Checks that an object can be renamed.
1894 \param entry entry of the object
1895 \brief Return \c true if object can be renamed
1897 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1899 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1903 Rename object by entry.
1904 \param entry entry of the object
1905 \param name new name of the object
1906 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1908 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1910 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1912 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1914 if(!aStudy || savePoint == -1)
1917 if ( !name.isNull() && !name.isEmpty() ) {
1918 aStudy->setNameOfSavePoint( savePoint, name );
1919 updateSavePointDataObjects( aStudy );
1921 //Mark study as modified
1929 \return default windows( Object Browser, Python Console )
1930 Adds to map \a aMap.
1932 void SalomeApp_Application::defaultWindows( QMap<int, int>& aMap ) const
1934 LightApp_Application::defaultWindows(aMap);
1935 if ( !aMap.contains( WT_NoteBook ) ) {
1936 if ( !myNoteBook ) {
1937 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1943 Gets current windows.
1944 \param winMap - output current windows map.
1946 void SalomeApp_Application::currentWindows(QMap<int, int>& aMap) const
1948 LightApp_Application::currentWindows( aMap );
1949 if ( !aMap.contains( WT_NoteBook) && myNoteBook )
1950 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1953 //============================================================================
1954 /*! Function : onUpdateStudy
1955 * Purpose : Slot to update the study.
1957 //============================================================================
1958 void SalomeApp_Application::onUpdateStudy()
1960 QApplication::setOverrideCursor( Qt::WaitCursor );
1962 if( !updateStudy() )
1963 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1965 QApplication::restoreOverrideCursor();
1968 //============================================================================
1969 /*! Function : updateStudy
1970 * Purpose : Update study by dumping the study to Python script and loading it.
1971 * It is used to apply variable modifications done in NoteBook to created objects.
1973 //============================================================================
1974 bool SalomeApp_Application::updateStudy()
1976 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1977 if ( !study || !myNoteBook )
1980 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1981 myNoteBook->setDumpedStudyName( study->studyName() );
1983 _PTR(Study) studyDS = study->studyDS();
1985 // get unique temporary directory name
1986 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1987 if( aTmpDir.isEmpty() )
1990 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1991 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1993 // dump study to the temporary directory
1994 QString aScriptName( "notebook" );
1995 bool toPublish = true;
1996 bool isMultiFile = false;
1997 bool toSaveGUI = true;
2000 _PTR(AttributeParameter) ap;
2001 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2002 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2003 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2004 ip->setDumpPython(studyDS);
2005 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2007 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2009 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2012 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2016 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2017 int anIndex = aList.indexOf( this );
2019 // Disconnect dialog from application desktop in case if:
2020 // 1) Application is not the first application in the session
2021 // 2) Application is the first application in session but not the only.
2022 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2023 if( changeDesktop ) {
2025 SalomeApp_Application* app = this;
2026 if( anIndex > 0 && anIndex < aList.count() )
2027 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2028 else if(anIndex == 0 && aList.count() > 1)
2029 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2034 // creation a new study and restoring will be done in another application
2035 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2036 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2039 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2040 QString aStudyName = myNoteBook->getDumpedStudyName();
2041 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2042 // clear a study (delete all objects)
2043 onCloseDoc( false );
2045 if( !changeDesktop ) {
2046 ok = onRestoreStudy( aDumpScript,
2054 //============================================================================
2055 /*! Function : onRestoreStudy
2056 * Purpose : Load the dumped study from Python script
2058 //============================================================================
2059 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2060 const QString& theStudyName,
2061 bool theIsStudySaved )
2065 // create a new study
2068 // get active application
2069 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2071 // load study from the temporary directory
2072 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2074 PyConsole_Console* pyConsole = app->pythonConsole();
2076 pyConsole->execAndWait( command );
2078 // remove temporary directory
2079 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2080 QString aStudyName = aScriptInfo.baseName();
2081 QDir aDir = aScriptInfo.absoluteDir();
2082 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2083 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2084 ok = aDir.remove( *it ) && ok;
2086 ok = aDir.rmdir( aDir.absolutePath() );
2088 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2090 _PTR(Study) aStudyDS = newStudy->studyDS();
2091 app->getNoteBook()->Init( aStudyDS );
2092 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2093 newStudy->Modified();
2094 updateDesktopTitle();
2104 Close the Application
2106 void SalomeApp_Application::afterCloseDoc()
2108 // emit signal to restore study from Python script
2110 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2111 myNoteBook->getDumpedStudyName(),
2112 myNoteBook->isDumpedStudySaved() );
2114 LightApp_Application::afterCloseDoc();