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 myIsSiman = false; // default
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 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
408 /*!SLOT. Load document.*/
409 void SalomeApp_Application::onLoadDoc()
413 std::vector<std::string> List = studyMgr()->GetOpenStudies();
415 // rnv: According to the single-study approach on the server side
416 // can be only one study. So if it is exists connect to them,
417 // overwise show warning message: "No active study on the server"
420 SUIT_Session* aSession = SUIT_Session::session();
421 QList<SUIT_Application*> aAppList = aSession->applications();
423 QStringList unloadedStudies;
425 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
426 studyName = List[ind].c_str();
427 // Add to list only unloaded studies
428 bool isAlreadyOpen = false;
429 QListIterator<SUIT_Application*> it( aAppList );
430 while ( it.hasNext() && !isAlreadyOpen ) {
431 SUIT_Application* aApp = it.next();
432 if( !aApp || !aApp->activeStudy() )
434 if ( aApp->activeStudy()->studyName() == studyName )
435 isAlreadyOpen = true;
438 if ( !isAlreadyOpen )
439 unloadedStudies << studyName;
441 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
442 if ( studyName.isEmpty() )
446 if(List.size() <= 0) {
447 SUIT_MessageBox::warning( desktop(),
448 QObject::tr("WRN_WARNING"),
449 QObject::tr("WRN_NO_STUDY_ON SERV") );
453 studyName = List[0].c_str();
456 // this code replaces marker of windows drive and path become invalid therefore
457 // defines placed there
458 studyName.replace( QRegExp(":"), "/" );
461 if ( onLoadDoc( studyName ) ) {
463 updateViewManagers();
464 updateObjectBrowser( true );
468 /*!SLOT. Unload document.*/
469 void SalomeApp_Application::onUnloadDoc( bool ask )
472 activeStudy()->abortAllOperations();
473 if ( activeStudy()->isModified() ) {
474 QString docName = activeStudy()->studyName().trimmed();
475 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
476 tr( "DISCONNECT_DESCRIPTION" ),
477 tr( "DISCONNECT_SAVE" ),
478 tr( "DISCONNECT_WO_SAVE" ),
479 tr( "APPCLOSE_CANCEL" ), 0 );
480 if ( answer == 0 ) { // save before unload
481 if ( activeStudy()->isSaved() )
483 else if ( !onSaveAsDoc() )
486 else if ( answer == 2 ) // Cancel
490 closeActiveDoc( false );
493 /*!SLOT. Create new study and load script*/
494 void SalomeApp_Application::onNewWithScript()
496 QStringList filtersList;
497 filtersList.append(tr("PYTHON_FILES_FILTER"));
498 filtersList.append(tr("ALL_FILES_FILTER"));
500 QString anInitialPath = "";
501 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
502 anInitialPath = QDir::currentPath();
504 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
506 if ( !aFile.isEmpty() )
510 QString command = QString("execfile(r\"%1\")").arg(aFile);
512 #ifndef DISABLE_PYCONSOLE
513 PyConsole_Console* pyConsole = pythonConsole();
516 pyConsole->exec( command );
522 /*!SLOT. Load document with \a aName.*/
523 bool SalomeApp_Application::onLoadDoc( const QString& aName )
525 #ifdef SINGLE_DESKTOP
526 if ( !LightApp_Application::closeDoc() )
530 if ( !activeStudy() ) {
531 // if no study - load in current desktop
532 res = useStudy( aName );
535 // if study exists - load in new desktop. Check: is the same file is loaded?
536 SUIT_Session* aSession = SUIT_Session::session();
537 QList<SUIT_Application*> aAppList = aSession->applications();
538 bool isAlreadyOpen = false;
539 SalomeApp_Application* aApp = 0;
540 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
541 it != aAppList.end() && !isAlreadyOpen; ++it ) {
542 aApp = dynamic_cast<SalomeApp_Application*>( *it );
543 if ( aApp && aApp->activeStudy()->studyName() == aName )
544 isAlreadyOpen = true;
546 if ( !isAlreadyOpen ) {
547 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
549 res = aApp->useStudy( aName );
552 aApp->desktop()->activateWindow();
559 /*!SLOT. Parse message for desktop.*/
560 void SalomeApp_Application::onDesktopMessage( const QString& message )
562 if (message.indexOf("simanCheckoutDone ") == 0) {
564 // Load document with a name, specified in aMessage.
565 onLoadDoc(message.section(' ', 1));
567 printf( "****************************************************************\n" );
568 printf( "* Warning: SALOME is built without SIMAN support.\n" );
569 printf( "****************************************************************\n" );
572 else if (message.indexOf("studyCreated:") == 0) {
573 // Enable 'Connect' action
574 updateCommandsStatus();
576 else if (message.indexOf("studyClosed:") == 0) {
577 /* message also contains ID of the closed study,
578 but as soon as SALOME is mono-study application for the moment,
579 this ID is not needed now.*/
580 //long aStudyId = message.section(':', 1).toLong();
581 // Disconnect GUI from active study, because it was closed on DS side.
582 closeActiveDoc( false );
583 // Disable 'Connect' action
584 QAction* a = action( ConnectId );
586 a->setEnabled( false );
588 LightApp_Application::onDesktopMessage( message );
591 /*!SLOT. Copy objects to study maneger from selection maneger..*/
592 void SalomeApp_Application::onCopy()
595 LightApp_SelectionMgr* mgr = selectionMgr();
596 mgr->selectedObjects(list);
598 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
599 if(study == NULL) return;
601 _PTR(Study) stdDS = study->studyDS();
604 SALOME_ListIteratorOfListIO it( list );
607 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
609 studyMgr()->Copy(so);
610 onSelectionChanged();
617 /*!SLOT. Paste objects to study maneger from selection manager.*/
618 void SalomeApp_Application::onPaste()
621 LightApp_SelectionMgr* mgr = selectionMgr();
622 mgr->selectedObjects(list);
624 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
625 if(study == NULL) return;
627 _PTR(Study) stdDS = study->studyDS();
630 if ( stdDS->GetProperties()->IsLocked() ) {
631 SUIT_MessageBox::warning( desktop(),
632 QObject::tr("WRN_WARNING"),
633 QObject::tr("WRN_STUDY_LOCKED") );
637 SALOME_ListIteratorOfListIO it( list );
640 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
642 studyMgr()->Paste(so);
643 updateObjectBrowser( true );
644 updateActions(); //SRN: BugID IPAL9377, case 3
651 /*!Check the application on closing.
652 * \retval true if possible, else false
654 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
656 return LightApp_Application::isPossibleToClose( closePermanently );
659 /*! Check if the study is locked */
660 void SalomeApp_Application::onCloseDoc( bool ask )
662 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
665 _PTR(Study) stdDS = study->studyDS();
666 if(stdDS && stdDS->IsStudyLocked()) {
667 if ( SUIT_MessageBox::question( desktop(),
668 QObject::tr( "WRN_WARNING" ),
669 QObject::tr( "CLOSE_LOCKED_STUDY" ),
670 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
671 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
675 LightApp_Application::onCloseDoc( ask );
678 /*!Sets enable or disable some actions on selection changed.*/
679 void SalomeApp_Application::onSelectionChanged()
682 LightApp_SelectionMgr* mgr = selectionMgr();
683 mgr->selectedObjects(list);
685 bool canCopy = false;
686 bool canPaste = false;
688 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
690 _PTR(Study) stdDS = study->studyDS();
693 SALOME_ListIteratorOfListIO it ( list );
695 if (it.More() && list.Extent() == 1) {
696 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
699 canCopy = studyMgr()->CanCopy(so);
700 canPaste = studyMgr()->CanPaste(so);
706 action(EditCopyId)->setEnabled(canCopy);
707 action(EditPasteId)->setEnabled(canPaste);
710 /*!Delete references.*/
711 void SalomeApp_Application::onDeleteInvalidReferences()
714 LightApp_SelectionMgr* mgr = selectionMgr();
715 mgr->selectedObjects( aList, QString(), false );
717 if( aList.IsEmpty() )
720 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
721 _PTR(Study) aStudyDS = aStudy->studyDS();
722 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
725 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
726 if ( it.Value()->hasEntry() )
728 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
729 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
732 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
733 aStudyBuilder->RemoveReference( aSObject );
735 updateObjectBrowser();
739 void SalomeApp_Application::onOpenWith()
741 QApplication::setOverrideCursor( Qt::WaitCursor );
743 LightApp_SelectionMgr* mgr = selectionMgr();
744 mgr->selectedObjects(aList);
745 if (aList.Extent() != 1)
747 QApplication::restoreOverrideCursor();
750 Handle(SALOME_InteractiveObject) aIObj = aList.First();
751 QString aModuleName(aIObj->getComponentDataType());
752 QString aModuleTitle = moduleTitle(aModuleName);
753 activateModule(aModuleTitle);
754 QApplication::restoreOverrideCursor();
760 SUIT_Study* SalomeApp_Application::createNewStudy()
762 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
764 // Set up processing of major study-related events
765 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
766 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
767 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
768 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
770 #ifndef DISABLE_PYCONSOLE
771 //to receive signal in application that NoteBook's variable was modified
772 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
773 this, SIGNAL(notebookVarUpdated(QString)) );
780 Enable/Disable menu items and toolbar buttons. Rebuild menu
782 void SalomeApp_Application::updateCommandsStatus()
784 LightApp_Application::updateCommandsStatus();
787 QAction* a = action( DumpStudyId );
789 a->setEnabled( activeStudy() );
792 a = action( LoadScriptId );
794 a->setEnabled( pythonConsole() );
797 a = action( PropertiesId );
799 a->setEnabled( activeStudy() );
801 // Save GUI state menu
802 a = action( SaveGUIStateId );
804 a->setEnabled( activeStudy() );
806 // Connect study menu
807 a = action( ConnectId );
809 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
811 // Disconnect study menu
812 a = action( DisconnectId );
814 a->setEnabled( activeStudy() );
816 // update state of Copy/Paste menu items
817 onSelectionChanged();
821 \class DumpStudyFileDlg
822 Private class used in Dump Study operation. Consists 2 check boxes:
823 "Publish in study" and "Save GUI parameters"
825 class DumpStudyFileDlg : public SUIT_FileDlg
828 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
830 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
833 QWidget *hB = new QWidget( this );
834 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
835 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
836 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
838 QHBoxLayout *layout = new QHBoxLayout;
839 layout->addWidget(myPublishChk);
840 layout->addWidget(myMultiFileChk);
841 layout->addWidget(mySaveGUIChk);
842 hB->setLayout(layout);
844 QPushButton* pb = new QPushButton(this);
846 int row = grid->rowCount();
847 grid->addWidget( new QLabel("", this), row, 0 );
848 grid->addWidget( hB, row, 1, 1, 3 );
849 grid->addWidget( pb, row, 5 );
854 QCheckBox* myPublishChk;
855 QCheckBox* myMultiFileChk;
856 QCheckBox* mySaveGUIChk;
859 class DumpStudyFileValidator : public SUIT_FileValidator
862 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
863 virtual ~DumpStudyFileValidator() {};
864 virtual bool canSave( const QString& file, bool permissions );
867 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
869 QFileInfo fi( file );
870 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
871 SUIT_MessageBox::critical( parent(),
872 QObject::tr("WRN_WARNING"),
873 QObject::tr("WRN_FILE_NAME_BAD") );
876 return SUIT_FileValidator::canSave( file, permissions);
879 /*!Private SLOT. On dump study.*/
880 void SalomeApp_Application::onDumpStudy( )
882 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
883 if ( !appStudy ) return;
884 _PTR(Study) aStudy = appStudy->studyDS();
886 QStringList aFilters;
887 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
889 bool anIsPublish = true;
890 bool anIsMultiFile = false;
891 bool anIsSaveGUI = true;
893 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
894 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
895 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
896 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
899 DumpStudyFileDlg fd( desktop() );
900 fd.setValidator( new DumpStudyFileValidator( &fd ) );
901 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
902 fd.setFilters( aFilters );
903 fd.myPublishChk->setChecked( anIsPublish );
904 fd.myMultiFileChk->setChecked( anIsMultiFile );
905 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
906 if ( fd.exec() == QDialog::Accepted )
908 QString aFileName = fd.selectedFile();
910 bool toPublish = fd.myPublishChk->isChecked();
911 bool isMultiFile = fd.myMultiFileChk->isChecked();
912 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
914 if ( !aFileName.isEmpty() ) {
915 QFileInfo aFileInfo(aFileName);
916 if( aFileInfo.isDir() ) // IPAL19257
919 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
922 SUIT_OverrideCursor wc;
923 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
926 SUIT_MessageBox::warning( desktop(),
927 QObject::tr("WRN_WARNING"),
928 tr("WRN_DUMP_STUDY_FAILED") );
933 /*!Private SLOT. On load script.*/
934 void SalomeApp_Application::onLoadScript( )
936 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
938 _PTR(Study) aStudy = appStudy->studyDS();
939 if ( aStudy->GetProperties()->IsLocked() ) {
940 SUIT_MessageBox::warning( desktop(),
941 QObject::tr("WRN_WARNING"),
942 QObject::tr("WRN_STUDY_LOCKED") );
947 QStringList filtersList;
948 filtersList.append(tr("PYTHON_FILES_FILTER"));
949 filtersList.append(tr("ALL_FILES_FILTER"));
951 QString anInitialPath = "";
952 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
953 anInitialPath = QDir::currentPath();
956 // MPV: if it is SIMAN study, make the initial path as the path to the Siman scripts storage
958 SALOMEDSClient_StudyManager* aMgr = studyMgr();
959 aMgr->GetSimanStudy()->StudyId();
960 anInitialPath = QString(QDir::separator()) + "tmp" + QDir::separator() + "SimanSalome" + QDir::separator() +
961 aMgr->GetSimanStudy()->StudyId().c_str() + QDir::separator() +
962 aMgr->GetSimanStudy()->ScenarioId().c_str() + QDir::separator() + aMgr->GetSimanStudy()->UserId().c_str();
966 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
968 if ( !aFile.isEmpty() )
970 QString command = QString("execfile(r\"%1\")").arg(aFile);
972 #ifndef DISABLE_PYCONSOLE
973 PyConsole_Console* pyConsole = pythonConsole();
976 pyConsole->exec( command );
981 /*!Private SLOT. On save GUI state.*/
982 void SalomeApp_Application::onSaveGUIState()
984 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
986 SalomeApp_VisualState( this ).storeState();
987 updateSavePointDataObjects( study );
988 updateObjectBrowser();
993 /*!Public SLOT. On SIMAN check in operation.*/
994 void SalomeApp_Application::onCheckIn()
997 setMenuShown(SimanCheckInId, false); // check in may be performed only once
998 setMenuShown(SimanLocalCheckInId, false);
999 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1000 aMgr->GetSimanStudy()->CheckIn("");
1002 printf( "****************************************************************\n" );
1003 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1004 printf( "****************************************************************\n" );
1008 /*!Public SLOT. On SIMAN local check in operation.*/
1009 void SalomeApp_Application::onLocalCheckIn()
1012 // get the active module
1013 CAM_Module* aModule = activeModule();
1014 if (!aModule) return; // there is no active module
1016 setMenuShown(SimanCheckInId, false); // check in may be performed only once
1017 setMenuShown(SimanLocalCheckInId, false);
1018 SALOMEDSClient_StudyManager* aMgr = studyMgr();
1019 aMgr->GetSimanStudy()->CheckIn(aModule->name().toLatin1().data());
1021 printf( "****************************************************************\n" );
1022 printf( "* Warning: SALOME is built without SIMAN support.\n" );
1023 printf( "****************************************************************\n" );
1027 /*!Gets file filter.
1028 *\retval QString "(*.hdf)"
1030 QString SalomeApp_Application::getFileFilter() const
1036 QWidget* SalomeApp_Application::createWindow( const int flag )
1039 #ifndef DISABLE_PYCONSOLE
1040 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1042 wid = LightApp_Application::createWindow(flag);
1045 SUIT_ResourceMgr* resMgr = resourceMgr();
1047 if ( flag == WT_ObjectBrowser )
1049 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1051 // temporary commented
1052 //ob->setUpdater( new SalomeApp_Updater() );
1054 #ifdef WITH_SALOMEDS_OBSERVER
1055 //do not activate the automatic update of Qt tree through signal/slot
1056 ob->setAutoUpdate(false);
1057 //activate update of modified objects only
1058 ob->setUpdateModified(true);
1061 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1064 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1065 IORCol = QObject::tr( "IOR_COLUMN" ),
1066 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1067 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1069 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1070 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1071 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1072 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1073 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1074 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1075 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1076 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1077 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1079 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1080 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1081 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1083 ob->setAutoSizeFirstColumn(autoSizeFirst);
1084 ob->setAutoSizeColumns(autoSize);
1085 ob->setResizeOnExpandItem(resizeOnExpandItem);
1086 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1088 // temporary commented
1090 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1092 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1093 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1094 QString().sprintf( "visibility_column_%d", i ), true ) );
1098 // temporary commented
1100 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1101 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1102 ob->resize( desktop()->width()/3, ob->height() );
1106 #ifndef DISABLE_PYCONSOLE
1107 else if ( flag == WT_PyConsole )
1109 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
1110 pyCons->setObjectName( "pythonConsole" );
1111 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1112 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1113 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1114 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1116 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1117 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1119 else if ( flag == WT_NoteBook )
1121 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1123 _PTR(Study) aStudy = appStudy->studyDS();
1124 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1125 //to receive signal in NoteBook that it's variable was modified
1126 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1127 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1129 wid = getNoteBook();
1130 wid->setObjectName( "noteBook" );
1136 /*!Create preferences.*/
1137 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1139 LightApp_Application::createPreferences(pref);
1144 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1145 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1146 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1147 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1149 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1150 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1152 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1154 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1155 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1156 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1157 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1158 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1159 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1160 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1161 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1162 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1163 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1166 /*!Update desktop title.*/
1167 void SalomeApp_Application::updateDesktopTitle() {
1168 QString aTitle = applicationName();
1169 QString aVer = applicationVersion();
1170 if ( !aVer.isEmpty() )
1171 aTitle += QString( " " ) + aVer;
1173 if ( activeStudy() )
1175 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1176 if ( !sName.isEmpty() ) {
1177 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1179 _PTR(Study) stdDS = study->studyDS();
1181 if ( stdDS->GetProperties()->IsLocked() ) {
1182 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1184 aTitle += QString( " - [%1]" ).arg( sName );
1191 desktop()->setWindowTitle( aTitle );
1194 int SalomeApp_Application::closeChoice( const QString& docName )
1196 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ),
1197 tr ("APPCLOSE_SAVE"), tr ("APPCLOSE_CLOSE"),
1198 //tr ("APPCLOSE_UNLOAD"),
1199 tr ("APPCLOSE_CANCEL"), 0 );
1201 int res = CloseCancel;
1204 else if ( answer == 1 )
1206 // else if ( answer == 2 )
1207 // res = CloseUnload;
1212 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1218 if ( activeStudy()->isSaved() )
1220 else if ( !onSaveAsDoc() )
1226 closePermanently = false;
1236 int SalomeApp_Application::openChoice( const QString& aName )
1238 int choice = LightApp_Application::openChoice( aName );
1240 if ( QFileInfo( aName ).exists() ) {
1241 if ( choice == OpenNew ) { // The document isn't already open.
1243 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1244 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1245 if ( aName == QString( lst[i].c_str() ) )
1248 // The document already exists in the study manager.
1249 // Do you want to reload it?
1251 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1252 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1253 if ( answer == SUIT_MessageBox::Yes )
1254 choice = OpenRefresh;
1256 choice = OpenCancel;
1259 } else { // file is not exist on disk
1260 SUIT_MessageBox::warning( desktop(),
1261 QObject::tr("WRN_WARNING"),
1262 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1269 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1272 int choice = aChoice;
1277 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1280 studyMgr()->Close( aStudy );
1285 res = LightApp_Application::openAction( choice, aName );
1293 \brief Get map of the operations which can be performed
1294 on the module activation.
1296 The method should return the map of the kind \c {<id>:<name>}
1297 where \c <id> is an integer identifier of the operation and
1298 \c <name> is a title for the button to be added to the
1299 dialog box. After user selects the required operation by the
1300 clicking the corresponding button in the dialog box, its identifier
1301 is passed to the moduleActionSelected() method to process
1304 \return map of the operations
1305 \sa moduleActionSelected()
1307 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1309 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1311 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1313 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1318 \brief Called when the used selectes required operation chosen
1319 from "Activate module" dialog box.
1321 Performs the required operation according to the user choice.
1323 \param id operation identifier
1324 \sa activateModuleActions()
1326 void SalomeApp_Application::moduleActionSelected( const int id )
1332 case NewAndScriptId:
1336 LightApp_Application::moduleActionSelected( id );
1341 /*!Gets CORBA::ORB_var*/
1342 CORBA::ORB_var SalomeApp_Application::orb()
1344 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1345 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
1349 /*!Create and return SALOMEDS_StudyManager.*/
1350 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1352 static _PTR(StudyManager) _sm;
1353 if(!_sm) _sm = ClientFactory::StudyManager();
1357 /*!Create and return SALOME_NamingService.*/
1358 SALOME_NamingService* SalomeApp_Application::namingService()
1360 static SALOME_NamingService _ns(orb());
1364 /*!Create and return SALOME_LifeCycleCORBA.*/
1365 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1367 static SALOME_LifeCycleCORBA _lcc( namingService() );
1371 /*!Private SLOT. On preferences.*/
1372 void SalomeApp_Application::onProperties()
1374 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1378 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1381 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1382 int res = aDlg.exec();
1383 if( res==QDialog::Accepted && aDlg.isChanged() )
1384 SB->CommitCommand();
1388 //study->updateCaptions();
1389 updateDesktopTitle();
1393 /*!Insert items in popup, which necessary for current application*/
1394 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1396 LightApp_SelectionMgr* mgr = selectionMgr();
1397 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1398 mgr->setSelectionCacheEnabled( true );
1400 LightApp_Application::contextMenuPopup( type, thePopup, title );
1402 // temporary commented
1403 /*OB_Browser* ob = objectBrowser();
1404 if ( !ob || type != ob->popupClientType() )
1407 // Get selected objects
1408 SALOME_ListIO aList;
1409 mgr->selectedObjects( aList, QString(), false );
1411 // add GUI state commands: restore, rename
1412 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1413 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1414 thePopup->addSeparator();
1415 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1416 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1417 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1418 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1421 // "Delete reference" item should appear only for invalid references
1423 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1424 bool isInvalidRefs = false;
1425 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1426 _PTR(Study) aStudyDS = aStudy->studyDS();
1427 _PTR(SObject) anObj;
1429 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1430 if( it.Value()->hasEntry() )
1432 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1433 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1436 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1437 isInvalidRefs = true;
1440 // Add "Delete reference" item to popup
1441 if ( isInvalidRefs )
1443 thePopup->addSeparator();
1444 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1448 // "Activate module" item should appear only if it's necessary
1449 if ( aList.Extent() == 1 ) {
1451 mgr->selectedObjects( aList );
1453 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1455 // add extra popup menu (defined in XML)
1456 if ( myExtActions.size() > 0 ) {
1457 // Use only first selected object
1458 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1460 _PTR(Study) stdDS = study->studyDS();
1462 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1464 _PTR( GenericAttribute ) anAttr;
1465 std::string auid = "AttributeUserID";
1466 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1467 if ( aSO->FindAttribute( anAttr, auid ) ) {
1468 _PTR(AttributeUserID) aAttrID = anAttr;
1469 QString aId = aAttrID->Value().c_str();
1470 if ( myExtActions.contains( aId ) ) {
1471 thePopup->addAction(myExtActions[aId]);
1479 // check if item is a "GUI state" item (also a first level object)
1480 QString entry( aIObj->getEntry() );
1481 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1482 QString aModuleName( aIObj->getComponentDataType() );
1483 QString aModuleTitle = moduleTitle( aModuleName );
1484 CAM_Module* currentModule = activeModule();
1485 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1486 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1490 mgr->setSelectionCacheEnabled( cacheIsOn );
1493 /*!Update obect browser:
1494 1.if 'updateModels' true, update existing data models;
1495 2. update "non-existing" (not loaded yet) data models;
1496 3. update object browser if it exists */
1497 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1499 // update "non-existing" (not loaded yet) data models
1500 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1503 _PTR(Study) stdDS = study->studyDS();
1506 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1508 _PTR(SComponent) aComponent ( it->Value() );
1510 #ifndef WITH_SALOMEDS_OBSERVER
1511 // with GUI observers this check is not needed anymore
1512 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1513 continue; // skip the magic "Interface Applicative" component
1515 if ( !objectBrowser() )
1516 getWindow( WT_ObjectBrowser );
1517 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1518 objectBrowser()->setAutoUpdate( false );
1519 SalomeApp_DataModel::synchronize( aComponent, study );
1520 objectBrowser()->setAutoUpdate( isAutoUpdate );
1525 // create data objects that correspond to GUI state save points
1526 if ( study ) updateSavePointDataObjects( study );
1528 // update existing data models (already loaded SComponents)
1529 LightApp_Application::updateObjectBrowser( updateModels );
1532 /*!Display Catalog Genenerator dialog */
1533 void SalomeApp_Application::onCatalogGen()
1535 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1539 /*!Display Registry Display dialog */
1540 void SalomeApp_Application::onRegDisplay()
1542 CORBA::ORB_var anOrb = orb();
1543 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1546 regWnd->activateWindow();
1549 /*!find original object by double click on item */
1550 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1552 // Issue 21379: References are supported at LightApp_DataObject level
1553 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1555 if( obj && obj->isReference() )
1557 QString entry = obj->refEntry();
1559 SUIT_DataOwnerPtrList aList;
1560 aList.append( new LightApp_DataOwner( entry ) );
1561 selectionMgr()->setSelected( aList, false );
1563 SUIT_DataBrowser* ob = objectBrowser();
1565 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1566 if ( !aSelectedIndexes.isEmpty() )
1567 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1572 Creates new view manager
1573 \param type - type of view manager
1575 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1577 return createViewManager(type);
1581 /*!Global utility function, returns selected GUI Save point object's ID */
1582 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1584 SALOME_ListIO aList;
1585 selMgr->selectedObjects( aList );
1586 if( aList.Extent() > 0 ) {
1587 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1588 QString entry( aIObj->getEntry() );
1589 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1590 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1592 bool ok; // conversion to integer is ok?
1593 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1594 return ok ? savePoint : -1;
1599 /*!Called on Restore GUI State popup command*/
1600 void SalomeApp_Application::onRestoreGUIState()
1602 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1603 if ( savePoint == -1 )
1605 SalomeApp_VisualState( this ).restoreState( savePoint );
1608 /*!Called on Delete GUI State popup command*/
1609 void SalomeApp_Application::onDeleteGUIState()
1611 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1612 if ( savePoint == -1 )
1614 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1618 study->removeSavePoint( savePoint );
1619 updateSavePointDataObjects( study );
1622 /*!Called on New study operation*/
1623 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1625 LightApp_Application::onStudyCreated( study );
1627 //#ifndef DISABLE_PYCONSOLE
1628 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1629 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1632 loadDockWindowsState();
1634 objectBrowserColumnsVisibility();
1637 /*!Called on Open study operation*/
1638 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1640 LightApp_Application::onStudyOpened( study );
1642 //#ifndef DISABLE_PYCONSOLE
1643 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1644 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1647 loadDockWindowsState();
1649 objectBrowserColumnsVisibility();
1651 // temporary commented
1652 /*if ( objectBrowser() ) {
1653 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1654 objectBrowser()->updateTree( study->root() );
1658 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1659 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1662 SUIT_DataBrowser* ob = objectBrowser();
1663 LightApp_SelectionMgr* selMgr = selectionMgr();
1665 if ( !study || !ob || !selMgr )
1668 // find GUI states root object
1669 SUIT_DataObject* guiRootObj = 0;
1671 study->root()->children( ch );
1672 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1673 for ( ; it != last ; ++it ) {
1674 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1679 std::vector<int> savePoints = study->getSavePoints();
1680 // case 1: no more save points but they existed in study's tree
1681 if ( savePoints.empty() && guiRootObj ) {
1682 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1683 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1684 const bool isAutoUpdate = ob->autoUpdate();
1685 selMgr->clearSelected();
1686 ob->setAutoUpdate(true);
1687 DataObjectList ch = guiRootObj->children();
1688 for( int i = 0; i < ch.size(); i++ )
1691 ob->setAutoUpdate(isAutoUpdate);
1694 // case 2: no more save points but root does not exist either
1695 if ( savePoints.empty() && !guiRootObj )
1697 // case 3: save points but no root for them - create it
1698 if ( !savePoints.empty() && !guiRootObj )
1699 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1700 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1701 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1703 if ( guiRootObj->nextBrother() ) {
1704 study->root()->removeChild(guiRootObj);
1705 study->root()->appendChild(guiRootObj);
1706 //study->root()->dump();
1709 // store data objects in a map id-to-DataObject
1710 QMap<int,SalomeApp_SavePointObject*> mapDO;
1712 guiRootObj->children( ch );
1713 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1714 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1716 mapDO[dobj->getId()] = dobj;
1719 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1720 // if in the map - remove it from map.
1721 for ( int i = 0; i < savePoints.size(); i++ )
1722 if ( !mapDO.contains( savePoints[i] ) )
1723 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1725 mapDO.remove( savePoints[i] );
1727 // delete DataObjects that are still in the map -- their IDs were not found in data model
1728 if( mapDO.size() > 0) {
1729 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1730 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1731 selMgr->clearSelected();
1732 const bool isAutoUpdate = ob->autoUpdate();
1733 ob->setAutoUpdate(true);
1734 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1736 ob->setAutoUpdate(isAutoUpdate);
1740 /*! Check data object */
1741 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1750 Opens other study into active Study. If Study is empty - creates it.
1751 \param theName - name of study
1753 bool SalomeApp_Application::useStudy( const QString& theName )
1756 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1759 res = aStudy->loadDocument( theName );
1760 updateDesktopTitle();
1761 updateCommandsStatus();
1765 /*! Show/hide object browser colums according to preferences */
1766 void SalomeApp_Application::objectBrowserColumnsVisibility()
1768 if ( objectBrowser() )
1769 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1771 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1772 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1776 #ifndef DISABLE_PYCONSOLE
1777 /*! Set SalomeApp_NoteBook pointer */
1778 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1780 myNoteBook = theNoteBook;
1783 /*! Return SalomeApp_NoteBook pointer */
1784 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1791 * Define extra actions defined in module definition XML file.
1792 * Additional popup items sections can be defined by parameter "popupitems".
1793 * Supported attributes:
1794 * title - title of menu item,
1795 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1796 * method - method which has to be called when menu item is selected
1798 * <section name="MODULENAME">
1799 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1801 * <section name="importmed">
1802 * <parameter name="title" value="My menu"/>
1803 * <parameter name="objectid" value="VISU.Result"/>
1804 * <parameter name="method" value="nameOfModuleMethod"/>
1807 void SalomeApp_Application::createExtraActions()
1809 myExtActions.clear();
1810 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1812 QStringList aModules;
1813 modules(aModules, false);
1814 foreach(QString aModile, aModules) {
1815 QString aModName = moduleName(aModile);
1816 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1817 if (!aSectionStr.isNull()) {
1818 QStringList aSections = aSectionStr.split(':');
1819 foreach(QString aSection, aSections) {
1820 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1821 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1822 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1823 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1826 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1827 if (aModuleName.isNull())
1828 aModuleName = aModName;
1830 QAction* aAction = new QAction(aTitle, this);
1832 aData<<aModuleName<<aSlot;
1833 aAction->setData(aData);
1834 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1835 myExtActions[aId] = aAction;
1842 * Called when extra action is selected
1844 void SalomeApp_Application::onExtAction()
1846 QAction* aAction = ::qobject_cast<QAction*>(sender());
1850 QVariant aData = aAction->data();
1851 QStringList aDataList = aData.value<QStringList>();
1852 if (aDataList.size() != 2)
1855 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1856 SALOME_ListIO aListIO;
1857 aSelectionMgr->selectedObjects(aListIO);
1858 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1859 if (aListIO.Extent() < 1)
1861 if (!anIO->hasEntry())
1864 QString aEntry(anIO->getEntry());
1866 QApplication::setOverrideCursor( Qt::WaitCursor );
1867 QString aModuleTitle = moduleTitle(aDataList[0]);
1868 activateModule(aModuleTitle);
1869 QApplication::restoreOverrideCursor();
1871 QCoreApplication::processEvents();
1873 CAM_Module* aModule = activeModule();
1877 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1878 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1882 Checks that an object can be renamed.
1883 \param entry entry of the object
1884 \brief Return \c true if object can be renamed
1886 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1888 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1892 Rename object by entry.
1893 \param entry entry of the object
1894 \param name new name of the object
1895 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1897 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1899 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1901 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1903 if(!aStudy || savePoint == -1)
1906 if ( !name.isNull() && !name.isEmpty() ) {
1907 aStudy->setNameOfSavePoint( savePoint, name );
1908 updateSavePointDataObjects( aStudy );
1910 //Mark study as modified
1917 #ifndef DISABLE_PYCONSOLE
1918 //============================================================================
1919 /*! Function : onUpdateStudy
1920 * Purpose : Slot to update the study.
1922 //============================================================================
1923 void SalomeApp_Application::onUpdateStudy()
1925 QApplication::setOverrideCursor( Qt::WaitCursor );
1927 if( !updateStudy() )
1928 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1930 QApplication::restoreOverrideCursor();
1933 //============================================================================
1934 /*! Function : updateStudy
1935 * Purpose : Update study by dumping the study to Python script and loading it.
1936 * It is used to apply variable modifications done in NoteBook to created objects.
1938 //============================================================================
1939 bool SalomeApp_Application::updateStudy()
1941 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1942 if ( !study || !myNoteBook )
1945 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1946 myNoteBook->setDumpedStudyName( study->studyName() );
1948 _PTR(Study) studyDS = study->studyDS();
1950 // get unique temporary directory name
1951 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1952 if( aTmpDir.isEmpty() )
1955 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1956 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1958 // dump study to the temporary directory
1959 QString aScriptName( "notebook" );
1960 bool toPublish = true;
1961 bool isMultiFile = false;
1962 bool toSaveGUI = true;
1965 _PTR(AttributeParameter) ap;
1966 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1967 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1968 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1969 ip->setDumpPython(studyDS);
1970 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1972 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1974 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1977 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1981 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1982 int anIndex = aList.indexOf( this );
1984 // Disconnect dialog from application desktop in case if:
1985 // 1) Application is not the first application in the session
1986 // 2) Application is the first application in session but not the only.
1987 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1988 if( changeDesktop ) {
1990 SalomeApp_Application* app = this;
1991 if( anIndex > 0 && anIndex < aList.count() )
1992 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1993 else if(anIndex == 0 && aList.count() > 1)
1994 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1999 // creation a new study and restoring will be done in another application
2000 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2001 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2004 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2005 QString aStudyName = myNoteBook->getDumpedStudyName();
2006 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2007 // clear a study (delete all objects)
2008 onCloseDoc( false );
2010 if( !changeDesktop ) {
2011 ok = onRestoreStudy( aDumpScript,
2020 //============================================================================
2021 /*! Function : onRestoreStudy
2022 * Purpose : Load the dumped study from Python script
2024 //============================================================================
2025 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2026 const QString& theStudyName,
2027 bool theIsStudySaved )
2031 // create a new study
2034 // get active application
2035 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2037 // load study from the temporary directory
2038 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2040 #ifndef DISABLE_PYCONSOLE
2041 PyConsole_Console* pyConsole = app->pythonConsole();
2043 pyConsole->execAndWait( command );
2046 // remove temporary directory
2047 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2048 QString aStudyName = aScriptInfo.baseName();
2049 QDir aDir = aScriptInfo.absoluteDir();
2050 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2051 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2052 ok = aDir.remove( *it ) && ok;
2054 ok = aDir.rmdir( aDir.absolutePath() );
2056 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2058 #ifndef DISABLE_PYCONSOLE
2059 _PTR(Study) aStudyDS = newStudy->studyDS();
2060 app->getNoteBook()->Init( aStudyDS );
2061 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2062 newStudy->Modified();
2063 updateDesktopTitle();
2074 Close the Application
2076 void SalomeApp_Application::afterCloseDoc()
2078 #ifndef DISABLE_PYCONSOLE
2079 // emit signal to restore study from Python script
2081 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2082 myNoteBook->getDumpedStudyName(),
2083 myNoteBook->isDumpedStudySaved() );
2086 LightApp_Application::afterCloseDoc();
2090 Asks to close existing document.
2092 bool SalomeApp_Application::checkExistingDoc()
2094 bool result = LightApp_Application::checkExistingDoc();
2095 if ( result && !activeStudy() ) {
2096 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2098 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2099 if( List.size() > 0 ) {
2100 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));