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());
1440 _PTR(Study) aStudyDS = aStudy->studyDS();
1441 _PTR(SObject) anObj;
1443 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1444 if( it.Value()->hasEntry() )
1446 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1447 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1450 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1451 isInvalidRefs = true;
1454 // Add "Delete reference" item to popup
1455 if ( isInvalidRefs )
1457 thePopup->addSeparator();
1458 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1462 // "Activate module" item should appear only if it's necessary
1463 if ( aList.Extent() == 1 ) {
1465 mgr->selectedObjects( aList );
1467 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1469 // add extra popup menu (defined in XML)
1470 if ( myExtActions.size() > 0 ) {
1471 // Use only first selected object
1472 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1474 _PTR(Study) stdDS = study->studyDS();
1476 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1478 _PTR( GenericAttribute ) anAttr;
1479 std::string auid = "AttributeUserID";
1480 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1481 if ( aSO->FindAttribute( anAttr, auid ) ) {
1482 _PTR(AttributeUserID) aAttrID = anAttr;
1483 QString aId = aAttrID->Value().c_str();
1484 if ( myExtActions.contains( aId ) ) {
1485 thePopup->addAction(myExtActions[aId]);
1493 // check if item is a "GUI state" item (also a first level object)
1494 QString entry( aIObj->getEntry() );
1495 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1496 QString aModuleName( aIObj->getComponentDataType() );
1497 QString aModuleTitle = moduleTitle( aModuleName );
1498 CAM_Module* currentModule = activeModule();
1499 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1500 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1504 mgr->setSelectionCacheEnabled( cacheIsOn );
1507 /*!Update obect browser:
1508 1.if 'updateModels' true, update existing data models;
1509 2. update "non-existing" (not loaded yet) data models;
1510 3. update object browser if it exists */
1511 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1513 // update "non-existing" (not loaded yet) data models
1514 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1517 _PTR(Study) stdDS = study->studyDS();
1520 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1522 _PTR(SComponent) aComponent ( it->Value() );
1524 #ifndef WITH_SALOMEDS_OBSERVER
1525 // with GUI observers this check is not needed anymore
1526 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1527 continue; // skip the magic "Interface Applicative" component
1529 if ( !objectBrowser() )
1530 getWindow( WT_ObjectBrowser );
1531 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1532 objectBrowser()->setAutoUpdate( false );
1533 SalomeApp_DataModel::synchronize( aComponent, study );
1534 objectBrowser()->setAutoUpdate( isAutoUpdate );
1539 // create data objects that correspond to GUI state save points
1540 if ( study ) updateSavePointDataObjects( study );
1542 // update existing data models (already loaded SComponents)
1543 LightApp_Application::updateObjectBrowser( updateModels );
1546 /*!Display Catalog Genenerator dialog */
1547 void SalomeApp_Application::onCatalogGen()
1549 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1553 /*!Display Registry Display dialog */
1554 void SalomeApp_Application::onRegDisplay()
1556 CORBA::ORB_var anOrb = orb();
1557 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1560 regWnd->activateWindow();
1563 /*!find original object by double click on item */
1564 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1566 // Issue 21379: References are supported at LightApp_DataObject level
1567 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1569 if( obj && obj->isReference() )
1571 QString entry = obj->refEntry();
1573 SUIT_DataOwnerPtrList aList;
1574 aList.append( new LightApp_DataOwner( entry ) );
1575 selectionMgr()->setSelected( aList, false );
1577 SUIT_DataBrowser* ob = objectBrowser();
1579 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1580 if ( !aSelectedIndexes.isEmpty() )
1581 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1586 Creates new view manager
1587 \param type - type of view manager
1589 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1591 return createViewManager(type);
1595 /*!Global utility function, returns selected GUI Save point object's ID */
1596 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1598 SALOME_ListIO aList;
1599 selMgr->selectedObjects( aList );
1600 if( aList.Extent() > 0 ) {
1601 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1602 QString entry( aIObj->getEntry() );
1603 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1604 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1606 bool ok; // conversion to integer is ok?
1607 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1608 return ok ? savePoint : -1;
1613 /*!Called on Restore GUI State popup command*/
1614 void SalomeApp_Application::onRestoreGUIState()
1616 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1617 if ( savePoint == -1 )
1619 SalomeApp_VisualState( this ).restoreState( savePoint );
1622 /*!Called on Delete GUI State popup command*/
1623 void SalomeApp_Application::onDeleteGUIState()
1625 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1626 if ( savePoint == -1 )
1628 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1632 study->removeSavePoint( savePoint );
1633 updateSavePointDataObjects( study );
1636 /*!Called on New study operation*/
1637 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1639 LightApp_Application::onStudyCreated( study );
1641 //#ifndef DISABLE_PYCONSOLE
1642 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1643 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1646 loadDockWindowsState();
1648 objectBrowserColumnsVisibility();
1651 /*!Called on Open study operation*/
1652 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1654 LightApp_Application::onStudyOpened( study );
1656 //#ifndef DISABLE_PYCONSOLE
1657 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1658 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1661 loadDockWindowsState();
1663 objectBrowserColumnsVisibility();
1665 // temporary commented
1666 /*if ( objectBrowser() ) {
1667 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1668 objectBrowser()->updateTree( study->root() );
1672 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1673 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1676 SUIT_DataBrowser* ob = objectBrowser();
1677 LightApp_SelectionMgr* selMgr = selectionMgr();
1679 if ( !study || !ob || !selMgr )
1682 // find GUI states root object
1683 SUIT_DataObject* guiRootObj = 0;
1685 study->root()->children( ch );
1686 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1687 for ( ; it != last ; ++it ) {
1688 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1693 std::vector<int> savePoints = study->getSavePoints();
1694 // case 1: no more save points but they existed in study's tree
1695 if ( savePoints.empty() && guiRootObj ) {
1696 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1697 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1698 const bool isAutoUpdate = ob->autoUpdate();
1699 selMgr->clearSelected();
1700 ob->setAutoUpdate(true);
1701 DataObjectList ch = guiRootObj->children();
1702 for( int i = 0; i < ch.size(); i++ )
1705 ob->setAutoUpdate(isAutoUpdate);
1708 // case 2: no more save points but root does not exist either
1709 if ( savePoints.empty() && !guiRootObj )
1711 // case 3: save points but no root for them - create it
1712 if ( !savePoints.empty() && !guiRootObj )
1713 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1714 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1715 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1717 if ( guiRootObj->nextBrother() ) {
1718 study->root()->removeChild(guiRootObj);
1719 study->root()->appendChild(guiRootObj);
1720 //study->root()->dump();
1723 // store data objects in a map id-to-DataObject
1724 QMap<int,SalomeApp_SavePointObject*> mapDO;
1726 guiRootObj->children( ch );
1727 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1728 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1730 mapDO[dobj->getId()] = dobj;
1733 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1734 // if in the map - remove it from map.
1735 for ( int i = 0; i < savePoints.size(); i++ )
1736 if ( !mapDO.contains( savePoints[i] ) )
1737 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1739 mapDO.remove( savePoints[i] );
1741 // delete DataObjects that are still in the map -- their IDs were not found in data model
1742 if( mapDO.size() > 0) {
1743 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1744 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1745 selMgr->clearSelected();
1746 const bool isAutoUpdate = ob->autoUpdate();
1747 ob->setAutoUpdate(true);
1748 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1750 ob->setAutoUpdate(isAutoUpdate);
1754 /*! Check data object */
1755 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1764 Opens other study into active Study. If Study is empty - creates it.
1765 \param theName - name of study
1767 bool SalomeApp_Application::useStudy( const QString& theName )
1770 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1773 res = aStudy->loadDocument( theName );
1774 updateDesktopTitle();
1775 updateCommandsStatus();
1779 /*! Show/hide object browser colums according to preferences */
1780 void SalomeApp_Application::objectBrowserColumnsVisibility()
1782 if ( objectBrowser() )
1783 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1785 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1786 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1790 #ifndef DISABLE_PYCONSOLE
1791 /*! Set SalomeApp_NoteBook pointer */
1792 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1794 myNoteBook = theNoteBook;
1797 /*! Return SalomeApp_NoteBook pointer */
1798 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1805 * Define extra actions defined in module definition XML file.
1806 * Additional popup items sections can be defined by parameter "popupitems".
1807 * Supported attributes:
1808 * title - title of menu item,
1809 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1810 * method - method which has to be called when menu item is selected
1812 * <section name="MODULENAME">
1813 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1815 * <section name="importmed">
1816 * <parameter name="title" value="My menu"/>
1817 * <parameter name="objectid" value="VISU.Result"/>
1818 * <parameter name="method" value="nameOfModuleMethod"/>
1821 void SalomeApp_Application::createExtraActions()
1823 myExtActions.clear();
1824 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1826 QStringList aModules;
1827 modules(aModules, false);
1828 foreach(QString aModile, aModules) {
1829 QString aModName = moduleName(aModile);
1830 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1831 if (!aSectionStr.isNull()) {
1832 QStringList aSections = aSectionStr.split(':');
1833 foreach(QString aSection, aSections) {
1834 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1835 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1836 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1837 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1840 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1841 if (aModuleName.isNull())
1842 aModuleName = aModName;
1844 QAction* aAction = new QAction(aTitle, this);
1846 aData<<aModuleName<<aSlot;
1847 aAction->setData(aData);
1848 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1849 myExtActions[aId] = aAction;
1856 * Called when extra action is selected
1858 void SalomeApp_Application::onExtAction()
1860 QAction* aAction = ::qobject_cast<QAction*>(sender());
1864 QVariant aData = aAction->data();
1865 QStringList aDataList = aData.value<QStringList>();
1866 if (aDataList.size() != 2)
1869 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1870 SALOME_ListIO aListIO;
1871 aSelectionMgr->selectedObjects(aListIO);
1872 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1873 if (aListIO.Extent() < 1)
1875 if (!anIO->hasEntry())
1878 QString aEntry(anIO->getEntry());
1880 QApplication::setOverrideCursor( Qt::WaitCursor );
1881 QString aModuleTitle = moduleTitle(aDataList[0]);
1882 activateModule(aModuleTitle);
1883 QApplication::restoreOverrideCursor();
1885 QCoreApplication::processEvents();
1887 CAM_Module* aModule = activeModule();
1891 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1892 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1896 Checks that an object can be renamed.
1897 \param entry entry of the object
1898 \brief Return \c true if object can be renamed
1900 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1902 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1906 Rename object by entry.
1907 \param entry entry of the object
1908 \param name new name of the object
1909 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1911 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1913 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1915 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1917 if(!aStudy || savePoint == -1)
1920 if ( !name.isNull() && !name.isEmpty() ) {
1921 aStudy->setNameOfSavePoint( savePoint, name );
1922 updateSavePointDataObjects( aStudy );
1924 //Mark study as modified
1931 #ifndef DISABLE_PYCONSOLE
1932 //============================================================================
1933 /*! Function : onUpdateStudy
1934 * Purpose : Slot to update the study.
1936 //============================================================================
1937 void SalomeApp_Application::onUpdateStudy()
1939 QApplication::setOverrideCursor( Qt::WaitCursor );
1941 if( !updateStudy() )
1942 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1944 QApplication::restoreOverrideCursor();
1947 //============================================================================
1948 /*! Function : updateStudy
1949 * Purpose : Update study by dumping the study to Python script and loading it.
1950 * It is used to apply variable modifications done in NoteBook to created objects.
1952 //============================================================================
1953 bool SalomeApp_Application::updateStudy()
1955 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1956 if ( !study || !myNoteBook )
1959 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1960 myNoteBook->setDumpedStudyName( study->studyName() );
1962 _PTR(Study) studyDS = study->studyDS();
1964 // get unique temporary directory name
1965 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1966 if( aTmpDir.isEmpty() )
1969 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1970 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1972 // dump study to the temporary directory
1973 QString aScriptName( "notebook" );
1974 bool toPublish = true;
1975 bool isMultiFile = false;
1976 bool toSaveGUI = true;
1979 _PTR(AttributeParameter) ap;
1980 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1981 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1982 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1983 ip->setDumpPython(studyDS);
1984 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1986 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1988 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1991 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1995 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1996 int anIndex = aList.indexOf( this );
1998 // Disconnect dialog from application desktop in case if:
1999 // 1) Application is not the first application in the session
2000 // 2) Application is the first application in session but not the only.
2001 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2002 if( changeDesktop ) {
2004 SalomeApp_Application* app = this;
2005 if( anIndex > 0 && anIndex < aList.count() )
2006 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2007 else if(anIndex == 0 && aList.count() > 1)
2008 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2013 // creation a new study and restoring will be done in another application
2014 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2015 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2018 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2019 QString aStudyName = myNoteBook->getDumpedStudyName();
2020 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2021 // clear a study (delete all objects)
2022 onCloseDoc( false );
2024 if( !changeDesktop ) {
2025 ok = onRestoreStudy( aDumpScript,
2034 //============================================================================
2035 /*! Function : onRestoreStudy
2036 * Purpose : Load the dumped study from Python script
2038 //============================================================================
2039 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2040 const QString& theStudyName,
2041 bool theIsStudySaved )
2045 // create a new study
2048 // get active application
2049 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2051 // load study from the temporary directory
2052 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2054 #ifndef DISABLE_PYCONSOLE
2055 PyConsole_Console* pyConsole = app->pythonConsole();
2057 pyConsole->execAndWait( command );
2060 // remove temporary directory
2061 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2062 QString aStudyName = aScriptInfo.baseName();
2063 QDir aDir = aScriptInfo.absoluteDir();
2064 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2065 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2066 ok = aDir.remove( *it ) && ok;
2068 ok = aDir.rmdir( aDir.absolutePath() );
2070 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2072 #ifndef DISABLE_PYCONSOLE
2073 _PTR(Study) aStudyDS = newStudy->studyDS();
2074 app->getNoteBook()->Init( aStudyDS );
2075 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2076 newStudy->Modified();
2077 updateDesktopTitle();
2088 Close the Application
2090 void SalomeApp_Application::afterCloseDoc()
2092 #ifndef DISABLE_PYCONSOLE
2093 // emit signal to restore study from Python script
2095 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2096 myNoteBook->getDumpedStudyName(),
2097 myNoteBook->isDumpedStudySaved() );
2100 LightApp_Application::afterCloseDoc();
2104 Asks to close existing document.
2106 bool SalomeApp_Application::checkExistingDoc()
2108 bool result = LightApp_Application::checkExistingDoc();
2109 if ( result && !activeStudy() ) {
2110 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2112 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2113 if( List.size() > 0 ) {
2114 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));