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 <PyConsole_Console.h>
40 #include "SalomeApp_NoteBook.h"
42 #include "SalomeApp_Application.h"
43 #include "SalomeApp_Study.h"
44 #include "SalomeApp_DataModel.h"
45 #include "SalomeApp_DataObject.h"
46 #include "SalomeApp_VisualState.h"
47 #include "SalomeApp_StudyPropertiesDlg.h"
48 #include "SalomeApp_LoadStudiesDlg.h"
49 #include "SalomeApp_ExitDlg.h"
51 #include <LightApp_Application.h>
52 #include <LightApp_Module.h>
53 #include <LightApp_Preferences.h>
54 #include <LightApp_SelectionMgr.h>
55 #include <LightApp_NameDlg.h>
56 #include <LightApp_DataOwner.h>
58 #include <CAM_Module.h>
60 #include <SUIT_Tools.h>
61 #include <SUIT_Session.h>
62 #include <SUIT_Desktop.h>
63 #include <SUIT_DataBrowser.h>
64 #include <SUIT_FileDlg.h>
65 #include <SUIT_FileValidator.h>
66 #include <SUIT_MessageBox.h>
67 #include <SUIT_ResourceMgr.h>
68 #include <SUIT_TreeModel.h>
69 #include <SUIT_ViewWindow.h>
70 #include <SUIT_ViewManager.h>
71 #include <SUIT_ViewModel.h>
72 #include <SUIT_OverrideCursor.h>
74 #include <QtxTreeView.h>
76 #include <SALOME_EventFilter.h>
78 // temporary commented
79 //#include <OB_ListItem.h>
82 #include <Utils_ORB_INIT.hxx>
83 #include <Utils_SINGLETON.hxx>
84 #include <SALOME_LifeCycleCORBA.hxx>
86 #include <QApplication>
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 PyConsole_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 PyConsole_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 PyConsole_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 // temporary commented
1054 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1056 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1057 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1058 QString().sprintf( "visibility_column_%d", i ), true ) );
1062 // temporary commented
1064 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1065 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1066 ob->resize( desktop()->width()/3, ob->height() );
1070 #ifndef DISABLE_PYCONSOLE
1071 else if ( flag == WT_PyConsole )
1073 PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), getPyInterp() );
1074 pyCons->setObjectName( "pythonConsole" );
1075 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1076 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1077 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1078 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1080 //pyCons->resize( pyCons->width(), desktop()->height()/4 );
1081 pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
1083 else if ( flag == WT_NoteBook )
1085 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1087 _PTR(Study) aStudy = appStudy->studyDS();
1088 setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) );
1089 //to receive signal in NoteBook that it's variable was modified
1090 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1091 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1093 wid = getNoteBook();
1094 wid->setObjectName( "noteBook" );
1100 /*!Create preferences.*/
1101 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1103 LightApp_Application::createPreferences(pref);
1108 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1109 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1110 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1111 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1113 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1114 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1116 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1118 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1119 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1120 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1121 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1122 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1123 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1124 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1125 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1126 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1127 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1130 /*!Update desktop title.*/
1131 void SalomeApp_Application::updateDesktopTitle() {
1132 QString aTitle = applicationName();
1133 QString aVer = applicationVersion();
1134 if ( !aVer.isEmpty() )
1135 aTitle += QString( " " ) + aVer;
1137 if ( activeStudy() )
1139 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1140 if ( !sName.isEmpty() ) {
1141 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1143 _PTR(Study) stdDS = study->studyDS();
1145 if ( stdDS->GetProperties()->IsLocked() ) {
1146 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1148 aTitle += QString( " - [%1]" ).arg( sName );
1155 desktop()->setWindowTitle( aTitle );
1158 int SalomeApp_Application::closeChoice( const QString& docName )
1160 QStringList buttons;
1161 QMap<int, int> choices;
1163 buttons << tr ("APPCLOSE_SAVE"); // Save & Close
1164 choices.insert( idx++, CloseSave ); // ...
1165 buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving
1166 choices.insert( idx++, CloseDiscard ); // ...
1167 if ( myIsCloseFromExit ) {
1168 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1169 choices.insert( idx++, CloseDisconnectSave ); // ...
1170 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1171 choices.insert( idx++, CloseDisconnect ); // ...
1173 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1174 choices.insert( idx++, CloseCancel ); // ...
1176 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1177 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1178 return choices[answer];
1181 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1187 if ( activeStudy()->isSaved() )
1189 else if ( !onSaveAsDoc() )
1194 case CloseDisconnectSave:
1195 if ( activeStudy()->isSaved() )
1197 else if ( !onSaveAsDoc() )
1199 case CloseDisconnect:
1200 closeActiveDoc( false );
1201 closePermanently = false;
1210 int SalomeApp_Application::openChoice( const QString& aName )
1212 int choice = LightApp_Application::openChoice( aName );
1214 if ( QFileInfo( aName ).exists() ) {
1215 if ( choice == OpenNew ) { // The document isn't already open.
1217 std::vector<std::string> lst = studyMgr()->GetOpenStudies();
1218 for ( uint i = 0; i < lst.size() && !exist; i++ ) {
1219 if ( aName == QString( lst[i].c_str() ) )
1222 // The document already exists in the study manager.
1223 // Do you want to reload it?
1225 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1226 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1227 if ( answer == SUIT_MessageBox::Yes )
1228 choice = OpenRefresh;
1230 choice = OpenCancel;
1233 } else { // file is not exist on disk
1234 SUIT_MessageBox::warning( desktop(),
1235 QObject::tr("WRN_WARNING"),
1236 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toLatin1().data()));
1243 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1246 int choice = aChoice;
1251 _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() );
1254 studyMgr()->Close( aStudy );
1259 res = LightApp_Application::openAction( choice, aName );
1267 \brief Get map of the operations which can be performed
1268 on the module activation.
1270 The method should return the map of the kind \c {<id>:<name>}
1271 where \c <id> is an integer identifier of the operation and
1272 \c <name> is a title for the button to be added to the
1273 dialog box. After user selects the required operation by the
1274 clicking the corresponding button in the dialog box, its identifier
1275 is passed to the moduleActionSelected() method to process
1278 \return map of the operations
1279 \sa moduleActionSelected()
1281 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1283 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1285 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1287 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1292 \brief Called when the used selectes required operation chosen
1293 from "Activate module" dialog box.
1295 Performs the required operation according to the user choice.
1297 \param id operation identifier
1298 \sa activateModuleActions()
1300 void SalomeApp_Application::moduleActionSelected( const int id )
1306 case NewAndScriptId:
1310 LightApp_Application::moduleActionSelected( id );
1315 /*!Gets CORBA::ORB_var*/
1316 CORBA::ORB_var SalomeApp_Application::orb()
1318 static CORBA::ORB_var _orb;
1320 if ( CORBA::is_nil( _orb ) ) {
1321 QStringList args = QApplication::arguments();
1322 int argc = args.size();
1323 std::vector<std::string> args1(argc);
1324 char** argv = new char*[argc];
1325 for ( int i = 0; i < argc; ++i ) {
1326 args1[i] = args[i].toStdString();
1327 argv[i] = const_cast<char*>( args1[i].c_str() );
1330 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1331 _orb = init( argc, argv );
1339 /*!Create and return SALOMEDS_StudyManager.*/
1340 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
1342 static _PTR(StudyManager) _sm;
1343 if(!_sm) _sm = ClientFactory::StudyManager();
1347 /*!Create and return SALOME_NamingService.*/
1348 SALOME_NamingService* SalomeApp_Application::namingService()
1350 static SALOME_NamingService _ns(orb());
1354 /*!Create and return SALOME_LifeCycleCORBA.*/
1355 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1357 static SALOME_LifeCycleCORBA _lcc( namingService() );
1361 /*!Private SLOT. On preferences.*/
1362 void SalomeApp_Application::onProperties()
1364 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1368 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1371 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1372 int res = aDlg.exec();
1373 if( res==QDialog::Accepted && aDlg.isChanged() )
1374 SB->CommitCommand();
1378 //study->updateCaptions();
1379 updateDesktopTitle();
1383 /*!Insert items in popup, which necessary for current application*/
1384 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1386 LightApp_SelectionMgr* mgr = selectionMgr();
1387 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1388 mgr->setSelectionCacheEnabled( true );
1390 LightApp_Application::contextMenuPopup( type, thePopup, title );
1392 // temporary commented
1393 /*OB_Browser* ob = objectBrowser();
1394 if ( !ob || type != ob->popupClientType() )
1397 // Get selected objects
1398 SALOME_ListIO aList;
1399 mgr->selectedObjects( aList, QString(), false );
1401 // add GUI state commands: restore, rename
1402 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1403 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1404 thePopup->addSeparator();
1405 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1406 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1407 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1408 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1411 // "Delete reference" item should appear only for invalid references
1413 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1414 bool isInvalidRefs = false;
1415 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1417 _PTR(Study) aStudyDS = aStudy->studyDS();
1418 _PTR(SObject) anObj;
1420 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1422 if( it.Value()->hasEntry() )
1424 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1425 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1428 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1429 isInvalidRefs = true;
1433 // Add "Delete reference" item to popup
1434 if ( isInvalidRefs )
1436 thePopup->addSeparator();
1437 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1441 // "Activate module" item should appear only if it's necessary
1442 if ( aList.Extent() == 1 ) {
1444 mgr->selectedObjects( aList );
1446 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1448 // add extra popup menu (defined in XML)
1449 if ( myExtActions.size() > 0 ) {
1450 // Use only first selected object
1451 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1453 _PTR(Study) stdDS = study->studyDS();
1455 _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() );
1457 _PTR( GenericAttribute ) anAttr;
1458 std::string auid = "AttributeUserID";
1459 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1460 if ( aSO->FindAttribute( anAttr, auid ) ) {
1461 _PTR(AttributeUserID) aAttrID = anAttr;
1462 QString aId = aAttrID->Value().c_str();
1463 if ( myExtActions.contains( aId ) ) {
1464 thePopup->addAction(myExtActions[aId]);
1472 // check if item is a "GUI state" item (also a first level object)
1473 QString entry( aIObj->getEntry() );
1474 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1475 QString aModuleName( aIObj->getComponentDataType() );
1476 QString aModuleTitle = moduleTitle( aModuleName );
1477 CAM_Module* currentModule = activeModule();
1478 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() )
1479 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1484 mgr->setSelectionCacheEnabled( cacheIsOn );
1487 /*!Update obect browser:
1488 1.if 'updateModels' true, update existing data models;
1489 2. update "non-existing" (not loaded yet) data models;
1490 3. update object browser if it exists */
1491 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1493 // update "non-existing" (not loaded yet) data models
1494 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1497 _PTR(Study) stdDS = study->studyDS();
1500 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1502 _PTR(SComponent) aComponent ( it->Value() );
1504 #ifndef WITH_SALOMEDS_OBSERVER
1505 // with GUI observers this check is not needed anymore
1506 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1507 continue; // skip the magic "Interface Applicative" component
1509 if ( !objectBrowser() )
1510 getWindow( WT_ObjectBrowser );
1511 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1512 objectBrowser()->setAutoUpdate( false );
1513 SalomeApp_DataModel::synchronize( aComponent, study );
1514 objectBrowser()->setAutoUpdate( isAutoUpdate );
1519 // create data objects that correspond to GUI state save points
1520 if ( study ) updateSavePointDataObjects( study );
1522 // update existing data models (already loaded SComponents)
1523 LightApp_Application::updateObjectBrowser( updateModels );
1526 /*!Display Catalog Genenerator dialog */
1527 void SalomeApp_Application::onCatalogGen()
1529 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1533 /*!Display Registry Display dialog */
1534 void SalomeApp_Application::onRegDisplay()
1536 CORBA::ORB_var anOrb = orb();
1537 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1540 regWnd->activateWindow();
1543 /*!find original object by double click on item */
1544 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1546 // Issue 21379: References are supported at LightApp_DataObject level
1547 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1549 if( obj && obj->isReference() )
1551 QString entry = obj->refEntry();
1553 SUIT_DataOwnerPtrList aList;
1554 aList.append( new LightApp_DataOwner( entry ) );
1555 selectionMgr()->setSelected( aList, false );
1557 SUIT_DataBrowser* ob = objectBrowser();
1559 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1560 if ( !aSelectedIndexes.isEmpty() )
1561 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1566 Creates new view manager
1567 \param type - type of view manager
1569 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1571 return createViewManager(type);
1575 /*!Global utility function, returns selected GUI Save point object's ID */
1576 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1578 SALOME_ListIO aList;
1579 selMgr->selectedObjects( aList );
1580 if( aList.Extent() > 0 ) {
1581 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1582 QString entry( aIObj->getEntry() );
1583 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1584 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1586 bool ok; // conversion to integer is ok?
1587 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1588 return ok ? savePoint : -1;
1593 /*!Called on Restore GUI State popup command*/
1594 void SalomeApp_Application::onRestoreGUIState()
1596 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1597 if ( savePoint == -1 )
1599 SalomeApp_VisualState( this ).restoreState( savePoint );
1602 /*!Called on Delete GUI State popup command*/
1603 void SalomeApp_Application::onDeleteGUIState()
1605 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1606 if ( savePoint == -1 )
1608 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1612 study->removeSavePoint( savePoint );
1613 updateSavePointDataObjects( study );
1616 /*!Called on New study operation*/
1617 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1619 LightApp_Application::onStudyCreated( study );
1621 //#ifndef DISABLE_PYCONSOLE
1622 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1623 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1626 loadDockWindowsState();
1628 objectBrowserColumnsVisibility();
1631 /*!Called on Open study operation*/
1632 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1634 LightApp_Application::onStudyOpened( study );
1636 //#ifndef DISABLE_PYCONSOLE
1637 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1638 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1641 loadDockWindowsState();
1643 objectBrowserColumnsVisibility();
1645 // temporary commented
1646 /*if ( objectBrowser() ) {
1647 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1648 objectBrowser()->updateTree( study->root() );
1652 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1653 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1656 SUIT_DataBrowser* ob = objectBrowser();
1657 LightApp_SelectionMgr* selMgr = selectionMgr();
1659 if ( !study || !ob || !selMgr )
1662 // find GUI states root object
1663 SUIT_DataObject* guiRootObj = 0;
1665 study->root()->children( ch );
1666 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1667 for ( ; it != last ; ++it ) {
1668 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1673 std::vector<int> savePoints = study->getSavePoints();
1674 // case 1: no more save points but they existed in study's tree
1675 if ( savePoints.empty() && guiRootObj ) {
1676 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1677 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1678 const bool isAutoUpdate = ob->autoUpdate();
1679 selMgr->clearSelected();
1680 ob->setAutoUpdate(true);
1681 DataObjectList ch = guiRootObj->children();
1682 for( int i = 0; i < ch.size(); i++ )
1685 ob->setAutoUpdate(isAutoUpdate);
1688 // case 2: no more save points but root does not exist either
1689 if ( savePoints.empty() && !guiRootObj )
1691 // case 3: save points but no root for them - create it
1692 if ( !savePoints.empty() && !guiRootObj )
1693 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1694 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1695 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1697 if ( guiRootObj->nextBrother() ) {
1698 study->root()->removeChild(guiRootObj);
1699 study->root()->appendChild(guiRootObj);
1700 //study->root()->dump();
1703 // store data objects in a map id-to-DataObject
1704 QMap<int,SalomeApp_SavePointObject*> mapDO;
1706 guiRootObj->children( ch );
1707 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1708 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1710 mapDO[dobj->getId()] = dobj;
1713 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1714 // if in the map - remove it from map.
1715 for ( int i = 0; i < savePoints.size(); i++ )
1716 if ( !mapDO.contains( savePoints[i] ) )
1717 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1719 mapDO.remove( savePoints[i] );
1721 // delete DataObjects that are still in the map -- their IDs were not found in data model
1722 if( mapDO.size() > 0) {
1723 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1724 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1725 selMgr->clearSelected();
1726 const bool isAutoUpdate = ob->autoUpdate();
1727 ob->setAutoUpdate(true);
1728 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1730 ob->setAutoUpdate(isAutoUpdate);
1734 /*! Check data object */
1735 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1744 Opens other study into active Study. If Study is empty - creates it.
1745 \param theName - name of study
1747 bool SalomeApp_Application::useStudy( const QString& theName )
1750 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1753 res = aStudy->loadDocument( theName );
1754 updateDesktopTitle();
1755 updateCommandsStatus();
1759 /*! Show/hide object browser colums according to preferences */
1760 void SalomeApp_Application::objectBrowserColumnsVisibility()
1762 if ( objectBrowser() )
1763 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1765 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1766 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1770 #ifndef DISABLE_PYCONSOLE
1771 /*! Set SalomeApp_NoteBook pointer */
1772 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1774 myNoteBook = theNoteBook;
1777 /*! Return SalomeApp_NoteBook pointer */
1778 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1785 * Define extra actions defined in module definition XML file.
1786 * Additional popup items sections can be defined by parameter "popupitems".
1787 * Supported attributes:
1788 * title - title of menu item,
1789 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1790 * method - method which has to be called when menu item is selected
1792 * <section name="MODULENAME">
1793 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1795 * <section name="importmed">
1796 * <parameter name="title" value="My menu"/>
1797 * <parameter name="objectid" value="VISU.Result"/>
1798 * <parameter name="method" value="nameOfModuleMethod"/>
1801 void SalomeApp_Application::createExtraActions()
1803 myExtActions.clear();
1804 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1806 QStringList aModules;
1807 modules(aModules, false);
1808 foreach(QString aModile, aModules) {
1809 QString aModName = moduleName(aModile);
1810 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1811 if (!aSectionStr.isNull()) {
1812 QStringList aSections = aSectionStr.split(':');
1813 foreach(QString aSection, aSections) {
1814 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1815 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1816 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1817 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1820 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1821 if (aModuleName.isNull())
1822 aModuleName = aModName;
1824 QAction* aAction = new QAction(aTitle, this);
1826 aData<<aModuleName<<aSlot;
1827 aAction->setData(aData);
1828 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1829 myExtActions[aId] = aAction;
1836 * Called when extra action is selected
1838 void SalomeApp_Application::onExtAction()
1840 QAction* aAction = ::qobject_cast<QAction*>(sender());
1844 QVariant aData = aAction->data();
1845 QStringList aDataList = aData.value<QStringList>();
1846 if (aDataList.size() != 2)
1849 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1850 SALOME_ListIO aListIO;
1851 aSelectionMgr->selectedObjects(aListIO);
1852 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1853 if (aListIO.Extent() < 1)
1855 if (!anIO->hasEntry())
1858 QString aEntry(anIO->getEntry());
1860 QApplication::setOverrideCursor( Qt::WaitCursor );
1861 QString aModuleTitle = moduleTitle(aDataList[0]);
1862 activateModule(aModuleTitle);
1863 QApplication::restoreOverrideCursor();
1865 QCoreApplication::processEvents();
1867 CAM_Module* aModule = activeModule();
1871 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1872 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1876 Checks that an object can be renamed.
1877 \param entry entry of the object
1878 \brief Return \c true if object can be renamed
1880 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1882 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1886 Rename object by entry.
1887 \param entry entry of the object
1888 \param name new name of the object
1889 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1891 bool SalomeApp_Application::renameObject( const QString& entry, const QString& name )
1893 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1895 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1897 if(!aStudy || savePoint == -1)
1900 if ( !name.isNull() && !name.isEmpty() ) {
1901 aStudy->setNameOfSavePoint( savePoint, name );
1902 updateSavePointDataObjects( aStudy );
1904 //Mark study as modified
1911 #ifndef DISABLE_PYCONSOLE
1912 //============================================================================
1913 /*! Function : onUpdateStudy
1914 * Purpose : Slot to update the study.
1916 //============================================================================
1917 void SalomeApp_Application::onUpdateStudy()
1919 QApplication::setOverrideCursor( Qt::WaitCursor );
1921 if( !updateStudy() )
1922 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1924 QApplication::restoreOverrideCursor();
1927 //============================================================================
1928 /*! Function : updateStudy
1929 * Purpose : Update study by dumping the study to Python script and loading it.
1930 * It is used to apply variable modifications done in NoteBook to created objects.
1932 //============================================================================
1933 bool SalomeApp_Application::updateStudy()
1935 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1936 if ( !study || !myNoteBook )
1939 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1940 myNoteBook->setDumpedStudyName( study->studyName() );
1942 _PTR(Study) studyDS = study->studyDS();
1944 // get unique temporary directory name
1945 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1946 if( aTmpDir.isEmpty() )
1949 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1950 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1952 // dump study to the temporary directory
1953 QString aScriptName( "notebook" );
1954 bool toPublish = true;
1955 bool isMultiFile = false;
1956 bool toSaveGUI = true;
1959 _PTR(AttributeParameter) ap;
1960 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1961 if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag.
1962 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1963 ip->setDumpPython(studyDS);
1964 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1966 bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1968 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1971 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1975 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1976 int anIndex = aList.indexOf( this );
1978 // Disconnect dialog from application desktop in case if:
1979 // 1) Application is not the first application in the session
1980 // 2) Application is the first application in session but not the only.
1981 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1982 if( changeDesktop ) {
1984 SalomeApp_Application* app = this;
1985 if( anIndex > 0 && anIndex < aList.count() )
1986 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
1987 else if(anIndex == 0 && aList.count() > 1)
1988 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
1993 // creation a new study and restoring will be done in another application
1994 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
1995 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
1998 QString aDumpScript = myNoteBook->getDumpedStudyScript();
1999 QString aStudyName = myNoteBook->getDumpedStudyName();
2000 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2001 // clear a study (delete all objects)
2002 onCloseDoc( false );
2004 if( !changeDesktop ) {
2005 ok = onRestoreStudy( aDumpScript,
2014 //============================================================================
2015 /*! Function : onRestoreStudy
2016 * Purpose : Load the dumped study from Python script
2018 //============================================================================
2019 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2020 const QString& theStudyName,
2021 bool theIsStudySaved )
2025 // create a new study
2028 // get active application
2029 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2031 // load study from the temporary directory
2032 QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript );
2034 #ifndef DISABLE_PYCONSOLE
2035 PyConsole_Console* pyConsole = app->pythonConsole();
2037 pyConsole->execAndWait( command );
2040 // remove temporary directory
2041 QFileInfo aScriptInfo = QFileInfo( theDumpScript );
2042 QString aStudyName = aScriptInfo.baseName();
2043 QDir aDir = aScriptInfo.absoluteDir();
2044 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2045 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2046 ok = aDir.remove( *it ) && ok;
2048 ok = aDir.rmdir( aDir.absolutePath() );
2050 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2052 #ifndef DISABLE_PYCONSOLE
2053 _PTR(Study) aStudyDS = newStudy->studyDS();
2054 app->getNoteBook()->Init( aStudyDS );
2055 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2056 newStudy->Modified();
2057 updateDesktopTitle();
2068 Close the Application
2070 void SalomeApp_Application::afterCloseDoc()
2072 #ifndef DISABLE_PYCONSOLE
2073 // emit signal to restore study from Python script
2075 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2076 myNoteBook->getDumpedStudyName(),
2077 myNoteBook->isDumpedStudySaved() );
2080 LightApp_Application::afterCloseDoc();
2084 Asks to close existing document.
2086 bool SalomeApp_Application::checkExistingDoc()
2088 bool result = LightApp_Application::checkExistingDoc();
2089 if ( result && !activeStudy() ) {
2090 SALOMEDSClient_StudyManager* aMgr = studyMgr();
2092 std::vector<std::string> List = studyMgr()->GetOpenStudies();
2093 if( List.size() > 0 ) {
2094 SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" ));
2103 #ifndef DISABLE_PYCONSOLE
2105 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2107 return new SalomeApp_PyInterp();
2110 #endif // DISABLE_PYCONSOLE