1 // Copyright (C) 2007-2015 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 <SalomePyConsole_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>
91 #include <QPushButton>
93 #include <QListWidget>
94 #include <QGridLayout>
98 #include <SALOMEDSClient_ClientFactory.hxx>
99 #include <Basics_Utils.hxx>
101 #include <SALOME_ListIO.hxx>
102 #include <SALOME_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(),
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 QStringList __getArgsList(QString argsString)
181 // Special process if some items of 'args:' list are themselves lists
182 // Note that an item can be a list, but not a list of lists...
183 // So we can have something like this:
184 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
185 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
186 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
187 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
188 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
190 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
195 return argsString.split(",", QString::SkipEmptyParts);
198 /*!Start application.*/
199 void SalomeApp_Application::start()
201 // process the command line options before start: to createActions in accordance to the options
202 static bool isFirst = true;
210 for (int i = 1; i < qApp->arguments().size(); i++) {
211 QRegExp rxs ("--study-hdf=(.+)");
212 if ( rxs.indexIn( qApp->arguments()[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
213 QString file = rxs.capturedTexts()[1];
214 QFileInfo fi ( file );
215 QString extension = fi.suffix().toLower();
216 if ( extension == "hdf" && fi.exists() )
217 hdffile = fi.absoluteFilePath();
220 QRegExp rxp ("--pyscript=\\[(.+)\\]");
221 if ( rxp.indexIn( qApp->arguments()[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
223 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
224 for (int k = 0; k < dictList.count(); ++k) {
225 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
226 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
227 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
228 pyfiles += rxd.capturedTexts()[m];
235 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
236 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
238 LightApp_Application::start();
239 SALOME_EventFilter::Init();
241 setProperty("open_study_from_command_line", true);
242 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
243 onOpenDoc( hdffile );
244 else if ( pyfiles.count() > 0 ) // create new study
246 else if (!loadStudy.isEmpty()) {// load study by name
247 if (onLoadDoc(loadStudy))
248 updateObjectBrowser(true);
250 setProperty("open_study_from_command_line", QVariant());
252 #ifndef DISABLE_PYCONSOLE
253 // import/execute python scripts
254 if ( pyfiles.count() > 0 && activeStudy() ) {
255 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
256 SalomePyConsole_Console* pyConsole = pythonConsole();
257 if ( appStudy && pyConsole ) {
258 _PTR(Study) aStudy = appStudy->studyDS();
259 if ( !aStudy->GetProperties()->IsLocked() ) {
260 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
261 // Path is absolute, script has .py extension
262 for (uint j = 0; j < pyfiles.count(); j++ ) {
263 // Extract scripts and their arguments, if any
264 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
265 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
266 QString script = rxp.capturedTexts()[1];
268 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
269 for (uint k = 0; k < argList.count(); k++ ) {
270 QString arg = argList[k].trimmed();
271 arg.remove( QRegExp("^[\"]") );
272 arg.remove( QRegExp("[\"]$") );
275 args.remove( QRegExp("[,]$") );
276 if (!args.isEmpty()) {
280 script.remove( QRegExp("^python.*[\\s]+") );
281 QString cmd = script+" "+args;
282 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
283 pyConsole->exec(command);
285 } // end for loop on pyfiles QStringList
291 LightApp_Application::start();
292 SALOME_EventFilter::Init();
297 void SalomeApp_Application::createActions()
299 LightApp_Application::createActions();
301 SUIT_Desktop* desk = desktop();
304 // "Save GUI State" command is moved to VISU module
305 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
306 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
307 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
310 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
311 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
312 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
315 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
316 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
317 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
320 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
321 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
322 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onProperties() ) );
324 //! Catalog Generator
325 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
326 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
327 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
330 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
331 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
332 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
334 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
335 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
336 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
338 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
339 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
340 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
343 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
345 // "Save GUI State" command is renamed to "Save VISU State" and
346 // creation of menu item is moved to VISU
347 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
349 createMenu( ConnectId, fileMenu, 5 );
350 createMenu( DisconnectId, fileMenu, 5 );
351 createMenu( separator(), fileMenu, -1, 5 );
353 createMenu( DumpStudyId, fileMenu, 10, -1 );
354 createMenu( LoadScriptId, fileMenu, 10, -1 );
355 createMenu( separator(), fileMenu, -1, 10, -1 );
356 createMenu( PropertiesId, fileMenu, 10, -1 );
357 createMenu( separator(), fileMenu, -1, 10, -1 );
359 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
360 createMenu( CatalogGenId, toolsMenu, 10, -1 );
361 createMenu( RegDisplayId, toolsMenu, 10, -1 );
362 createMenu( separator(), toolsMenu, -1, 15, -1 );
364 createExtraActions();
366 #ifndef DISABLE_PYCONSOLE
367 #ifndef DISABLE_SALOMEOBJECT
368 // import Python module that manages SALOME plugins
370 PyLockWrapper lck; // acquire GIL
371 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
372 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
376 // end of SALOME plugins loading
383 \brief Close application.
385 void SalomeApp_Application::onExit()
387 bool killServers = false;
390 if ( exitConfirmation() ) {
391 SalomeApp_ExitDlg dlg( desktop() );
392 result = dlg.exec() == QDialog::Accepted;
393 killServers = dlg.isServersShutdown();
397 if ( !killServers ) myIsCloseFromExit = true;
398 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
399 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
403 /*!SLOT. Load document.*/
404 void SalomeApp_Application::onLoadDoc()
408 std::vector<std::string> List = studyMgr()->GetOpenStudies();
410 // rnv: According to the single-study approach on the server side
411 // can be only one study. So if it is exists connect to them,
412 // overwise show warning message: "No active study on the server"
415 SUIT_Session* aSession = SUIT_Session::session();
416 QList<SUIT_Application*> aAppList = aSession->applications();
418 QStringList unloadedStudies;
420 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
421 studyName = List[ind].c_str();
422 // Add to list only unloaded studies
423 bool isAlreadyOpen = false;
424 QListIterator<SUIT_Application*> it( aAppList );
425 while ( it.hasNext() && !isAlreadyOpen ) {
426 SUIT_Application* aApp = it.next();
427 if( !aApp || !aApp->activeStudy() )
429 if ( aApp->activeStudy()->studyName() == studyName )
430 isAlreadyOpen = true;
433 if ( !isAlreadyOpen )
434 unloadedStudies << studyName;
436 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
437 if ( studyName.isEmpty() )
441 if(List.size() <= 0) {
442 SUIT_MessageBox::warning( desktop(),
443 QObject::tr("WRN_WARNING"),
444 QObject::tr("WRN_NO_STUDY_ON SERV") );
448 studyName = List[0].c_str();
451 // this code replaces marker of windows drive and path become invalid therefore
452 // defines placed there
453 studyName.replace( QRegExp(":"), "/" );
456 if ( onLoadDoc( studyName ) ) {
458 updateViewManagers();
459 updateObjectBrowser( true );
463 /*!SLOT. Unload document.*/
464 void SalomeApp_Application::onUnloadDoc( bool ask )
467 activeStudy()->abortAllOperations();
468 if ( activeStudy()->isModified() ) {
469 QString docName = activeStudy()->studyName().trimmed();
470 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
471 tr( "DISCONNECT_DESCRIPTION" ),
472 tr( "DISCONNECT_SAVE" ),
473 tr( "DISCONNECT_WO_SAVE" ),
474 tr( "APPCLOSE_CANCEL" ), 0 );
475 if ( answer == 0 ) { // save before unload
476 if ( activeStudy()->isSaved() )
478 else if ( !onSaveAsDoc() )
481 else if ( answer == 2 ) // Cancel
485 closeActiveDoc( false );
488 /*!SLOT. Create new study and load script*/
489 void SalomeApp_Application::onNewWithScript()
491 QStringList filtersList;
492 filtersList.append(tr("PYTHON_FILES_FILTER"));
493 filtersList.append(tr("ALL_FILES_FILTER"));
495 QString anInitialPath = "";
496 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
497 anInitialPath = QDir::currentPath();
499 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
501 if ( !aFile.isEmpty() )
505 QString command = QString("execfile(r\"%1\")").arg(aFile);
507 #ifndef DISABLE_PYCONSOLE
508 SalomePyConsole_Console* pyConsole = pythonConsole();
511 pyConsole->exec( command );
517 /*!SLOT. Load document with \a aName.*/
518 bool SalomeApp_Application::onLoadDoc( const QString& aName )
520 #ifdef SINGLE_DESKTOP
521 if ( !LightApp_Application::closeDoc() )
525 if ( !activeStudy() ) {
526 // if no study - load in current desktop
527 res = useStudy( aName );
530 // if study exists - load in new desktop. Check: is the same file is loaded?
531 SUIT_Session* aSession = SUIT_Session::session();
532 QList<SUIT_Application*> aAppList = aSession->applications();
533 bool isAlreadyOpen = false;
534 SalomeApp_Application* aApp = 0;
535 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
536 it != aAppList.end() && !isAlreadyOpen; ++it ) {
537 aApp = dynamic_cast<SalomeApp_Application*>( *it );
538 if ( aApp && aApp->activeStudy()->studyName() == aName )
539 isAlreadyOpen = true;
541 if ( !isAlreadyOpen ) {
542 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
544 res = aApp->useStudy( aName );
547 aApp->desktop()->activateWindow();
554 /*!SLOT. Parse message for desktop.*/
555 void SalomeApp_Application::onDesktopMessage( const QString& message )
557 if (message.indexOf("studyCreated:") == 0) {
558 // Enable 'Connect' action
559 updateCommandsStatus();
561 else if (message.indexOf("studyClosed:") == 0) {
562 /* message also contains ID of the closed study,
563 but as soon as SALOME is mono-study application for the moment,
564 this ID is not needed now.*/
565 //long aStudyId = message.section(':', 1).toLong();
566 // Disconnect GUI from active study, because it was closed on DS side.
567 closeActiveDoc( false );
568 // Disable 'Connect' action
569 QAction* a = action( ConnectId );
571 a->setEnabled( false );
573 else if ( message.toLower() == "connect_to_study" ) {
576 LightApp_Application::onDesktopMessage( message );
579 /*!SLOT. Copy objects to study maneger from selection maneger..*/
580 void SalomeApp_Application::onCopy()
583 LightApp_SelectionMgr* mgr = selectionMgr();
584 mgr->selectedObjects(list);
586 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
587 if(study == NULL) return;
589 _PTR(Study) stdDS = study->studyDS();
592 SALOME_ListIteratorOfListIO it( list );
595 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
597 studyMgr()->Copy(so);
598 onSelectionChanged();
605 /*!SLOT. Paste objects to study maneger from selection manager.*/
606 void SalomeApp_Application::onPaste()
609 LightApp_SelectionMgr* mgr = selectionMgr();
610 mgr->selectedObjects(list);
612 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
613 if(study == NULL) return;
615 _PTR(Study) stdDS = study->studyDS();
618 if ( stdDS->GetProperties()->IsLocked() ) {
619 SUIT_MessageBox::warning( desktop(),
620 QObject::tr("WRN_WARNING"),
621 QObject::tr("WRN_STUDY_LOCKED") );
625 SALOME_ListIteratorOfListIO it( list );
628 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
630 studyMgr()->Paste(so);
631 updateObjectBrowser( true );
632 updateActions(); //SRN: BugID IPAL9377, case 3
639 /*!Check the application on closing.
640 * \retval true if possible, else false
642 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
644 return LightApp_Application::isPossibleToClose( closePermanently );
647 /*! Check if the study is locked */
648 void SalomeApp_Application::onCloseDoc( bool ask )
650 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
653 _PTR(Study) stdDS = study->studyDS();
654 if(stdDS && stdDS->IsStudyLocked()) {
655 if ( SUIT_MessageBox::question( desktop(),
656 QObject::tr( "WRN_WARNING" ),
657 QObject::tr( "CLOSE_LOCKED_STUDY" ),
658 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
659 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
663 LightApp_Application::onCloseDoc( ask );
666 /*!Sets enable or disable some actions on selection changed.*/
667 void SalomeApp_Application::onSelectionChanged()
670 LightApp_SelectionMgr* mgr = selectionMgr();
671 mgr->selectedObjects(list);
673 bool canCopy = false;
674 bool canPaste = false;
676 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
679 canCopy = m->canCopy();
680 canPaste = m->canPaste();
683 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
685 _PTR(Study) stdDS = study->studyDS();
688 SALOME_ListIteratorOfListIO it ( list );
690 if (it.More() && list.Extent() == 1) {
691 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
694 canCopy = canCopy || studyMgr()->CanCopy(so);
695 canPaste = canPaste || studyMgr()->CanPaste(so);
701 action(EditCopyId)->setEnabled(canCopy);
702 action(EditPasteId)->setEnabled(canPaste);
705 /*!Delete references.*/
706 void SalomeApp_Application::onDeleteInvalidReferences()
709 LightApp_SelectionMgr* mgr = selectionMgr();
710 mgr->selectedObjects( aList, QString(), false );
712 if( aList.IsEmpty() )
715 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
716 _PTR(Study) aStudyDS = aStudy->studyDS();
717 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
720 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
721 if ( it.Value()->hasEntry() )
723 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
724 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
727 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
728 aStudyBuilder->RemoveReference( aSObject );
730 updateObjectBrowser();
734 void SalomeApp_Application::onOpenWith()
736 QApplication::setOverrideCursor( Qt::WaitCursor );
738 LightApp_SelectionMgr* mgr = selectionMgr();
739 mgr->selectedObjects(aList);
740 if (aList.Extent() != 1)
742 QApplication::restoreOverrideCursor();
745 Handle(SALOME_InteractiveObject) aIObj = aList.First();
746 QString aModuleName(aIObj->getComponentDataType());
747 QString aModuleTitle = moduleTitle(aModuleName);
748 activateModule(aModuleTitle);
749 QApplication::restoreOverrideCursor();
755 SUIT_Study* SalomeApp_Application::createNewStudy()
757 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
759 // Set up processing of major study-related events
760 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
761 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
762 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
763 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
765 #ifndef DISABLE_PYCONSOLE
766 //to receive signal in application that NoteBook's variable was modified
767 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
768 this, SIGNAL(notebookVarUpdated(QString)) );
775 Enable/Disable menu items and toolbar buttons. Rebuild menu
777 void SalomeApp_Application::updateCommandsStatus()
779 LightApp_Application::updateCommandsStatus();
782 QAction* a = action( DumpStudyId );
784 a->setEnabled( activeStudy() );
786 #ifndef DISABLE_PYCONSOLE
788 a = action( LoadScriptId );
790 a->setEnabled( pythonConsole() );
794 a = action( PropertiesId );
796 a->setEnabled( activeStudy() );
798 // Save GUI state menu
799 a = action( SaveGUIStateId );
801 a->setEnabled( activeStudy() );
803 // Connect study menu
804 a = action( ConnectId );
806 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
808 // Disconnect study menu
809 a = action( DisconnectId );
811 a->setEnabled( activeStudy() );
813 // update state of Copy/Paste menu items
814 onSelectionChanged();
818 \class DumpStudyFileDlg
819 Private class used in Dump Study operation. Consists 2 check boxes:
820 "Publish in study" and "Save GUI parameters"
822 class DumpStudyFileDlg : public SUIT_FileDlg
825 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
827 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
830 QWidget *hB = new QWidget( this );
831 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
832 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
833 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
835 QHBoxLayout *layout = new QHBoxLayout;
836 layout->addWidget(myPublishChk);
837 layout->addWidget(myMultiFileChk);
838 layout->addWidget(mySaveGUIChk);
839 hB->setLayout(layout);
841 QPushButton* pb = new QPushButton(this);
843 int row = grid->rowCount();
844 grid->addWidget( new QLabel("", this), row, 0 );
845 grid->addWidget( hB, row, 1, 1, 3 );
846 grid->addWidget( pb, row, 5 );
851 QCheckBox* myPublishChk;
852 QCheckBox* myMultiFileChk;
853 QCheckBox* mySaveGUIChk;
856 class DumpStudyFileValidator : public SUIT_FileValidator
859 DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {};
860 virtual ~DumpStudyFileValidator() {};
861 virtual bool canSave( const QString& file, bool permissions );
864 bool DumpStudyFileValidator::canSave(const QString& file, bool permissions)
866 QFileInfo fi( file );
867 if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
868 SUIT_MessageBox::critical( parent(),
869 QObject::tr("WRN_WARNING"),
870 QObject::tr("WRN_FILE_NAME_BAD") );
873 return SUIT_FileValidator::canSave( file, permissions);
876 /*!Private SLOT. On dump study.*/
877 void SalomeApp_Application::onDumpStudy( )
879 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
880 if ( !appStudy ) return;
881 _PTR(Study) aStudy = appStudy->studyDS();
883 QStringList aFilters;
884 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
886 bool anIsPublish = true;
887 bool anIsMultiFile = false;
888 bool anIsSaveGUI = true;
890 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
891 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
892 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
893 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
896 DumpStudyFileDlg fd( desktop() );
897 fd.setValidator( new DumpStudyFileValidator( &fd ) );
898 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
899 fd.setNameFilters( aFilters );
900 fd.myPublishChk->setChecked( anIsPublish );
901 fd.myMultiFileChk->setChecked( anIsMultiFile );
902 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
903 if ( fd.exec() == QDialog::Accepted )
905 QString aFileName = fd.selectedFile();
907 bool toPublish = fd.myPublishChk->isChecked();
908 bool isMultiFile = fd.myMultiFileChk->isChecked();
909 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
911 if ( !aFileName.isEmpty() ) {
912 QFileInfo aFileInfo(aFileName);
913 if( aFileInfo.isDir() ) // IPAL19257
916 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
919 SUIT_OverrideCursor wc;
920 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
923 SUIT_MessageBox::warning( desktop(),
924 QObject::tr("WRN_WARNING"),
925 tr("WRN_DUMP_STUDY_FAILED") );
930 /*!Private SLOT. On load script.*/
931 void SalomeApp_Application::onLoadScript( )
933 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
935 _PTR(Study) aStudy = appStudy->studyDS();
936 if ( aStudy->GetProperties()->IsLocked() ) {
937 SUIT_MessageBox::warning( desktop(),
938 QObject::tr("WRN_WARNING"),
939 QObject::tr("WRN_STUDY_LOCKED") );
944 QStringList filtersList;
945 filtersList.append(tr("PYTHON_FILES_FILTER"));
946 filtersList.append(tr("ALL_FILES_FILTER"));
948 QString anInitialPath = "";
949 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
950 anInitialPath = QDir::currentPath();
952 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
954 if ( !aFile.isEmpty() )
956 QString command = QString("execfile(r\"%1\")").arg(aFile);
958 #ifndef DISABLE_PYCONSOLE
959 SalomePyConsole_Console* pyConsole = pythonConsole();
962 pyConsole->exec( command );
967 /*!Private SLOT. On save GUI state.*/
968 void SalomeApp_Application::onSaveGUIState()
970 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
972 SalomeApp_VisualState( this ).storeState();
973 updateSavePointDataObjects( study );
974 updateObjectBrowser();
979 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
980 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
982 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
983 QAction* send = ::qobject_cast<QAction*>( sender() );
986 QString aWinName = send->data().toString();
987 if ( theIsVisible && aWinName == "objectBrowser" )
988 objectBrowserColumnsVisibility();
992 *\retval QString "(*.hdf)"
994 QString SalomeApp_Application::getFileFilter() const
1000 QWidget* SalomeApp_Application::createWindow( const int flag )
1003 #ifndef DISABLE_PYCONSOLE
1004 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1006 wid = LightApp_Application::createWindow(flag);
1009 SUIT_ResourceMgr* resMgr = resourceMgr();
1011 if ( flag == WT_ObjectBrowser )
1013 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1015 // temporary commented
1016 //ob->setUpdater( new SalomeApp_Updater() );
1018 #ifdef WITH_SALOMEDS_OBSERVER
1019 //do not activate the automatic update of Qt tree through signal/slot
1020 ob->setAutoUpdate(false);
1021 //activate update of modified objects only
1022 ob->setUpdateModified(true);
1025 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1028 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1029 IORCol = QObject::tr( "IOR_COLUMN" ),
1030 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1031 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1033 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1034 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1035 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1036 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1037 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1038 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1039 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1040 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1041 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1043 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1044 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1045 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1047 ob->setAutoSizeFirstColumn(autoSizeFirst);
1048 ob->setAutoSizeColumns(autoSize);
1049 ob->setResizeOnExpandItem(resizeOnExpandItem);
1050 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1052 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1054 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1055 ob->treeView()->setColumnHidden( i, !shown );
1058 // temporary commented
1060 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1062 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1063 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1064 QString().sprintf( "visibility_column_%d", i ), true ) );
1068 // temporary commented
1070 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1071 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1072 ob->resize( desktop()->width()/3, ob->height() );
1076 #ifndef DISABLE_PYCONSOLE
1077 else if ( flag == WT_PyConsole )
1079 SalomePyConsole_Console* pyCons = new SalomePyConsole_EnhConsole( desktop(), getPyInterp() );
1080 pyCons->setObjectName( "pythonConsole" );
1081 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1082 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1083 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1084 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1086 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1087 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1089 else if ( flag == WT_NoteBook )
1091 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1093 _PTR(Study) aStudy = appStudy->studyDS();
1094 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1095 //to receive signal in NoteBook that it's variable was modified
1096 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1097 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1099 wid = getNoteBook();
1100 wid->setObjectName( "noteBook" );
1106 /*!Create preferences.*/
1107 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1109 LightApp_Application::createPreferences(pref);
1114 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1115 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1116 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1117 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1119 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1120 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1122 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1124 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1125 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1126 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1127 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1128 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1129 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1130 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1131 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1132 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1133 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1136 /*!Update desktop title.*/
1137 void SalomeApp_Application::updateDesktopTitle() {
1138 QString aTitle = applicationName();
1139 QString aVer = applicationVersion();
1140 if ( !aVer.isEmpty() )
1141 aTitle += QString( " " ) + aVer;
1143 if ( activeStudy() )
1145 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1146 if ( !sName.isEmpty() ) {
1147 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1149 _PTR(Study) stdDS = study->studyDS();
1151 if ( stdDS->GetProperties()->IsLocked() ) {
1152 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1154 aTitle += QString( " - [%1]" ).arg( sName );
1161 desktop()->setWindowTitle( aTitle );
1164 int SalomeApp_Application::closeChoice( const QString& docName )
1166 QStringList buttons;
1167 QMap<int, int> choices;
1169 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1170 choices.insert( idx++, CloseSave ); // ...
1171 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1172 choices.insert( idx++, CloseDiscard ); // ...
1173 if ( myIsCloseFromExit ) {
1174 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1175 choices.insert( idx++, CloseDisconnectSave ); // ...
1176 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1177 choices.insert( idx++, CloseDisconnect ); // ...
1179 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1180 choices.insert( idx++, CloseCancel ); // ...
1182 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1183 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1184 return choices[answer];
1187 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1193 if ( activeStudy()->isSaved() )
1195 else if ( !onSaveAsDoc() )
1200 case CloseDisconnectSave:
1201 if ( activeStudy()->isSaved() )
1203 else if ( !onSaveAsDoc() )
1205 case CloseDisconnect:
1206 closeActiveDoc( false );
1207 closePermanently = false;
1216 int SalomeApp_Application::openChoice( const QString& aName )
1218 int choice = LightApp_Application::openChoice( aName );
1220 if ( QFileInfo( aName ).exists() ) {
1221 if ( choice == OpenNew ) { // The document isn't already open.
1223 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1224 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1225 if ( aName == QString( lst[i].c_str() ) )
1228 // The document already exists in the study manager.
1229 // Do you want to reload it?
1231 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1232 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1233 if ( answer == SUIT_MessageBox::Yes )
1234 choice = OpenRefresh;
1236 choice = OpenCancel;
1239 } else { // file is not exist on disk
1240 SUIT_MessageBox::warning( desktop(),
1241 QObject::tr("WRN_WARNING"),
1242 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1249 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1252 int choice = aChoice;
1257 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1260 studyMgr()->Close( aStudy );
1265 res = LightApp_Application::openAction( choice, aName );
1273 \brief Get map of the operations which can be performed
1274 on the module activation.
1276 The method should return the map of the kind \c {<id>:<name>}
1277 where \c <id> is an integer identifier of the operation and
1278 \c <name> is a title for the button to be added to the
1279 dialog box. After user selects the required operation by the
1280 clicking the corresponding button in the dialog box, its identifier
1281 is passed to the moduleActionSelected() method to process
1284 \return map of the operations
1285 \sa moduleActionSelected()
1287 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1289 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1291 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1293 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1298 \brief Called when the used selectes required operation chosen
1299 from "Activate module" dialog box.
1301 Performs the required operation according to the user choice.
1303 \param id operation identifier
1304 \sa activateModuleActions()
1306 void SalomeApp_Application::moduleActionSelected( const int id )
1312 case NewAndScriptId:
1316 LightApp_Application::moduleActionSelected( id );
1321 /*!Gets CORBA::ORB_var*/
1322 CORBA::ORB_var SalomeApp_Application::orb()
1324 static CORBA::ORB_var _orb;
1326 if ( CORBA::is_nil( _orb ) ) {
1327 Qtx::CmdLineArgs args;
1328 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1329 _orb = init( args.argc(), args.argv() );
1335 /*!Create and return SALOMEDS_StudyManager.*/
1336 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1338 static _PTR(StudyManager) _sm;
1339 if(!_sm) _sm = ClientFactory::StudyManager();
1343 /*!Create and return SALOME_NamingService.*/
1344 SALOME_NamingService* SalomeApp_Application::namingService()
1346 static SALOME_NamingService _ns(orb());
1350 /*!Create and return SALOME_LifeCycleCORBA.*/
1351 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1353 static SALOME_LifeCycleCORBA _lcc( namingService() );
1357 /*!Private SLOT. On preferences.*/
1358 void SalomeApp_Application::onProperties()
1360 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1364 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1367 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1368 int res = aDlg.exec();
1369 if( res==QDialog::Accepted && aDlg.isChanged() )
1370 SB->CommitCommand();
1374 //study->updateCaptions();
1375 updateDesktopTitle();
1379 /*!Insert items in popup, which necessary for current application*/
1380 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1382 LightApp_SelectionMgr* mgr = selectionMgr();
1383 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1384 mgr->setSelectionCacheEnabled( true );
1386 LightApp_Application::contextMenuPopup( type, thePopup, title );
1388 // temporary commented
1389 /*OB_Browser* ob = objectBrowser();
1390 if ( !ob || type != ob->popupClientType() )
1393 // Get selected objects
1394 SALOME_ListIO aList;
1395 mgr->selectedObjects( aList, QString(), false );
1397 // add GUI state commands: restore, rename
1398 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1399 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1400 thePopup->addSeparator();
1401 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1402 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1403 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1404 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1407 // "Delete reference" item should appear only for invalid references
1409 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1410 bool isInvalidRefs = false;
1411 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1413 _PTR(Study) aStudyDS = aStudy->studyDS();
1414 _PTR(SObject) anObj;
1416 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1418 if( it.Value()->hasEntry() )
1420 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1421 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1424 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1425 isInvalidRefs = true;
1429 // Add "Delete reference" item to popup
1430 if ( isInvalidRefs )
1432 thePopup->addSeparator();
1433 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1437 // "Activate module" item should appear only if it's necessary
1438 if ( aList.Extent() == 1 ) {
1440 mgr->selectedObjects( aList );
1442 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1444 // add extra popup menu (defined in XML)
1445 if ( myExtActions.size() > 0 ) {
1446 // Use only first selected object
1447 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1449 _PTR(Study) stdDS = study->studyDS();
1451 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1453 _PTR( GenericAttribute ) anAttr;
1454 std::string auid = "AttributeUserID";
1455 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1456 if ( aSO->FindAttribute( anAttr, auid ) ) {
1457 _PTR(AttributeUserID) aAttrID = anAttr;
1458 QString aId = aAttrID->Value().c_str();
1459 if ( myExtActions.contains( aId ) ) {
1460 thePopup->addAction(myExtActions[aId]);
1468 // check if item is a "GUI state" item (also a first level object)
1469 QString entry( aIObj->getEntry() );
1470 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1471 QString aModuleName( aIObj->getComponentDataType() );
1472 QString aModuleTitle = moduleTitle( aModuleName );
1473 CAM_Module* currentModule = activeModule();
1474 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1475 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1480 mgr->setSelectionCacheEnabled( cacheIsOn );
1483 /*!Update obect browser:
1484 1.if 'updateModels' true, update existing data models;
1485 2. update "non-existing" (not loaded yet) data models;
1486 3. update object browser if it exists */
1487 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1489 // update "non-existing" (not loaded yet) data models
1490 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1493 _PTR(Study) stdDS = study->studyDS();
1496 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1498 _PTR(SComponent) aComponent ( it->Value() );
1500 #ifndef WITH_SALOMEDS_OBSERVER
1501 // with GUI observers this check is not needed anymore
1502 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1503 continue; // skip the magic "Interface Applicative" component
1505 if ( !objectBrowser() )
1506 getWindow( WT_ObjectBrowser );
1507 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1508 objectBrowser()->setAutoUpdate( false );
1509 SalomeApp_DataModel::synchronize( aComponent, study );
1510 objectBrowser()->setAutoUpdate( isAutoUpdate );
1515 // create data objects that correspond to GUI state save points
1516 if ( study ) updateSavePointDataObjects( study );
1518 // update existing data models (already loaded SComponents)
1519 LightApp_Application::updateObjectBrowser( updateModels );
1522 /*!Display Catalog Genenerator dialog */
1523 void SalomeApp_Application::onCatalogGen()
1525 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1529 /*!Display Registry Display dialog */
1530 void SalomeApp_Application::onRegDisplay()
1532 CORBA::ORB_var anOrb = orb();
1533 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1536 regWnd->activateWindow();
1539 /*!find original object by double click on item */
1540 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1542 // Issue 21379: References are supported at LightApp_DataObject level
1543 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1545 if( obj && obj->isReference() )
1547 QString entry = obj->refEntry();
1549 SUIT_DataOwnerPtrList aList;
1550 aList.append( new LightApp_DataOwner( entry ) );
1551 selectionMgr()->setSelected( aList, false );
1553 SUIT_DataBrowser* ob = objectBrowser();
1555 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1556 if ( !aSelectedIndexes.isEmpty() )
1557 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1562 Creates new view manager
1563 \param type - type of view manager
1565 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1567 return createViewManager(type);
1571 /*!Global utility function, returns selected GUI Save point object's ID */
1572 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1574 SALOME_ListIO aList;
1575 selMgr->selectedObjects( aList );
1576 if( aList.Extent() > 0 ) {
1577 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1578 QString entry( aIObj->getEntry() );
1579 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1580 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1582 bool ok; // conversion to integer is ok?
1583 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1584 return ok ? savePoint : -1;
1589 /*!Called on Restore GUI State popup command*/
1590 void SalomeApp_Application::onRestoreGUIState()
1592 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1593 if ( savePoint == -1 )
1595 SalomeApp_VisualState( this ).restoreState( savePoint );
1598 /*!Called on Delete GUI State popup command*/
1599 void SalomeApp_Application::onDeleteGUIState()
1601 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1602 if ( savePoint == -1 )
1604 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1608 study->removeSavePoint( savePoint );
1609 updateSavePointDataObjects( study );
1612 /*!Called on New study operation*/
1613 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1615 LightApp_Application::onStudyCreated( study );
1617 //#ifndef DISABLE_PYCONSOLE
1618 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1619 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1622 loadDockWindowsState();
1624 objectBrowserColumnsVisibility();
1627 /*!Called on Open study operation*/
1628 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1630 LightApp_Application::onStudyOpened( study );
1632 //#ifndef DISABLE_PYCONSOLE
1633 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1634 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1637 loadDockWindowsState();
1639 objectBrowserColumnsVisibility();
1641 // temporary commented
1642 /*if ( objectBrowser() ) {
1643 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1644 objectBrowser()->updateTree( study->root() );
1648 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1649 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1652 SUIT_DataBrowser* ob = objectBrowser();
1653 LightApp_SelectionMgr* selMgr = selectionMgr();
1655 if ( !study || !ob || !selMgr )
1658 // find GUI states root object
1659 SUIT_DataObject* guiRootObj = 0;
1661 study->root()->children( ch );
1662 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1663 for ( ; it != last ; ++it ) {
1664 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1669 std::vector<int> savePoints = study->getSavePoints();
1670 // case 1: no more save points but they existed in study's tree
1671 if ( savePoints.empty() && guiRootObj ) {
1672 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1673 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1674 const bool isAutoUpdate = ob->autoUpdate();
1675 selMgr->clearSelected();
1676 ob->setAutoUpdate(true);
1677 DataObjectList ch = guiRootObj->children();
1678 for( int i = 0; i < ch.size(); i++ )
1681 ob->setAutoUpdate(isAutoUpdate);
1684 // case 2: no more save points but root does not exist either
1685 if ( savePoints.empty() && !guiRootObj )
1687 // case 3: save points but no root for them - create it
1688 if ( !savePoints.empty() && !guiRootObj )
1689 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1690 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1691 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1693 if ( guiRootObj->nextBrother() ) {
1694 study->root()->removeChild(guiRootObj);
1695 study->root()->appendChild(guiRootObj);
1696 //study->root()->dump();
1699 // store data objects in a map id-to-DataObject
1700 QMap<int,SalomeApp_SavePointObject*> mapDO;
1702 guiRootObj->children( ch );
1703 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1704 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1706 mapDO[dobj->getId()] = dobj;
1709 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1710 // if in the map - remove it from map.
1711 for ( int i = 0; i < savePoints.size(); i++ )
1712 if ( !mapDO.contains( savePoints[i] ) )
1713 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1715 mapDO.remove( savePoints[i] );
1717 // delete DataObjects that are still in the map -- their IDs were not found in data model
1718 if( mapDO.size() > 0) {
1719 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1720 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1721 selMgr->clearSelected();
1722 const bool isAutoUpdate = ob->autoUpdate();
1723 ob->setAutoUpdate(true);
1724 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1726 ob->setAutoUpdate(isAutoUpdate);
1730 /*! Check data object */
1731 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1740 Opens other study into active Study. If Study is empty - creates it.
1741 \param theName - name of study
1743 bool SalomeApp_Application::useStudy( const QString& theName )
1746 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1749 res = aStudy->loadDocument( theName );
1750 updateDesktopTitle();
1751 updateCommandsStatus();
1755 /*! Show/hide object browser colums according to preferences */
1756 void SalomeApp_Application::objectBrowserColumnsVisibility()
1758 if ( objectBrowser() )
1759 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1761 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1762 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1766 #ifndef DISABLE_PYCONSOLE
1767 /*! Set SalomeApp_NoteBook pointer */
1768 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1770 myNoteBook = theNoteBook;
1773 /*! Return SalomeApp_NoteBook pointer */
1774 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1781 * Define extra actions defined in module definition XML file.
1782 * Additional popup items sections can be defined by parameter "popupitems".
1783 * Supported attributes:
1784 * title - title of menu item,
1785 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1786 * method - method which has to be called when menu item is selected
1788 * <section name="MODULENAME">
1789 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1791 * <section name="importmed">
1792 * <parameter name="title" value="My menu"/>
1793 * <parameter name="objectid" value="VISU.Result"/>
1794 * <parameter name="method" value="nameOfModuleMethod"/>
1797 void SalomeApp_Application::createExtraActions()
1799 myExtActions.clear();
1800 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1802 QStringList aModules;
1803 modules(aModules, false);
1804 foreach(QString aModile, aModules) {
1805 QString aModName = moduleName(aModile);
1806 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1807 if (!aSectionStr.isNull()) {
1808 QStringList aSections = aSectionStr.split(':');
1809 foreach(QString aSection, aSections) {
1810 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1811 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1812 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1813 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1816 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1817 if (aModuleName.isNull())
1818 aModuleName = aModName;
1820 QAction* aAction = new QAction(aTitle, this);
1822 aData<<aModuleName<<aSlot;
1823 aAction->setData(aData);
1824 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1825 myExtActions[aId] = aAction;
1832 * Called when extra action is selected
1834 void SalomeApp_Application::onExtAction()
1836 QAction* aAction = ::qobject_cast<QAction*>(sender());
1840 QVariant aData = aAction->data();
1841 QStringList aDataList = aData.value<QStringList>();
1842 if (aDataList.size() != 2)
1845 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1846 SALOME_ListIO aListIO;
1847 aSelectionMgr->selectedObjects(aListIO);
1848 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1849 if (aListIO.Extent() < 1)
1851 if (!anIO->hasEntry())
1854 QString aEntry(anIO->getEntry());
1856 QApplication::setOverrideCursor( Qt::WaitCursor );
1857 QString aModuleTitle = moduleTitle(aDataList[0]);
1858 activateModule(aModuleTitle);
1859 QApplication::restoreOverrideCursor();
1861 QCoreApplication::processEvents();
1863 CAM_Module* aModule = activeModule();
1867 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1868 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1872 Checks that an object can be renamed.
1873 \param entry entry of the object
1874 \brief Return \c true if object can be renamed
1876 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1878 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1882 Rename object by entry.
1883 \param entry entry of the object
1884 \param name new name of the object
1885 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1887 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1889 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1891 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1893 if(!aStudy || savePoint == -1)
1896 if ( !name.isNull() && !name.isEmpty() ) {
1897 aStudy->setNameOfSavePoint( savePoint, name );
1898 updateSavePointDataObjects( aStudy );
1900 //Mark study as modified
1907 #ifndef DISABLE_PYCONSOLE
1908 //============================================================================
1909 /*! Function : onUpdateStudy
1910 * Purpose : Slot to update the study.
1912 //============================================================================
1913 void SalomeApp_Application::onUpdateStudy()
1915 QApplication::setOverrideCursor( Qt::WaitCursor );
1917 if( !updateStudy() )
1918 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1920 QApplication::restoreOverrideCursor();
1923 //============================================================================
1924 /*! Function : updateStudy
1925 * Purpose : Update study by dumping the study to Python script and loading it.
1926 * It is used to apply variable modifications done in NoteBook to created objects.
1928 //============================================================================
1929 bool SalomeApp_Application::updateStudy()
1931 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1932 if ( !study || !myNoteBook )
1935 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1936 myNoteBook->setDumpedStudyName( study->studyName() );
1938 _PTR(Study) studyDS = study->studyDS();
1940 // get unique temporary directory name
1941 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1942 if( aTmpDir.isEmpty() )
1945 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1946 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1948 // dump study to the temporary directory
1949 QString aScriptName( "notebook" );
1950 bool toPublish = true;
1951 bool isMultiFile = false;
1952 bool toSaveGUI = true;
1955 _PTR(AttributeParameter) ap;
1956 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1957 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1958 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1959 ip->setDumpPython(studyDS);
1960 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1962 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1964 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1967 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1971 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1972 int anIndex = aList.indexOf( this );
1974 // Disconnect dialog from application desktop in case if:
1975 // 1) Application is not the first application in the session
1976 // 2) Application is the first application in session but not the only.
1977 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1978 if( changeDesktop ) {
1980 SalomeApp_Application* app = this;
1981 if( anIndex > 0 && anIndex < aList.count() )
1982 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1983 else if(anIndex == 0 && aList.count() > 1)
1984 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1989 // creation a new study and restoring will be done in another application
1990 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
1991 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
1994 QString aDumpScript = myNoteBook->getDumpedStudyScript();
1995 QString aStudyName = myNoteBook->getDumpedStudyName();
1996 bool isStudySaved = myNoteBook->isDumpedStudySaved();
1997 // clear a study (delete all objects)
1998 onCloseDoc( false );
2000 if( !changeDesktop ) {
2001 ok = onRestoreStudy( aDumpScript,
2010 //============================================================================
2011 /*! Function : onRestoreStudy
2012 * Purpose : Load the dumped study from Python script
2014 //============================================================================
2015 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2016 const QString& theStudyName,
2017 bool theIsStudySaved )
2021 // create a new study
2024 // get active application
2025 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2027 // load study from the temporary directory
2028 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2030 #ifndef DISABLE_PYCONSOLE
2031 SalomePyConsole_Console* pyConsole = app->pythonConsole();
2033 pyConsole->execAndWait( command );
2036 // remove temporary directory
2037 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2038 QString aStudyName = aScriptInfo.baseName();
2039 QDir aDir = aScriptInfo.absoluteDir();
2040 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2041 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2042 ok = aDir.remove( *it ) && ok;
2044 ok = aDir.rmdir( aDir.absolutePath() );
2046 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2048 #ifndef DISABLE_PYCONSOLE
2049 _PTR(Study) aStudyDS = newStudy->studyDS();
2050 app->getNoteBook()->Init( aStudyDS );
2051 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2052 newStudy->Modified();
2053 updateDesktopTitle();
2064 Close the Application
2066 void SalomeApp_Application::afterCloseDoc()
2068 #ifndef DISABLE_PYCONSOLE
2069 // emit signal to restore study from Python script
2071 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2072 myNoteBook->getDumpedStudyName(),
2073 myNoteBook->isDumpedStudySaved() );
2076 LightApp_Application::afterCloseDoc();
2080 Asks to close existing document.
2082 bool SalomeApp_Application::checkExistingDoc()
2084 bool result = LightApp_Application::checkExistingDoc();
2085 if ( result && !activeStudy() ) {
2086 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2088 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2089 if( List.size() > 0 ) {
2090 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2099 #ifndef DISABLE_PYCONSOLE
2101 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2103 return new SalomeApp_PyInterp();
2106 #endif // DISABLE_PYCONSOLE