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>
58 #include <CAM_Module.h>
60 #include <SUIT_Tools.h>
61 #include <SUIT_Session.h>
62 #include <SUIT_Desktop.h>
63 #include <SUIT_DataBrowser.h>
64 #include <SUIT_FileDlg.h>
65 #include <SUIT_FileValidator.h>
66 #include <SUIT_MessageBox.h>
67 #include <SUIT_ResourceMgr.h>
68 #include <SUIT_TreeModel.h>
69 #include <SUIT_ViewWindow.h>
70 #include <SUIT_ViewManager.h>
71 #include <SUIT_ViewModel.h>
72 #include <SUIT_OverrideCursor.h>
74 #include <QtxTreeView.h>
76 #include <SALOME_EventFilter.h>
78 // temporary commented
79 //#include <OB_ListItem.h>
82 #include <Utils_ORB_INIT.hxx>
83 #include <Utils_SINGLETON.hxx>
84 #include <SALOME_LifeCycleCORBA.hxx>
86 #include <QApplication>
90 #include <QPushButton>
92 #include <QListWidget>
93 #include <QGridLayout>
97 #include <SALOMEDSClient_ClientFactory.hxx>
98 #include <Basics_Utils.hxx>
100 #include <SALOME_ListIO.hxx>
101 #include <SALOME_ListIteratorOfListIO.hxx>
102 #include <SALOME_Prs.h>
105 #include <ToolsGUI_CatalogGeneratorDlg.h>
106 #include <ToolsGUI_RegWidget.h>
110 #include <SALOMEDS_Tool.hxx>
112 /*!Internal class that updates object browser item properties */
113 // temporary commented
114 /*class SalomeApp_Updater : public OB_Updater
117 SalomeApp_Updater() : OB_Updater(){};
118 virtual ~SalomeApp_Updater(){};
119 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
122 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
124 if( !theObj || !theItem )
127 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
131 _PTR(SObject) SObj = SAObj->object();
134 _PTR( GenericAttribute ) anAttr;
137 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
139 _PTR(AttributeSelectable) aAttrSel = anAttr;
140 theItem->setSelectable( aAttrSel->IsSelectable() );
143 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
145 _PTR(AttributeExpandable) aAttrExpand = anAttr;
146 theItem->setExpandable( aAttrExpand->IsExpandable() );
149 //this attribute is not supported in the version of SALOME 3.x
150 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
152 // _PTR(AttributeOpened) aAttrOpen = anAttr;
153 // theItem->setOpen( aAttrOpen->IsOpened() );
157 /*!Create new instance of SalomeApp_Application.*/
158 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
160 return new SalomeApp_Application();
164 SalomeApp_Application::SalomeApp_Application()
165 : LightApp_Application(),
167 myIsCloseFromExit( false )
172 *\li Destroy event filter.
174 SalomeApp_Application::~SalomeApp_Application()
176 // Do not destroy. It's a singleton !
177 //SALOME_EventFilter::Destroy();
180 /*!Start application.*/
181 void SalomeApp_Application::start()
183 // process the command line options before start: to createActions in accordance to the options
184 static bool isFirst = true;
192 for (int i = 1; i < qApp->argc(); i++) {
193 QRegExp rxs ("--study-hdf=(.+)");
194 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
195 QString file = rxs.capturedTexts()[1];
196 QFileInfo fi ( file );
197 QString extension = fi.suffix().toLower();
198 if ( extension == "hdf" && fi.exists() )
199 hdffile = fi.absoluteFilePath();
202 QRegExp rxp ("--pyscript=\\[(.+)\\]");
203 QRegExp rxl ("--siman-study=(.+)");
204 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
206 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
207 for (int k = 0; k < dictList.count(); ++k) {
208 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
209 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
210 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
211 pyfiles += rxd.capturedTexts()[m];
217 if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
219 loadStudy = rxl.capturedTexts()[1];
225 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
226 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
228 LightApp_Application::start();
229 SALOME_EventFilter::Init();
231 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
232 onOpenDoc( hdffile );
233 else if ( pyfiles.count() > 0 ) // create new study
235 else if (!loadStudy.isEmpty()) {// load study by name
236 if (onLoadDoc(loadStudy))
237 updateObjectBrowser(true);
240 #ifndef DISABLE_PYCONSOLE
241 // import/execute python scripts
242 if ( pyfiles.count() > 0 && activeStudy() ) {
243 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
244 PyConsole_Console* pyConsole = pythonConsole();
245 if ( appStudy && pyConsole ) {
246 _PTR(Study) aStudy = appStudy->studyDS();
247 if ( !aStudy->GetProperties()->IsLocked() ) {
248 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
249 // Path is absolute, script has .py extension
250 for (uint j = 0; j < pyfiles.count(); j++ ) {
251 // Extract scripts and their arguments, if any
252 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
253 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
254 QString script = rxp.capturedTexts()[1];
256 QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
257 for (uint k = 0; k < argList.count(); k++ ) {
258 QString arg = argList[k].trimmed();
259 arg.remove( QRegExp("^[\"]") );
260 arg.remove( QRegExp("[\"]$") );
263 args.remove( QRegExp("[,]$") );
264 if (!args.isEmpty()) {
268 script.remove( QRegExp("^python.*[\\s]+") );
269 QString cmd = script+" "+args;
270 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
271 pyConsole->exec(command);
273 } // end for loop on pyfiles QStringList
279 LightApp_Application::start();
280 SALOME_EventFilter::Init();
285 void SalomeApp_Application::createActions()
287 LightApp_Application::createActions();
289 SUIT_Desktop* desk = desktop();
292 // "Save GUI State" command is moved to VISU module
293 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
294 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
295 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
298 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
299 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
300 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
303 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
304 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
305 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
308 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
309 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
310 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
312 //! Catalog Generator
313 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
314 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
315 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
318 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
319 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
320 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
322 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
323 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
324 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
326 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
327 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
328 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
333 // check-in operations for SIMAN study
334 createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
335 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
336 0, desk, false, this, SLOT( onCheckIn() ) );
337 createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
338 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
339 0, desk, false, this, SLOT( onLocalCheckIn() ) );
343 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
345 // "Save GUI State" command is renamed to "Save VISU State" and
346 // creation of menu item is moved to VISU
347 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
349 createMenu( ConnectId, fileMenu, 5 );
350 createMenu( DisconnectId, fileMenu, 5 );
351 createMenu( separator(), fileMenu, -1, 5 );
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( LoadScriptId, fileMenu, 10, -1 );
364 createMenu( separator(), fileMenu, -1, 10, -1 );
365 createMenu( PropertiesId, fileMenu, 10, -1 );
366 createMenu( separator(), fileMenu, -1, 10, -1 );
368 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
369 createMenu( CatalogGenId, toolsMenu, 10, -1 );
370 createMenu( RegDisplayId, toolsMenu, 10, -1 );
371 createMenu( separator(), toolsMenu, -1, 15, -1 );
373 createExtraActions();
375 #ifndef DISABLE_PYCONSOLE
376 #ifndef DISABLE_SALOMEOBJECT
377 // import Python module that manages SALOME plugins
379 PyLockWrapper lck; // acquire GIL
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());
385 // end of SALOME plugins loading
392 \brief Close application.
394 void SalomeApp_Application::onExit()
396 bool killServers = false;
399 if ( exitConfirmation() ) {
400 SalomeApp_ExitDlg dlg( desktop() );
401 result = dlg.exec() == QDialog::Accepted;
402 killServers = dlg.isServersShutdown();
406 if ( !killServers ) myIsCloseFromExit = true;
407 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
408 myIsCloseFromExit = false;
412 /*!SLOT. Load document.*/
413 void SalomeApp_Application::onLoadDoc()
417 std::vector<std::string> List = studyMgr()->GetOpenStudies();
419 // rnv: According to the single-study approach on the server side
420 // can be only one study. So if it is exists connect to them,
421 // overwise show warning message: "No active study on the server"
424 SUIT_Session* aSession = SUIT_Session::session();
425 QList<SUIT_Application*> aAppList = aSession->applications();
427 QStringList unloadedStudies;
429 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
430 studyName = List[ind].c_str();
431 // Add to list only unloaded studies
432 bool isAlreadyOpen = false;
433 QListIterator<SUIT_Application*> it( aAppList );
434 while ( it.hasNext() && !isAlreadyOpen ) {
435 SUIT_Application* aApp = it.next();
436 if( !aApp || !aApp->activeStudy() )
438 if ( aApp->activeStudy()->studyName() == studyName )
439 isAlreadyOpen = true;
442 if ( !isAlreadyOpen )
443 unloadedStudies << studyName;
445 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
446 if ( studyName.isEmpty() )
450 if(List.size() <= 0) {
451 SUIT_MessageBox::warning( desktop(),
452 QObject::tr("WRN_WARNING"),
453 QObject::tr("WRN_NO_STUDY_ON SERV") );
457 studyName = List[0].c_str();
460 // this code replaces marker of windows drive and path become invalid therefore
461 // defines placed there
462 studyName.replace( QRegExp(":"), "/" );
465 if ( onLoadDoc( studyName ) ) {
467 updateViewManagers();
468 updateObjectBrowser( true );
472 /*!SLOT. Unload document.*/
473 void SalomeApp_Application::onUnloadDoc( bool ask )
476 activeStudy()->abortAllOperations();
477 if ( activeStudy()->isModified() ) {
478 QString docName = activeStudy()->studyName().trimmed();
479 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
480 tr( "DISCONNECT_DESCRIPTION" ),
481 tr( "DISCONNECT_SAVE" ),
482 tr( "DISCONNECT_WO_SAVE" ),
483 tr( "APPCLOSE_CANCEL" ), 0 );
484 if ( answer == 0 ) { // save before unload
485 if ( activeStudy()->isSaved() )
487 else if ( !onSaveAsDoc() )
490 else if ( answer == 2 ) // Cancel
494 closeActiveDoc( false );
497 /*!SLOT. Create new study and load script*/
498 void SalomeApp_Application::onNewWithScript()
500 QStringList filtersList;
501 filtersList.append(tr("PYTHON_FILES_FILTER"));
502 filtersList.append(tr("ALL_FILES_FILTER"));
504 QString anInitialPath = "";
505 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
506 anInitialPath = QDir::currentPath();
508 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
510 if ( !aFile.isEmpty() )
514 QString command = QString("execfile(r\"%1\")").arg(aFile);
516 #ifndef DISABLE_PYCONSOLE
517 PyConsole_Console* pyConsole = pythonConsole();
520 pyConsole->exec( command );
526 /*!SLOT. Load document with \a aName.*/
527 bool SalomeApp_Application::onLoadDoc( const QString& aName )
529 #ifdef SINGLE_DESKTOP
530 if ( !LightApp_Application::closeDoc() )
534 if ( !activeStudy() ) {
535 // if no study - load in current desktop
536 res = useStudy( aName );
539 // if study exists - load in new desktop. Check: is the same file is loaded?
540 SUIT_Session* aSession = SUIT_Session::session();
541 QList<SUIT_Application*> aAppList = aSession->applications();
542 bool isAlreadyOpen = false;
543 SalomeApp_Application* aApp = 0;
544 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
545 it != aAppList.end() && !isAlreadyOpen; ++it ) {
546 aApp = dynamic_cast<SalomeApp_Application*>( *it );
547 if ( aApp && aApp->activeStudy()->studyName() == aName )
548 isAlreadyOpen = true;
550 if ( !isAlreadyOpen ) {
551 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
553 res = aApp->useStudy( aName );
556 aApp->desktop()->activateWindow();
563 /*!SLOT. Parse message for desktop.*/
564 void SalomeApp_Application::onDesktopMessage( const QString& message )
566 if (message.indexOf("simanCheckoutDone ") == 0) {
568 // Load document with a name, specified in aMessage.
569 onLoadDoc(message.section(' ', 1));
571 printf( "****************************************************************\n" );
572 printf( "* Warning: SALOME is built without SIMAN support.\n" );
573 printf( "****************************************************************\n" );
576 else if (message.indexOf("studyCreated:") == 0) {
577 // Enable 'Connect' action
578 updateCommandsStatus();
580 else if (message.indexOf("studyClosed:") == 0) {
581 /* message also contains ID of the closed study,
582 but as soon as SALOME is mono-study application for the moment,
583 this ID is not needed now.*/
584 //long aStudyId = message.section(':', 1).toLong();
585 // Disconnect GUI from active study, because it was closed on DS side.
586 closeActiveDoc( false );
587 // Disable 'Connect' action
588 QAction* a = action( ConnectId );
590 a->setEnabled( false );
592 LightApp_Application::onDesktopMessage( message );
595 /*!SLOT. Copy objects to study maneger from selection maneger..*/
596 void SalomeApp_Application::onCopy()
599 LightApp_SelectionMgr* mgr = selectionMgr();
600 mgr->selectedObjects(list);
602 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
603 if(study == NULL) return;
605 _PTR(Study) stdDS = study->studyDS();
608 SALOME_ListIteratorOfListIO it( list );
611 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
613 studyMgr()->Copy(so);
614 onSelectionChanged();
621 /*!SLOT. Paste objects to study maneger from selection manager.*/
622 void SalomeApp_Application::onPaste()
625 LightApp_SelectionMgr* mgr = selectionMgr();
626 mgr->selectedObjects(list);
628 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
629 if(study == NULL) return;
631 _PTR(Study) stdDS = study->studyDS();
634 if ( stdDS->GetProperties()->IsLocked() ) {
635 SUIT_MessageBox::warning( desktop(),
636 QObject::tr("WRN_WARNING"),
637 QObject::tr("WRN_STUDY_LOCKED") );
641 SALOME_ListIteratorOfListIO it( list );
644 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
646 studyMgr()->Paste(so);
647 updateObjectBrowser( true );
648 updateActions(); //SRN: BugID IPAL9377, case 3
655 /*!Check the application on closing.
656 * \retval true if possible, else false
658 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
660 return LightApp_Application::isPossibleToClose( closePermanently );
663 /*! Check if the study is locked */
664 void SalomeApp_Application::onCloseDoc( bool ask )
666 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
669 _PTR(Study) stdDS = study->studyDS();
670 if(stdDS && stdDS->IsStudyLocked()) {
671 if ( SUIT_MessageBox::question( desktop(),
672 QObject::tr( "WRN_WARNING" ),
673 QObject::tr( "CLOSE_LOCKED_STUDY" ),
674 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
675 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
679 LightApp_Application::onCloseDoc( ask );
682 /*!Sets enable or disable some actions on selection changed.*/
683 void SalomeApp_Application::onSelectionChanged()
686 LightApp_SelectionMgr* mgr = selectionMgr();
687 mgr->selectedObjects(list);
689 bool canCopy = false;
690 bool canPaste = false;
692 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
694 _PTR(Study) stdDS = study->studyDS();
697 SALOME_ListIteratorOfListIO it ( list );
699 if (it.More() && list.Extent() == 1) {
700 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
703 canCopy = studyMgr()->CanCopy(so);
704 canPaste = studyMgr()->CanPaste(so);
710 action(EditCopyId)->setEnabled(canCopy);
711 action(EditPasteId)->setEnabled(canPaste);
714 /*!Delete references.*/
715 void SalomeApp_Application::onDeleteInvalidReferences()
718 LightApp_SelectionMgr* mgr = selectionMgr();
719 mgr->selectedObjects( aList, QString(), false );
721 if( aList.IsEmpty() )
724 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
725 _PTR(Study) aStudyDS = aStudy->studyDS();
726 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
729 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
730 if ( it.Value()->hasEntry() )
732 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
733 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
736 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
737 aStudyBuilder->RemoveReference( aSObject );
739 updateObjectBrowser();
743 void SalomeApp_Application::onOpenWith()
745 QApplication::setOverrideCursor( Qt::WaitCursor );
747 LightApp_SelectionMgr* mgr = selectionMgr();
748 mgr->selectedObjects(aList);
749 if (aList.Extent() != 1)
751 QApplication::restoreOverrideCursor();
754 Handle(SALOME_InteractiveObject) aIObj = aList.First();
755 QString aModuleName(aIObj->getComponentDataType());
756 QString aModuleTitle = moduleTitle(aModuleName);
757 activateModule(aModuleTitle);
758 QApplication::restoreOverrideCursor();
764 SUIT_Study* SalomeApp_Application::createNewStudy()
766 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
768 // Set up processing of major study-related events
769 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
770 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
771 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
772 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
774 #ifndef DISABLE_PYCONSOLE
775 //to receive signal in application that NoteBook's variable was modified
776 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
777 this, SIGNAL(notebookVarUpdated(QString)) );
784 Enable/Disable menu items and toolbar buttons. Rebuild menu
786 void SalomeApp_Application::updateCommandsStatus()
788 LightApp_Application::updateCommandsStatus();
791 QAction* a = action( DumpStudyId );
793 a->setEnabled( activeStudy() );
796 a = action( LoadScriptId );
798 a->setEnabled( pythonConsole() );
801 a = action( PropertiesId );
803 a->setEnabled( activeStudy() );
805 // Save GUI state menu
806 a = action( SaveGUIStateId );
808 a->setEnabled( activeStudy() );
810 // Connect study menu
811 a = action( ConnectId );
813 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
815 // Disconnect study menu
816 a = action( DisconnectId );
818 a->setEnabled( activeStudy() );
820 // update state of Copy/Paste menu items
821 onSelectionChanged();
825 \class DumpStudyFileDlg
826 Private class used in Dump Study operation. Consists 2 check boxes:
827 "Publish in study" and "Save GUI parameters"
829 class DumpStudyFileDlg : public SUIT_FileDlg
832 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
834 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
837 QWidget *hB = new QWidget( this );
838 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
839 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
840 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
842 QHBoxLayout *layout = new QHBoxLayout;
843 layout->addWidget(myPublishChk);
844 layout->addWidget(myMultiFileChk);
845 layout->addWidget(mySaveGUIChk);
846 hB->setLayout(layout);
848 QPushButton* pb = new QPushButton(this);
850 int row = grid->rowCount();
851 grid->addWidget( new QLabel("", this), row, 0 );
852 grid->addWidget( hB, row, 1, 1, 3 );
853 grid->addWidget( pb, row, 5 );
858 QCheckBox* myPublishChk;
859 QCheckBox* myMultiFileChk;
860 QCheckBox* mySaveGUIChk;
863 class DumpStudyFileValidator : public SUIT_FileValidator
866 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
867 virtual ~DumpStudyFileValidator() {};
868 virtual bool canSave( const QString& file, bool permissions );
871 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
873 QFileInfo fi( file );
874 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
875 SUIT_MessageBox::critical( parent(),
876 QObject::tr("WRN_WARNING"),
877 QObject::tr("WRN_FILE_NAME_BAD") );
880 return SUIT_FileValidator::canSave( file, permissions);
883 /*!Private SLOT. On dump study.*/
884 void SalomeApp_Application::onDumpStudy( )
886 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
887 if ( !appStudy ) return;
888 _PTR(Study) aStudy = appStudy->studyDS();
890 QStringList aFilters;
891 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
893 bool anIsPublish = true;
894 bool anIsMultiFile = false;
895 bool anIsSaveGUI = true;
897 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
898 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
899 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
900 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
903 DumpStudyFileDlg fd( desktop() );
904 fd.setValidator( new DumpStudyFileValidator( &fd ) );
905 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
906 fd.setFilters( aFilters );
907 fd.myPublishChk->setChecked( anIsPublish );
908 fd.myMultiFileChk->setChecked( anIsMultiFile );
909 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
910 if ( fd.exec() == QDialog::Accepted )
912 QString aFileName = fd.selectedFile();
914 bool toPublish = fd.myPublishChk->isChecked();
915 bool isMultiFile = fd.myMultiFileChk->isChecked();
916 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
918 if ( !aFileName.isEmpty() ) {
919 QFileInfo aFileInfo(aFileName);
920 if( aFileInfo.isDir() ) // IPAL19257
923 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
926 SUIT_OverrideCursor wc;
927 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
930 SUIT_MessageBox::warning( desktop(),
931 QObject::tr("WRN_WARNING"),
932 tr("WRN_DUMP_STUDY_FAILED") );
937 /*!Private SLOT. On load script.*/
938 void SalomeApp_Application::onLoadScript( )
940 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
942 _PTR(Study) aStudy = appStudy->studyDS();
943 if ( aStudy->GetProperties()->IsLocked() ) {
944 SUIT_MessageBox::warning( desktop(),
945 QObject::tr("WRN_WARNING"),
946 QObject::tr("WRN_STUDY_LOCKED") );
951 QStringList filtersList;
952 filtersList.append(tr("PYTHON_FILES_FILTER"));
953 filtersList.append(tr("ALL_FILES_FILTER"));
955 QString anInitialPath = "";
956 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
957 anInitialPath = QDir::currentPath();
960 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
962 SALOMEDSClient_StudyManager* aMgr = studyMgr();
963 aMgr->GetSimanStudy()->StudyId();
964 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
965 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
966 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
970 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
972 if ( !aFile.isEmpty() )
974 QString command = QString("execfile(r\"%1\")").arg(aFile);
976 #ifndef DISABLE_PYCONSOLE
977 PyConsole_Console* pyConsole = pythonConsole();
980 pyConsole->exec( command );
985 /*!Private SLOT. On save GUI state.*/
986 void SalomeApp_Application::onSaveGUIState()
988 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
990 SalomeApp_VisualState( this ).storeState();
991 updateSavePointDataObjects( study );
992 updateObjectBrowser();
997 /*!Public SLOT. On SIMAN check in operation.*/
998 void SalomeApp_Application::onCheckIn()
1001 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1002 setMenuShown(SimanLocalCheckInId, false);
1003 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1004 aMgr->GetSimanStudy()->CheckIn("");
1006 printf( "****************************************************************\n" );
1007 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1008 printf( "****************************************************************\n" );
1012 /*!Public SLOT. On SIMAN local check in operation.*/
1013 void SalomeApp_Application::onLocalCheckIn()
1016 // get the active module
1017 CAM_Module* aModule = activeModule();
1018 if (!aModule) return; // there is no active module
1020 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1021 setMenuShown(SimanLocalCheckInId, false);
1022 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1023 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1025 printf( "****************************************************************\n" );
1026 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1027 printf( "****************************************************************\n" );
1031 /*!Gets file filter.
1032 *\retval QString "(*.hdf)"
1034 QString SalomeApp_Application::getFileFilter() const
1040 QWidget* SalomeApp_Application::createWindow( const int flag )
1043 #ifndef DISABLE_PYCONSOLE
1044 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1046 wid = LightApp_Application::createWindow(flag);
1049 SUIT_ResourceMgr* resMgr = resourceMgr();
1051 if ( flag == WT_ObjectBrowser )
1053 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1055 // temporary commented
1056 //ob->setUpdater( new SalomeApp_Updater() );
1058 #ifdef WITH_SALOMEDS_OBSERVER
1059 //do not activate the automatic update of Qt tree through signal/slot
1060 ob->setAutoUpdate(false);
1061 //activate update of modified objects only
1062 ob->setUpdateModified(true);
1065 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1068 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1069 IORCol = QObject::tr( "IOR_COLUMN" ),
1070 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1071 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1073 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1074 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1075 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1076 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1077 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1078 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1079 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1080 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1081 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1083 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1084 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1085 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1087 ob->setAutoSizeFirstColumn(autoSizeFirst);
1088 ob->setAutoSizeColumns(autoSize);
1089 ob->setResizeOnExpandItem(resizeOnExpandItem);
1090 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1092 // temporary commented
1094 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1096 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1097 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1098 QString().sprintf( "visibility_column_%d", i ), true ) );
1102 // temporary commented
1104 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1105 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1106 ob->resize( desktop()->width()/3, ob->height() );
1110 #ifndef DISABLE_PYCONSOLE
1111 else if ( flag == WT_PyConsole )
1113 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1114 pyCons->setObjectName( "pythonConsole" );
1115 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1116 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1117 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1118 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1120 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1121 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1123 else if ( flag == WT_NoteBook )
1125 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1127 _PTR(Study) aStudy = appStudy->studyDS();
1128 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1129 //to receive signal in NoteBook that it's variable was modified
1130 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1131 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1133 wid = getNoteBook();
1134 wid->setObjectName( "noteBook" );
1140 /*!Create preferences.*/
1141 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1143 LightApp_Application::createPreferences(pref);
1148 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1149 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1150 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1151 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1153 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1154 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1156 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1158 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1159 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1160 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1161 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1162 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1163 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1164 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1165 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1166 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1167 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1170 /*!Update desktop title.*/
1171 void SalomeApp_Application::updateDesktopTitle() {
1172 QString aTitle = applicationName();
1173 QString aVer = applicationVersion();
1174 if ( !aVer.isEmpty() )
1175 aTitle += QString( " " ) + aVer;
1177 if ( activeStudy() )
1179 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1180 if ( !sName.isEmpty() ) {
1181 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1183 _PTR(Study) stdDS = study->studyDS();
1185 if ( stdDS->GetProperties()->IsLocked() ) {
1186 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1188 aTitle += QString( " - [%1]" ).arg( sName );
1195 desktop()->setWindowTitle( aTitle );
1198 int SalomeApp_Application::closeChoice( const QString& docName )
1200 QStringList buttons;
1201 QMap<int, int> choices;
1203 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1204 choices.insert( idx++, CloseSave ); // ...
1205 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1206 choices.insert( idx++, CloseDiscard ); // ...
1207 if ( myIsCloseFromExit ) {
1208 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1209 choices.insert( idx++, CloseDisconnectSave ); // ...
1210 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1211 choices.insert( idx++, CloseDisconnect ); // ...
1213 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1214 choices.insert( idx++, CloseCancel ); // ...
1216 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1217 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1218 return choices[answer];
1221 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1227 if ( activeStudy()->isSaved() )
1229 else if ( !onSaveAsDoc() )
1234 case CloseDisconnectSave:
1235 if ( activeStudy()->isSaved() )
1237 else if ( !onSaveAsDoc() )
1239 case CloseDisconnect:
1240 closeActiveDoc( false );
1241 closePermanently = false;
1250 int SalomeApp_Application::openChoice( const QString& aName )
1252 int choice = LightApp_Application::openChoice( aName );
1254 if ( QFileInfo( aName ).exists() ) {
1255 if ( choice == OpenNew ) { // The document isn't already open.
1257 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1258 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1259 if ( aName == QString( lst[i].c_str() ) )
1262 // The document already exists in the study manager.
1263 // Do you want to reload it?
1265 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1266 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1267 if ( answer == SUIT_MessageBox::Yes )
1268 choice = OpenRefresh;
1270 choice = OpenCancel;
1273 } else { // file is not exist on disk
1274 SUIT_MessageBox::warning( desktop(),
1275 QObject::tr("WRN_WARNING"),
1276 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1283 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1286 int choice = aChoice;
1291 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1294 studyMgr()->Close( aStudy );
1299 res = LightApp_Application::openAction( choice, aName );
1307 \brief Get map of the operations which can be performed
1308 on the module activation.
1310 The method should return the map of the kind \c {<id>:<name>}
1311 where \c <id> is an integer identifier of the operation and
1312 \c <name> is a title for the button to be added to the
1313 dialog box. After user selects the required operation by the
1314 clicking the corresponding button in the dialog box, its identifier
1315 is passed to the moduleActionSelected() method to process
1318 \return map of the operations
1319 \sa moduleActionSelected()
1321 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1323 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1325 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1327 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1332 \brief Called when the used selectes required operation chosen
1333 from "Activate module" dialog box.
1335 Performs the required operation according to the user choice.
1337 \param id operation identifier
1338 \sa activateModuleActions()
1340 void SalomeApp_Application::moduleActionSelected( const int id )
1346 case NewAndScriptId:
1350 LightApp_Application::moduleActionSelected( id );
1355 /*!Gets CORBA::ORB_var*/
1356 CORBA::ORB_var SalomeApp_Application::orb()
1358 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1359 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1363 /*!Create and return SALOMEDS_StudyManager.*/
1364 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1366 static _PTR(StudyManager) _sm;
1367 if(!_sm) _sm = ClientFactory::StudyManager();
1371 /*!Create and return SALOME_NamingService.*/
1372 SALOME_NamingService* SalomeApp_Application::namingService()
1374 static SALOME_NamingService _ns(orb());
1378 /*!Create and return SALOME_LifeCycleCORBA.*/
1379 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1381 static SALOME_LifeCycleCORBA _lcc( namingService() );
1385 /*!Private SLOT. On preferences.*/
1386 void SalomeApp_Application::onProperties()
1388 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1392 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1395 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1396 int res = aDlg.exec();
1397 if( res==QDialog::Accepted && aDlg.isChanged() )
1398 SB->CommitCommand();
1402 //study->updateCaptions();
1403 updateDesktopTitle();
1407 /*!Insert items in popup, which necessary for current application*/
1408 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1410 LightApp_SelectionMgr* mgr = selectionMgr();
1411 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1412 mgr->setSelectionCacheEnabled( true );
1414 LightApp_Application::contextMenuPopup( type, thePopup, title );
1416 // temporary commented
1417 /*OB_Browser* ob = objectBrowser();
1418 if ( !ob || type != ob->popupClientType() )
1421 // Get selected objects
1422 SALOME_ListIO aList;
1423 mgr->selectedObjects( aList, QString(), false );
1425 // add GUI state commands: restore, rename
1426 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1427 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1428 thePopup->addSeparator();
1429 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1430 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1431 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1432 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1435 // "Delete reference" item should appear only for invalid references
1437 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1438 bool isInvalidRefs = false;
1439 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1441 _PTR(Study) aStudyDS = aStudy->studyDS();
1442 _PTR(SObject) anObj;
1444 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1446 if( it.Value()->hasEntry() )
1448 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1449 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1452 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1453 isInvalidRefs = true;
1457 // Add "Delete reference" item to popup
1458 if ( isInvalidRefs )
1460 thePopup->addSeparator();
1461 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1465 // "Activate module" item should appear only if it's necessary
1466 if ( aList.Extent() == 1 ) {
1468 mgr->selectedObjects( aList );
1470 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1472 // add extra popup menu (defined in XML)
1473 if ( myExtActions.size() > 0 ) {
1474 // Use only first selected object
1475 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1477 _PTR(Study) stdDS = study->studyDS();
1479 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1481 _PTR( GenericAttribute ) anAttr;
1482 std::string auid = "AttributeUserID";
1483 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1484 if ( aSO->FindAttribute( anAttr, auid ) ) {
1485 _PTR(AttributeUserID) aAttrID = anAttr;
1486 QString aId = aAttrID->Value().c_str();
1487 if ( myExtActions.contains( aId ) ) {
1488 thePopup->addAction(myExtActions[aId]);
1496 // check if item is a "GUI state" item (also a first level object)
1497 QString entry( aIObj->getEntry() );
1498 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1499 QString aModuleName( aIObj->getComponentDataType() );
1500 QString aModuleTitle = moduleTitle( aModuleName );
1501 CAM_Module* currentModule = activeModule();
1502 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1503 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1508 mgr->setSelectionCacheEnabled( cacheIsOn );
1511 /*!Update obect browser:
1512 1.if 'updateModels' true, update existing data models;
1513 2. update "non-existing" (not loaded yet) data models;
1514 3. update object browser if it exists */
1515 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1517 // update "non-existing" (not loaded yet) data models
1518 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1521 _PTR(Study) stdDS = study->studyDS();
1524 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1526 _PTR(SComponent) aComponent ( it->Value() );
1528 #ifndef WITH_SALOMEDS_OBSERVER
1529 // with GUI observers this check is not needed anymore
1530 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1531 continue; // skip the magic "Interface Applicative" component
1533 if ( !objectBrowser() )
1534 getWindow( WT_ObjectBrowser );
1535 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1536 objectBrowser()->setAutoUpdate( false );
1537 SalomeApp_DataModel::synchronize( aComponent, study );
1538 objectBrowser()->setAutoUpdate( isAutoUpdate );
1543 // create data objects that correspond to GUI state save points
1544 if ( study ) updateSavePointDataObjects( study );
1546 // update existing data models (already loaded SComponents)
1547 LightApp_Application::updateObjectBrowser( updateModels );
1550 /*!Display Catalog Genenerator dialog */
1551 void SalomeApp_Application::onCatalogGen()
1553 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1557 /*!Display Registry Display dialog */
1558 void SalomeApp_Application::onRegDisplay()
1560 CORBA::ORB_var anOrb = orb();
1561 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1564 regWnd->activateWindow();
1567 /*!find original object by double click on item */
1568 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1570 // Issue 21379: References are supported at LightApp_DataObject level
1571 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1573 if( obj && obj->isReference() )
1575 QString entry = obj->refEntry();
1577 SUIT_DataOwnerPtrList aList;
1578 aList.append( new LightApp_DataOwner( entry ) );
1579 selectionMgr()->setSelected( aList, false );
1581 SUIT_DataBrowser* ob = objectBrowser();
1583 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1584 if ( !aSelectedIndexes.isEmpty() )
1585 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1590 Creates new view manager
1591 \param type - type of view manager
1593 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1595 return createViewManager(type);
1599 /*!Global utility function, returns selected GUI Save point object's ID */
1600 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1602 SALOME_ListIO aList;
1603 selMgr->selectedObjects( aList );
1604 if( aList.Extent() > 0 ) {
1605 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1606 QString entry( aIObj->getEntry() );
1607 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1608 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1610 bool ok; // conversion to integer is ok?
1611 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1612 return ok ? savePoint : -1;
1617 /*!Called on Restore GUI State popup command*/
1618 void SalomeApp_Application::onRestoreGUIState()
1620 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1621 if ( savePoint == -1 )
1623 SalomeApp_VisualState( this ).restoreState( savePoint );
1626 /*!Called on Delete GUI State popup command*/
1627 void SalomeApp_Application::onDeleteGUIState()
1629 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1630 if ( savePoint == -1 )
1632 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1636 study->removeSavePoint( savePoint );
1637 updateSavePointDataObjects( study );
1640 /*!Called on New study operation*/
1641 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1643 LightApp_Application::onStudyCreated( study );
1645 //#ifndef DISABLE_PYCONSOLE
1646 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1647 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1650 loadDockWindowsState();
1652 objectBrowserColumnsVisibility();
1655 /*!Called on Open study operation*/
1656 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1658 LightApp_Application::onStudyOpened( study );
1660 //#ifndef DISABLE_PYCONSOLE
1661 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1662 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1665 loadDockWindowsState();
1667 objectBrowserColumnsVisibility();
1669 // temporary commented
1670 /*if ( objectBrowser() ) {
1671 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1672 objectBrowser()->updateTree( study->root() );
1676 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1677 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1680 SUIT_DataBrowser* ob = objectBrowser();
1681 LightApp_SelectionMgr* selMgr = selectionMgr();
1683 if ( !study || !ob || !selMgr )
1686 // find GUI states root object
1687 SUIT_DataObject* guiRootObj = 0;
1689 study->root()->children( ch );
1690 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1691 for ( ; it != last ; ++it ) {
1692 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1697 std::vector<int> savePoints = study->getSavePoints();
1698 // case 1: no more save points but they existed in study's tree
1699 if ( savePoints.empty() && guiRootObj ) {
1700 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1701 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1702 const bool isAutoUpdate = ob->autoUpdate();
1703 selMgr->clearSelected();
1704 ob->setAutoUpdate(true);
1705 DataObjectList ch = guiRootObj->children();
1706 for( int i = 0; i < ch.size(); i++ )
1709 ob->setAutoUpdate(isAutoUpdate);
1712 // case 2: no more save points but root does not exist either
1713 if ( savePoints.empty() && !guiRootObj )
1715 // case 3: save points but no root for them - create it
1716 if ( !savePoints.empty() && !guiRootObj )
1717 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1718 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1719 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1721 if ( guiRootObj->nextBrother() ) {
1722 study->root()->removeChild(guiRootObj);
1723 study->root()->appendChild(guiRootObj);
1724 //study->root()->dump();
1727 // store data objects in a map id-to-DataObject
1728 QMap<int,SalomeApp_SavePointObject*> mapDO;
1730 guiRootObj->children( ch );
1731 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1732 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1734 mapDO[dobj->getId()] = dobj;
1737 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1738 // if in the map - remove it from map.
1739 for ( int i = 0; i < savePoints.size(); i++ )
1740 if ( !mapDO.contains( savePoints[i] ) )
1741 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1743 mapDO.remove( savePoints[i] );
1745 // delete DataObjects that are still in the map -- their IDs were not found in data model
1746 if( mapDO.size() > 0) {
1747 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1748 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1749 selMgr->clearSelected();
1750 const bool isAutoUpdate = ob->autoUpdate();
1751 ob->setAutoUpdate(true);
1752 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1754 ob->setAutoUpdate(isAutoUpdate);
1758 /*! Check data object */
1759 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1768 Opens other study into active Study. If Study is empty - creates it.
1769 \param theName - name of study
1771 bool SalomeApp_Application::useStudy( const QString& theName )
1774 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1777 res = aStudy->loadDocument( theName );
1778 updateDesktopTitle();
1779 updateCommandsStatus();
1783 /*! Show/hide object browser colums according to preferences */
1784 void SalomeApp_Application::objectBrowserColumnsVisibility()
1786 if ( objectBrowser() )
1787 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1789 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1790 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1794 #ifndef DISABLE_PYCONSOLE
1795 /*! Set SalomeApp_NoteBook pointer */
1796 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1798 myNoteBook = theNoteBook;
1801 /*! Return SalomeApp_NoteBook pointer */
1802 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1809 * Define extra actions defined in module definition XML file.
1810 * Additional popup items sections can be defined by parameter "popupitems".
1811 * Supported attributes:
1812 * title - title of menu item,
1813 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1814 * method - method which has to be called when menu item is selected
1816 * <section name="MODULENAME">
1817 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1819 * <section name="importmed">
1820 * <parameter name="title" value="My menu"/>
1821 * <parameter name="objectid" value="VISU.Result"/>
1822 * <parameter name="method" value="nameOfModuleMethod"/>
1825 void SalomeApp_Application::createExtraActions()
1827 myExtActions.clear();
1828 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1830 QStringList aModules;
1831 modules(aModules, false);
1832 foreach(QString aModile, aModules) {
1833 QString aModName = moduleName(aModile);
1834 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1835 if (!aSectionStr.isNull()) {
1836 QStringList aSections = aSectionStr.split(':');
1837 foreach(QString aSection, aSections) {
1838 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1839 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1840 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1841 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1844 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1845 if (aModuleName.isNull())
1846 aModuleName = aModName;
1848 QAction* aAction = new QAction(aTitle, this);
1850 aData<<aModuleName<<aSlot;
1851 aAction->setData(aData);
1852 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1853 myExtActions[aId] = aAction;
1860 * Called when extra action is selected
1862 void SalomeApp_Application::onExtAction()
1864 QAction* aAction = ::qobject_cast<QAction*>(sender());
1868 QVariant aData = aAction->data();
1869 QStringList aDataList = aData.value<QStringList>();
1870 if (aDataList.size() != 2)
1873 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1874 SALOME_ListIO aListIO;
1875 aSelectionMgr->selectedObjects(aListIO);
1876 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1877 if (aListIO.Extent() < 1)
1879 if (!anIO->hasEntry())
1882 QString aEntry(anIO->getEntry());
1884 QApplication::setOverrideCursor( Qt::WaitCursor );
1885 QString aModuleTitle = moduleTitle(aDataList[0]);
1886 activateModule(aModuleTitle);
1887 QApplication::restoreOverrideCursor();
1889 QCoreApplication::processEvents();
1891 CAM_Module* aModule = activeModule();
1895 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1896 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1900 Checks that an object can be renamed.
1901 \param entry entry of the object
1902 \brief Return \c true if object can be renamed
1904 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1906 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1910 Rename object by entry.
1911 \param entry entry of the object
1912 \param name new name of the object
1913 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1915 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1917 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1919 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1921 if(!aStudy || savePoint == -1)
1924 if ( !name.isNull() && !name.isEmpty() ) {
1925 aStudy->setNameOfSavePoint( savePoint, name );
1926 updateSavePointDataObjects( aStudy );
1928 //Mark study as modified
1935 #ifndef DISABLE_PYCONSOLE
1936 //============================================================================
1937 /*! Function : onUpdateStudy
1938 * Purpose : Slot to update the study.
1940 //============================================================================
1941 void SalomeApp_Application::onUpdateStudy()
1943 QApplication::setOverrideCursor( Qt::WaitCursor );
1945 if( !updateStudy() )
1946 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1948 QApplication::restoreOverrideCursor();
1951 //============================================================================
1952 /*! Function : updateStudy
1953 * Purpose : Update study by dumping the study to Python script and loading it.
1954 * It is used to apply variable modifications done in NoteBook to created objects.
1956 //============================================================================
1957 bool SalomeApp_Application::updateStudy()
1959 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1960 if ( !study || !myNoteBook )
1963 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1964 myNoteBook->setDumpedStudyName( study->studyName() );
1966 _PTR(Study) studyDS = study->studyDS();
1968 // get unique temporary directory name
1969 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1970 if( aTmpDir.isEmpty() )
1973 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1974 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1976 // dump study to the temporary directory
1977 QString aScriptName( "notebook" );
1978 bool toPublish = true;
1979 bool isMultiFile = false;
1980 bool toSaveGUI = true;
1983 _PTR(AttributeParameter) ap;
1984 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1985 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1986 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1987 ip->setDumpPython(studyDS);
1988 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1990 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1992 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1995 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1999 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2000 int anIndex = aList.indexOf( this );
2002 // Disconnect dialog from application desktop in case if:
2003 // 1) Application is not the first application in the session
2004 // 2) Application is the first application in session but not the only.
2005 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2006 if( changeDesktop ) {
2008 SalomeApp_Application* app = this;
2009 if( anIndex > 0 && anIndex < aList.count() )
2010 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2011 else if(anIndex == 0 && aList.count() > 1)
2012 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2017 // creation a new study and restoring will be done in another application
2018 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2019 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2022 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2023 QString aStudyName = myNoteBook->getDumpedStudyName();
2024 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2025 // clear a study (delete all objects)
2026 onCloseDoc( false );
2028 if( !changeDesktop ) {
2029 ok = onRestoreStudy( aDumpScript,
2038 //============================================================================
2039 /*! Function : onRestoreStudy
2040 * Purpose : Load the dumped study from Python script
2042 //============================================================================
2043 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2044 const QString& theStudyName,
2045 bool theIsStudySaved )
2049 // create a new study
2052 // get active application
2053 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2055 // load study from the temporary directory
2056 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2058 #ifndef DISABLE_PYCONSOLE
2059 PyConsole_Console* pyConsole = app->pythonConsole();
2061 pyConsole->execAndWait( command );
2064 // remove temporary directory
2065 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2066 QString aStudyName = aScriptInfo.baseName();
2067 QDir aDir = aScriptInfo.absoluteDir();
2068 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2069 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2070 ok = aDir.remove( *it ) && ok;
2072 ok = aDir.rmdir( aDir.absolutePath() );
2074 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2076 #ifndef DISABLE_PYCONSOLE
2077 _PTR(Study) aStudyDS = newStudy->studyDS();
2078 app->getNoteBook()->Init( aStudyDS );
2079 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2080 newStudy->Modified();
2081 updateDesktopTitle();
2092 Close the Application
2094 void SalomeApp_Application::afterCloseDoc()
2096 #ifndef DISABLE_PYCONSOLE
2097 // emit signal to restore study from Python script
2099 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2100 myNoteBook->getDumpedStudyName(),
2101 myNoteBook->isDumpedStudySaved() );
2104 LightApp_Application::afterCloseDoc();
2108 Asks to close existing document.
2110 bool SalomeApp_Application::checkExistingDoc()
2112 bool result = LightApp_Application::checkExistingDoc();
2113 if ( result && !activeStudy() ) {
2114 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2116 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2117 if( List.size() > 0 ) {
2118 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));