1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: SalomeApp_Application.cxx
24 // Created: 10/22/2004 3:23:45 PM
25 // Author: Sergey LITONIN
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
32 #ifndef DISABLE_PYCONSOLE
37 #ifndef DISABLE_PYCONSOLE
38 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
39 #include <PyConsole_Console.h>
40 #include "SalomeApp_NoteBook.h"
42 #include "SalomeApp_Application.h"
43 #include "SalomeApp_Study.h"
44 #include "SalomeApp_DataModel.h"
45 #include "SalomeApp_DataObject.h"
46 #include "SalomeApp_VisualState.h"
47 #include "SalomeApp_StudyPropertiesDlg.h"
48 #include "SalomeApp_LoadStudiesDlg.h"
49 #include "SalomeApp_ExitDlg.h"
51 #include <LightApp_Application.h>
52 #include <LightApp_Module.h>
53 #include <LightApp_Preferences.h>
54 #include <LightApp_SelectionMgr.h>
55 #include <LightApp_NameDlg.h>
56 #include <LightApp_DataOwner.h>
57 #include <LightApp_Displayer.h>
59 #include <CAM_Module.h>
61 #include <SUIT_Tools.h>
62 #include <SUIT_Session.h>
63 #include <SUIT_Desktop.h>
64 #include <SUIT_DataBrowser.h>
65 #include <SUIT_FileDlg.h>
66 #include <SUIT_FileValidator.h>
67 #include <SUIT_MessageBox.h>
68 #include <SUIT_ResourceMgr.h>
69 #include <SUIT_TreeModel.h>
70 #include <SUIT_ViewWindow.h>
71 #include <SUIT_ViewManager.h>
72 #include <SUIT_ViewModel.h>
73 #include <SUIT_OverrideCursor.h>
75 #include <QtxTreeView.h>
77 #include <SALOME_EventFilter.h>
79 // temporary commented
80 //#include <OB_ListItem.h>
83 #include <Utils_ORB_INIT.hxx>
84 #include <Utils_SINGLETON.hxx>
85 #include <SALOME_LifeCycleCORBA.hxx>
87 #include <QApplication>
91 #include <QPushButton>
93 #include <QListWidget>
94 #include <QGridLayout>
98 #include <SALOMEDSClient_ClientFactory.hxx>
99 #include <Basics_Utils.hxx>
101 #include <SALOME_ListIO.hxx>
102 #include <SALOME_ListIteratorOfListIO.hxx>
103 #include <SALOME_Prs.h>
106 #include <ToolsGUI_CatalogGeneratorDlg.h>
107 #include <ToolsGUI_RegWidget.h>
111 #include <SALOMEDS_Tool.hxx>
113 /*!Internal class that updates object browser item properties */
114 // temporary commented
115 /*class SalomeApp_Updater : public OB_Updater
118 SalomeApp_Updater() : OB_Updater(){};
119 virtual ~SalomeApp_Updater(){};
120 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
123 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
125 if( !theObj || !theItem )
128 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
132 _PTR(SObject) SObj = SAObj->object();
135 _PTR( GenericAttribute ) anAttr;
138 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
140 _PTR(AttributeSelectable) aAttrSel = anAttr;
141 theItem->setSelectable( aAttrSel->IsSelectable() );
144 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
146 _PTR(AttributeExpandable) aAttrExpand = anAttr;
147 theItem->setExpandable( aAttrExpand->IsExpandable() );
150 //this attribute is not supported in the version of SALOME 3.x
151 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
153 // _PTR(AttributeOpened) aAttrOpen = anAttr;
154 // theItem->setOpen( aAttrOpen->IsOpened() );
158 /*!Create new instance of SalomeApp_Application.*/
159 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
161 return new SalomeApp_Application();
165 SalomeApp_Application::SalomeApp_Application()
166 : LightApp_Application()
168 connect( desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
169 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
170 connect( desktop(), SIGNAL( message( const QString& ) ),
171 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
172 myIsSiman = false; // default
176 *\li Destroy event filter.
178 SalomeApp_Application::~SalomeApp_Application()
180 // Do not destroy. It's a singleton !
181 //SALOME_EventFilter::Destroy();
184 /*!Start application.*/
185 void SalomeApp_Application::start()
187 // process the command line options before start: to createActions in accordance to the options
188 static bool isFirst = true;
196 for (int i = 1; i < qApp->argc(); i++) {
197 QRegExp rxs ("--study-hdf=(.+)");
198 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
199 QString file = rxs.capturedTexts()[1];
200 QFileInfo fi ( file );
201 QString extension = fi.suffix().toLower();
202 if ( extension == "hdf" && fi.exists() )
203 hdffile = fi.absoluteFilePath();
206 QRegExp rxp ("--pyscript=\\[(.+)\\]");
207 QRegExp rxl ("--siman-study=(.+)");
208 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
210 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
211 for (int k = 0; k < dictList.count(); ++k) {
212 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
213 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
214 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
215 pyfiles += rxd.capturedTexts()[m];
221 if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
223 loadStudy = rxl.capturedTexts()[1];
229 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
230 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
232 LightApp_Application::start();
233 SALOME_EventFilter::Init();
235 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
236 onOpenDoc( hdffile );
237 else if ( pyfiles.count() > 0 ) // create new study
239 else if (!loadStudy.isEmpty()) {// load study by name
240 if (onLoadDoc(loadStudy))
241 updateObjectBrowser(true);
244 #ifndef DISABLE_PYCONSOLE
245 // import/execute python scripts
246 if ( pyfiles.count() > 0 && activeStudy() ) {
247 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
248 PyConsole_Console* pyConsole = pythonConsole();
249 if ( appStudy && pyConsole ) {
250 _PTR(Study) aStudy = appStudy->studyDS();
251 if ( !aStudy->GetProperties()->IsLocked() ) {
252 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
253 // Path is absolute, script has .py extension
254 for (uint j = 0; j < pyfiles.count(); j++ ) {
255 // Extract scripts and their arguments, if any
256 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
257 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
258 QString script = rxp.capturedTexts()[1];
260 QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
261 for (uint k = 0; k < argList.count(); k++ ) {
262 QString arg = argList[k].trimmed();
263 arg.remove( QRegExp("^[\"]") );
264 arg.remove( QRegExp("[\"]$") );
267 args.remove( QRegExp("[,]$") );
268 if (!args.isEmpty()) {
272 script.remove( QRegExp("^python.*[\\s]+") );
273 QString cmd = script+" "+args;
274 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
275 pyConsole->exec(command);
277 } // end for loop on pyfiles QStringList
283 LightApp_Application::start();
284 SALOME_EventFilter::Init();
289 void SalomeApp_Application::createActions()
291 LightApp_Application::createActions();
293 SUIT_Desktop* desk = desktop();
296 // "Save GUI State" command is moved to VISU module
297 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
298 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
299 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
302 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
303 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
304 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
307 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
308 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
309 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
312 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
313 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
314 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
316 //! Catalog Generator
317 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
318 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
319 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
322 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
323 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
324 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
326 //SRN: BugID IPAL9021, add an action "Load"
327 createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
328 resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
329 tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
330 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
331 //SRN: BugID IPAL9021: End
335 // check-in operations for SIMAN study
336 createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
337 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
338 0, desk, false, this, SLOT( onCheckIn() ) );
339 createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
340 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
341 0, desk, false, this, SLOT( onLocalCheckIn() ) );
345 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
347 // "Save GUI State" command is renamed to "Save VISU State" and
348 // creation of menu item is moved to VISU
349 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
351 createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load"
355 // check-in operation for SIMAN study
356 // last argument "5" locates this just after "Save As" but certain constant is bad => insert after the separator
357 createMenu( SimanCheckInId, fileMenu, 5);
358 createMenu( SimanLocalCheckInId, fileMenu, 5);
359 createMenu( separator(), fileMenu, 5 );
362 createMenu( DumpStudyId, fileMenu, 10, -1 );
363 createMenu( separator(), fileMenu, -1, 10, -1 );
364 createMenu( LoadScriptId, fileMenu, 10, -1 );
365 createMenu( separator(), fileMenu, -1, 10, -1 );
366 createMenu( PropertiesId, fileMenu, 10, -1 );
367 createMenu( separator(), fileMenu, -1, 10, -1 );
369 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
370 createMenu( CatalogGenId, toolsMenu, 10, -1 );
371 createMenu( RegDisplayId, toolsMenu, 10, -1 );
372 createMenu( separator(), toolsMenu, -1, 15, -1 );
374 createExtraActions();
376 #ifndef DISABLE_PYCONSOLE
377 #ifndef DISABLE_SALOMEOBJECT
378 // import Python module that manages SALOME plugins
380 PyLockWrapper lck; // acquire GIL
381 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
382 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());
386 // end of SALOME plugins loading
394 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
396 LightApp_Application::setDesktop( desk );
399 connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
400 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
401 connect( desk, SIGNAL( message( const QString& ) ),
402 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
407 \brief Close application.
409 void SalomeApp_Application::onExit()
411 bool killServers = false;
414 if ( exitConfirmation() ) {
415 SalomeApp_ExitDlg dlg( desktop() );
416 result = dlg.exec() == QDialog::Accepted;
417 killServers = dlg.isServersShutdown();
421 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
424 /*!SLOT. Load document.*/
425 void SalomeApp_Application::onLoadDoc()
429 std::vector<std::string> List = studyMgr()->GetOpenStudies();
431 SUIT_Session* aSession = SUIT_Session::session();
432 QList<SUIT_Application*> aAppList = aSession->applications();
434 QStringList unloadedStudies;
436 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
437 studyName = List[ind].c_str();
438 // Add to list only unloaded studies
439 bool isAlreadyOpen = false;
440 QListIterator<SUIT_Application*> it( aAppList );
441 while ( it.hasNext() && !isAlreadyOpen ) {
442 SUIT_Application* aApp = it.next();
443 if( !aApp || !aApp->activeStudy() )
445 if ( aApp->activeStudy()->studyName() == studyName )
446 isAlreadyOpen = true;
449 if ( !isAlreadyOpen )
450 unloadedStudies << studyName;
453 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
454 if ( studyName.isEmpty() )
458 // this code replaces marker of windows drive and path become invalid therefore
459 // defines placed there
460 studyName.replace( QRegExp(":"), "/" );
463 if ( onLoadDoc( studyName ) ) {
465 updateViewManagers();
466 updateObjectBrowser( true );
470 /*!SLOT. Create new study and load script*/
471 void SalomeApp_Application::onNewWithScript()
473 QStringList filtersList;
474 filtersList.append(tr("PYTHON_FILES_FILTER"));
475 filtersList.append(tr("ALL_FILES_FILTER"));
477 QString anInitialPath = "";
478 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
479 anInitialPath = QDir::currentPath();
481 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
483 if ( !aFile.isEmpty() )
487 QString command = QString("execfile(r\"%1\")").arg(aFile);
489 #ifndef DISABLE_PYCONSOLE
490 PyConsole_Console* pyConsole = pythonConsole();
493 pyConsole->exec( command );
499 /*!SLOT. Load document with \a aName.*/
500 bool SalomeApp_Application::onLoadDoc( const QString& aName )
502 #ifdef SINGLE_DESKTOP
503 if ( !LightApp_Application::closeDoc() )
507 if ( !activeStudy() ) {
508 // if no study - load in current desktop
509 res = useStudy( aName );
512 // if study exists - load in new desktop. Check: is the same file is loaded?
513 SUIT_Session* aSession = SUIT_Session::session();
514 QList<SUIT_Application*> aAppList = aSession->applications();
515 bool isAlreadyOpen = false;
516 SalomeApp_Application* aApp = 0;
517 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
518 it != aAppList.end() && !isAlreadyOpen; ++it ) {
519 aApp = dynamic_cast<SalomeApp_Application*>( *it );
520 if ( aApp && aApp->activeStudy()->studyName() == aName )
521 isAlreadyOpen = true;
523 if ( !isAlreadyOpen ) {
524 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
526 res = aApp->useStudy( aName );
529 aApp->desktop()->activateWindow();
536 /*!SLOT. Load document with a name, specified in \a aMessage.*/
537 void SalomeApp_Application::onLoadDocMessage(const QString& aMessage)
539 if (aMessage.indexOf("simanCheckoutDone ") == 0) {
541 onLoadDoc(aMessage.section(' ', 1));
543 printf( "****************************************************************\n" );
544 printf( "* Warning: SALOME is built without SIMAN support.\n" );
545 printf( "****************************************************************\n" );
550 /*!SLOT. Copy objects to study maneger from selection maneger..*/
551 void SalomeApp_Application::onCopy()
554 LightApp_SelectionMgr* mgr = selectionMgr();
555 mgr->selectedObjects(list);
557 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
558 if(study == NULL) return;
560 _PTR(Study) stdDS = study->studyDS();
563 SALOME_ListIteratorOfListIO it( list );
566 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
568 studyMgr()->Copy(so);
569 onSelectionChanged();
576 /*!SLOT. Paste objects to study maneger from selection manager.*/
577 void SalomeApp_Application::onPaste()
580 LightApp_SelectionMgr* mgr = selectionMgr();
581 mgr->selectedObjects(list);
583 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
584 if(study == NULL) return;
586 _PTR(Study) stdDS = study->studyDS();
589 if ( stdDS->GetProperties()->IsLocked() ) {
590 SUIT_MessageBox::warning( desktop(),
591 QObject::tr("WRN_WARNING"),
592 QObject::tr("WRN_STUDY_LOCKED") );
596 SALOME_ListIteratorOfListIO it( list );
599 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
601 studyMgr()->Paste(so);
602 updateObjectBrowser( true );
603 updateActions(); //SRN: BugID IPAL9377, case 3
610 /*!Check the application on closing.
611 * \retval true if possible, else false
613 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
615 return LightApp_Application::isPossibleToClose( closePermanently );
618 /*! Check if the study is locked */
619 void SalomeApp_Application::onCloseDoc( bool ask )
621 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
624 _PTR(Study) stdDS = study->studyDS();
625 if(stdDS && stdDS->IsStudyLocked()) {
626 if ( SUIT_MessageBox::question( desktop(),
627 QObject::tr( "WRN_WARNING" ),
628 QObject::tr( "CLOSE_LOCKED_STUDY" ),
629 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
630 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
635 LightApp_Application::onCloseDoc( ask );
638 /*!Sets enable or disable some actions on selection changed.*/
639 void SalomeApp_Application::onSelectionChanged()
642 LightApp_SelectionMgr* mgr = selectionMgr();
643 mgr->selectedObjects(list);
645 bool canCopy = false;
646 bool canPaste = false;
648 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
650 _PTR(Study) stdDS = study->studyDS();
653 SALOME_ListIteratorOfListIO it ( list );
655 if (it.More() && list.Extent() == 1) {
656 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
659 canCopy = studyMgr()->CanCopy(so);
660 canPaste = studyMgr()->CanPaste(so);
666 action(EditCopyId)->setEnabled(canCopy);
667 action(EditPasteId)->setEnabled(canPaste);
670 /*!Delete references.*/
671 void SalomeApp_Application::onDeleteInvalidReferences()
674 LightApp_SelectionMgr* mgr = selectionMgr();
675 mgr->selectedObjects( aList, QString(), false );
677 if( aList.IsEmpty() )
680 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
681 _PTR(Study) aStudyDS = aStudy->studyDS();
682 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
685 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
686 if ( it.Value()->hasEntry() )
688 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
689 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
692 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
693 aStudyBuilder->RemoveReference( aSObject );
695 updateObjectBrowser();
699 void SalomeApp_Application::onOpenWith()
701 QApplication::setOverrideCursor( Qt::WaitCursor );
703 LightApp_SelectionMgr* mgr = selectionMgr();
704 mgr->selectedObjects(aList);
705 if (aList.Extent() != 1)
707 QApplication::restoreOverrideCursor();
710 Handle(SALOME_InteractiveObject) aIObj = aList.First();
711 QString aModuleName(aIObj->getComponentDataType());
712 QString aModuleTitle = moduleTitle(aModuleName);
713 activateModule(aModuleTitle);
714 QApplication::restoreOverrideCursor();
720 SUIT_Study* SalomeApp_Application::createNewStudy()
722 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
724 // Set up processing of major study-related events
725 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
726 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
727 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
728 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
730 #ifndef DISABLE_PYCONSOLE
731 //to receive signal in application that NoteBook's variable was modified
732 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
733 this, SIGNAL(notebookVarUpdated(QString)) );
740 Enable/Disable menu items and toolbar buttons. Rebuild menu
742 void SalomeApp_Application::updateCommandsStatus()
744 LightApp_Application::updateCommandsStatus();
747 QAction* a = action( DumpStudyId );
749 a->setEnabled( activeStudy() );
752 a = action( LoadScriptId );
754 a->setEnabled( activeStudy() );
757 a = action( PropertiesId );
759 a->setEnabled( activeStudy() );
761 // Save GUI state menu
762 a = action( SaveGUIStateId );
764 a->setEnabled( activeStudy() );
766 // update state of Copy/Paste menu items
767 onSelectionChanged();
771 \class DumpStudyFileDlg
772 Private class used in Dump Study operation. Consists 2 check boxes:
773 "Publish in study" and "Save GUI parameters"
775 class DumpStudyFileDlg : public SUIT_FileDlg
778 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
780 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
783 QWidget *hB = new QWidget( this );
784 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
785 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
786 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
788 QHBoxLayout *layout = new QHBoxLayout;
789 layout->addWidget(myPublishChk);
790 layout->addWidget(myMultiFileChk);
791 layout->addWidget(mySaveGUIChk);
792 hB->setLayout(layout);
794 QPushButton* pb = new QPushButton(this);
796 int row = grid->rowCount();
797 grid->addWidget( new QLabel("", this), row, 0 );
798 grid->addWidget( hB, row, 1, 1, 3 );
799 grid->addWidget( pb, row, 5 );
804 QCheckBox* myPublishChk;
805 QCheckBox* myMultiFileChk;
806 QCheckBox* mySaveGUIChk;
809 class DumpStudyFileValidator : public SUIT_FileValidator
812 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
813 virtual ~DumpStudyFileValidator() {};
814 virtual bool canSave( const QString& file, bool permissions );
817 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
819 QFileInfo fi( file );
820 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
821 SUIT_MessageBox::critical( parent(),
822 QObject::tr("WRN_WARNING"),
823 QObject::tr("WRN_FILE_NAME_BAD") );
826 return SUIT_FileValidator::canSave( file, permissions);
829 /*!Private SLOT. On dump study.*/
830 void SalomeApp_Application::onDumpStudy( )
832 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
833 if ( !appStudy ) return;
834 _PTR(Study) aStudy = appStudy->studyDS();
836 QStringList aFilters;
837 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
839 bool anIsPublish = true;
840 bool anIsMultiFile = false;
841 bool anIsSaveGUI = true;
843 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
844 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
845 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
846 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
849 DumpStudyFileDlg fd( desktop() );
850 fd.setValidator( new DumpStudyFileValidator( &fd ) );
851 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
852 fd.setFilters( aFilters );
853 fd.myPublishChk->setChecked( anIsPublish );
854 fd.myMultiFileChk->setChecked( anIsMultiFile );
855 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
856 if ( fd.exec() == QDialog::Accepted )
858 QString aFileName = fd.selectedFile();
860 bool toPublish = fd.myPublishChk->isChecked();
861 bool isMultiFile = fd.myMultiFileChk->isChecked();
862 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
864 if ( !aFileName.isEmpty() ) {
865 QFileInfo aFileInfo(aFileName);
866 if( aFileInfo.isDir() ) // IPAL19257
869 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
872 SUIT_OverrideCursor wc;
873 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
876 SUIT_MessageBox::warning( desktop(),
877 QObject::tr("WRN_WARNING"),
878 tr("WRN_DUMP_STUDY_FAILED") );
883 /*!Private SLOT. On load script.*/
884 void SalomeApp_Application::onLoadScript( )
886 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
887 if ( !appStudy ) return;
888 _PTR(Study) aStudy = appStudy->studyDS();
890 if ( aStudy->GetProperties()->IsLocked() ) {
891 SUIT_MessageBox::warning( desktop(),
892 QObject::tr("WRN_WARNING"),
893 QObject::tr("WRN_STUDY_LOCKED") );
897 QStringList filtersList;
898 filtersList.append(tr("PYTHON_FILES_FILTER"));
899 filtersList.append(tr("ALL_FILES_FILTER"));
901 QString anInitialPath = "";
902 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
903 anInitialPath = QDir::currentPath();
906 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
908 SALOMEDSClient_StudyManager* aMgr = studyMgr();
909 aMgr->GetSimanStudy()->StudyId();
910 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
911 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
912 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
916 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
918 if ( !aFile.isEmpty() )
920 QString command = QString("execfile(r\"%1\")").arg(aFile);
922 #ifndef DISABLE_PYCONSOLE
923 PyConsole_Console* pyConsole = pythonConsole();
926 pyConsole->exec( command );
931 /*!Private SLOT. On save GUI state.*/
932 void SalomeApp_Application::onSaveGUIState()
934 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
936 SalomeApp_VisualState( this ).storeState();
937 updateSavePointDataObjects( study );
938 updateObjectBrowser();
943 /*!Public SLOT. On SIMAN check in operation.*/
944 void SalomeApp_Application::onCheckIn()
947 setMenuShown(SimanCheckInId, false); // check in may be performed only once
948 setMenuShown(SimanLocalCheckInId, false);
949 SALOMEDSClient_StudyManager* aMgr = studyMgr();
950 aMgr->GetSimanStudy()->CheckIn("");
952 printf( "****************************************************************\n" );
953 printf( "* Warning: SALOME is built without SIMAN support.\n" );
954 printf( "****************************************************************\n" );
958 /*!Public SLOT. On SIMAN local check in operation.*/
959 void SalomeApp_Application::onLocalCheckIn()
962 // get the active module
963 CAM_Module* aModule = activeModule();
964 if (!aModule) return; // there is no active module
966 setMenuShown(SimanCheckInId, false); // check in may be performed only once
967 setMenuShown(SimanLocalCheckInId, false);
968 SALOMEDSClient_StudyManager* aMgr = studyMgr();
969 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
971 printf( "****************************************************************\n" );
972 printf( "* Warning: SALOME is built without SIMAN support.\n" );
973 printf( "****************************************************************\n" );
978 *\retval QString "(*.hdf)"
980 QString SalomeApp_Application::getFileFilter() const
986 QWidget* SalomeApp_Application::createWindow( const int flag )
989 #ifndef DISABLE_PYCONSOLE
990 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
992 wid = LightApp_Application::createWindow(flag);
995 SUIT_ResourceMgr* resMgr = resourceMgr();
997 if ( flag == WT_ObjectBrowser )
999 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1001 // temporary commented
1002 //ob->setUpdater( new SalomeApp_Updater() );
1004 #ifdef WITH_SALOMEDS_OBSERVER
1005 //do not activate the automatic update of Qt tree through signal/slot
1006 ob->setAutoUpdate(false);
1007 //activate update of modified objects only
1008 ob->setUpdateModified(true);
1011 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1014 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1015 IORCol = QObject::tr( "IOR_COLUMN" ),
1016 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1017 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1019 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1020 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1021 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1022 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1023 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1024 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1025 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1026 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1027 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1029 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1030 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1031 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1033 ob->setAutoSizeFirstColumn(autoSizeFirst);
1034 ob->setAutoSizeColumns(autoSize);
1035 ob->setResizeOnExpandItem(resizeOnExpandItem);
1036 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1038 // temporary commented
1040 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1042 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1043 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1044 QString().sprintf( "visibility_column_%d", i ), true ) );
1048 // temporary commented
1050 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1051 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1052 ob->resize( desktop()->width()/3, ob->height() );
1056 #ifndef DISABLE_PYCONSOLE
1057 else if ( flag == WT_PyConsole )
1059 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1060 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1061 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1062 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1063 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1065 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1066 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1068 else if ( flag == WT_NoteBook )
1070 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1072 _PTR(Study) aStudy = appStudy->studyDS();
1073 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1074 //to receive signal in NoteBook that it's variable was modified
1075 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1076 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1078 wid = getNoteBook();
1084 /*!Create preferences.*/
1085 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1087 LightApp_Application::createPreferences(pref);
1092 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1093 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1094 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1095 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1097 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1098 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1100 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1102 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1103 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1104 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1105 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1106 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1107 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1108 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1109 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1110 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1111 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1114 /*!Update desktop title.*/
1115 void SalomeApp_Application::updateDesktopTitle() {
1116 QString aTitle = applicationName();
1117 QString aVer = applicationVersion();
1118 if ( !aVer.isEmpty() )
1119 aTitle += QString( " " ) + aVer;
1121 if ( activeStudy() )
1123 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1124 if ( !sName.isEmpty() ) {
1125 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1127 _PTR(Study) stdDS = study->studyDS();
1129 if ( stdDS->GetProperties()->IsLocked() ) {
1130 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1132 aTitle += QString( " - [%1]" ).arg( sName );
1139 desktop()->setWindowTitle( aTitle );
1142 int SalomeApp_Application::closeChoice( const QString& docName )
1144 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1145 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1146 tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
1148 int res = CloseCancel;
1151 else if ( answer == 1 )
1153 else if ( answer == 2 )
1159 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1165 if ( activeStudy()->isSaved() )
1167 else if ( !onSaveAsDoc() )
1173 closePermanently = false;
1183 int SalomeApp_Application::openChoice( const QString& aName )
1185 int choice = LightApp_Application::openChoice( aName );
1187 if ( QFileInfo( aName ).exists() ) {
1188 if ( choice == OpenNew ) { // The document isn't already open.
1190 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1191 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1192 if ( aName == QString( lst[i].c_str() ) )
1195 // The document already exists in the study manager.
1196 // Do you want to reload it?
1198 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1199 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1200 if ( answer == SUIT_MessageBox::Yes )
1201 choice = OpenRefresh;
1203 choice = OpenCancel;
1206 } else { // file is not exist on disk
1207 SUIT_MessageBox::warning( desktop(),
1208 QObject::tr("WRN_WARNING"),
1209 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1216 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1219 int choice = aChoice;
1224 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1227 studyMgr()->Close( aStudy );
1232 res = LightApp_Application::openAction( choice, aName );
1240 \brief Get map of the operations which can be performed
1241 on the module activation.
1243 The method should return the map of the kind \c {<id>:<name>}
1244 where \c <id> is an integer identifier of the operation and
1245 \c <name> is a title for the button to be added to the
1246 dialog box. After user selects the required operation by the
1247 clicking the corresponding button in the dialog box, its identifier
1248 is passed to the moduleActionSelected() method to process
1251 \return map of the operations
1252 \sa moduleActionSelected()
1254 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1256 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1257 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1258 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1263 \brief Called when the used selectes required operation chosen
1264 from "Activate module" dialog box.
1266 Performs the required operation according to the user choice.
1268 \param id operation identifier
1269 \sa activateModuleActions()
1271 void SalomeApp_Application::moduleActionSelected( const int id )
1277 case NewAndScriptId:
1281 LightApp_Application::moduleActionSelected( id );
1286 /*!Gets CORBA::ORB_var*/
1287 CORBA::ORB_var SalomeApp_Application::orb()
1289 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1290 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1294 /*!Create and return SALOMEDS_StudyManager.*/
1295 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1297 static _PTR(StudyManager) _sm;
1298 if(!_sm) _sm = ClientFactory::StudyManager();
1302 /*!Create and return SALOME_NamingService.*/
1303 SALOME_NamingService* SalomeApp_Application::namingService()
1305 static SALOME_NamingService _ns(orb());
1309 /*!Create and return SALOME_LifeCycleCORBA.*/
1310 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1312 static SALOME_LifeCycleCORBA _lcc( namingService() );
1316 /*!Private SLOT. On preferences.*/
1317 void SalomeApp_Application::onProperties()
1319 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1323 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1326 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1327 int res = aDlg.exec();
1328 if( res==QDialog::Accepted && aDlg.isChanged() )
1329 SB->CommitCommand();
1333 //study->updateCaptions();
1334 updateDesktopTitle();
1338 /*!Insert items in popup, which necessary for current application*/
1339 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1341 LightApp_SelectionMgr* mgr = selectionMgr();
1342 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1343 mgr->setSelectionCacheEnabled( true );
1345 LightApp_Application::contextMenuPopup( type, thePopup, title );
1347 // temporary commented
1348 /*OB_Browser* ob = objectBrowser();
1349 if ( !ob || type != ob->popupClientType() )
1352 // Get selected objects
1353 SALOME_ListIO aList;
1354 mgr->selectedObjects( aList, QString(), false );
1356 // add GUI state commands: restore, rename
1357 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1358 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1359 thePopup->addSeparator();
1360 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1361 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1362 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1363 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1366 // "Delete reference" item should appear only for invalid references
1368 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1369 bool isInvalidRefs = false;
1370 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1371 _PTR(Study) aStudyDS = aStudy->studyDS();
1372 _PTR(SObject) anObj;
1374 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1375 if( it.Value()->hasEntry() )
1377 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1378 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1381 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1382 isInvalidRefs = true;
1385 // Add "Delete reference" item to popup
1386 if ( isInvalidRefs )
1388 thePopup->addSeparator();
1389 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1393 // "Activate module" item should appear only if it's necessary
1394 if ( aList.Extent() == 1 ) {
1396 mgr->selectedObjects( aList );
1398 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1400 // add extra popup menu (defined in XML)
1401 if ( myExtActions.size() > 0 ) {
1402 // Use only first selected object
1403 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1405 _PTR(Study) stdDS = study->studyDS();
1407 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1409 _PTR( GenericAttribute ) anAttr;
1410 std::string auid = "AttributeUserID";
1411 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1412 if ( aSO->FindAttribute( anAttr, auid ) ) {
1413 _PTR(AttributeUserID) aAttrID = anAttr;
1414 QString aId = aAttrID->Value().c_str();
1415 if ( myExtActions.contains( aId ) ) {
1416 thePopup->addAction(myExtActions[aId]);
1424 // check if item is a "GUI state" item (also a first level object)
1425 QString entry( aIObj->getEntry() );
1426 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1427 QString aModuleName( aIObj->getComponentDataType() );
1428 QString aModuleTitle = moduleTitle( aModuleName );
1429 CAM_Module* currentModule = activeModule();
1430 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1431 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1435 mgr->setSelectionCacheEnabled( cacheIsOn );
1438 /*!Update obect browser:
1439 1.if 'updateModels' true, update existing data models;
1440 2. update "non-existing" (not loaded yet) data models;
1441 3. update object browser if it exists */
1442 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1444 // update "non-existing" (not loaded yet) data models
1445 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1448 _PTR(Study) stdDS = study->studyDS();
1451 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1453 _PTR(SComponent) aComponent ( it->Value() );
1455 #ifndef WITH_SALOMEDS_OBSERVER
1456 // with GUI observers this check is not needed anymore
1457 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1458 continue; // skip the magic "Interface Applicative" component
1460 if ( !objectBrowser() )
1461 getWindow( WT_ObjectBrowser );
1462 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1463 objectBrowser()->setAutoUpdate( false );
1464 SalomeApp_DataModel::synchronize( aComponent, study );
1465 objectBrowser()->setAutoUpdate( isAutoUpdate );
1470 // create data objects that correspond to GUI state save points
1471 if ( study ) updateSavePointDataObjects( study );
1473 // update existing data models (already loaded SComponents)
1474 LightApp_Application::updateObjectBrowser( updateModels );
1477 /*!Display Catalog Genenerator dialog */
1478 void SalomeApp_Application::onCatalogGen()
1480 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1484 /*!Display Registry Display dialog */
1485 void SalomeApp_Application::onRegDisplay()
1487 CORBA::ORB_var anOrb = orb();
1488 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1491 regWnd->activateWindow();
1494 /*!find original object by double click on item */
1495 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1497 // Issue 21379: References are supported at LightApp_DataObject level
1498 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1500 if( obj && obj->isReference() )
1502 QString entry = obj->refEntry();
1504 SUIT_DataOwnerPtrList aList;
1505 aList.append( new LightApp_DataOwner( entry ) );
1506 selectionMgr()->setSelected( aList, false );
1508 SUIT_DataBrowser* ob = objectBrowser();
1510 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1511 if ( !aSelectedIndexes.isEmpty() )
1512 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1517 Creates new view manager
1518 \param type - type of view manager
1520 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1522 return createViewManager(type);
1526 /*!Global utility function, returns selected GUI Save point object's ID */
1527 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1529 SALOME_ListIO aList;
1530 selMgr->selectedObjects( aList );
1531 if( aList.Extent() > 0 ) {
1532 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1533 QString entry( aIObj->getEntry() );
1534 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1535 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1537 bool ok; // conversion to integer is ok?
1538 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1539 return ok ? savePoint : -1;
1544 /*!Called on Restore GUI State popup command*/
1545 void SalomeApp_Application::onRestoreGUIState()
1547 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1548 if ( savePoint == -1 )
1550 SalomeApp_VisualState( this ).restoreState( savePoint );
1553 /*!Called on Delete GUI State popup command*/
1554 void SalomeApp_Application::onDeleteGUIState()
1556 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1557 if ( savePoint == -1 )
1559 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1563 study->removeSavePoint( savePoint );
1564 updateSavePointDataObjects( study );
1567 /*!Called on New study operation*/
1568 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1570 LightApp_Application::onStudyCreated( study );
1572 #ifndef DISABLE_PYCONSOLE
1573 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1574 windowDock( getWindow( WT_ObjectBrowser ) ) );
1577 loadDockWindowsState();
1579 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1580 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1583 objectBrowserColumnsVisibility();
1586 /*!Called on Save study operation*/
1587 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1589 LightApp_Application::onStudySaved( study );
1591 // temporary commented
1592 /*if ( objectBrowser() ) {
1593 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1594 objectBrowser()->updateTree( study->root() );
1598 /*!Called on Open study operation*/
1599 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1601 LightApp_Application::onStudyOpened( study );
1603 #ifndef DISABLE_PYCONSOLE
1604 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1605 windowDock( getWindow( WT_ObjectBrowser ) ) );
1608 loadDockWindowsState();
1610 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1611 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1613 objectBrowserColumnsVisibility();
1615 // temporary commented
1616 /*if ( objectBrowser() ) {
1617 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1618 objectBrowser()->updateTree( study->root() );
1622 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1623 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1626 SUIT_DataBrowser* ob = objectBrowser();
1627 LightApp_SelectionMgr* selMgr = selectionMgr();
1629 if ( !study || !ob || !selMgr )
1632 // find GUI states root object
1633 SUIT_DataObject* guiRootObj = 0;
1635 study->root()->children( ch );
1636 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1637 for ( ; it != last ; ++it ) {
1638 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1643 std::vector<int> savePoints = study->getSavePoints();
1644 // case 1: no more save points but they existed in study's tree
1645 if ( savePoints.empty() && guiRootObj ) {
1646 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1647 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1648 const bool isAutoUpdate = ob->autoUpdate();
1649 selMgr->clearSelected();
1650 ob->setAutoUpdate(true);
1651 DataObjectList ch = guiRootObj->children();
1652 for( int i = 0; i < ch.size(); i++ )
1655 ob->setAutoUpdate(isAutoUpdate);
1658 // case 2: no more save points but root does not exist either
1659 if ( savePoints.empty() && !guiRootObj )
1661 // case 3: save points but no root for them - create it
1662 if ( !savePoints.empty() && !guiRootObj )
1663 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1664 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1665 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1667 if ( guiRootObj->nextBrother() ) {
1668 study->root()->removeChild(guiRootObj);
1669 study->root()->appendChild(guiRootObj);
1670 //study->root()->dump();
1673 // store data objects in a map id-to-DataObject
1674 QMap<int,SalomeApp_SavePointObject*> mapDO;
1676 guiRootObj->children( ch );
1677 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1678 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1680 mapDO[dobj->getId()] = dobj;
1683 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1684 // if in the map - remove it from map.
1685 for ( int i = 0; i < savePoints.size(); i++ )
1686 if ( !mapDO.contains( savePoints[i] ) )
1687 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1689 mapDO.remove( savePoints[i] );
1691 // delete DataObjects that are still in the map -- their IDs were not found in data model
1692 if( mapDO.size() > 0) {
1693 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1694 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1695 selMgr->clearSelected();
1696 const bool isAutoUpdate = ob->autoUpdate();
1697 ob->setAutoUpdate(true);
1698 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1700 ob->setAutoUpdate(isAutoUpdate);
1704 /*! Check data object */
1705 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1714 Opens other study into active Study. If Study is empty - creates it.
1715 \param theName - name of study
1717 bool SalomeApp_Application::useStudy( const QString& theName )
1720 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1723 res = aStudy->loadDocument( theName );
1724 updateDesktopTitle();
1725 updateCommandsStatus();
1729 /*! Show/hide object browser colums according to preferences */
1730 void SalomeApp_Application::objectBrowserColumnsVisibility()
1732 if ( objectBrowser() )
1733 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1735 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1736 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1740 #ifndef DISABLE_PYCONSOLE
1741 /*! Set SalomeApp_NoteBook pointer */
1742 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1744 myNoteBook = theNoteBook;
1747 /*! Return SalomeApp_NoteBook pointer */
1748 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1755 * Define extra actions defined in module definition XML file.
1756 * Additional popup items sections can be defined by parameter "popupitems".
1757 * Supported attributes:
1758 * title - title of menu item,
1759 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1760 * method - method which has to be called when menu item is selected
1762 * <section name="MODULENAME">
1763 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1765 * <section name="importmed">
1766 * <parameter name="title" value="My menu"/>
1767 * <parameter name="objectid" value="VISU.Result"/>
1768 * <parameter name="method" value="nameOfModuleMethod"/>
1771 void SalomeApp_Application::createExtraActions()
1773 myExtActions.clear();
1774 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1776 QStringList aModules;
1777 modules(aModules, false);
1778 foreach(QString aModile, aModules) {
1779 QString aModName = moduleName(aModile);
1780 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1781 if (!aSectionStr.isNull()) {
1782 QStringList aSections = aSectionStr.split(':');
1783 foreach(QString aSection, aSections) {
1784 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1785 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1786 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1787 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1790 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1791 if (aModuleName.isNull())
1792 aModuleName = aModName;
1794 QAction* aAction = new QAction(aTitle, this);
1796 aData<<aModuleName<<aSlot;
1797 aAction->setData(aData);
1798 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1799 myExtActions[aId] = aAction;
1806 * Called when extra action is selected
1808 void SalomeApp_Application::onExtAction()
1810 QAction* aAction = ::qobject_cast<QAction*>(sender());
1814 QVariant aData = aAction->data();
1815 QStringList aDataList = aData.value<QStringList>();
1816 if (aDataList.size() != 2)
1819 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1820 SALOME_ListIO aListIO;
1821 aSelectionMgr->selectedObjects(aListIO);
1822 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1823 if (aListIO.Extent() < 1)
1825 if (!anIO->hasEntry())
1828 QString aEntry(anIO->getEntry());
1830 QApplication::setOverrideCursor( Qt::WaitCursor );
1831 QString aModuleTitle = moduleTitle(aDataList[0]);
1832 activateModule(aModuleTitle);
1833 QApplication::restoreOverrideCursor();
1835 QCoreApplication::processEvents();
1837 CAM_Module* aModule = activeModule();
1841 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1842 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1846 * Called when window activated
1848 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
1850 SUIT_DataBrowser* anOB = objectBrowser();
1853 SUIT_DataObject* rootObj = anOB->root();
1857 DataObjectList listObj = rootObj->children( true );
1859 SUIT_ViewModel* vmod = 0;
1860 if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
1861 vmod = vman->getViewModel();
1862 updateVisibilityState( listObj, vmod );
1866 Update visibility state of given objects
1868 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
1869 SUIT_ViewModel* theViewModel )
1871 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1876 SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
1878 if (theList.isEmpty() || !aStudy)
1881 for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
1882 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
1884 if (!obj || aStudy->isComponent(obj->entry()))
1887 LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
1888 Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
1891 LightApp_Displayer* aDisplayer = anObjModule->displayer();
1893 if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
1894 if(aView && aDisplayer->IsDisplayed(obj->entry(),aView))
1895 anObjState = Qtx::ShownState;
1897 anObjState = Qtx::HiddenState;
1899 aStudy->setVisibilityState( obj->entry(), anObjState );
1906 Called then view manager removed
1908 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
1910 ViewManagerList lst;
1912 if( lst.count() == 1) { // in case if closed last view window
1913 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1915 aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
1920 Checks that an object can be renamed.
1921 \param entry entry of the object
1922 \brief Return \c true if object can be renamed
1924 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1926 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1930 Rename object by entry.
1931 \param entry entry of the object
1932 \param name new name of the object
1933 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1935 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1937 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1939 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1941 if(!aStudy || savePoint == -1)
1944 if ( !name.isNull() && !name.isEmpty() ) {
1945 aStudy->setNameOfSavePoint( savePoint, name );
1946 updateSavePointDataObjects( aStudy );
1948 //Mark study as modified
1956 \return default windows( Object Browser, Python Console )
1957 Adds to map \a aMap.
1959 void SalomeApp_Application::defaultWindows( QMap<int, int>& aMap ) const
1961 LightApp_Application::defaultWindows(aMap);
1962 #ifndef DISABLE_PYCONSOLE
1963 if ( !aMap.contains( WT_NoteBook ) ) {
1964 if ( !myNoteBook ) {
1965 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1972 Gets current windows.
1973 \param winMap - output current windows map.
1975 void SalomeApp_Application::currentWindows(QMap<int, int>& aMap) const
1977 LightApp_Application::currentWindows( aMap );
1978 #ifndef DISABLE_PYCONSOLE
1979 if ( !aMap.contains( WT_NoteBook) && myNoteBook )
1980 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1984 #ifndef DISABLE_PYCONSOLE
1985 //============================================================================
1986 /*! Function : onUpdateStudy
1987 * Purpose : Slot to update the study.
1989 //============================================================================
1990 void SalomeApp_Application::onUpdateStudy()
1992 QApplication::setOverrideCursor( Qt::WaitCursor );
1994 if( !updateStudy() )
1995 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1997 QApplication::restoreOverrideCursor();
2000 //============================================================================
2001 /*! Function : updateStudy
2002 * Purpose : Update study by dumping the study to Python script and loading it.
2003 * It is used to apply variable modifications done in NoteBook to created objects.
2005 //============================================================================
2006 bool SalomeApp_Application::updateStudy()
2008 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
2009 if ( !study || !myNoteBook )
2012 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
2013 myNoteBook->setDumpedStudyName( study->studyName() );
2015 _PTR(Study) studyDS = study->studyDS();
2017 // get unique temporary directory name
2018 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
2019 if( aTmpDir.isEmpty() )
2022 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
2023 aTmpDir.remove( aTmpDir.length() - 1, 1 );
2025 // dump study to the temporary directory
2026 QString aScriptName( "notebook" );
2027 bool toPublish = true;
2028 bool isMultiFile = false;
2029 bool toSaveGUI = true;
2032 _PTR(AttributeParameter) ap;
2033 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2034 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2035 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2036 ip->setDumpPython(studyDS);
2037 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2039 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2041 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2044 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2048 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2049 int anIndex = aList.indexOf( this );
2051 // Disconnect dialog from application desktop in case if:
2052 // 1) Application is not the first application in the session
2053 // 2) Application is the first application in session but not the only.
2054 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2055 if( changeDesktop ) {
2057 SalomeApp_Application* app = this;
2058 if( anIndex > 0 && anIndex < aList.count() )
2059 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2060 else if(anIndex == 0 && aList.count() > 1)
2061 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2066 // creation a new study and restoring will be done in another application
2067 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2068 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2071 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2072 QString aStudyName = myNoteBook->getDumpedStudyName();
2073 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2074 // clear a study (delete all objects)
2075 onCloseDoc( false );
2077 if( !changeDesktop ) {
2078 ok = onRestoreStudy( aDumpScript,
2087 //============================================================================
2088 /*! Function : onRestoreStudy
2089 * Purpose : Load the dumped study from Python script
2091 //============================================================================
2092 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2093 const QString& theStudyName,
2094 bool theIsStudySaved )
2098 // create a new study
2101 // get active application
2102 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2104 // load study from the temporary directory
2105 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2107 #ifndef DISABLE_PYCONSOLE
2108 PyConsole_Console* pyConsole = app->pythonConsole();
2110 pyConsole->execAndWait( command );
2113 // remove temporary directory
2114 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2115 QString aStudyName = aScriptInfo.baseName();
2116 QDir aDir = aScriptInfo.absoluteDir();
2117 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2118 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2119 ok = aDir.remove( *it ) && ok;
2121 ok = aDir.rmdir( aDir.absolutePath() );
2123 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2125 #ifndef DISABLE_PYCONSOLE
2126 _PTR(Study) aStudyDS = newStudy->studyDS();
2127 app->getNoteBook()->Init( aStudyDS );
2128 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2129 newStudy->Modified();
2130 updateDesktopTitle();
2141 Close the Application
2143 void SalomeApp_Application::afterCloseDoc()
2145 #ifndef DISABLE_PYCONSOLE
2146 // emit signal to restore study from Python script
2148 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2149 myNoteBook->getDumpedStudyName(),
2150 myNoteBook->isDumpedStudySaved() );
2153 LightApp_Application::afterCloseDoc();