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
379 PyGILState_STATE gstate = PyGILState_Ensure();
380 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
381 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());
384 PyGILState_Release(gstate);
385 // end of SALOME plugins loading
393 void SalomeApp_Application::setDesktop( SUIT_Desktop* desk )
395 LightApp_Application::setDesktop( desk );
398 connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
399 this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
400 connect( desk, SIGNAL( message( const QString& ) ),
401 this, SLOT( onLoadDocMessage( const QString& ) ), Qt::UniqueConnection );
406 \brief Close application.
408 void SalomeApp_Application::onExit()
410 bool killServers = false;
413 if ( exitConfirmation() ) {
414 SalomeApp_ExitDlg dlg( desktop() );
415 result = dlg.exec() == QDialog::Accepted;
416 killServers = dlg.isServersShutdown();
420 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
423 /*!SLOT. Load document.*/
424 void SalomeApp_Application::onLoadDoc()
428 std::vector<std::string> List = studyMgr()->GetOpenStudies();
430 SUIT_Session* aSession = SUIT_Session::session();
431 QList<SUIT_Application*> aAppList = aSession->applications();
433 QStringList unloadedStudies;
435 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
436 studyName = List[ind].c_str();
437 // Add to list only unloaded studies
438 bool isAlreadyOpen = false;
439 QListIterator<SUIT_Application*> it( aAppList );
440 while ( it.hasNext() && !isAlreadyOpen ) {
441 SUIT_Application* aApp = it.next();
442 if( !aApp || !aApp->activeStudy() )
444 if ( aApp->activeStudy()->studyName() == studyName )
445 isAlreadyOpen = true;
448 if ( !isAlreadyOpen )
449 unloadedStudies << studyName;
452 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
453 if ( studyName.isEmpty() )
457 // this code replaces marker of windows drive and path become invalid therefore
458 // defines placed there
459 studyName.replace( QRegExp(":"), "/" );
462 if ( onLoadDoc( studyName ) ) {
464 updateViewManagers();
465 updateObjectBrowser( true );
469 /*!SLOT. Create new study and load script*/
470 void SalomeApp_Application::onNewWithScript()
472 QStringList filtersList;
473 filtersList.append(tr("PYTHON_FILES_FILTER"));
474 filtersList.append(tr("ALL_FILES_FILTER"));
476 QString anInitialPath = "";
477 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
478 anInitialPath = QDir::currentPath();
480 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
482 if ( !aFile.isEmpty() )
486 QString command = QString("execfile(r\"%1\")").arg(aFile);
488 #ifndef DISABLE_PYCONSOLE
489 PyConsole_Console* pyConsole = pythonConsole();
492 pyConsole->exec( command );
498 /*!SLOT. Load document with \a aName.*/
499 bool SalomeApp_Application::onLoadDoc( const QString& aName )
502 if ( !activeStudy() ) {
503 // if no study - load in current desktop
504 res = useStudy( aName );
507 // if study exists - load in new desktop. Check: is the same file is loaded?
508 SUIT_Session* aSession = SUIT_Session::session();
509 QList<SUIT_Application*> aAppList = aSession->applications();
510 bool isAlreadyOpen = false;
511 SalomeApp_Application* aApp = 0;
512 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
513 it != aAppList.end() && !isAlreadyOpen; ++it ) {
514 aApp = dynamic_cast<SalomeApp_Application*>( *it );
515 if ( aApp && aApp->activeStudy()->studyName() == aName )
516 isAlreadyOpen = true;
518 if ( !isAlreadyOpen ) {
519 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
521 res = aApp->useStudy( aName );
524 aApp->desktop()->activateWindow();
531 /*!SLOT. Load document with a name, specified in \a aMessage.*/
532 void SalomeApp_Application::onLoadDocMessage(const QString& aMessage)
534 if (aMessage.indexOf("simanCheckoutDone ") == 0) {
536 onLoadDoc(aMessage.section(' ', 1));
538 printf( "****************************************************************\n" );
539 printf( "* Warning: SALOME is built without SIMAN support.\n" );
540 printf( "****************************************************************\n" );
545 /*!SLOT. Copy objects to study maneger from selection maneger..*/
546 void SalomeApp_Application::onCopy()
549 LightApp_SelectionMgr* mgr = selectionMgr();
550 mgr->selectedObjects(list);
552 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
553 if(study == NULL) return;
555 _PTR(Study) stdDS = study->studyDS();
558 SALOME_ListIteratorOfListIO it( list );
561 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
563 studyMgr()->Copy(so);
564 onSelectionChanged();
571 /*!SLOT. Paste objects to study maneger from selection manager.*/
572 void SalomeApp_Application::onPaste()
575 LightApp_SelectionMgr* mgr = selectionMgr();
576 mgr->selectedObjects(list);
578 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
579 if(study == NULL) return;
581 _PTR(Study) stdDS = study->studyDS();
584 if ( stdDS->GetProperties()->IsLocked() ) {
585 SUIT_MessageBox::warning( desktop(),
586 QObject::tr("WRN_WARNING"),
587 QObject::tr("WRN_STUDY_LOCKED") );
591 SALOME_ListIteratorOfListIO it( list );
594 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
596 studyMgr()->Paste(so);
597 updateObjectBrowser( true );
598 updateActions(); //SRN: BugID IPAL9377, case 3
605 /*!Check the application on closing.
606 * \retval true if possible, else false
608 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
610 return LightApp_Application::isPossibleToClose( closePermanently );
613 /*! Check if the study is locked */
614 void SalomeApp_Application::onCloseDoc( bool ask )
616 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
619 _PTR(Study) stdDS = study->studyDS();
620 if(stdDS && stdDS->IsStudyLocked()) {
621 if ( SUIT_MessageBox::question( desktop(),
622 QObject::tr( "WRN_WARNING" ),
623 QObject::tr( "CLOSE_LOCKED_STUDY" ),
624 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
625 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
630 LightApp_Application::onCloseDoc( ask );
633 /*!Sets enable or disable some actions on selection changed.*/
634 void SalomeApp_Application::onSelectionChanged()
637 LightApp_SelectionMgr* mgr = selectionMgr();
638 mgr->selectedObjects(list);
640 bool canCopy = false;
641 bool canPaste = false;
643 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
645 _PTR(Study) stdDS = study->studyDS();
648 SALOME_ListIteratorOfListIO it ( list );
650 if (it.More() && list.Extent() == 1) {
651 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
654 canCopy = studyMgr()->CanCopy(so);
655 canPaste = studyMgr()->CanPaste(so);
661 action(EditCopyId)->setEnabled(canCopy);
662 action(EditPasteId)->setEnabled(canPaste);
665 /*!Delete references.*/
666 void SalomeApp_Application::onDeleteInvalidReferences()
669 LightApp_SelectionMgr* mgr = selectionMgr();
670 mgr->selectedObjects( aList, QString(), false );
672 if( aList.IsEmpty() )
675 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
676 _PTR(Study) aStudyDS = aStudy->studyDS();
677 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
680 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
681 if ( it.Value()->hasEntry() )
683 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
684 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
687 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
688 aStudyBuilder->RemoveReference( aSObject );
690 updateObjectBrowser();
694 void SalomeApp_Application::onOpenWith()
696 QApplication::setOverrideCursor( Qt::WaitCursor );
698 LightApp_SelectionMgr* mgr = selectionMgr();
699 mgr->selectedObjects(aList);
700 if (aList.Extent() != 1)
702 QApplication::restoreOverrideCursor();
705 Handle(SALOME_InteractiveObject) aIObj = aList.First();
706 QString aModuleName(aIObj->getComponentDataType());
707 QString aModuleTitle = moduleTitle(aModuleName);
708 activateModule(aModuleTitle);
709 QApplication::restoreOverrideCursor();
715 SUIT_Study* SalomeApp_Application::createNewStudy()
717 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
719 // Set up processing of major study-related events
720 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
721 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
722 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
723 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
725 #ifndef DISABLE_PYCONSOLE
726 //to receive signal in application that NoteBook's variable was modified
727 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
728 this, SIGNAL(notebookVarUpdated(QString)) );
735 Enable/Disable menu items and toolbar buttons. Rebuild menu
737 void SalomeApp_Application::updateCommandsStatus()
739 LightApp_Application::updateCommandsStatus();
742 QAction* a = action( DumpStudyId );
744 a->setEnabled( activeStudy() );
747 a = action( LoadScriptId );
749 a->setEnabled( activeStudy() );
752 a = action( PropertiesId );
754 a->setEnabled( activeStudy() );
756 // Save GUI state menu
757 a = action( SaveGUIStateId );
759 a->setEnabled( activeStudy() );
761 // update state of Copy/Paste menu items
762 onSelectionChanged();
766 \class DumpStudyFileDlg
767 Private class used in Dump Study operation. Consists 2 check boxes:
768 "Publish in study" and "Save GUI parameters"
770 class DumpStudyFileDlg : public SUIT_FileDlg
773 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
775 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
778 QWidget *hB = new QWidget( this );
779 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
780 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
781 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
783 QHBoxLayout *layout = new QHBoxLayout;
784 layout->addWidget(myPublishChk);
785 layout->addWidget(myMultiFileChk);
786 layout->addWidget(mySaveGUIChk);
787 hB->setLayout(layout);
789 QPushButton* pb = new QPushButton(this);
791 int row = grid->rowCount();
792 grid->addWidget( new QLabel("", this), row, 0 );
793 grid->addWidget( hB, row, 1, 1, 3 );
794 grid->addWidget( pb, row, 5 );
799 QCheckBox* myPublishChk;
800 QCheckBox* myMultiFileChk;
801 QCheckBox* mySaveGUIChk;
804 class DumpStudyFileValidator : public SUIT_FileValidator
807 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
808 virtual ~DumpStudyFileValidator() {};
809 virtual bool canSave( const QString& file, bool permissions );
812 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
814 QFileInfo fi( file );
815 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
816 SUIT_MessageBox::critical( parent(),
817 QObject::tr("WRN_WARNING"),
818 QObject::tr("WRN_FILE_NAME_BAD") );
821 return SUIT_FileValidator::canSave( file, permissions);
824 /*!Private SLOT. On dump study.*/
825 void SalomeApp_Application::onDumpStudy( )
827 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
828 if ( !appStudy ) return;
829 _PTR(Study) aStudy = appStudy->studyDS();
831 QStringList aFilters;
832 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
834 bool anIsPublish = true;
835 bool anIsMultiFile = false;
836 bool anIsSaveGUI = true;
838 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
839 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
840 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
841 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
844 DumpStudyFileDlg fd( desktop() );
845 fd.setValidator( new DumpStudyFileValidator( &fd ) );
846 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
847 fd.setFilters( aFilters );
848 fd.myPublishChk->setChecked( anIsPublish );
849 fd.myMultiFileChk->setChecked( anIsMultiFile );
850 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
851 if ( fd.exec() == QDialog::Accepted )
853 QString aFileName = fd.selectedFile();
855 bool toPublish = fd.myPublishChk->isChecked();
856 bool isMultiFile = fd.myMultiFileChk->isChecked();
857 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
859 if ( !aFileName.isEmpty() ) {
860 QFileInfo aFileInfo(aFileName);
861 if( aFileInfo.isDir() ) // IPAL19257
864 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
867 SUIT_OverrideCursor wc;
868 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
871 SUIT_MessageBox::warning( desktop(),
872 QObject::tr("WRN_WARNING"),
873 tr("WRN_DUMP_STUDY_FAILED") );
878 /*!Private SLOT. On load script.*/
879 void SalomeApp_Application::onLoadScript( )
881 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
882 if ( !appStudy ) return;
883 _PTR(Study) aStudy = appStudy->studyDS();
885 if ( aStudy->GetProperties()->IsLocked() ) {
886 SUIT_MessageBox::warning( desktop(),
887 QObject::tr("WRN_WARNING"),
888 QObject::tr("WRN_STUDY_LOCKED") );
892 QStringList filtersList;
893 filtersList.append(tr("PYTHON_FILES_FILTER"));
894 filtersList.append(tr("ALL_FILES_FILTER"));
896 QString anInitialPath = "";
897 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
898 anInitialPath = QDir::currentPath();
901 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
903 SALOMEDSClient_StudyManager* aMgr = studyMgr();
904 aMgr->GetSimanStudy()->StudyId();
905 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
906 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
907 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
911 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
913 if ( !aFile.isEmpty() )
915 QString command = QString("execfile(r\"%1\")").arg(aFile);
917 #ifndef DISABLE_PYCONSOLE
918 PyConsole_Console* pyConsole = pythonConsole();
921 pyConsole->exec( command );
926 /*!Private SLOT. On save GUI state.*/
927 void SalomeApp_Application::onSaveGUIState()
929 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
931 SalomeApp_VisualState( this ).storeState();
932 updateSavePointDataObjects( study );
933 updateObjectBrowser();
938 /*!Public SLOT. On SIMAN check in operation.*/
939 void SalomeApp_Application::onCheckIn()
942 setMenuShown(SimanCheckInId, false); // check in may be performed only once
943 setMenuShown(SimanLocalCheckInId, false);
944 SALOMEDSClient_StudyManager* aMgr = studyMgr();
945 aMgr->GetSimanStudy()->CheckIn("");
947 printf( "****************************************************************\n" );
948 printf( "* Warning: SALOME is built without SIMAN support.\n" );
949 printf( "****************************************************************\n" );
953 /*!Public SLOT. On SIMAN local check in operation.*/
954 void SalomeApp_Application::onLocalCheckIn()
957 // get the active module
958 CAM_Module* aModule = activeModule();
959 if (!aModule) return; // there is no active module
961 setMenuShown(SimanCheckInId, false); // check in may be performed only once
962 setMenuShown(SimanLocalCheckInId, false);
963 SALOMEDSClient_StudyManager* aMgr = studyMgr();
964 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
966 printf( "****************************************************************\n" );
967 printf( "* Warning: SALOME is built without SIMAN support.\n" );
968 printf( "****************************************************************\n" );
973 *\retval QString "(*.hdf)"
975 QString SalomeApp_Application::getFileFilter() const
981 QWidget* SalomeApp_Application::createWindow( const int flag )
984 #ifndef DISABLE_PYCONSOLE
985 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
987 wid = LightApp_Application::createWindow(flag);
990 SUIT_ResourceMgr* resMgr = resourceMgr();
992 if ( flag == WT_ObjectBrowser )
994 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
996 // temporary commented
997 //ob->setUpdater( new SalomeApp_Updater() );
999 #ifdef WITH_SALOMEDS_OBSERVER
1000 //do not activate the automatic update of Qt tree through signal/slot
1001 ob->setAutoUpdate(false);
1002 //activate update of modified objects only
1003 ob->setUpdateModified(true);
1006 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1009 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1010 IORCol = QObject::tr( "IOR_COLUMN" ),
1011 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1012 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1014 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1015 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1016 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1017 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1018 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1019 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1020 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1021 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1022 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1024 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1025 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1026 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1028 ob->setAutoSizeFirstColumn(autoSizeFirst);
1029 ob->setAutoSizeColumns(autoSize);
1030 ob->setResizeOnExpandItem(resizeOnExpandItem);
1031 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1033 // temporary commented
1035 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1037 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1038 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1039 QString().sprintf( "visibility_column_%d", i ), true ) );
1043 // temporary commented
1045 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1046 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1047 ob->resize( desktop()->width()/3, ob->height() );
1051 #ifndef DISABLE_PYCONSOLE
1052 else if ( flag == WT_PyConsole )
1054 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1055 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1056 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1057 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1058 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1060 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1061 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1063 else if ( flag == WT_NoteBook )
1065 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1067 _PTR(Study) aStudy = appStudy->studyDS();
1068 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1069 //to receive signal in NoteBook that it's variable was modified
1070 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1071 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1073 wid = getNoteBook();
1079 /*!Create preferences.*/
1080 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1082 LightApp_Application::createPreferences(pref);
1087 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1088 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1089 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1090 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1092 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1093 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1095 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1097 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1098 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1099 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1100 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1101 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1102 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1103 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1104 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1105 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1106 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1109 /*!Update desktop title.*/
1110 void SalomeApp_Application::updateDesktopTitle() {
1111 QString aTitle = applicationName();
1112 QString aVer = applicationVersion();
1113 if ( !aVer.isEmpty() )
1114 aTitle += QString( " " ) + aVer;
1116 if ( activeStudy() )
1118 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1119 if ( !sName.isEmpty() ) {
1120 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1122 _PTR(Study) stdDS = study->studyDS();
1124 if ( stdDS->GetProperties()->IsLocked() ) {
1125 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1127 aTitle += QString( " - [%1]" ).arg( sName );
1134 desktop()->setWindowTitle( aTitle );
1137 int SalomeApp_Application::closeChoice( const QString& docName )
1139 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ).arg( docName ),
1140 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1141 tr ("APPCLOSE_UNLOAD"), tr ("APPCLOSE_CANCEL"), 0 );
1143 int res = CloseCancel;
1146 else if ( answer == 1 )
1148 else if ( answer == 2 )
1154 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1160 if ( activeStudy()->isSaved() )
1162 else if ( !onSaveAsDoc() )
1168 closePermanently = false;
1178 int SalomeApp_Application::openChoice( const QString& aName )
1180 int choice = LightApp_Application::openChoice( aName );
1182 if ( QFileInfo( aName ).exists() ) {
1183 if ( choice == OpenNew ) { // The document isn't already open.
1185 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1186 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1187 if ( aName == QString( lst[i].c_str() ) )
1190 // The document already exists in the study manager.
1191 // Do you want to reload it?
1193 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1194 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1195 if ( answer == SUIT_MessageBox::Yes )
1196 choice = OpenRefresh;
1198 choice = OpenCancel;
1201 } else { // file is not exist on disk
1202 SUIT_MessageBox::warning( desktop(),
1203 QObject::tr("WRN_WARNING"),
1204 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1211 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1214 int choice = aChoice;
1219 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1222 studyMgr()->Close( aStudy );
1227 res = LightApp_Application::openAction( choice, aName );
1235 \brief Get map of the operations which can be performed
1236 on the module activation.
1238 The method should return the map of the kind \c {<id>:<name>}
1239 where \c <id> is an integer identifier of the operation and
1240 \c <name> is a title for the button to be added to the
1241 dialog box. After user selects the required operation by the
1242 clicking the corresponding button in the dialog box, its identifier
1243 is passed to the moduleActionSelected() method to process
1246 \return map of the operations
1247 \sa moduleActionSelected()
1249 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1251 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1252 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1253 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1258 \brief Called when the used selectes required operation chosen
1259 from "Activate module" dialog box.
1261 Performs the required operation according to the user choice.
1263 \param id operation identifier
1264 \sa activateModuleActions()
1266 void SalomeApp_Application::moduleActionSelected( const int id )
1272 case NewAndScriptId:
1276 LightApp_Application::moduleActionSelected( id );
1281 /*!Gets CORBA::ORB_var*/
1282 CORBA::ORB_var SalomeApp_Application::orb()
1284 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1285 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1289 /*!Create and return SALOMEDS_StudyManager.*/
1290 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1292 static _PTR(StudyManager) _sm;
1293 if(!_sm) _sm = ClientFactory::StudyManager();
1297 /*!Create and return SALOME_NamingService.*/
1298 SALOME_NamingService* SalomeApp_Application::namingService()
1300 static SALOME_NamingService _ns(orb());
1304 /*!Create and return SALOME_LifeCycleCORBA.*/
1305 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1307 static SALOME_LifeCycleCORBA _lcc( namingService() );
1311 /*!Private SLOT. On preferences.*/
1312 void SalomeApp_Application::onProperties()
1314 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1318 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1321 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1322 int res = aDlg.exec();
1323 if( res==QDialog::Accepted && aDlg.isChanged() )
1324 SB->CommitCommand();
1328 //study->updateCaptions();
1329 updateDesktopTitle();
1333 /*!Insert items in popup, which necessary for current application*/
1334 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1336 LightApp_SelectionMgr* mgr = selectionMgr();
1337 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1338 mgr->setSelectionCacheEnabled( true );
1340 LightApp_Application::contextMenuPopup( type, thePopup, title );
1342 // temporary commented
1343 /*OB_Browser* ob = objectBrowser();
1344 if ( !ob || type != ob->popupClientType() )
1347 // Get selected objects
1348 SALOME_ListIO aList;
1349 mgr->selectedObjects( aList, QString(), false );
1351 // add GUI state commands: restore, rename
1352 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1353 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1354 thePopup->addSeparator();
1355 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1356 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1357 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1358 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1361 // "Delete reference" item should appear only for invalid references
1363 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1364 bool isInvalidRefs = false;
1365 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1366 _PTR(Study) aStudyDS = aStudy->studyDS();
1367 _PTR(SObject) anObj;
1369 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1370 if( it.Value()->hasEntry() )
1372 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1373 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1376 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1377 isInvalidRefs = true;
1380 // Add "Delete reference" item to popup
1381 if ( isInvalidRefs )
1383 thePopup->addSeparator();
1384 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1388 // "Activate module" item should appear only if it's necessary
1389 if ( aList.Extent() == 1 ) {
1391 mgr->selectedObjects( aList );
1393 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1395 // add extra popup menu (defined in XML)
1396 if ( myExtActions.size() > 0 ) {
1397 // Use only first selected object
1398 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1400 _PTR(Study) stdDS = study->studyDS();
1402 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1404 _PTR( GenericAttribute ) anAttr;
1405 std::string auid = "AttributeUserID";
1406 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1407 if ( aSO->FindAttribute( anAttr, auid ) ) {
1408 _PTR(AttributeUserID) aAttrID = anAttr;
1409 QString aId = aAttrID->Value().c_str();
1410 if ( myExtActions.contains( aId ) ) {
1411 thePopup->addAction(myExtActions[aId]);
1419 // check if item is a "GUI state" item (also a first level object)
1420 QString entry( aIObj->getEntry() );
1421 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1422 QString aModuleName( aIObj->getComponentDataType() );
1423 QString aModuleTitle = moduleTitle( aModuleName );
1424 CAM_Module* currentModule = activeModule();
1425 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1426 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1430 mgr->setSelectionCacheEnabled( cacheIsOn );
1433 /*!Update obect browser:
1434 1.if 'updateModels' true, update existing data models;
1435 2. update "non-existing" (not loaded yet) data models;
1436 3. update object browser if it exists */
1437 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1439 // update "non-existing" (not loaded yet) data models
1440 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1443 _PTR(Study) stdDS = study->studyDS();
1446 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1448 _PTR(SComponent) aComponent ( it->Value() );
1450 #ifndef WITH_SALOMEDS_OBSERVER
1451 // with GUI observers this check is not needed anymore
1452 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1453 continue; // skip the magic "Interface Applicative" component
1455 if ( !objectBrowser() )
1456 getWindow( WT_ObjectBrowser );
1457 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1458 objectBrowser()->setAutoUpdate( false );
1459 SalomeApp_DataModel::synchronize( aComponent, study );
1460 objectBrowser()->setAutoUpdate( isAutoUpdate );
1465 // create data objects that correspond to GUI state save points
1466 if ( study ) updateSavePointDataObjects( study );
1468 // update existing data models (already loaded SComponents)
1469 LightApp_Application::updateObjectBrowser( updateModels );
1472 /*!Display Catalog Genenerator dialog */
1473 void SalomeApp_Application::onCatalogGen()
1475 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1479 /*!Display Registry Display dialog */
1480 void SalomeApp_Application::onRegDisplay()
1482 CORBA::ORB_var anOrb = orb();
1483 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1486 regWnd->activateWindow();
1489 /*!find original object by double click on item */
1490 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1492 // Issue 21379: References are supported at LightApp_DataObject level
1493 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1495 if( obj && obj->isReference() )
1497 QString entry = obj->refEntry();
1499 SUIT_DataOwnerPtrList aList;
1500 aList.append( new LightApp_DataOwner( entry ) );
1501 selectionMgr()->setSelected( aList, false );
1503 SUIT_DataBrowser* ob = objectBrowser();
1505 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1506 if ( !aSelectedIndexes.isEmpty() )
1507 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1512 Creates new view manager
1513 \param type - type of view manager
1515 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1517 return createViewManager(type);
1521 /*!Global utility function, returns selected GUI Save point object's ID */
1522 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1524 SALOME_ListIO aList;
1525 selMgr->selectedObjects( aList );
1526 if( aList.Extent() > 0 ) {
1527 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1528 QString entry( aIObj->getEntry() );
1529 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1530 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1532 bool ok; // conversion to integer is ok?
1533 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1534 return ok ? savePoint : -1;
1539 /*!Called on Restore GUI State popup command*/
1540 void SalomeApp_Application::onRestoreGUIState()
1542 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1543 if ( savePoint == -1 )
1545 SalomeApp_VisualState( this ).restoreState( savePoint );
1548 /*!Called on Delete GUI State popup command*/
1549 void SalomeApp_Application::onDeleteGUIState()
1551 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1552 if ( savePoint == -1 )
1554 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1558 study->removeSavePoint( savePoint );
1559 updateSavePointDataObjects( study );
1562 /*!Called on New study operation*/
1563 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1565 LightApp_Application::onStudyCreated( study );
1567 #ifndef DISABLE_PYCONSOLE
1568 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1569 windowDock( getWindow( WT_ObjectBrowser ) ) );
1572 loadDockWindowsState();
1574 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1575 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1578 objectBrowserColumnsVisibility();
1581 /*!Called on Save study operation*/
1582 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1584 LightApp_Application::onStudySaved( study );
1586 // temporary commented
1587 /*if ( objectBrowser() ) {
1588 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1589 objectBrowser()->updateTree( study->root() );
1593 /*!Called on Open study operation*/
1594 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1596 LightApp_Application::onStudyOpened( study );
1598 #ifndef DISABLE_PYCONSOLE
1599 desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1600 windowDock( getWindow( WT_ObjectBrowser ) ) );
1603 loadDockWindowsState();
1605 connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
1606 this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
1608 objectBrowserColumnsVisibility();
1610 // temporary commented
1611 /*if ( objectBrowser() ) {
1612 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1613 objectBrowser()->updateTree( study->root() );
1617 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1618 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1621 SUIT_DataBrowser* ob = objectBrowser();
1622 LightApp_SelectionMgr* selMgr = selectionMgr();
1624 if ( !study || !ob || !selMgr )
1627 // find GUI states root object
1628 SUIT_DataObject* guiRootObj = 0;
1630 study->root()->children( ch );
1631 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1632 for ( ; it != last ; ++it ) {
1633 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1638 std::vector<int> savePoints = study->getSavePoints();
1639 // case 1: no more save points but they existed in study's tree
1640 if ( savePoints.empty() && guiRootObj ) {
1641 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1642 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1643 const bool isAutoUpdate = ob->autoUpdate();
1644 selMgr->clearSelected();
1645 ob->setAutoUpdate(true);
1646 DataObjectList ch = guiRootObj->children();
1647 for( int i = 0; i < ch.size(); i++ )
1650 ob->setAutoUpdate(isAutoUpdate);
1653 // case 2: no more save points but root does not exist either
1654 if ( savePoints.empty() && !guiRootObj )
1656 // case 3: save points but no root for them - create it
1657 if ( !savePoints.empty() && !guiRootObj )
1658 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1659 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1660 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1662 if ( guiRootObj->nextBrother() ) {
1663 study->root()->removeChild(guiRootObj);
1664 study->root()->appendChild(guiRootObj);
1665 //study->root()->dump();
1668 // store data objects in a map id-to-DataObject
1669 QMap<int,SalomeApp_SavePointObject*> mapDO;
1671 guiRootObj->children( ch );
1672 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1673 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1675 mapDO[dobj->getId()] = dobj;
1678 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1679 // if in the map - remove it from map.
1680 for ( int i = 0; i < savePoints.size(); i++ )
1681 if ( !mapDO.contains( savePoints[i] ) )
1682 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1684 mapDO.remove( savePoints[i] );
1686 // delete DataObjects that are still in the map -- their IDs were not found in data model
1687 if( mapDO.size() > 0) {
1688 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1689 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1690 selMgr->clearSelected();
1691 const bool isAutoUpdate = ob->autoUpdate();
1692 ob->setAutoUpdate(true);
1693 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1695 ob->setAutoUpdate(isAutoUpdate);
1699 /*! Check data object */
1700 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1709 Opens other study into active Study. If Study is empty - creates it.
1710 \param theName - name of study
1712 bool SalomeApp_Application::useStudy( const QString& theName )
1715 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1718 res = aStudy->loadDocument( theName );
1719 updateDesktopTitle();
1720 updateCommandsStatus();
1724 /*! Show/hide object browser colums according to preferences */
1725 void SalomeApp_Application::objectBrowserColumnsVisibility()
1727 if ( objectBrowser() )
1728 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1730 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1731 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1735 #ifndef DISABLE_PYCONSOLE
1736 /*! Set SalomeApp_NoteBook pointer */
1737 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1739 myNoteBook = theNoteBook;
1742 /*! Return SalomeApp_NoteBook pointer */
1743 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1750 * Define extra actions defined in module definition XML file.
1751 * Additional popup items sections can be defined by parameter "popupitems".
1752 * Supported attributes:
1753 * title - title of menu item,
1754 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1755 * method - method which has to be called when menu item is selected
1757 * <section name="MODULENAME">
1758 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1760 * <section name="importmed">
1761 * <parameter name="title" value="My menu"/>
1762 * <parameter name="objectid" value="VISU.Result"/>
1763 * <parameter name="method" value="nameOfModuleMethod"/>
1766 void SalomeApp_Application::createExtraActions()
1768 myExtActions.clear();
1769 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1771 QStringList aModules;
1772 modules(aModules, false);
1773 foreach(QString aModile, aModules) {
1774 QString aModName = moduleName(aModile);
1775 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1776 if (!aSectionStr.isNull()) {
1777 QStringList aSections = aSectionStr.split(':');
1778 foreach(QString aSection, aSections) {
1779 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1780 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1781 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1782 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1785 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1786 if (aModuleName.isNull())
1787 aModuleName = aModName;
1789 QAction* aAction = new QAction(aTitle, this);
1791 aData<<aModuleName<<aSlot;
1792 aAction->setData(aData);
1793 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1794 myExtActions[aId] = aAction;
1801 * Called when extra action is selected
1803 void SalomeApp_Application::onExtAction()
1805 QAction* aAction = ::qobject_cast<QAction*>(sender());
1809 QVariant aData = aAction->data();
1810 QStringList aDataList = aData.value<QStringList>();
1811 if (aDataList.size() != 2)
1814 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1815 SALOME_ListIO aListIO;
1816 aSelectionMgr->selectedObjects(aListIO);
1817 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1818 if (aListIO.Extent() < 1)
1820 if (!anIO->hasEntry())
1823 QString aEntry(anIO->getEntry());
1825 QApplication::setOverrideCursor( Qt::WaitCursor );
1826 QString aModuleTitle = moduleTitle(aDataList[0]);
1827 activateModule(aModuleTitle);
1828 QApplication::restoreOverrideCursor();
1830 QCoreApplication::processEvents();
1832 CAM_Module* aModule = activeModule();
1836 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1837 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1841 * Called when window activated
1843 void SalomeApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
1845 SUIT_DataBrowser* anOB = objectBrowser();
1848 SUIT_DataObject* rootObj = anOB->root();
1852 DataObjectList listObj = rootObj->children( true );
1854 SUIT_ViewModel* vmod = 0;
1855 if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
1856 vmod = vman->getViewModel();
1857 updateVisibilityState( listObj, vmod );
1861 Update visibility state of given objects
1863 void SalomeApp_Application::updateVisibilityState( DataObjectList& theList,
1864 SUIT_ViewModel* theViewModel )
1866 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1871 SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
1873 if (theList.isEmpty() || !aStudy)
1876 for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
1877 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
1879 if (!obj || aStudy->isComponent(obj->entry()))
1882 LightApp_Module* anObjModule = dynamic_cast<LightApp_Module*>(obj->module());
1883 Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
1886 LightApp_Displayer* aDisplayer = anObjModule->displayer();
1888 if( aDisplayer->canBeDisplayed(obj->entry(), theViewModel->getType()) ) {
1889 if(aView && aDisplayer->IsDisplayed(obj->entry(),aView))
1890 anObjState = Qtx::ShownState;
1892 anObjState = Qtx::HiddenState;
1894 aStudy->setVisibilityState( obj->entry(), anObjState );
1901 Called then view manager removed
1903 void SalomeApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
1905 ViewManagerList lst;
1907 if( lst.count() == 1) { // in case if closed last view window
1908 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
1910 aStudy->setVisibilityStateForAll(Qtx::UnpresentableState);
1915 Checks that an object can be renamed.
1916 \param entry entry of the object
1917 \brief Return \c true if object can be renamed
1919 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1921 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1925 Rename object by entry.
1926 \param entry entry of the object
1927 \param name new name of the object
1928 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1930 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1932 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1934 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1936 if(!aStudy || savePoint == -1)
1939 if ( !name.isNull() && !name.isEmpty() ) {
1940 aStudy->setNameOfSavePoint( savePoint, name );
1941 updateSavePointDataObjects( aStudy );
1943 //Mark study as modified
1951 \return default windows( Object Browser, Python Console )
1952 Adds to map \a aMap.
1954 void SalomeApp_Application::defaultWindows( QMap<int, int>& aMap ) const
1956 LightApp_Application::defaultWindows(aMap);
1957 #ifndef DISABLE_PYCONSOLE
1958 if ( !aMap.contains( WT_NoteBook ) ) {
1959 if ( !myNoteBook ) {
1960 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1967 Gets current windows.
1968 \param winMap - output current windows map.
1970 void SalomeApp_Application::currentWindows(QMap<int, int>& aMap) const
1972 LightApp_Application::currentWindows( aMap );
1973 #ifndef DISABLE_PYCONSOLE
1974 if ( !aMap.contains( WT_NoteBook) && myNoteBook )
1975 aMap.insert( WT_NoteBook, Qt::LeftDockWidgetArea );
1979 #ifndef DISABLE_PYCONSOLE
1980 //============================================================================
1981 /*! Function : onUpdateStudy
1982 * Purpose : Slot to update the study.
1984 //============================================================================
1985 void SalomeApp_Application::onUpdateStudy()
1987 QApplication::setOverrideCursor( Qt::WaitCursor );
1989 if( !updateStudy() )
1990 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1992 QApplication::restoreOverrideCursor();
1995 //============================================================================
1996 /*! Function : updateStudy
1997 * Purpose : Update study by dumping the study to Python script and loading it.
1998 * It is used to apply variable modifications done in NoteBook to created objects.
2000 //============================================================================
2001 bool SalomeApp_Application::updateStudy()
2003 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
2004 if ( !study || !myNoteBook )
2007 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
2008 myNoteBook->setDumpedStudyName( study->studyName() );
2010 _PTR(Study) studyDS = study->studyDS();
2012 // get unique temporary directory name
2013 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
2014 if( aTmpDir.isEmpty() )
2017 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
2018 aTmpDir.remove( aTmpDir.length() - 1, 1 );
2020 // dump study to the temporary directory
2021 QString aScriptName( "notebook" );
2022 bool toPublish = true;
2023 bool isMultiFile = false;
2024 bool toSaveGUI = true;
2027 _PTR(AttributeParameter) ap;
2028 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2029 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
2030 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2031 ip->setDumpPython(studyDS);
2032 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2034 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2036 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2039 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2043 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2044 int anIndex = aList.indexOf( this );
2046 // Disconnect dialog from application desktop in case if:
2047 // 1) Application is not the first application in the session
2048 // 2) Application is the first application in session but not the only.
2049 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2050 if( changeDesktop ) {
2052 SalomeApp_Application* app = this;
2053 if( anIndex > 0 && anIndex < aList.count() )
2054 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2055 else if(anIndex == 0 && aList.count() > 1)
2056 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2061 // creation a new study and restoring will be done in another application
2062 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2063 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2066 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2067 QString aStudyName = myNoteBook->getDumpedStudyName();
2068 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2069 // clear a study (delete all objects)
2070 onCloseDoc( false );
2072 if( !changeDesktop ) {
2073 ok = onRestoreStudy( aDumpScript,
2082 //============================================================================
2083 /*! Function : onRestoreStudy
2084 * Purpose : Load the dumped study from Python script
2086 //============================================================================
2087 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2088 const QString& theStudyName,
2089 bool theIsStudySaved )
2093 // create a new study
2096 // get active application
2097 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2099 // load study from the temporary directory
2100 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2102 #ifndef DISABLE_PYCONSOLE
2103 PyConsole_Console* pyConsole = app->pythonConsole();
2105 pyConsole->execAndWait( command );
2108 // remove temporary directory
2109 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2110 QString aStudyName = aScriptInfo.baseName();
2111 QDir aDir = aScriptInfo.absoluteDir();
2112 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2113 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2114 ok = aDir.remove( *it ) && ok;
2116 ok = aDir.rmdir( aDir.absolutePath() );
2118 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2120 #ifndef DISABLE_PYCONSOLE
2121 _PTR(Study) aStudyDS = newStudy->studyDS();
2122 app->getNoteBook()->Init( aStudyDS );
2123 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2124 newStudy->Modified();
2125 updateDesktopTitle();
2136 Close the Application
2138 void SalomeApp_Application::afterCloseDoc()
2140 #ifndef DISABLE_PYCONSOLE
2141 // emit signal to restore study from Python script
2143 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2144 myNoteBook->getDumpedStudyName(),
2145 myNoteBook->isDumpedStudySaved() );
2148 LightApp_Application::afterCloseDoc();