1 // Copyright (C) 2007-2016 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"
39 #include "SalomeApp_NoteBook.h"
40 #include "LightApp_PyEditor.h"
41 #include "PyConsole_Console.h"
43 #include "SalomeApp_Application.h"
44 #include "SalomeApp_Study.h"
45 #include "SalomeApp_DataModel.h"
46 #include "SalomeApp_DataObject.h"
47 #include "SalomeApp_VisualState.h"
48 #include "SalomeApp_StudyPropertiesDlg.h"
49 #include "SalomeApp_LoadStudiesDlg.h"
50 #include "SalomeApp_ExitDlg.h"
52 #include <LightApp_Application.h>
53 #include <LightApp_FileValidator.h>
54 #include <LightApp_Module.h>
55 #include <LightApp_Preferences.h>
56 #include <LightApp_SelectionMgr.h>
57 #include <LightApp_NameDlg.h>
58 #include <LightApp_DataOwner.h>
60 #include <CAM_Module.h>
62 #include <SUIT_Tools.h>
63 #include <SUIT_Session.h>
64 #include <SUIT_Desktop.h>
65 #include <SUIT_DataBrowser.h>
66 #include <SUIT_FileDlg.h>
67 #include <SUIT_MessageBox.h>
68 #include <SUIT_ResourceMgr.h>
69 #include <SUIT_TreeModel.h>
70 #include <SUIT_ViewWindow.h>
71 #include <SUIT_ViewManager.h>
72 #include <SUIT_ViewModel.h>
73 #include <SUIT_OverrideCursor.h>
75 #include <QtxTreeView.h>
77 #include <SALOME_EventFilter.h>
79 // temporary commented
80 //#include <OB_ListItem.h>
83 #include <Utils_ORB_INIT.hxx>
84 #include <Utils_SINGLETON.hxx>
85 #include <SALOME_LifeCycleCORBA.hxx>
87 #include <QApplication>
92 #include <QPushButton>
94 #include <QListWidget>
95 #include <QGridLayout>
99 #include <SALOMEDSClient_ClientFactory.hxx>
100 #include <Basics_Utils.hxx>
102 #include <SALOME_ListIO.hxx>
103 #include <SALOME_Prs.h>
106 #include <ToolsGUI_CatalogGeneratorDlg.h>
107 #include <ToolsGUI_RegWidget.h>
111 #include <SALOMEDS_Tool.hxx>
113 /*!Internal class that updates object browser item properties */
114 // temporary commented
115 /*class SalomeApp_Updater : public OB_Updater
118 SalomeApp_Updater() : OB_Updater(){};
119 virtual ~SalomeApp_Updater(){};
120 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
123 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
125 if( !theObj || !theItem )
128 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
132 _PTR(SObject) SObj = SAObj->object();
135 _PTR( GenericAttribute ) anAttr;
138 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
140 _PTR(AttributeSelectable) aAttrSel = anAttr;
141 theItem->setSelectable( aAttrSel->IsSelectable() );
144 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
146 _PTR(AttributeExpandable) aAttrExpand = anAttr;
147 theItem->setExpandable( aAttrExpand->IsExpandable() );
150 //this attribute is not supported in the version of SALOME 3.x
151 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
153 // _PTR(AttributeOpened) aAttrOpen = anAttr;
154 // theItem->setOpen( aAttrOpen->IsOpened() );
158 /*!Create new instance of SalomeApp_Application.*/
159 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
161 return new SalomeApp_Application();
165 SalomeApp_Application::SalomeApp_Application()
166 : LightApp_Application(),
167 myIsCloseFromExit( false )
172 *\li Destroy event filter.
174 SalomeApp_Application::~SalomeApp_Application()
176 // Do not destroy. It's a singleton !
177 //SALOME_EventFilter::Destroy();
180 QStringList __getArgsList(QString argsString)
182 // Special process if some items of 'args:' list are themselves lists
183 // Note that an item can be a list, but not a list of lists...
184 // So we can have something like this:
185 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
186 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
187 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
188 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
189 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
191 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
196 return argsString.split(",", QString::SkipEmptyParts);
199 /*!Start application.*/
200 void SalomeApp_Application::start()
202 // process the command line options before start: to createActions in accordance to the options
203 static bool isFirst = true;
211 for (int i = 1; i < qApp->arguments().size(); i++) {
212 QRegExp rxs ("--study-hdf=(.+)");
213 if ( rxs.indexIn( qApp->arguments()[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
214 QString file = rxs.capturedTexts()[1];
215 QFileInfo fi ( file );
216 QString extension = fi.suffix().toLower();
217 if ( extension == "hdf" && fi.exists() )
218 hdffile = fi.absoluteFilePath();
221 QRegExp rxp ("--pyscript=\\[(.+)\\]");
222 if ( rxp.indexIn( qApp->arguments()[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
224 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
225 for (int k = 0; k < dictList.count(); ++k) {
226 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
227 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
228 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
229 pyfiles += rxd.capturedTexts()[m];
236 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
237 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
239 LightApp_Application::start();
240 SALOME_EventFilter::Init();
242 setProperty("open_study_from_command_line", true);
243 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
244 onOpenDoc( hdffile );
245 else if ( pyfiles.count() > 0 ) // create new study
247 else if (!loadStudy.isEmpty()) {// load study by name
248 if (onLoadDoc(loadStudy))
249 updateObjectBrowser(true);
251 setProperty("open_study_from_command_line", QVariant());
253 #ifndef DISABLE_PYCONSOLE
254 // import/execute python scripts
255 if ( pyfiles.count() > 0 && activeStudy() ) {
256 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
257 PyConsole_Console* pyConsole = pythonConsole();
258 if ( appStudy && pyConsole ) {
259 _PTR(Study) aStudy = appStudy->studyDS();
260 if ( !aStudy->GetProperties()->IsLocked() ) {
261 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
262 // Path is absolute, script has .py extension
263 for (uint j = 0; j < pyfiles.count(); j++ ) {
264 // Extract scripts and their arguments, if any
265 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
266 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
267 QString script = rxp.capturedTexts()[1];
269 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
270 for (uint k = 0; k < argList.count(); k++ ) {
271 QString arg = argList[k].trimmed();
272 arg.remove( QRegExp("^[\"]") );
273 arg.remove( QRegExp("[\"]$") );
276 args.remove( QRegExp("[,]$") );
277 if (!args.isEmpty()) {
281 script.remove( QRegExp("^python.*[\\s]+") );
282 QString cmd = script+" "+args;
283 QString command = QString( "execfile(r\"%1\")" ).arg(cmd.trimmed());
284 pyConsole->exec(command);
286 } // end for loop on pyfiles QStringList
292 LightApp_Application::start();
293 SALOME_EventFilter::Init();
298 void SalomeApp_Application::createActions()
300 LightApp_Application::createActions();
302 SUIT_Desktop* desk = desktop();
305 // "Save GUI State" command is moved to VISU module
306 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
307 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
308 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
311 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
312 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
313 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
316 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
317 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
318 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
321 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
322 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
323 0, desk, false, this, SLOT( onProperties() ) );
325 //! Catalog Generator
326 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
327 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
328 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
331 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
332 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
333 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
335 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
336 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
337 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
339 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
340 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
341 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
344 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
346 // "Save GUI State" command is renamed to "Save VISU State" and
347 // creation of menu item is moved to VISU
348 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
350 createMenu( ConnectId, fileMenu, 5 );
351 createMenu( DisconnectId, fileMenu, 5 );
352 createMenu( separator(), fileMenu, -1, 5 );
354 createMenu( DumpStudyId, fileMenu, 10, -1 );
355 createMenu( LoadScriptId, fileMenu, 10, -1 );
356 createMenu( separator(), fileMenu, -1, 10, -1 );
357 createMenu( PropertiesId, fileMenu, 10, -1 );
358 createMenu( separator(), fileMenu, -1, 10, -1 );
360 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
361 createMenu( CatalogGenId, toolsMenu, 10, -1 );
362 createMenu( RegDisplayId, toolsMenu, 10, -1 );
363 createMenu( separator(), toolsMenu, -1, 15, -1 );
365 createExtraActions();
367 #ifndef DISABLE_PYCONSOLE
368 #ifndef DISABLE_SALOMEOBJECT
369 // import Python module that manages SALOME plugins
371 PyLockWrapper lck; // acquire GIL
372 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
373 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
377 // end of SALOME plugins loading
384 \brief Close application.
386 void SalomeApp_Application::onExit()
388 bool killServers = false;
391 if ( exitConfirmation() ) {
392 SalomeApp_ExitDlg dlg( desktop() );
393 result = dlg.exec() == QDialog::Accepted;
394 killServers = dlg.isServersShutdown();
398 if ( !killServers ) myIsCloseFromExit = true;
399 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
400 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
404 /*!SLOT. Load document.*/
405 void SalomeApp_Application::onLoadDoc()
409 std::vector<std::string> List = studyMgr()->GetOpenStudies();
411 // rnv: According to the single-study approach on the server side
412 // can be only one study. So if it is exists connect to them,
413 // overwise show warning message: "No active study on the server"
416 SUIT_Session* aSession = SUIT_Session::session();
417 QList<SUIT_Application*> aAppList = aSession->applications();
419 QStringList unloadedStudies;
421 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
422 studyName = List[ind].c_str();
423 // Add to list only unloaded studies
424 bool isAlreadyOpen = false;
425 QListIterator<SUIT_Application*> it( aAppList );
426 while ( it.hasNext() && !isAlreadyOpen ) {
427 SUIT_Application* aApp = it.next();
428 if( !aApp || !aApp->activeStudy() )
430 if ( aApp->activeStudy()->studyName() == studyName )
431 isAlreadyOpen = true;
434 if ( !isAlreadyOpen )
435 unloadedStudies << studyName;
437 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
438 if ( studyName.isEmpty() )
442 if(List.size() <= 0) {
443 SUIT_MessageBox::warning( desktop(),
444 QObject::tr("WRN_WARNING"),
445 QObject::tr("WRN_NO_STUDY_ON SERV") );
449 studyName = List[0].c_str();
452 // this code replaces marker of windows drive and path become invalid therefore
453 // defines placed there
454 studyName.replace( QRegExp(":"), "/" );
457 if ( onLoadDoc( studyName ) ) {
459 updateViewManagers();
460 updateObjectBrowser( true );
464 /*!SLOT. Unload document.*/
465 void SalomeApp_Application::onUnloadDoc( bool ask )
468 activeStudy()->abortAllOperations();
469 if ( activeStudy()->isModified() ) {
470 QString docName = activeStudy()->studyName().trimmed();
471 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
472 tr( "DISCONNECT_DESCRIPTION" ),
473 tr( "DISCONNECT_SAVE" ),
474 tr( "DISCONNECT_WO_SAVE" ),
475 tr( "APPCLOSE_CANCEL" ), 0 );
476 if ( answer == 0 ) { // save before unload
477 if ( activeStudy()->isSaved() )
479 else if ( !onSaveAsDoc() )
482 else if ( answer == 2 ) // Cancel
486 closeActiveDoc( false );
489 /*!SLOT. Create new study and load script*/
490 void SalomeApp_Application::onNewWithScript()
492 QStringList filtersList;
493 filtersList.append(tr("PYTHON_FILES_FILTER"));
494 filtersList.append(tr("ALL_FILES_FILTER"));
496 QString anInitialPath = "";
497 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
498 anInitialPath = QDir::currentPath();
500 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
502 if ( !aFile.isEmpty() )
506 QString command = QString("execfile(r\"%1\")").arg(aFile);
508 #ifndef DISABLE_PYCONSOLE
509 PyConsole_Console* pyConsole = pythonConsole();
512 pyConsole->exec( command );
518 /*!SLOT. Load document with \a aName.*/
519 bool SalomeApp_Application::onLoadDoc( const QString& aName )
521 #ifdef SINGLE_DESKTOP
522 if ( !LightApp_Application::closeDoc() )
526 if ( !activeStudy() ) {
527 // if no study - load in current desktop
528 res = useStudy( aName );
531 // if study exists - load in new desktop. Check: is the same file is loaded?
532 SUIT_Session* aSession = SUIT_Session::session();
533 QList<SUIT_Application*> aAppList = aSession->applications();
534 bool isAlreadyOpen = false;
535 SalomeApp_Application* aApp = 0;
536 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
537 it != aAppList.end() && !isAlreadyOpen; ++it ) {
538 aApp = dynamic_cast<SalomeApp_Application*>( *it );
539 if ( aApp && aApp->activeStudy()->studyName() == aName )
540 isAlreadyOpen = true;
542 if ( !isAlreadyOpen ) {
543 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
545 res = aApp->useStudy( aName );
548 aApp->desktop()->activateWindow();
555 /*!SLOT. Parse message for desktop.*/
556 void SalomeApp_Application::onDesktopMessage( const QString& message )
558 if (message.indexOf("studyCreated:") == 0) {
559 // Enable 'Connect' action
560 updateCommandsStatus();
562 else if (message.indexOf("studyClosed:") == 0) {
563 /* message also contains ID of the closed study,
564 but as soon as SALOME is mono-study application for the moment,
565 this ID is not needed now.*/
566 //long aStudyId = message.section(':', 1).toLong();
567 // Disconnect GUI from active study, because it was closed on DS side.
568 closeActiveDoc( false );
569 // Disable 'Connect' action
570 QAction* a = action( ConnectId );
572 a->setEnabled( false );
574 else if ( message.toLower() == "connect_to_study" ) {
577 LightApp_Application::onDesktopMessage( message );
580 /*!SLOT. Copy objects to study maneger from selection maneger..*/
581 void SalomeApp_Application::onCopy()
583 LightApp_Application::onCopy();
586 LightApp_SelectionMgr* mgr = selectionMgr();
587 mgr->selectedObjects(list);
589 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
590 if(study == NULL) return;
592 _PTR(Study) stdDS = study->studyDS();
595 SALOME_ListIteratorOfListIO it( list );
598 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
602 studyMgr()->Copy(so);
603 onSelectionChanged();
611 /*!SLOT. Paste objects to study maneger from selection manager.*/
612 void SalomeApp_Application::onPaste()
614 LightApp_Application::onPaste();
617 LightApp_SelectionMgr* mgr = selectionMgr();
618 mgr->selectedObjects(list);
620 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
621 if(study == NULL) return;
623 _PTR(Study) stdDS = study->studyDS();
626 if ( stdDS->GetProperties()->IsLocked() ) {
627 SUIT_MessageBox::warning( desktop(),
628 QObject::tr("WRN_WARNING"),
629 QObject::tr("WRN_STUDY_LOCKED") );
633 SALOME_ListIteratorOfListIO it( list );
636 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
640 studyMgr()->Paste(so);
641 updateObjectBrowser( true );
642 updateActions(); //SRN: BugID IPAL9377, case 3
650 /*!Check the application on closing.
651 * \retval true if possible, else false
653 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
655 return LightApp_Application::isPossibleToClose( closePermanently );
658 /*! Check if the study is locked */
659 void SalomeApp_Application::onCloseDoc( bool ask )
661 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
664 _PTR(Study) stdDS = study->studyDS();
665 if(stdDS && stdDS->IsStudyLocked()) {
666 if ( SUIT_MessageBox::question( desktop(),
667 QObject::tr( "WRN_WARNING" ),
668 QObject::tr( "CLOSE_LOCKED_STUDY" ),
669 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
670 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
674 LightApp_Application::onCloseDoc( ask );
677 /*!Sets enable or disable some actions on selection changed.*/
678 void SalomeApp_Application::onSelectionChanged()
681 LightApp_SelectionMgr* mgr = selectionMgr();
682 mgr->selectedObjects(list);
684 bool canCopy = false;
685 bool canPaste = false;
687 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
690 canCopy = m->canCopy();
691 canPaste = m->canPaste();
694 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
696 _PTR(Study) stdDS = study->studyDS();
699 SALOME_ListIteratorOfListIO it ( list );
701 if (it.More() && list.Extent() == 1) {
702 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
705 canCopy = canCopy || studyMgr()->CanCopy(so);
706 canPaste = canPaste || studyMgr()->CanPaste(so);
712 action(EditCopyId)->setEnabled(canCopy);
713 action(EditPasteId)->setEnabled(canPaste);
716 /*!Delete references.*/
717 void SalomeApp_Application::onDeleteInvalidReferences()
720 LightApp_SelectionMgr* mgr = selectionMgr();
721 mgr->selectedObjects( aList, QString(), false );
723 if( aList.IsEmpty() )
726 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
727 _PTR(Study) aStudyDS = aStudy->studyDS();
728 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
731 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
732 if ( it.Value()->hasEntry() )
734 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
735 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
738 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
739 aStudyBuilder->RemoveReference( aSObject );
741 updateObjectBrowser();
745 void SalomeApp_Application::onOpenWith()
747 QApplication::setOverrideCursor( Qt::WaitCursor );
749 LightApp_SelectionMgr* mgr = selectionMgr();
750 mgr->selectedObjects(aList);
751 if (aList.Extent() != 1)
753 QApplication::restoreOverrideCursor();
756 Handle(SALOME_InteractiveObject) aIObj = aList.First();
757 QString aModuleName(aIObj->getComponentDataType());
758 QString aModuleTitle = moduleTitle(aModuleName);
759 activateModule(aModuleTitle);
760 QApplication::restoreOverrideCursor();
766 SUIT_Study* SalomeApp_Application::createNewStudy()
768 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
770 // Set up processing of major study-related events
771 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
772 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
773 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
774 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
776 #ifndef DISABLE_PYCONSOLE
777 //to receive signal in application that NoteBook's variable was modified
778 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
779 this, SIGNAL(notebookVarUpdated(QString)) );
786 Enable/Disable menu items and toolbar buttons. Rebuild menu
788 void SalomeApp_Application::updateCommandsStatus()
790 LightApp_Application::updateCommandsStatus();
793 QAction* a = action( DumpStudyId );
795 a->setEnabled( activeStudy() );
797 #ifndef DISABLE_PYCONSOLE
799 a = action( LoadScriptId );
801 a->setEnabled( pythonConsole() );
805 a = action( PropertiesId );
807 a->setEnabled( activeStudy() );
809 // Save GUI state menu
810 a = action( SaveGUIStateId );
812 a->setEnabled( activeStudy() );
814 // Connect study menu
815 a = action( ConnectId );
817 a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 );
819 // Disconnect study menu
820 a = action( DisconnectId );
822 a->setEnabled( activeStudy() );
824 // update state of Copy/Paste menu items
825 onSelectionChanged();
829 \class DumpStudyFileDlg
830 Private class used in Dump Study operation. Consists 2 check boxes:
831 "Publish in study" and "Save GUI parameters"
833 class DumpStudyFileDlg : public SUIT_FileDlg
836 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
838 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
841 QWidget *hB = new QWidget( this );
842 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
843 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
844 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
846 QHBoxLayout *layout = new QHBoxLayout;
847 layout->addWidget(myPublishChk);
848 layout->addWidget(myMultiFileChk);
849 layout->addWidget(mySaveGUIChk);
850 hB->setLayout(layout);
852 QPushButton* pb = new QPushButton(this);
854 int row = grid->rowCount();
855 grid->addWidget( new QLabel("", this), row, 0 );
856 grid->addWidget( hB, row, 1, 1, 3 );
857 grid->addWidget( pb, row, 5 );
862 QCheckBox* myPublishChk;
863 QCheckBox* myMultiFileChk;
864 QCheckBox* mySaveGUIChk;
867 /*!Private SLOT. On dump study.*/
868 void SalomeApp_Application::onDumpStudy( )
870 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
871 if ( !appStudy ) return;
872 _PTR(Study) aStudy = appStudy->studyDS();
874 QStringList aFilters;
875 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
877 bool anIsPublish = true;
878 bool anIsMultiFile = false;
879 bool anIsSaveGUI = true;
881 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
882 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
883 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
884 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
887 DumpStudyFileDlg fd( desktop() );
888 fd.setValidator( new LightApp_PyFileValidator( &fd ) );
889 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
890 fd.setNameFilters( aFilters );
891 fd.myPublishChk->setChecked( anIsPublish );
892 fd.myMultiFileChk->setChecked( anIsMultiFile );
893 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
894 if ( fd.exec() == QDialog::Accepted )
896 QString aFileName = fd.selectedFile();
898 bool toPublish = fd.myPublishChk->isChecked();
899 bool isMultiFile = fd.myMultiFileChk->isChecked();
900 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
902 if ( !aFileName.isEmpty() ) {
903 QFileInfo aFileInfo(aFileName);
904 if( aFileInfo.isDir() ) // IPAL19257
907 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
910 SUIT_OverrideCursor wc;
911 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
914 SUIT_MessageBox::warning( desktop(),
915 QObject::tr("WRN_WARNING"),
916 tr("WRN_DUMP_STUDY_FAILED") );
921 /*!Private SLOT. On load script.*/
922 void SalomeApp_Application::onLoadScript( )
924 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
926 _PTR(Study) aStudy = appStudy->studyDS();
927 if ( aStudy->GetProperties()->IsLocked() ) {
928 SUIT_MessageBox::warning( desktop(),
929 QObject::tr("WRN_WARNING"),
930 QObject::tr("WRN_STUDY_LOCKED") );
935 QStringList filtersList;
936 filtersList.append(tr("PYTHON_FILES_FILTER"));
937 filtersList.append(tr("ALL_FILES_FILTER"));
939 QString anInitialPath = "";
940 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
941 anInitialPath = QDir::currentPath();
943 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
945 if ( !aFile.isEmpty() )
947 QString command = QString("execfile(r\"%1\")").arg(aFile);
949 #ifndef DISABLE_PYCONSOLE
950 PyConsole_Console* pyConsole = pythonConsole();
953 pyConsole->exec( command );
958 /*!Private SLOT. On save GUI state.*/
959 void SalomeApp_Application::onSaveGUIState()
961 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
963 SalomeApp_VisualState( this ).storeState();
964 updateSavePointDataObjects( study );
965 updateObjectBrowser();
970 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
971 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
973 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
974 QAction* send = ::qobject_cast<QAction*>( sender() );
977 QString aWinName = send->data().toString();
978 if ( theIsVisible && aWinName == "objectBrowser" )
979 objectBrowserColumnsVisibility();
983 QWidget* SalomeApp_Application::createWindow( const int flag )
986 #ifndef DISABLE_PYCONSOLE
987 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
989 wid = LightApp_Application::createWindow(flag);
992 SUIT_ResourceMgr* resMgr = resourceMgr();
994 if ( flag == WT_ObjectBrowser )
996 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
998 // temporary commented
999 //ob->setUpdater( new SalomeApp_Updater() );
1001 #ifdef WITH_SALOMEDS_OBSERVER
1002 //do not activate the automatic update of Qt tree through signal/slot
1003 ob->setAutoUpdate(false);
1004 //activate update of modified objects only
1005 ob->setUpdateModified(true);
1008 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1011 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1012 IORCol = QObject::tr( "IOR_COLUMN" ),
1013 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1014 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1016 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1017 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1018 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1019 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1020 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1021 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1022 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1023 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1024 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1026 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1027 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1028 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1030 ob->setAutoSizeFirstColumn(autoSizeFirst);
1031 ob->setAutoSizeColumns(autoSize);
1032 ob->setResizeOnExpandItem(resizeOnExpandItem);
1033 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1035 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1037 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1038 ob->treeView()->setColumnHidden( i, !shown );
1041 // temporary commented
1043 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1045 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1046 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1047 QString().sprintf( "visibility_column_%d", i ), true ) );
1051 // temporary commented
1053 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1054 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1055 ob->resize( desktop()->width()/3, ob->height() );
1059 #ifndef DISABLE_PYCONSOLE
1060 else if ( flag == WT_PyConsole )
1062 PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
1063 pyCons->setObjectName( "pythonConsole" );
1064 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1065 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1066 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1067 pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
1068 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1071 else if ( flag == WT_NoteBook )
1073 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1075 _PTR(Study) aStudy = appStudy->studyDS();
1076 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1077 //to receive signal in NoteBook that it's variable was modified
1078 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1079 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1081 wid = getNoteBook();
1082 wid->setObjectName( "noteBook" );
1088 /*!Create preferences.*/
1089 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1091 LightApp_Application::createPreferences(pref);
1096 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1097 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1098 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1099 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1101 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1102 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1104 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1106 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1107 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1108 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1109 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1110 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1111 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1112 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1113 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1114 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1115 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1118 /*!Update desktop title.*/
1119 void SalomeApp_Application::updateDesktopTitle() {
1120 QString aTitle = applicationName();
1121 QString aVer = applicationVersion();
1122 if ( !aVer.isEmpty() )
1123 aTitle += QString( " " ) + aVer;
1125 if ( activeStudy() )
1127 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1128 if ( !sName.isEmpty() ) {
1129 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1131 _PTR(Study) stdDS = study->studyDS();
1133 if ( stdDS->GetProperties()->IsLocked() ) {
1134 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1136 aTitle += QString( " - [%1]" ).arg( sName );
1143 desktop()->setWindowTitle( aTitle );
1146 int SalomeApp_Application::closeChoice( const QString& docName )
1148 QStringList buttons;
1149 QMap<int, int> choices;
1151 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1152 choices.insert( idx++, CloseSave ); // ...
1153 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1154 choices.insert( idx++, CloseDiscard ); // ...
1155 if ( myIsCloseFromExit ) {
1156 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1157 choices.insert( idx++, CloseDisconnectSave ); // ...
1158 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1159 choices.insert( idx++, CloseDisconnect ); // ...
1161 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1162 choices.insert( idx++, CloseCancel ); // ...
1164 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1165 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1166 return choices[answer];
1169 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1175 if ( activeStudy()->isSaved() )
1177 else if ( !onSaveAsDoc() )
1182 case CloseDisconnectSave:
1183 if ( activeStudy()->isSaved() )
1185 else if ( !onSaveAsDoc() )
1187 case CloseDisconnect:
1188 closeActiveDoc( false );
1189 closePermanently = false;
1198 int SalomeApp_Application::openChoice( const QString& aName )
1200 int choice = LightApp_Application::openChoice( aName );
1202 if ( QFileInfo( aName ).exists() ) {
1203 if ( choice == OpenNew ) { // The document isn't already open.
1205 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1206 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1207 if ( aName == QString( lst[i].c_str() ) )
1210 // The document already exists in the study manager.
1211 // Do you want to reload it?
1213 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1214 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1215 if ( answer == SUIT_MessageBox::Yes )
1216 choice = OpenRefresh;
1218 choice = OpenCancel;
1221 } else { // file is not exist on disk
1222 SUIT_MessageBox::warning( desktop(),
1223 QObject::tr("WRN_WARNING"),
1224 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1231 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1234 int choice = aChoice;
1239 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1242 studyMgr()->Close( aStudy );
1247 res = LightApp_Application::openAction( choice, aName );
1255 \brief Get map of the operations which can be performed
1256 on the module activation.
1258 The method should return the map of the kind \c {<id>:<name>}
1259 where \c <id> is an integer identifier of the operation and
1260 \c <name> is a title for the button to be added to the
1261 dialog box. After user selects the required operation by the
1262 clicking the corresponding button in the dialog box, its identifier
1263 is passed to the moduleActionSelected() method to process
1266 \return map of the operations
1267 \sa moduleActionSelected()
1269 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1271 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1273 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1275 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1280 \brief Called when the used selectes required operation chosen
1281 from "Activate module" dialog box.
1283 Performs the required operation according to the user choice.
1285 \param id operation identifier
1286 \sa activateModuleActions()
1288 void SalomeApp_Application::moduleActionSelected( const int id )
1294 case NewAndScriptId:
1298 LightApp_Application::moduleActionSelected( id );
1303 /*!Gets CORBA::ORB_var*/
1304 CORBA::ORB_var SalomeApp_Application::orb()
1306 static CORBA::ORB_var _orb;
1308 if ( CORBA::is_nil( _orb ) ) {
1309 Qtx::CmdLineArgs args;
1310 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1311 _orb = init( args.argc(), args.argv() );
1317 /*!Create and return SALOMEDS_StudyManager.*/
1318 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1320 static _PTR(StudyManager) _sm;
1321 if(!_sm) _sm = ClientFactory::StudyManager();
1325 /*!Create and return SALOME_NamingService.*/
1326 SALOME_NamingService* SalomeApp_Application::namingService()
1328 static SALOME_NamingService _ns(orb());
1332 /*!Create and return SALOME_LifeCycleCORBA.*/
1333 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1335 static SALOME_LifeCycleCORBA _lcc( namingService() );
1339 /*!Private SLOT. On preferences.*/
1340 void SalomeApp_Application::onProperties()
1342 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1346 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1349 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1350 int res = aDlg.exec();
1351 if( res==QDialog::Accepted && aDlg.isChanged() )
1352 SB->CommitCommand();
1356 //study->updateCaptions();
1357 updateDesktopTitle();
1361 /*!Insert items in popup, which necessary for current application*/
1362 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1364 LightApp_SelectionMgr* mgr = selectionMgr();
1365 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1366 mgr->setSelectionCacheEnabled( true );
1368 LightApp_Application::contextMenuPopup( type, thePopup, title );
1370 // temporary commented
1371 /*OB_Browser* ob = objectBrowser();
1372 if ( !ob || type != ob->popupClientType() )
1375 // Get selected objects
1376 SALOME_ListIO aList;
1377 mgr->selectedObjects( aList, QString(), false );
1379 // add GUI state commands: restore, rename
1380 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1381 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1382 thePopup->addSeparator();
1383 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1384 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1385 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1386 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1389 // "Delete reference" item should appear only for invalid references
1391 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1392 bool isInvalidRefs = false;
1393 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1395 _PTR(Study) aStudyDS = aStudy->studyDS();
1396 _PTR(SObject) anObj;
1398 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1400 if( it.Value()->hasEntry() )
1402 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1403 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1406 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1407 isInvalidRefs = true;
1411 // Add "Delete reference" item to popup
1412 if ( isInvalidRefs )
1414 thePopup->addSeparator();
1415 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1419 // "Activate module" item should appear only if it's necessary
1420 if ( aList.Extent() == 1 ) {
1422 mgr->selectedObjects( aList );
1424 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1426 // add extra popup menu (defined in XML)
1427 if ( myExtActions.size() > 0 ) {
1428 // Use only first selected object
1429 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1431 _PTR(Study) stdDS = study->studyDS();
1433 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1435 _PTR( GenericAttribute ) anAttr;
1436 std::string auid = "AttributeUserID";
1437 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1438 if ( aSO->FindAttribute( anAttr, auid ) ) {
1439 _PTR(AttributeUserID) aAttrID = anAttr;
1440 QString aId = aAttrID->Value().c_str();
1441 if ( myExtActions.contains( aId ) ) {
1442 thePopup->addAction(myExtActions[aId]);
1450 // check if item is a "GUI state" item (also a first level object)
1451 QString entry( aIObj->getEntry() );
1452 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1453 QString aModuleName( aIObj->getComponentDataType() );
1454 QString aModuleTitle = moduleTitle( aModuleName );
1455 CAM_Module* currentModule = activeModule();
1456 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1457 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1462 mgr->setSelectionCacheEnabled( cacheIsOn );
1465 /*!Update obect browser:
1466 1.if 'updateModels' true, update existing data models;
1467 2. update "non-existing" (not loaded yet) data models;
1468 3. update object browser if it exists */
1469 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1471 // update "non-existing" (not loaded yet) data models
1472 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1475 _PTR(Study) stdDS = study->studyDS();
1478 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1480 _PTR(SComponent) aComponent ( it->Value() );
1482 #ifndef WITH_SALOMEDS_OBSERVER
1483 // with GUI observers this check is not needed anymore
1484 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1485 continue; // skip the magic "Interface Applicative" component
1487 if ( !objectBrowser() )
1488 getWindow( WT_ObjectBrowser );
1489 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1490 objectBrowser()->setAutoUpdate( false );
1491 SalomeApp_DataModel::synchronize( aComponent, study );
1492 objectBrowser()->setAutoUpdate( isAutoUpdate );
1497 // create data objects that correspond to GUI state save points
1498 if ( study ) updateSavePointDataObjects( study );
1500 // update existing data models (already loaded SComponents)
1501 LightApp_Application::updateObjectBrowser( updateModels );
1504 /*!Display Catalog Genenerator dialog */
1505 void SalomeApp_Application::onCatalogGen()
1507 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1511 /*!Display Registry Display dialog */
1512 void SalomeApp_Application::onRegDisplay()
1514 CORBA::ORB_var anOrb = orb();
1515 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1518 regWnd->activateWindow();
1521 /*!find original object by double click on item */
1522 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1524 // Issue 21379: References are supported at LightApp_DataObject level
1525 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1527 if( obj && obj->isReference() )
1529 QString entry = obj->refEntry();
1531 SUIT_DataOwnerPtrList aList;
1532 aList.append( new LightApp_DataOwner( entry ) );
1533 selectionMgr()->setSelected( aList, false );
1535 SUIT_DataBrowser* ob = objectBrowser();
1537 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1538 if ( !aSelectedIndexes.isEmpty() )
1539 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1541 emit objectDoubleClicked( theObj );
1545 Creates new view manager
1546 \param type - type of view manager
1548 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1550 return createViewManager(type);
1554 /*!Global utility function, returns selected GUI Save point object's ID */
1555 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1557 SALOME_ListIO aList;
1558 selMgr->selectedObjects( aList );
1559 if( aList.Extent() > 0 ) {
1560 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1561 QString entry( aIObj->getEntry() );
1562 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1563 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1565 bool ok; // conversion to integer is ok?
1566 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1567 return ok ? savePoint : -1;
1572 /*!Called on Restore GUI State popup command*/
1573 void SalomeApp_Application::onRestoreGUIState()
1575 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1576 if ( savePoint == -1 )
1578 SalomeApp_VisualState( this ).restoreState( savePoint );
1581 /*!Called on Delete GUI State popup command*/
1582 void SalomeApp_Application::onDeleteGUIState()
1584 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1585 if ( savePoint == -1 )
1587 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1591 study->removeSavePoint( savePoint );
1592 updateSavePointDataObjects( study );
1595 /*!Called on New study operation*/
1596 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1598 LightApp_Application::onStudyCreated( study );
1600 //#ifndef DISABLE_PYCONSOLE
1601 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1602 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1605 loadDockWindowsState();
1607 objectBrowserColumnsVisibility();
1610 /*!Called on Open study operation*/
1611 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1613 LightApp_Application::onStudyOpened( study );
1615 //#ifndef DISABLE_PYCONSOLE
1616 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1617 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1620 loadDockWindowsState();
1622 objectBrowserColumnsVisibility();
1624 // temporary commented
1625 /*if ( objectBrowser() ) {
1626 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1627 objectBrowser()->updateTree( study->root() );
1631 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1632 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1635 SUIT_DataBrowser* ob = objectBrowser();
1636 LightApp_SelectionMgr* selMgr = selectionMgr();
1638 if ( !study || !ob || !selMgr )
1641 // find GUI states root object
1642 SUIT_DataObject* guiRootObj = 0;
1644 study->root()->children( ch );
1645 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1646 for ( ; it != last ; ++it ) {
1647 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1652 std::vector<int> savePoints = study->getSavePoints();
1653 // case 1: no more save points but they existed in study's tree
1654 if ( savePoints.empty() && guiRootObj ) {
1655 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1656 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1657 const bool isAutoUpdate = ob->autoUpdate();
1658 selMgr->clearSelected();
1659 ob->setAutoUpdate(true);
1660 DataObjectList ch = guiRootObj->children();
1661 for( int i = 0; i < ch.size(); i++ )
1664 ob->setAutoUpdate(isAutoUpdate);
1667 // case 2: no more save points but root does not exist either
1668 if ( savePoints.empty() && !guiRootObj )
1670 // case 3: save points but no root for them - create it
1671 if ( !savePoints.empty() && !guiRootObj )
1672 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1673 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1674 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1676 if ( guiRootObj->nextBrother() ) {
1677 study->root()->removeChild(guiRootObj);
1678 study->root()->appendChild(guiRootObj);
1679 //study->root()->dump();
1682 // store data objects in a map id-to-DataObject
1683 QMap<int,SalomeApp_SavePointObject*> mapDO;
1685 guiRootObj->children( ch );
1686 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1687 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1689 mapDO[dobj->getId()] = dobj;
1692 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1693 // if in the map - remove it from map.
1694 for ( int i = 0; i < savePoints.size(); i++ )
1695 if ( !mapDO.contains( savePoints[i] ) )
1696 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1698 mapDO.remove( savePoints[i] );
1700 // delete DataObjects that are still in the map -- their IDs were not found in data model
1701 if( mapDO.size() > 0) {
1702 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1703 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1704 selMgr->clearSelected();
1705 const bool isAutoUpdate = ob->autoUpdate();
1706 ob->setAutoUpdate(true);
1707 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1709 ob->setAutoUpdate(isAutoUpdate);
1713 /*! Check data object */
1714 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1723 Opens other study into active Study. If Study is empty - creates it.
1724 \param theName - name of study
1726 bool SalomeApp_Application::useStudy( const QString& theName )
1729 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1732 res = aStudy->loadDocument( theName );
1733 updateDesktopTitle();
1734 updateCommandsStatus();
1738 /*! Show/hide object browser colums according to preferences */
1739 void SalomeApp_Application::objectBrowserColumnsVisibility()
1741 if ( objectBrowser() )
1742 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1744 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1745 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1749 #ifndef DISABLE_PYCONSOLE
1750 /*! Set SalomeApp_NoteBook pointer */
1751 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1753 myNoteBook = theNoteBook;
1756 /*! Return SalomeApp_NoteBook pointer */
1757 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1764 * Define extra actions defined in module definition XML file.
1765 * Additional popup items sections can be defined by parameter "popupitems".
1766 * Supported attributes:
1767 * title - title of menu item,
1768 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1769 * method - method which has to be called when menu item is selected
1771 * <section name="MODULENAME">
1772 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1774 * <section name="importmed">
1775 * <parameter name="title" value="My menu"/>
1776 * <parameter name="objectid" value="VISU.Result"/>
1777 * <parameter name="method" value="nameOfModuleMethod"/>
1780 void SalomeApp_Application::createExtraActions()
1782 myExtActions.clear();
1783 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1785 QStringList aModules;
1786 modules(aModules, false);
1787 foreach(QString aModile, aModules) {
1788 QString aModName = moduleName(aModile);
1789 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1790 if (!aSectionStr.isNull()) {
1791 QStringList aSections = aSectionStr.split(':');
1792 foreach(QString aSection, aSections) {
1793 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1794 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1795 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1796 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1799 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1800 if (aModuleName.isNull())
1801 aModuleName = aModName;
1803 QAction* aAction = new QAction(aTitle, this);
1805 aData<<aModuleName<<aSlot;
1806 aAction->setData(aData);
1807 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1808 myExtActions[aId] = aAction;
1815 * Called when extra action is selected
1817 void SalomeApp_Application::onExtAction()
1819 QAction* aAction = ::qobject_cast<QAction*>(sender());
1823 QVariant aData = aAction->data();
1824 QStringList aDataList = aData.value<QStringList>();
1825 if (aDataList.size() != 2)
1828 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1829 SALOME_ListIO aListIO;
1830 aSelectionMgr->selectedObjects(aListIO);
1831 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1832 if (aListIO.Extent() < 1)
1834 if (!anIO->hasEntry())
1837 QString aEntry(anIO->getEntry());
1839 QApplication::setOverrideCursor( Qt::WaitCursor );
1840 QString aModuleTitle = moduleTitle(aDataList[0]);
1841 activateModule(aModuleTitle);
1842 QApplication::restoreOverrideCursor();
1844 QCoreApplication::processEvents();
1846 CAM_Module* aModule = activeModule();
1850 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1851 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1855 Checks that an object can be renamed.
1856 \param entry entry of the object
1857 \brief Return \c true if object can be renamed
1859 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1861 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1865 Rename object by entry.
1866 \param entry entry of the object
1867 \param name new name of the object
1868 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1870 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1872 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1874 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1876 if(!aStudy || savePoint == -1)
1879 if ( !name.isNull() && !name.isEmpty() ) {
1880 aStudy->setNameOfSavePoint( savePoint, name );
1881 updateSavePointDataObjects( aStudy );
1883 //Mark study as modified
1890 #ifndef DISABLE_PYCONSOLE
1891 //============================================================================
1892 /*! Function : onUpdateStudy
1893 * Purpose : Slot to update the study.
1895 //============================================================================
1896 void SalomeApp_Application::onUpdateStudy()
1898 QApplication::setOverrideCursor( Qt::WaitCursor );
1900 if( !updateStudy() )
1901 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1903 QApplication::restoreOverrideCursor();
1906 //============================================================================
1907 /*! Function : updateStudy
1908 * Purpose : Update study by dumping the study to Python script and loading it.
1909 * It is used to apply variable modifications done in NoteBook to created objects.
1911 //============================================================================
1912 bool SalomeApp_Application::updateStudy()
1914 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1915 if ( !study || !myNoteBook )
1918 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1919 myNoteBook->setDumpedStudyName( study->studyName() );
1921 _PTR(Study) studyDS = study->studyDS();
1923 // get unique temporary directory name
1924 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1925 if( aTmpDir.isEmpty() )
1928 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1929 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1931 // dump study to the temporary directory
1932 QString aScriptName( "notebook" );
1933 bool toPublish = true;
1934 bool isMultiFile = false;
1935 bool toSaveGUI = true;
1938 _PTR(AttributeParameter) ap;
1939 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1940 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1941 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1942 ip->setDumpPython(studyDS);
1943 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1945 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1947 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1950 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1954 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1955 int anIndex = aList.indexOf( this );
1957 // Disconnect dialog from application desktop in case if:
1958 // 1) Application is not the first application in the session
1959 // 2) Application is the first application in session but not the only.
1960 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1961 if( changeDesktop ) {
1963 SalomeApp_Application* app = this;
1964 if( anIndex > 0 && anIndex < aList.count() )
1965 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1966 else if(anIndex == 0 && aList.count() > 1)
1967 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1972 // creation a new study and restoring will be done in another application
1973 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
1974 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
1977 QString aDumpScript = myNoteBook->getDumpedStudyScript();
1978 QString aStudyName = myNoteBook->getDumpedStudyName();
1979 bool isStudySaved = myNoteBook->isDumpedStudySaved();
1980 // clear a study (delete all objects)
1981 onCloseDoc( false );
1983 if( !changeDesktop ) {
1984 ok = onRestoreStudy( aDumpScript,
1993 //============================================================================
1994 /*! Function : onRestoreStudy
1995 * Purpose : Load the dumped study from Python script
1997 //============================================================================
1998 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
1999 const QString& theStudyName,
2000 bool theIsStudySaved )
2004 // create a new study
2007 // get active application
2008 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2010 // load study from the temporary directory
2011 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2013 #ifndef DISABLE_PYCONSOLE
2014 PyConsole_Console* pyConsole = app->pythonConsole();
2016 pyConsole->execAndWait( command );
2019 // remove temporary directory
2020 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2021 QString aStudyName = aScriptInfo.baseName();
2022 QDir aDir = aScriptInfo.absoluteDir();
2023 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2024 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2025 ok = aDir.remove( *it ) && ok;
2027 ok = aDir.rmdir( aDir.absolutePath() );
2029 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2031 #ifndef DISABLE_PYCONSOLE
2032 _PTR(Study) aStudyDS = newStudy->studyDS();
2033 if ( app->getNoteBook() )
2034 app->getNoteBook()->Init( aStudyDS );
2035 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2036 newStudy->Modified();
2037 updateDesktopTitle();
2048 Close the Application
2050 void SalomeApp_Application::afterCloseDoc()
2052 #ifndef DISABLE_PYCONSOLE
2053 // emit signal to restore study from Python script
2055 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2056 myNoteBook->getDumpedStudyName(),
2057 myNoteBook->isDumpedStudySaved() );
2060 LightApp_Application::afterCloseDoc();
2064 Asks to close existing document.
2066 bool SalomeApp_Application::checkExistingDoc()
2068 bool result = LightApp_Application::checkExistingDoc();
2069 if ( result && !activeStudy() ) {
2070 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2072 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2073 if( List.size() > 0 ) {
2074 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2083 #ifndef DISABLE_PYCONSOLE
2085 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2087 return new SalomeApp_PyInterp;
2090 #endif // DISABLE_PYCONSOLE