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_Prs.h>
104 #include <ToolsGUI_CatalogGeneratorDlg.h>
105 #include <ToolsGUI_RegWidget.h>
109 #include <SALOMEDS_Tool.hxx>
111 /*!Internal class that updates object browser item properties */
112 // temporary commented
113 /*class SalomeApp_Updater : public OB_Updater
116 SalomeApp_Updater() : OB_Updater(){};
117 virtual ~SalomeApp_Updater(){};
118 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
121 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
123 if( !theObj || !theItem )
126 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
130 _PTR(SObject) SObj = SAObj->object();
133 _PTR( GenericAttribute ) anAttr;
136 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
138 _PTR(AttributeSelectable) aAttrSel = anAttr;
139 theItem->setSelectable( aAttrSel->IsSelectable() );
142 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
144 _PTR(AttributeExpandable) aAttrExpand = anAttr;
145 theItem->setExpandable( aAttrExpand->IsExpandable() );
148 //this attribute is not supported in the version of SALOME 3.x
149 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
151 // _PTR(AttributeOpened) aAttrOpen = anAttr;
152 // theItem->setOpen( aAttrOpen->IsOpened() );
156 /*!Create new instance of SalomeApp_Application.*/
157 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
159 return new SalomeApp_Application();
163 SalomeApp_Application::SalomeApp_Application()
164 : LightApp_Application(),
166 myIsCloseFromExit( false )
171 *\li Destroy event filter.
173 SalomeApp_Application::~SalomeApp_Application()
175 // Do not destroy. It's a singleton !
176 //SALOME_EventFilter::Destroy();
179 /*!Start application.*/
180 void SalomeApp_Application::start()
182 // process the command line options before start: to createActions in accordance to the options
183 static bool isFirst = true;
191 for (int i = 1; i < qApp->argc(); i++) {
192 QRegExp rxs ("--study-hdf=(.+)");
193 if ( rxs.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
194 QString file = rxs.capturedTexts()[1];
195 QFileInfo fi ( file );
196 QString extension = fi.suffix().toLower();
197 if ( extension == "hdf" && fi.exists() )
198 hdffile = fi.absoluteFilePath();
201 QRegExp rxp ("--pyscript=\\[(.+)\\]");
202 QRegExp rxl ("--siman-study=(.+)");
203 if ( rxp.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
205 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
206 for (int k = 0; k < dictList.count(); ++k) {
207 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
208 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
209 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
210 pyfiles += rxd.capturedTexts()[m];
216 if ( rxl.indexIn( QString(qApp->argv()[i]) ) >= 0 && rxl.capturedTexts().count() > 1 ) {
218 loadStudy = rxl.capturedTexts()[1];
224 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
225 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
227 LightApp_Application::start();
228 SALOME_EventFilter::Init();
230 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
231 onOpenDoc( hdffile );
232 else if ( pyfiles.count() > 0 ) // create new study
234 else if (!loadStudy.isEmpty()) {// load study by name
235 if (onLoadDoc(loadStudy))
236 updateObjectBrowser(true);
239 #ifndef DISABLE_PYCONSOLE
240 // import/execute python scripts
241 if ( pyfiles.count() > 0 && activeStudy() ) {
242 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
243 PyConsole_Console* pyConsole = pythonConsole();
244 if ( appStudy && pyConsole ) {
245 _PTR(Study) aStudy = appStudy->studyDS();
246 if ( !aStudy->GetProperties()->IsLocked() ) {
247 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
248 // Path is absolute, script has .py extension
249 for (uint j = 0; j < pyfiles.count(); j++ ) {
250 // Extract scripts and their arguments, if any
251 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
252 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
253 QString script = rxp.capturedTexts()[1];
255 QStringList argList = rxp.capturedTexts()[2].split(",", QString::SkipEmptyParts);
256 for (uint k = 0; k < argList.count(); k++ ) {
257 QString arg = argList[k].trimmed();
258 arg.remove( QRegExp("^[\"]") );
259 arg.remove( QRegExp("[\"]$") );
262 args.remove( QRegExp("[,]$") );
263 if (!args.isEmpty()) {
267 script.remove( QRegExp("^python.*[\\s]+") );
268 QString cmd = script+" "+args;
269 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
270 pyConsole->exec(command);
272 } // end for loop on pyfiles QStringList
278 LightApp_Application::start();
279 SALOME_EventFilter::Init();
284 void SalomeApp_Application::createActions()
286 LightApp_Application::createActions();
288 SUIT_Desktop* desk = desktop();
291 // "Save GUI State" command is moved to VISU module
292 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
293 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
294 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
297 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
298 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
299 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
302 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
303 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
304 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
307 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
308 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
309 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
311 //! Catalog Generator
312 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
313 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
314 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
317 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
318 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
319 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
321 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
322 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
323 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
325 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
326 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
327 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
332 // check-in operations for SIMAN study
333 createAction( SimanCheckInId, tr( "TOT_SIMAN_CHECK_IN" ), QIcon(),
334 tr( "MEN_SIMAN_CHECK_IN" ), tr( "PRP_SIMAN_CHECK_IN" ),
335 0, desk, false, this, SLOT( onCheckIn() ) );
336 createAction( SimanLocalCheckInId, tr( "TOT_SIMAN_LOCAL_CHECK_IN" ), QIcon(),
337 tr( "MEN_SIMAN_LOCAL_CHECK_IN" ), tr( "PRP_SIMAN_LOCAL_CHECK_IN" ),
338 0, desk, false, this, SLOT( onLocalCheckIn() ) );
342 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
344 // "Save GUI State" command is renamed to "Save VISU State" and
345 // creation of menu item is moved to VISU
346 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
348 createMenu( ConnectId, fileMenu, 5 );
349 createMenu( DisconnectId, fileMenu, 5 );
350 createMenu( separator(), fileMenu, -1, 5 );
354 // check-in operation for SIMAN study
355 // last argument "5" locates this just after "Save As" but certain constant is bad => insert after the separator
356 createMenu( SimanCheckInId, fileMenu, 5);
357 createMenu( SimanLocalCheckInId, fileMenu, 5);
358 createMenu( separator(), fileMenu, 5 );
361 createMenu( DumpStudyId, fileMenu, 10, -1 );
362 createMenu( LoadScriptId, fileMenu, 10, -1 );
363 createMenu( separator(), fileMenu, -1, 10, -1 );
364 createMenu( PropertiesId, fileMenu, 10, -1 );
365 createMenu( separator(), fileMenu, -1, 10, -1 );
367 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
368 createMenu( CatalogGenId, toolsMenu, 10, -1 );
369 createMenu( RegDisplayId, toolsMenu, 10, -1 );
370 createMenu( separator(), toolsMenu, -1, 15, -1 );
372 createExtraActions();
374 #ifndef DISABLE_PYCONSOLE
375 #ifndef DISABLE_SALOMEOBJECT
376 // import Python module that manages SALOME plugins
378 PyLockWrapper lck; // acquire GIL
379 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
380 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_PLUGINS_TOOLS").toStdString().c_str(),tr("MEN_DESK_PLUGINS").toStdString().c_str());
384 // end of SALOME plugins loading
391 \brief Close application.
393 void SalomeApp_Application::onExit()
395 bool killServers = false;
398 if ( exitConfirmation() ) {
399 SalomeApp_ExitDlg dlg( desktop() );
400 result = dlg.exec() == QDialog::Accepted;
401 killServers = dlg.isServersShutdown();
405 if ( !killServers ) myIsCloseFromExit = true;
406 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
407 myIsCloseFromExit = false;
411 /*!SLOT. Load document.*/
412 void SalomeApp_Application::onLoadDoc()
416 std::vector<std::string> List = studyMgr()->GetOpenStudies();
418 // rnv: According to the single-study approach on the server side
419 // can be only one study. So if it is exists connect to them,
420 // overwise show warning message: "No active study on the server"
423 SUIT_Session* aSession = SUIT_Session::session();
424 QList<SUIT_Application*> aAppList = aSession->applications();
426 QStringList unloadedStudies;
428 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
429 studyName = List[ind].c_str();
430 // Add to list only unloaded studies
431 bool isAlreadyOpen = false;
432 QListIterator<SUIT_Application*> it( aAppList );
433 while ( it.hasNext() && !isAlreadyOpen ) {
434 SUIT_Application* aApp = it.next();
435 if( !aApp || !aApp->activeStudy() )
437 if ( aApp->activeStudy()->studyName() == studyName )
438 isAlreadyOpen = true;
441 if ( !isAlreadyOpen )
442 unloadedStudies << studyName;
444 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
445 if ( studyName.isEmpty() )
449 if(List.size() <= 0) {
450 SUIT_MessageBox::warning( desktop(),
451 QObject::tr("WRN_WARNING"),
452 QObject::tr("WRN_NO_STUDY_ON SERV") );
456 studyName = List[0].c_str();
459 // this code replaces marker of windows drive and path become invalid therefore
460 // defines placed there
461 studyName.replace( QRegExp(":"), "/" );
464 if ( onLoadDoc( studyName ) ) {
466 updateViewManagers();
467 updateObjectBrowser( true );
471 /*!SLOT. Unload document.*/
472 void SalomeApp_Application::onUnloadDoc( bool ask )
475 activeStudy()->abortAllOperations();
476 if ( activeStudy()->isModified() ) {
477 QString docName = activeStudy()->studyName().trimmed();
478 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
479 tr( "DISCONNECT_DESCRIPTION" ),
480 tr( "DISCONNECT_SAVE" ),
481 tr( "DISCONNECT_WO_SAVE" ),
482 tr( "APPCLOSE_CANCEL" ), 0 );
483 if ( answer == 0 ) { // save before unload
484 if ( activeStudy()->isSaved() )
486 else if ( !onSaveAsDoc() )
489 else if ( answer == 2 ) // Cancel
493 closeActiveDoc( false );
496 /*!SLOT. Create new study and load script*/
497 void SalomeApp_Application::onNewWithScript()
499 QStringList filtersList;
500 filtersList.append(tr("PYTHON_FILES_FILTER"));
501 filtersList.append(tr("ALL_FILES_FILTER"));
503 QString anInitialPath = "";
504 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
505 anInitialPath = QDir::currentPath();
507 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
509 if ( !aFile.isEmpty() )
513 QString command = QString("execfile(r\"%1\")").arg(aFile);
515 #ifndef DISABLE_PYCONSOLE
516 PyConsole_Console* pyConsole = pythonConsole();
519 pyConsole->exec( command );
525 /*!SLOT. Load document with \a aName.*/
526 bool SalomeApp_Application::onLoadDoc( const QString& aName )
528 #ifdef SINGLE_DESKTOP
529 if ( !LightApp_Application::closeDoc() )
533 if ( !activeStudy() ) {
534 // if no study - load in current desktop
535 res = useStudy( aName );
538 // if study exists - load in new desktop. Check: is the same file is loaded?
539 SUIT_Session* aSession = SUIT_Session::session();
540 QList<SUIT_Application*> aAppList = aSession->applications();
541 bool isAlreadyOpen = false;
542 SalomeApp_Application* aApp = 0;
543 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
544 it != aAppList.end() && !isAlreadyOpen; ++it ) {
545 aApp = dynamic_cast<SalomeApp_Application*>( *it );
546 if ( aApp && aApp->activeStudy()->studyName() == aName )
547 isAlreadyOpen = true;
549 if ( !isAlreadyOpen ) {
550 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
552 res = aApp->useStudy( aName );
555 aApp->desktop()->activateWindow();
562 /*!SLOT. Parse message for desktop.*/
563 void SalomeApp_Application::onDesktopMessage( const QString& message )
565 if (message.indexOf("simanCheckoutDone ") == 0) {
567 // Load document with a name, specified in aMessage.
568 onLoadDoc(message.section(' ', 1));
570 printf( "****************************************************************\n" );
571 printf( "* Warning: SALOME is built without SIMAN support.\n" );
572 printf( "****************************************************************\n" );
575 else if (message.indexOf("studyCreated:") == 0) {
576 // Enable 'Connect' action
577 updateCommandsStatus();
579 else if (message.indexOf("studyClosed:") == 0) {
580 /* message also contains ID of the closed study,
581 but as soon as SALOME is mono-study application for the moment,
582 this ID is not needed now.*/
583 //long aStudyId = message.section(':', 1).toLong();
584 // Disconnect GUI from active study, because it was closed on DS side.
585 closeActiveDoc( false );
586 // Disable 'Connect' action
587 QAction* a = action( ConnectId );
589 a->setEnabled( false );
591 else if ( message.toLower() == "connect_to_study" ) {
594 LightApp_Application::onDesktopMessage( message );
597 /*!SLOT. Copy objects to study maneger from selection maneger..*/
598 void SalomeApp_Application::onCopy()
601 LightApp_SelectionMgr* mgr = selectionMgr();
602 mgr->selectedObjects(list);
604 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
605 if(study == NULL) return;
607 _PTR(Study) stdDS = study->studyDS();
610 SALOME_ListIteratorOfListIO it( list );
613 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
615 studyMgr()->Copy(so);
616 onSelectionChanged();
623 /*!SLOT. Paste objects to study maneger from selection manager.*/
624 void SalomeApp_Application::onPaste()
627 LightApp_SelectionMgr* mgr = selectionMgr();
628 mgr->selectedObjects(list);
630 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
631 if(study == NULL) return;
633 _PTR(Study) stdDS = study->studyDS();
636 if ( stdDS->GetProperties()->IsLocked() ) {
637 SUIT_MessageBox::warning( desktop(),
638 QObject::tr("WRN_WARNING"),
639 QObject::tr("WRN_STUDY_LOCKED") );
643 SALOME_ListIteratorOfListIO it( list );
646 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
648 studyMgr()->Paste(so);
649 updateObjectBrowser( true );
650 updateActions(); //SRN: BugID IPAL9377, case 3
657 /*!Check the application on closing.
658 * \retval true if possible, else false
660 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
662 return LightApp_Application::isPossibleToClose( closePermanently );
665 /*! Check if the study is locked */
666 void SalomeApp_Application::onCloseDoc( bool ask )
668 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
671 _PTR(Study) stdDS = study->studyDS();
672 if(stdDS && stdDS->IsStudyLocked()) {
673 if ( SUIT_MessageBox::question( desktop(),
674 QObject::tr( "WRN_WARNING" ),
675 QObject::tr( "CLOSE_LOCKED_STUDY" ),
676 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
677 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
681 LightApp_Application::onCloseDoc( ask );
684 /*!Sets enable or disable some actions on selection changed.*/
685 void SalomeApp_Application::onSelectionChanged()
688 LightApp_SelectionMgr* mgr = selectionMgr();
689 mgr->selectedObjects(list);
691 bool canCopy = false;
692 bool canPaste = false;
694 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
696 _PTR(Study) stdDS = study->studyDS();
699 SALOME_ListIteratorOfListIO it ( list );
701 if (it.More() && list.Extent() == 1) {
702 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
705 canCopy = studyMgr()->CanCopy(so);
706 canPaste = studyMgr()->CanPaste(so);
712 action(EditCopyId)->setEnabled(canCopy);
713 action(EditPasteId)->setEnabled(canPaste);
716 /*!Delete references.*/
717 void SalomeApp_Application::onDeleteInvalidReferences()
720 LightApp_SelectionMgr* mgr = selectionMgr();
721 mgr->selectedObjects( aList, QString(), false );
723 if( aList.IsEmpty() )
726 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
727 _PTR(Study) aStudyDS = aStudy->studyDS();
728 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
731 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
732 if ( it.Value()->hasEntry() )
734 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
735 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
738 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
739 aStudyBuilder->RemoveReference( aSObject );
741 updateObjectBrowser();
745 void SalomeApp_Application::onOpenWith()
747 QApplication::setOverrideCursor( Qt::WaitCursor );
749 LightApp_SelectionMgr* mgr = selectionMgr();
750 mgr->selectedObjects(aList);
751 if (aList.Extent() != 1)
753 QApplication::restoreOverrideCursor();
756 Handle(SALOME_InteractiveObject) aIObj = aList.First();
757 QString aModuleName(aIObj->getComponentDataType());
758 QString aModuleTitle = moduleTitle(aModuleName);
759 activateModule(aModuleTitle);
760 QApplication::restoreOverrideCursor();
766 SUIT_Study* SalomeApp_Application::createNewStudy()
768 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
770 // Set up processing of major study-related events
771 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
772 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
773 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
774 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
776 #ifndef DISABLE_PYCONSOLE
777 //to receive signal in application that NoteBook's variable was modified
778 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
779 this, SIGNAL(notebookVarUpdated(QString)) );
786 Enable/Disable menu items and toolbar buttons. Rebuild menu
788 void SalomeApp_Application::updateCommandsStatus()
790 LightApp_Application::updateCommandsStatus();
793 QAction* a = action( DumpStudyId );
795 a->setEnabled( activeStudy() );
798 a = action( LoadScriptId );
800 a->setEnabled( pythonConsole() );
803 a = action( PropertiesId );
805 a->setEnabled( activeStudy() );
807 // Save GUI state menu
808 a = action( SaveGUIStateId );
810 a->setEnabled( activeStudy() );
812 // Connect study menu
813 a = action( ConnectId );
815 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
817 // Disconnect study menu
818 a = action( DisconnectId );
820 a->setEnabled( activeStudy() );
822 // update state of Copy/Paste menu items
823 onSelectionChanged();
827 \class DumpStudyFileDlg
828 Private class used in Dump Study operation. Consists 2 check boxes:
829 "Publish in study" and "Save GUI parameters"
831 class DumpStudyFileDlg : public SUIT_FileDlg
834 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
836 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
839 QWidget *hB = new QWidget( this );
840 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
841 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
842 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
844 QHBoxLayout *layout = new QHBoxLayout;
845 layout->addWidget(myPublishChk);
846 layout->addWidget(myMultiFileChk);
847 layout->addWidget(mySaveGUIChk);
848 hB->setLayout(layout);
850 QPushButton* pb = new QPushButton(this);
852 int row = grid->rowCount();
853 grid->addWidget( new QLabel("", this), row, 0 );
854 grid->addWidget( hB, row, 1, 1, 3 );
855 grid->addWidget( pb, row, 5 );
860 QCheckBox* myPublishChk;
861 QCheckBox* myMultiFileChk;
862 QCheckBox* mySaveGUIChk;
865 class DumpStudyFileValidator : public SUIT_FileValidator
868 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
869 virtual ~DumpStudyFileValidator() {};
870 virtual bool canSave( const QString& file, bool permissions );
873 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
875 QFileInfo fi( file );
876 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
877 SUIT_MessageBox::critical( parent(),
878 QObject::tr("WRN_WARNING"),
879 QObject::tr("WRN_FILE_NAME_BAD") );
882 return SUIT_FileValidator::canSave( file, permissions);
885 /*!Private SLOT. On dump study.*/
886 void SalomeApp_Application::onDumpStudy( )
888 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
889 if ( !appStudy ) return;
890 _PTR(Study) aStudy = appStudy->studyDS();
892 QStringList aFilters;
893 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
895 bool anIsPublish = true;
896 bool anIsMultiFile = false;
897 bool anIsSaveGUI = true;
899 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
900 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
901 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
902 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
905 DumpStudyFileDlg fd( desktop() );
906 fd.setValidator( new DumpStudyFileValidator( &fd ) );
907 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
908 fd.setFilters( aFilters );
909 fd.myPublishChk->setChecked( anIsPublish );
910 fd.myMultiFileChk->setChecked( anIsMultiFile );
911 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
912 if ( fd.exec() == QDialog::Accepted )
914 QString aFileName = fd.selectedFile();
916 bool toPublish = fd.myPublishChk->isChecked();
917 bool isMultiFile = fd.myMultiFileChk->isChecked();
918 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
920 if ( !aFileName.isEmpty() ) {
921 QFileInfo aFileInfo(aFileName);
922 if( aFileInfo.isDir() ) // IPAL19257
925 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
928 SUIT_OverrideCursor wc;
929 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
932 SUIT_MessageBox::warning( desktop(),
933 QObject::tr("WRN_WARNING"),
934 tr("WRN_DUMP_STUDY_FAILED") );
939 /*!Private SLOT. On load script.*/
940 void SalomeApp_Application::onLoadScript( )
942 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
944 _PTR(Study) aStudy = appStudy->studyDS();
945 if ( aStudy->GetProperties()->IsLocked() ) {
946 SUIT_MessageBox::warning( desktop(),
947 QObject::tr("WRN_WARNING"),
948 QObject::tr("WRN_STUDY_LOCKED") );
953 QStringList filtersList;
954 filtersList.append(tr("PYTHON_FILES_FILTER"));
955 filtersList.append(tr("ALL_FILES_FILTER"));
957 QString anInitialPath = "";
958 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
959 anInitialPath = QDir::currentPath();
962 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
964 SALOMEDSClient_StudyManager* aMgr = studyMgr();
965 aMgr->GetSimanStudy()->StudyId();
966 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
967 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
968 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
972 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
974 if ( !aFile.isEmpty() )
976 QString command = QString("execfile(r\"%1\")").arg(aFile);
978 #ifndef DISABLE_PYCONSOLE
979 PyConsole_Console* pyConsole = pythonConsole();
982 pyConsole->exec( command );
987 /*!Private SLOT. On save GUI state.*/
988 void SalomeApp_Application::onSaveGUIState()
990 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
992 SalomeApp_VisualState( this ).storeState();
993 updateSavePointDataObjects( study );
994 updateObjectBrowser();
999 /*!Public SLOT. On SIMAN check in operation.*/
1000 void SalomeApp_Application::onCheckIn()
1003 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1004 setMenuShown(SimanLocalCheckInId, false);
1005 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1006 aMgr->GetSimanStudy()->CheckIn("");
1008 printf( "****************************************************************\n" );
1009 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1010 printf( "****************************************************************\n" );
1014 /*!Public SLOT. On SIMAN local check in operation.*/
1015 void SalomeApp_Application::onLocalCheckIn()
1018 // get the active module
1019 CAM_Module* aModule = activeModule();
1020 if (!aModule) return; // there is no active module
1022 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1023 setMenuShown(SimanLocalCheckInId, false);
1024 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1025 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1027 printf( "****************************************************************\n" );
1028 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1029 printf( "****************************************************************\n" );
1033 /*!Gets file filter.
1034 *\retval QString "(*.hdf)"
1036 QString SalomeApp_Application::getFileFilter() const
1042 QWidget* SalomeApp_Application::createWindow( const int flag )
1045 #ifndef DISABLE_PYCONSOLE
1046 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1048 wid = LightApp_Application::createWindow(flag);
1051 SUIT_ResourceMgr* resMgr = resourceMgr();
1053 if ( flag == WT_ObjectBrowser )
1055 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1057 // temporary commented
1058 //ob->setUpdater( new SalomeApp_Updater() );
1060 #ifdef WITH_SALOMEDS_OBSERVER
1061 //do not activate the automatic update of Qt tree through signal/slot
1062 ob->setAutoUpdate(false);
1063 //activate update of modified objects only
1064 ob->setUpdateModified(true);
1067 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1070 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1071 IORCol = QObject::tr( "IOR_COLUMN" ),
1072 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1073 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1075 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1076 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1077 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1078 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1079 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1080 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1081 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1082 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1083 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1085 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1086 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1087 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1089 ob->setAutoSizeFirstColumn(autoSizeFirst);
1090 ob->setAutoSizeColumns(autoSize);
1091 ob->setResizeOnExpandItem(resizeOnExpandItem);
1092 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1094 // temporary commented
1096 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1098 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1099 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1100 QString().sprintf( "visibility_column_%d", i ), true ) );
1104 // temporary commented
1106 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1107 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1108 ob->resize( desktop()->width()/3, ob->height() );
1112 #ifndef DISABLE_PYCONSOLE
1113 else if ( flag == WT_PyConsole )
1115 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1116 pyCons->setObjectName( "pythonConsole" );
1117 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1118 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1119 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1120 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1122 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1123 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1125 else if ( flag == WT_NoteBook )
1127 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1129 _PTR(Study) aStudy = appStudy->studyDS();
1130 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1131 //to receive signal in NoteBook that it's variable was modified
1132 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1133 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1135 wid = getNoteBook();
1136 wid->setObjectName( "noteBook" );
1142 /*!Create preferences.*/
1143 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1145 LightApp_Application::createPreferences(pref);
1150 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1151 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1152 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1153 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1155 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1156 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1158 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1160 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1161 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1162 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1163 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1164 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1165 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1166 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1167 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1168 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1169 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1172 /*!Update desktop title.*/
1173 void SalomeApp_Application::updateDesktopTitle() {
1174 QString aTitle = applicationName();
1175 QString aVer = applicationVersion();
1176 if ( !aVer.isEmpty() )
1177 aTitle += QString( " " ) + aVer;
1179 if ( activeStudy() )
1181 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1182 if ( !sName.isEmpty() ) {
1183 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1185 _PTR(Study) stdDS = study->studyDS();
1187 if ( stdDS->GetProperties()->IsLocked() ) {
1188 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1190 aTitle += QString( " - [%1]" ).arg( sName );
1197 desktop()->setWindowTitle( aTitle );
1200 int SalomeApp_Application::closeChoice( const QString& docName )
1202 QStringList buttons;
1203 QMap<int, int> choices;
1205 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1206 choices.insert( idx++, CloseSave ); // ...
1207 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1208 choices.insert( idx++, CloseDiscard ); // ...
1209 if ( myIsCloseFromExit ) {
1210 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1211 choices.insert( idx++, CloseDisconnectSave ); // ...
1212 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1213 choices.insert( idx++, CloseDisconnect ); // ...
1215 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1216 choices.insert( idx++, CloseCancel ); // ...
1218 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1219 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1220 return choices[answer];
1223 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1229 if ( activeStudy()->isSaved() )
1231 else if ( !onSaveAsDoc() )
1236 case CloseDisconnectSave:
1237 if ( activeStudy()->isSaved() )
1239 else if ( !onSaveAsDoc() )
1241 case CloseDisconnect:
1242 closeActiveDoc( false );
1243 closePermanently = false;
1252 int SalomeApp_Application::openChoice( const QString& aName )
1254 int choice = LightApp_Application::openChoice( aName );
1256 if ( QFileInfo( aName ).exists() ) {
1257 if ( choice == OpenNew ) { // The document isn't already open.
1259 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1260 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1261 if ( aName == QString( lst[i].c_str() ) )
1264 // The document already exists in the study manager.
1265 // Do you want to reload it?
1267 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1268 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1269 if ( answer == SUIT_MessageBox::Yes )
1270 choice = OpenRefresh;
1272 choice = OpenCancel;
1275 } else { // file is not exist on disk
1276 SUIT_MessageBox::warning( desktop(),
1277 QObject::tr("WRN_WARNING"),
1278 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1285 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1288 int choice = aChoice;
1293 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1296 studyMgr()->Close( aStudy );
1301 res = LightApp_Application::openAction( choice, aName );
1309 \brief Get map of the operations which can be performed
1310 on the module activation.
1312 The method should return the map of the kind \c {<id>:<name>}
1313 where \c <id> is an integer identifier of the operation and
1314 \c <name> is a title for the button to be added to the
1315 dialog box. After user selects the required operation by the
1316 clicking the corresponding button in the dialog box, its identifier
1317 is passed to the moduleActionSelected() method to process
1320 \return map of the operations
1321 \sa moduleActionSelected()
1323 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1325 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1327 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1329 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1334 \brief Called when the used selectes required operation chosen
1335 from "Activate module" dialog box.
1337 Performs the required operation according to the user choice.
1339 \param id operation identifier
1340 \sa activateModuleActions()
1342 void SalomeApp_Application::moduleActionSelected( const int id )
1348 case NewAndScriptId:
1352 LightApp_Application::moduleActionSelected( id );
1357 /*!Gets CORBA::ORB_var*/
1358 CORBA::ORB_var SalomeApp_Application::orb()
1360 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1361 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1365 /*!Create and return SALOMEDS_StudyManager.*/
1366 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1368 static _PTR(StudyManager) _sm;
1369 if(!_sm) _sm = ClientFactory::StudyManager();
1373 /*!Create and return SALOME_NamingService.*/
1374 SALOME_NamingService* SalomeApp_Application::namingService()
1376 static SALOME_NamingService _ns(orb());
1380 /*!Create and return SALOME_LifeCycleCORBA.*/
1381 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1383 static SALOME_LifeCycleCORBA _lcc( namingService() );
1387 /*!Private SLOT. On preferences.*/
1388 void SalomeApp_Application::onProperties()
1390 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1394 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1397 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1398 int res = aDlg.exec();
1399 if( res==QDialog::Accepted && aDlg.isChanged() )
1400 SB->CommitCommand();
1404 //study->updateCaptions();
1405 updateDesktopTitle();
1409 /*!Insert items in popup, which necessary for current application*/
1410 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1412 LightApp_SelectionMgr* mgr = selectionMgr();
1413 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1414 mgr->setSelectionCacheEnabled( true );
1416 LightApp_Application::contextMenuPopup( type, thePopup, title );
1418 // temporary commented
1419 /*OB_Browser* ob = objectBrowser();
1420 if ( !ob || type != ob->popupClientType() )
1423 // Get selected objects
1424 SALOME_ListIO aList;
1425 mgr->selectedObjects( aList, QString(), false );
1427 // add GUI state commands: restore, rename
1428 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1429 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1430 thePopup->addSeparator();
1431 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1432 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1433 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1434 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1437 // "Delete reference" item should appear only for invalid references
1439 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1440 bool isInvalidRefs = false;
1441 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1443 _PTR(Study) aStudyDS = aStudy->studyDS();
1444 _PTR(SObject) anObj;
1446 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1448 if( it.Value()->hasEntry() )
1450 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1451 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1454 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1455 isInvalidRefs = true;
1459 // Add "Delete reference" item to popup
1460 if ( isInvalidRefs )
1462 thePopup->addSeparator();
1463 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1467 // "Activate module" item should appear only if it's necessary
1468 if ( aList.Extent() == 1 ) {
1470 mgr->selectedObjects( aList );
1472 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1474 // add extra popup menu (defined in XML)
1475 if ( myExtActions.size() > 0 ) {
1476 // Use only first selected object
1477 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1479 _PTR(Study) stdDS = study->studyDS();
1481 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1483 _PTR( GenericAttribute ) anAttr;
1484 std::string auid = "AttributeUserID";
1485 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1486 if ( aSO->FindAttribute( anAttr, auid ) ) {
1487 _PTR(AttributeUserID) aAttrID = anAttr;
1488 QString aId = aAttrID->Value().c_str();
1489 if ( myExtActions.contains( aId ) ) {
1490 thePopup->addAction(myExtActions[aId]);
1498 // check if item is a "GUI state" item (also a first level object)
1499 QString entry( aIObj->getEntry() );
1500 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1501 QString aModuleName( aIObj->getComponentDataType() );
1502 QString aModuleTitle = moduleTitle( aModuleName );
1503 CAM_Module* currentModule = activeModule();
1504 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1505 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1510 mgr->setSelectionCacheEnabled( cacheIsOn );
1513 /*!Update obect browser:
1514 1.if 'updateModels' true, update existing data models;
1515 2. update "non-existing" (not loaded yet) data models;
1516 3. update object browser if it exists */
1517 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1519 // update "non-existing" (not loaded yet) data models
1520 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1523 _PTR(Study) stdDS = study->studyDS();
1526 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1528 _PTR(SComponent) aComponent ( it->Value() );
1530 #ifndef WITH_SALOMEDS_OBSERVER
1531 // with GUI observers this check is not needed anymore
1532 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1533 continue; // skip the magic "Interface Applicative" component
1535 if ( !objectBrowser() )
1536 getWindow( WT_ObjectBrowser );
1537 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1538 objectBrowser()->setAutoUpdate( false );
1539 SalomeApp_DataModel::synchronize( aComponent, study );
1540 objectBrowser()->setAutoUpdate( isAutoUpdate );
1545 // create data objects that correspond to GUI state save points
1546 if ( study ) updateSavePointDataObjects( study );
1548 // update existing data models (already loaded SComponents)
1549 LightApp_Application::updateObjectBrowser( updateModels );
1552 /*!Display Catalog Genenerator dialog */
1553 void SalomeApp_Application::onCatalogGen()
1555 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1559 /*!Display Registry Display dialog */
1560 void SalomeApp_Application::onRegDisplay()
1562 CORBA::ORB_var anOrb = orb();
1563 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1566 regWnd->activateWindow();
1569 /*!find original object by double click on item */
1570 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1572 // Issue 21379: References are supported at LightApp_DataObject level
1573 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1575 if( obj && obj->isReference() )
1577 QString entry = obj->refEntry();
1579 SUIT_DataOwnerPtrList aList;
1580 aList.append( new LightApp_DataOwner( entry ) );
1581 selectionMgr()->setSelected( aList, false );
1583 SUIT_DataBrowser* ob = objectBrowser();
1585 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1586 if ( !aSelectedIndexes.isEmpty() )
1587 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1592 Creates new view manager
1593 \param type - type of view manager
1595 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1597 return createViewManager(type);
1601 /*!Global utility function, returns selected GUI Save point object's ID */
1602 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1604 SALOME_ListIO aList;
1605 selMgr->selectedObjects( aList );
1606 if( aList.Extent() > 0 ) {
1607 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1608 QString entry( aIObj->getEntry() );
1609 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1610 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1612 bool ok; // conversion to integer is ok?
1613 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1614 return ok ? savePoint : -1;
1619 /*!Called on Restore GUI State popup command*/
1620 void SalomeApp_Application::onRestoreGUIState()
1622 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1623 if ( savePoint == -1 )
1625 SalomeApp_VisualState( this ).restoreState( savePoint );
1628 /*!Called on Delete GUI State popup command*/
1629 void SalomeApp_Application::onDeleteGUIState()
1631 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1632 if ( savePoint == -1 )
1634 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1638 study->removeSavePoint( savePoint );
1639 updateSavePointDataObjects( study );
1642 /*!Called on New study operation*/
1643 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1645 LightApp_Application::onStudyCreated( study );
1647 //#ifndef DISABLE_PYCONSOLE
1648 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1649 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1652 loadDockWindowsState();
1654 objectBrowserColumnsVisibility();
1657 /*!Called on Open study operation*/
1658 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1660 LightApp_Application::onStudyOpened( study );
1662 //#ifndef DISABLE_PYCONSOLE
1663 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1664 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1667 loadDockWindowsState();
1669 objectBrowserColumnsVisibility();
1671 // temporary commented
1672 /*if ( objectBrowser() ) {
1673 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1674 objectBrowser()->updateTree( study->root() );
1678 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1679 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1682 SUIT_DataBrowser* ob = objectBrowser();
1683 LightApp_SelectionMgr* selMgr = selectionMgr();
1685 if ( !study || !ob || !selMgr )
1688 // find GUI states root object
1689 SUIT_DataObject* guiRootObj = 0;
1691 study->root()->children( ch );
1692 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1693 for ( ; it != last ; ++it ) {
1694 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1699 std::vector<int> savePoints = study->getSavePoints();
1700 // case 1: no more save points but they existed in study's tree
1701 if ( savePoints.empty() && guiRootObj ) {
1702 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1703 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1704 const bool isAutoUpdate = ob->autoUpdate();
1705 selMgr->clearSelected();
1706 ob->setAutoUpdate(true);
1707 DataObjectList ch = guiRootObj->children();
1708 for( int i = 0; i < ch.size(); i++ )
1711 ob->setAutoUpdate(isAutoUpdate);
1714 // case 2: no more save points but root does not exist either
1715 if ( savePoints.empty() && !guiRootObj )
1717 // case 3: save points but no root for them - create it
1718 if ( !savePoints.empty() && !guiRootObj )
1719 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1720 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1721 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1723 if ( guiRootObj->nextBrother() ) {
1724 study->root()->removeChild(guiRootObj);
1725 study->root()->appendChild(guiRootObj);
1726 //study->root()->dump();
1729 // store data objects in a map id-to-DataObject
1730 QMap<int,SalomeApp_SavePointObject*> mapDO;
1732 guiRootObj->children( ch );
1733 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1734 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1736 mapDO[dobj->getId()] = dobj;
1739 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1740 // if in the map - remove it from map.
1741 for ( int i = 0; i < savePoints.size(); i++ )
1742 if ( !mapDO.contains( savePoints[i] ) )
1743 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1745 mapDO.remove( savePoints[i] );
1747 // delete DataObjects that are still in the map -- their IDs were not found in data model
1748 if( mapDO.size() > 0) {
1749 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1750 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1751 selMgr->clearSelected();
1752 const bool isAutoUpdate = ob->autoUpdate();
1753 ob->setAutoUpdate(true);
1754 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1756 ob->setAutoUpdate(isAutoUpdate);
1760 /*! Check data object */
1761 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1770 Opens other study into active Study. If Study is empty - creates it.
1771 \param theName - name of study
1773 bool SalomeApp_Application::useStudy( const QString& theName )
1776 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1779 res = aStudy->loadDocument( theName );
1780 updateDesktopTitle();
1781 updateCommandsStatus();
1785 /*! Show/hide object browser colums according to preferences */
1786 void SalomeApp_Application::objectBrowserColumnsVisibility()
1788 if ( objectBrowser() )
1789 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1791 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1792 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1796 #ifndef DISABLE_PYCONSOLE
1797 /*! Set SalomeApp_NoteBook pointer */
1798 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1800 myNoteBook = theNoteBook;
1803 /*! Return SalomeApp_NoteBook pointer */
1804 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1811 * Define extra actions defined in module definition XML file.
1812 * Additional popup items sections can be defined by parameter "popupitems".
1813 * Supported attributes:
1814 * title - title of menu item,
1815 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1816 * method - method which has to be called when menu item is selected
1818 * <section name="MODULENAME">
1819 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1821 * <section name="importmed">
1822 * <parameter name="title" value="My menu"/>
1823 * <parameter name="objectid" value="VISU.Result"/>
1824 * <parameter name="method" value="nameOfModuleMethod"/>
1827 void SalomeApp_Application::createExtraActions()
1829 myExtActions.clear();
1830 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1832 QStringList aModules;
1833 modules(aModules, false);
1834 foreach(QString aModile, aModules) {
1835 QString aModName = moduleName(aModile);
1836 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1837 if (!aSectionStr.isNull()) {
1838 QStringList aSections = aSectionStr.split(':');
1839 foreach(QString aSection, aSections) {
1840 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1841 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1842 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1843 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1846 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1847 if (aModuleName.isNull())
1848 aModuleName = aModName;
1850 QAction* aAction = new QAction(aTitle, this);
1852 aData<<aModuleName<<aSlot;
1853 aAction->setData(aData);
1854 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1855 myExtActions[aId] = aAction;
1862 * Called when extra action is selected
1864 void SalomeApp_Application::onExtAction()
1866 QAction* aAction = ::qobject_cast<QAction*>(sender());
1870 QVariant aData = aAction->data();
1871 QStringList aDataList = aData.value<QStringList>();
1872 if (aDataList.size() != 2)
1875 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1876 SALOME_ListIO aListIO;
1877 aSelectionMgr->selectedObjects(aListIO);
1878 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1879 if (aListIO.Extent() < 1)
1881 if (!anIO->hasEntry())
1884 QString aEntry(anIO->getEntry());
1886 QApplication::setOverrideCursor( Qt::WaitCursor );
1887 QString aModuleTitle = moduleTitle(aDataList[0]);
1888 activateModule(aModuleTitle);
1889 QApplication::restoreOverrideCursor();
1891 QCoreApplication::processEvents();
1893 CAM_Module* aModule = activeModule();
1897 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1898 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1902 Checks that an object can be renamed.
1903 \param entry entry of the object
1904 \brief Return \c true if object can be renamed
1906 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1908 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1912 Rename object by entry.
1913 \param entry entry of the object
1914 \param name new name of the object
1915 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1917 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1919 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1921 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1923 if(!aStudy || savePoint == -1)
1926 if ( !name.isNull() && !name.isEmpty() ) {
1927 aStudy->setNameOfSavePoint( savePoint, name );
1928 updateSavePointDataObjects( aStudy );
1930 //Mark study as modified
1937 #ifndef DISABLE_PYCONSOLE
1938 //============================================================================
1939 /*! Function : onUpdateStudy
1940 * Purpose : Slot to update the study.
1942 //============================================================================
1943 void SalomeApp_Application::onUpdateStudy()
1945 QApplication::setOverrideCursor( Qt::WaitCursor );
1947 if( !updateStudy() )
1948 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1950 QApplication::restoreOverrideCursor();
1953 //============================================================================
1954 /*! Function : updateStudy
1955 * Purpose : Update study by dumping the study to Python script and loading it.
1956 * It is used to apply variable modifications done in NoteBook to created objects.
1958 //============================================================================
1959 bool SalomeApp_Application::updateStudy()
1961 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1962 if ( !study || !myNoteBook )
1965 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1966 myNoteBook->setDumpedStudyName( study->studyName() );
1968 _PTR(Study) studyDS = study->studyDS();
1970 // get unique temporary directory name
1971 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1972 if( aTmpDir.isEmpty() )
1975 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1976 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1978 // dump study to the temporary directory
1979 QString aScriptName( "notebook" );
1980 bool toPublish = true;
1981 bool isMultiFile = false;
1982 bool toSaveGUI = true;
1985 _PTR(AttributeParameter) ap;
1986 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1987 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1988 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1989 ip->setDumpPython(studyDS);
1990 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1992 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1994 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1997 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2001 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2002 int anIndex = aList.indexOf( this );
2004 // Disconnect dialog from application desktop in case if:
2005 // 1) Application is not the first application in the session
2006 // 2) Application is the first application in session but not the only.
2007 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2008 if( changeDesktop ) {
2010 SalomeApp_Application* app = this;
2011 if( anIndex > 0 && anIndex < aList.count() )
2012 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2013 else if(anIndex == 0 && aList.count() > 1)
2014 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2019 // creation a new study and restoring will be done in another application
2020 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2021 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2024 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2025 QString aStudyName = myNoteBook->getDumpedStudyName();
2026 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2027 // clear a study (delete all objects)
2028 onCloseDoc( false );
2030 if( !changeDesktop ) {
2031 ok = onRestoreStudy( aDumpScript,
2040 //============================================================================
2041 /*! Function : onRestoreStudy
2042 * Purpose : Load the dumped study from Python script
2044 //============================================================================
2045 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2046 const QString& theStudyName,
2047 bool theIsStudySaved )
2051 // create a new study
2054 // get active application
2055 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2057 // load study from the temporary directory
2058 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2060 #ifndef DISABLE_PYCONSOLE
2061 PyConsole_Console* pyConsole = app->pythonConsole();
2063 pyConsole->execAndWait( command );
2066 // remove temporary directory
2067 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2068 QString aStudyName = aScriptInfo.baseName();
2069 QDir aDir = aScriptInfo.absoluteDir();
2070 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2071 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2072 ok = aDir.remove( *it ) && ok;
2074 ok = aDir.rmdir( aDir.absolutePath() );
2076 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2078 #ifndef DISABLE_PYCONSOLE
2079 _PTR(Study) aStudyDS = newStudy->studyDS();
2080 app->getNoteBook()->Init( aStudyDS );
2081 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2082 newStudy->Modified();
2083 updateDesktopTitle();
2094 Close the Application
2096 void SalomeApp_Application::afterCloseDoc()
2098 #ifndef DISABLE_PYCONSOLE
2099 // emit signal to restore study from Python script
2101 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2102 myNoteBook->getDumpedStudyName(),
2103 myNoteBook->isDumpedStudySaved() );
2106 LightApp_Application::afterCloseDoc();
2110 Asks to close existing document.
2112 bool SalomeApp_Application::checkExistingDoc()
2114 bool result = LightApp_Application::checkExistingDoc();
2115 if ( result && !activeStudy() ) {
2116 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2118 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2119 if( List.size() > 0 ) {
2120 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2129 #ifndef DISABLE_PYCONSOLE
2131 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2133 return new SalomeApp_PyInterp();
2136 #endif // DISABLE_PYCONSOLE