1 // Copyright (C) 2007-2023 CEA, EDF, 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 <SALOME_LifeCycleCORBA.hxx>
85 #include <QApplication>
90 #include <QPushButton>
92 #include <QListWidget>
93 #include <QGridLayout>
97 #include <SALOMEDSClient_ClientFactory.hxx>
98 #include <ArgvKeeper.hxx>
99 #include <Basics_Utils.hxx>
100 #include <OpUtil.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 #include <SALOMEconfig.h>
114 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
116 std::unique_ptr<SALOME_NamingService_Abstract> SalomeApp_Application::_ns;
118 /*!Internal class that updates object browser item properties */
119 // temporary commented
120 /*class SalomeApp_Updater : public OB_Updater
123 SalomeApp_Updater() : OB_Updater(){};
124 virtual ~SalomeApp_Updater(){};
125 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
128 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
130 if( !theObj || !theItem )
133 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
137 _PTR(SObject) SObj = SAObj->object();
140 _PTR( GenericAttribute ) anAttr;
143 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
145 _PTR(AttributeSelectable) aAttrSel = anAttr;
146 theItem->setSelectable( aAttrSel->IsSelectable() );
149 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
151 _PTR(AttributeExpandable) aAttrExpand = anAttr;
152 theItem->setExpandable( aAttrExpand->IsExpandable() );
155 //this attribute is not supported in the version of SALOME 3.x
156 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
158 // _PTR(AttributeOpened) aAttrOpen = anAttr;
159 // theItem->setOpen( aAttrOpen->IsOpened() );
171 //! Constructor. Sets passed boolean flag to \c true.
172 MessageLocker( bool& Lock ) : myPrevState( Lock ), myLock( Lock ) { myLock = true; }
173 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
174 ~MessageLocker() { myLock = myPrevState; }
177 bool& myLock; //! External 'Lock state' boolean flag
181 \brief Dynamic property manager
188 PropertyMgr(QObject* object, const QString& property, const QVariant& value)
189 : myObject(object), myProperty(property)
191 myObject->setProperty(qPrintable(myProperty), value);
195 myObject->setProperty(qPrintable(myProperty), QVariant());
201 SalomeApp_Application::SalomeApp_Application(SALOME_NamingService_Abstract *ns):myIsCloseFromExit( false ),myToIgnoreMessages( false )
204 _ns.reset(new SALOME_NamingService(orb()));
210 *\li Destroy event filter.
212 SalomeApp_Application::~SalomeApp_Application()
214 // Do not destroy. It's a singleton !
215 //SALOME_EventFilter::Destroy();
218 QStringList __getArgsList(QString argsString)
220 // Special process if some items of 'args:' list are themselves lists
221 // Note that an item can be a list, but not a list of lists...
222 // So we can have something like this:
223 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
224 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
225 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
226 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
227 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
229 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
234 return argsString.split(",", QString::SkipEmptyParts);
237 /*!Start application.*/
238 void SalomeApp_Application::start()
240 // process the command line options before start: to createActions in accordance to the options
241 static bool isFirst = true;
248 QStringList args = QApplication::arguments();
249 for (int i = 1; i < args.count(); i++) {
250 QRegExp rxs ("--study-hdf=(.+)");
251 if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
252 QString file = rxs.capturedTexts()[1];
253 QFileInfo fi ( file );
254 QString extension = fi.suffix().toLower();
255 if ( extension == "hdf" && fi.exists() )
256 hdffile = fi.absoluteFilePath();
259 QRegExp rxp ("--pyscript=\\[(.+)\\]");
260 if ( rxp.indexIn( args[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
262 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
263 for (int k = 0; k < dictList.count(); ++k) {
264 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
265 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
266 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
267 pyfiles += rxd.capturedTexts()[m];
274 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
275 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
277 LightApp_Application::start();
278 SALOME_EventFilter::Init();
280 if ( !hdffile.isEmpty() )
282 // open hdf file given as parameter
283 PropertyMgr propm( this, "open_study_from_command_line", true );
284 onOpenDoc( hdffile );
287 #ifndef DISABLE_PYCONSOLE
288 // import/execute python scripts
289 if ( pyfiles.count() > 0 && activeStudy() ) {
290 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
291 PyConsole_Console* pyConsole = pythonConsole();
292 if ( appStudy && pyConsole ) {
293 if ( !getStudy()->GetProperties()->IsLocked() ) {
294 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
295 // Path is absolute, script has .py extension
296 for (int j = 0; j < pyfiles.count(); j++ ) {
297 // Extract scripts and their arguments, if any
298 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
299 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
300 QString script = rxp.capturedTexts()[1];
302 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
303 for (int k = 0; k < argList.count(); k++ ) {
304 QString arg = argList[k].trimmed();
305 arg.remove( QRegExp("^[\"]") );
306 arg.remove( QRegExp("[\"]$") );
307 args << QString("\"%1\"").arg(arg);
309 if (args.count() == 1)
312 script.remove( QRegExp("^python.*[\\s]+") );
313 QString command = QString( "exec(open(\"%1\", \"rb\").read(), args=(%2))" ).arg(script).arg(args.join(","));
314 PropertyMgr propm( this, "IsLoadedScript", true );
315 pyConsole->exec(command);
317 } // end for loop on pyfiles QStringList
323 LightApp_Application::start();
324 SALOME_EventFilter::Init();
329 void SalomeApp_Application::createActions()
331 LightApp_Application::createActions();
333 SUIT_Desktop* desk = desktop();
336 // "Save GUI State" command is moved to VISU module
337 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
338 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
339 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
342 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
343 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
344 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
347 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
348 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
349 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
352 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
353 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
354 0, desk, false, this, SLOT( onProperties() ) );
356 //! Catalog Generator
357 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
358 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
359 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
362 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
363 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
364 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
366 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
367 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
368 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
369 //no need at this action for mono-study application because study is always exists
370 action( ConnectId )->setVisible( false );
372 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
373 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
374 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
375 //no need at this action for mono-study application because study is always exists
376 action( DisconnectId )->setVisible( false );
379 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
381 // "Save GUI State" command is renamed to "Save VISU State" and
382 // creation of menu item is moved to VISU
383 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
385 createMenu( ConnectId, fileMenu, 5 );
386 createMenu( DisconnectId, fileMenu, 5 );
387 createMenu( separator(), fileMenu, -1, 5 );
389 createMenu( DumpStudyId, fileMenu, 10, -1 );
390 createMenu( LoadScriptId, fileMenu, 10, -1 );
391 createMenu( separator(), fileMenu, -1, 10, -1 );
392 createMenu( PropertiesId, fileMenu, 10, -1 );
393 createMenu( separator(), fileMenu, -1, 10, -1 );
395 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
396 createMenu( CatalogGenId, toolsMenu, 10, -1 );
397 createMenu( RegDisplayId, toolsMenu, 10, -1 );
398 createMenu( separator(), toolsMenu, -1, 15, -1 );
400 createExtraActions();
402 #ifndef DISABLE_PYCONSOLE
403 #ifndef DISABLE_SALOMEOBJECT
404 // import Python module that manages SALOME plugins
406 PyLockWrapper lck; // acquire GIL
407 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
408 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
412 // end of SALOME plugins loading
419 \brief Close application.
421 void SalomeApp_Application::onExit()
423 //MessageLocker ml( myToIgnoreMessages );
425 bool killServers = false;
428 if ( exitConfirmation() ) {
429 SalomeApp_ExitDlg dlg( desktop() );
430 result = dlg.exec() == QDialog::Accepted;
431 killServers = dlg.isServersShutdown();
435 if ( !killServers ) myIsCloseFromExit = true;
436 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
437 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
441 /*!SLOT. Create a document.*/
442 void SalomeApp_Application::onNewDoc()
444 MessageLocker ml( myToIgnoreMessages );
446 LightApp_Application::onNewDoc();
449 /*!SLOT. Load document.*/
450 void SalomeApp_Application::onLoadDoc()
452 MessageLocker ml( myToIgnoreMessages );
456 // rnv: According to the single-study approach on the server side
457 // can be only one study. So if it is exists connect to them,
458 // overwise show warning message: "No active study on the server"
461 SUIT_Session* aSession = SUIT_Session::session();
462 QList<SUIT_Application*> aAppList = aSession->applications();
464 QStringList unloadedStudies;
466 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
467 studyName = List[ind].c_str();
468 // Add to list only unloaded studies
469 bool isAlreadyOpen = false;
470 QListIterator<SUIT_Application*> it( aAppList );
471 while ( it.hasNext() && !isAlreadyOpen ) {
472 SUIT_Application* aApp = it.next();
473 if( !aApp || !aApp->activeStudy() )
475 if ( aApp->activeStudy()->studyName() == studyName )
476 isAlreadyOpen = true;
479 if ( !isAlreadyOpen )
480 unloadedStudies << studyName;
482 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
483 if ( studyName.isEmpty() )
488 SUIT_MessageBox::warning( desktop(),
489 QObject::tr("WRN_WARNING"),
490 QObject::tr("WRN_NO_STUDY_ON SERV") );
494 studyName = activeStudy()->studyName();
497 // this code replaces marker of windows drive and path become invalid therefore
498 // defines placed there
499 studyName.replace( QRegExp(":"), "/" );
502 if ( onLoadDoc( studyName ) ) {
504 updateViewManagers();
505 updateObjectBrowser( true );
509 /*!SLOT. Unload document.*/
510 void SalomeApp_Application::onUnloadDoc( bool ask )
513 activeStudy()->abortAllOperations();
514 if ( activeStudy()->isModified() ) {
515 QString docName = activeStudy()->studyName().trimmed();
516 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
517 tr( "DISCONNECT_DESCRIPTION" ),
518 tr( "DISCONNECT_SAVE" ),
519 tr( "DISCONNECT_WO_SAVE" ),
520 tr( "APPCLOSE_CANCEL" ), 0 );
521 if ( answer == 0 ) { // save before unload
522 if ( activeStudy()->isSaved() )
524 else if ( !onSaveAsDoc() )
527 else if ( answer == 2 ) // Cancel
531 closeActiveDoc( false );
534 /*!SLOT. Create new study and load script*/
535 void SalomeApp_Application::onNewWithScript()
537 QStringList filtersList;
538 filtersList.append(tr("PYTHON_FILES_FILTER"));
539 filtersList.append(tr("ALL_FILES_FILTER"));
541 QString anInitialPath = "";
542 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
543 anInitialPath = QDir::currentPath();
545 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
547 if ( !aFile.isEmpty() )
551 #ifndef DISABLE_PYCONSOLE
552 QString command = QString("exec(open(\"%1\", \"rb\").read())").arg(aFile);
553 PyConsole_Console* pyConsole = pythonConsole();
554 PropertyMgr propm( this, "IsLoadedScript", true );
556 pyConsole->exec( command );
562 /*!SLOT. Load document with \a aName.*/
563 bool SalomeApp_Application::onLoadDoc( const QString& aName )
565 if ( !LightApp_Application::closeDoc() )
569 if ( !activeStudy() ) {
570 // if no study - load in current desktop
571 res = useStudy( aName );
574 // if study exists - load in new desktop. Check: is the same file is loaded?
575 SUIT_Session* aSession = SUIT_Session::session();
576 QList<SUIT_Application*> aAppList = aSession->applications();
577 bool isAlreadyOpen = false;
578 SalomeApp_Application* aApp = 0;
579 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
580 it != aAppList.end() && !isAlreadyOpen; ++it ) {
581 aApp = dynamic_cast<SalomeApp_Application*>( *it );
582 if ( aApp && aApp->activeStudy()->studyName() == aName )
583 isAlreadyOpen = true;
585 if ( !isAlreadyOpen ) {
586 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
588 res = aApp->useStudy( aName );
591 aApp->desktop()->activateWindow();
598 /*!SLOT. Parse message for desktop.*/
599 void SalomeApp_Application::onDesktopMessage( const QString& message )
601 if ( myToIgnoreMessages )
602 return; // a message from SALOMEDS is caused by GUI action
604 MessageLocker ml( myToIgnoreMessages );
606 if (message.indexOf("studyCreated") == 0) {
607 if (!activeStudy()) {
609 updateCommandsStatus();
612 if (message.indexOf("studyCleared") == 0) {
613 // Disconnect GUI from active study, because it was closed on DS side.
615 closeActiveDoc( false );
616 // Disable 'Connect' action
617 QAction* a = action( ConnectId );
619 a->setEnabled( false );
622 else if ( message.toLower() == "connect_to_study" ) {
624 useStudy( activeStudy()->studyName() );
626 if (message.indexOf("studyNameChanged") == 0) {
627 updateDesktopTitle();
629 LightApp_Application::onDesktopMessage( message );
632 /*!On module activation action.*/
633 void SalomeApp_Application::onModuleActivation( const QString& modName )
635 if (!activeStudy() && !modName.isEmpty())
638 LightApp_Application::onModuleActivation( modName );
641 /*!SLOT. Copy objects to study maneger from selection maneger..*/
642 void SalomeApp_Application::onCopy()
644 LightApp_Application::onCopy();
647 LightApp_SelectionMgr* mgr = selectionMgr();
648 mgr->selectedObjects(list);
650 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
651 if(study == NULL) return;
653 _PTR(Study) stdDS = getStudy();
656 SALOME_ListIteratorOfListIO it( list );
659 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
664 onSelectionChanged();
672 /*!SLOT. Paste objects to study maneger from selection manager.*/
673 void SalomeApp_Application::onPaste()
675 LightApp_Application::onPaste();
678 LightApp_SelectionMgr* mgr = selectionMgr();
679 mgr->selectedObjects(list);
681 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
682 if(study == NULL) return;
684 _PTR(Study) stdDS = getStudy();
687 if ( stdDS->GetProperties()->IsLocked() ) {
688 SUIT_MessageBox::warning( desktop(),
689 QObject::tr("WRN_WARNING"),
690 QObject::tr("WRN_STUDY_LOCKED") );
694 SALOME_ListIteratorOfListIO it( list );
697 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
702 updateObjectBrowser( true );
703 updateActions(); //SRN: BugID IPAL9377, case 3
711 /*!Check the application on closing.
712 * \retval true if possible, else false
714 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
716 return LightApp_Application::isPossibleToClose( closePermanently );
719 /*! Check if the study is locked */
720 void SalomeApp_Application::onCloseDoc( bool ask )
722 if(getStudy()->IsStudyLocked()) {
723 if ( SUIT_MessageBox::question( desktop(),
724 QObject::tr( "WRN_WARNING" ),
725 QObject::tr( "CLOSE_LOCKED_STUDY" ),
726 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
727 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
730 MessageLocker ml( myToIgnoreMessages );
732 LightApp_Application::onCloseDoc( ask );
734 // reinitialize study to have empty data
735 //getStudy()->Init();
738 /*!SLOT. Reload document from the file.*/
739 bool SalomeApp_Application::onReopenDoc()
741 MessageLocker ml( myToIgnoreMessages );
743 return LightApp_Application::onReopenDoc();
747 /*!SLOT. Load document.*/
748 void SalomeApp_Application::onOpenDoc()
750 MessageLocker ml( myToIgnoreMessages );
752 LightApp_Application::onOpenDoc();
755 /*!SLOT. Load document.*/
756 bool SalomeApp_Application::onOpenDoc(const QString& name)
758 MessageLocker ml( myToIgnoreMessages );
760 return LightApp_Application::onOpenDoc(name);
763 /*!Sets enable or disable some actions on selection changed.*/
764 void SalomeApp_Application::onSelectionChanged()
767 LightApp_SelectionMgr* mgr = selectionMgr();
768 mgr->selectedObjects(list);
770 bool canCopy = false;
771 bool canPaste = false;
773 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
776 canCopy = m->canCopy();
777 canPaste = m->canPaste();
780 SALOME_ListIteratorOfListIO it ( list );
782 if (it.More() && list.Extent() == 1) {
783 _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry());
786 canCopy = canCopy || getStudy()->CanCopy(so);
787 canPaste = canPaste || getStudy()->CanPaste(so);
791 action(EditCopyId)->setEnabled(canCopy);
792 action(EditPasteId)->setEnabled(canPaste);
795 /*!Delete references.*/
796 void SalomeApp_Application::onDeleteInvalidReferences()
799 LightApp_SelectionMgr* mgr = selectionMgr();
800 mgr->selectedObjects( aList, QString(), false );
802 if( aList.IsEmpty() )
805 _PTR(Study) aStudyDS = getStudy();
806 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
809 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
810 if ( it.Value()->hasEntry() )
812 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
813 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
816 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
817 aStudyBuilder->RemoveReference( aSObject );
819 updateObjectBrowser();
823 void SalomeApp_Application::onOpenWith()
825 QApplication::setOverrideCursor( Qt::WaitCursor );
827 LightApp_SelectionMgr* mgr = selectionMgr();
828 mgr->selectedObjects(aList);
829 if (aList.Extent() != 1)
831 QApplication::restoreOverrideCursor();
834 Handle(SALOME_InteractiveObject) aIObj = aList.First();
835 QString aModuleName(aIObj->getComponentDataType());
836 QString aModuleTitle = moduleTitle(aModuleName);
837 if (aModuleTitle.isEmpty()) // no gui
838 aModuleTitle = moduleDisplayer(aModuleName);
839 activateModule(aModuleTitle);
840 QApplication::restoreOverrideCursor();
846 SUIT_Study* SalomeApp_Application::createNewStudy()
848 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
850 // Set up processing of major study-related events
851 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
852 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
853 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
854 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
856 #ifndef DISABLE_PYCONSOLE
857 //to receive signal in application that NoteBook's variable was modified
858 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
859 this, SIGNAL(notebookVarUpdated(QString)) );
868 Enable/Disable menu items and toolbar buttons. Rebuild menu
870 void SalomeApp_Application::updateCommandsStatus()
872 LightApp_Application::updateCommandsStatus();
875 QAction* a = action( DumpStudyId );
877 a->setEnabled( activeStudy() );
879 #ifndef DISABLE_PYCONSOLE
881 a = action( LoadScriptId );
883 a->setEnabled( pythonConsole() );
887 a = action( PropertiesId );
889 a->setEnabled( activeStudy() );
891 // Save GUI state menu
892 a = action( SaveGUIStateId );
894 a->setEnabled( activeStudy() );
896 // Connect study menu
897 a = action( ConnectId );
899 a->setEnabled( !activeStudy() );
901 // Disconnect study menu
902 a = action( DisconnectId );
904 a->setEnabled( activeStudy() );
906 // update state of Copy/Paste menu items
907 onSelectionChanged();
911 \class DumpStudyFileDlg
912 Private class used in Dump Study operation. Consists 2 check boxes:
913 "Publish in study" and "Save GUI parameters"
915 class DumpStudyFileDlg : public SUIT_FileDlg
918 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
920 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
923 QWidget *hB = new QWidget( this );
924 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
925 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
926 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
928 QHBoxLayout *layout = new QHBoxLayout;
929 layout->addWidget(myPublishChk);
930 layout->addWidget(myMultiFileChk);
931 layout->addWidget(mySaveGUIChk);
932 hB->setLayout(layout);
934 QPushButton* pb = new QPushButton(this);
936 int row = grid->rowCount();
937 grid->addWidget( new QLabel("", this), row, 0 );
938 grid->addWidget( hB, row, 1, 1, 3 );
939 grid->addWidget( pb, row, 5 );
944 QCheckBox* myPublishChk;
945 QCheckBox* myMultiFileChk;
946 QCheckBox* mySaveGUIChk;
949 /*!Private SLOT. On dump study.*/
950 void SalomeApp_Application::onDumpStudy( )
952 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
953 if ( !appStudy ) return;
955 QStringList aFilters;
956 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
958 bool anIsPublish = true;
959 bool anIsMultiFile = false;
960 bool anIsSaveGUI = true;
962 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
963 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
964 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
965 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
968 DumpStudyFileDlg fd( desktop() );
969 fd.setValidator( new LightApp_PyFileValidator( &fd ) );
970 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
971 fd.setNameFilters( aFilters );
972 fd.myPublishChk->setChecked( anIsPublish );
973 fd.myMultiFileChk->setChecked( anIsMultiFile );
974 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
975 if ( fd.exec() == QDialog::Accepted )
977 QString aFileName = fd.selectedFile();
979 bool toPublish = fd.myPublishChk->isChecked();
980 bool isMultiFile = fd.myMultiFileChk->isChecked();
981 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
983 if ( !aFileName.isEmpty() ) {
984 QFileInfo aFileInfo(aFileName);
985 if( aFileInfo.isDir() ) // IPAL19257
988 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
991 SUIT_OverrideCursor wc;
992 ensureShaperIsActivated();
993 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
996 SUIT_MessageBox::warning( desktop(),
997 QObject::tr("WRN_WARNING"),
998 tr("WRN_DUMP_STUDY_FAILED") );
1003 /*!Private SLOT. On load script.*/
1004 void SalomeApp_Application::onLoadScript( )
1006 if ( getStudy()->GetProperties()->IsLocked() ) {
1007 SUIT_MessageBox::warning( desktop(),
1008 QObject::tr("WRN_WARNING"),
1009 QObject::tr("WRN_STUDY_LOCKED") );
1013 QStringList filtersList;
1014 filtersList.append(tr("PYTHON_FILES_FILTER"));
1015 filtersList.append(tr("ALL_FILES_FILTER"));
1017 QString anInitialPath = "";
1018 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
1019 anInitialPath = QDir::currentPath();
1021 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
1023 if ( !aFile.isEmpty() )
1025 #ifndef DISABLE_PYCONSOLE
1026 QString command = QString("exec(compile(open('%1', 'rb').read(), '%1', 'exec'))").arg(aFile);
1027 PyConsole_Console* pyConsole = pythonConsole();
1028 PropertyMgr propm( this, "IsLoadedScript", true );
1030 pyConsole->exec(command);
1035 /*!Private SLOT. On save GUI state.*/
1036 void SalomeApp_Application::onSaveGUIState()
1038 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1040 SalomeApp_VisualState( this ).storeState();
1041 updateSavePointDataObjects( study );
1042 updateObjectBrowser();
1047 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1048 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1050 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1051 QAction* send = ::qobject_cast<QAction*>( sender() );
1054 QString aWinName = send->data().toString();
1055 if ( theIsVisible && aWinName == "objectBrowser" )
1056 objectBrowserColumnsVisibility();
1060 QWidget* SalomeApp_Application::createWindow( const int flag )
1063 #ifndef DISABLE_PYCONSOLE
1064 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1066 wid = LightApp_Application::createWindow(flag);
1069 SUIT_ResourceMgr* resMgr = resourceMgr();
1071 if ( flag == WT_ObjectBrowser )
1073 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1075 // temporary commented
1076 //ob->setUpdater( new SalomeApp_Updater() );
1078 #ifdef WITH_SALOMEDS_OBSERVER
1079 //do not activate the automatic update of Qt tree through signal/slot
1080 ob->setAutoUpdate(false);
1081 //activate update of modified objects only
1082 ob->setUpdateModified(true);
1085 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1088 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1089 IORCol = QObject::tr( "IOR_COLUMN" ),
1090 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1091 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1093 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1094 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1095 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1096 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1097 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1098 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1099 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1100 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1101 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1103 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1104 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1105 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1107 ob->setAutoSizeFirstColumn(autoSizeFirst);
1108 ob->setAutoSizeColumns(autoSize);
1109 ob->setResizeOnExpandItem(resizeOnExpandItem);
1110 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1112 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1114 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1115 ob->treeView()->setColumnHidden( i, !shown );
1118 // temporary commented
1120 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1122 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1123 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1124 QString().sprintf( "visibility_column_%d", i ), true ) );
1128 // temporary commented
1130 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1131 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1132 ob->resize( desktop()->width()/3, ob->height() );
1136 #ifndef DISABLE_PYCONSOLE
1137 else if ( flag == WT_PyConsole )
1139 PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
1140 pyCons->setObjectName( "pythonConsole" );
1141 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1142 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1143 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1144 pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
1145 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1148 else if ( flag == WT_NoteBook )
1150 setNoteBook( new SalomeApp_NoteBook( desktop() ) );
1151 //to receive signal in NoteBook that it's variable was modified
1152 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1153 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1155 wid = getNoteBook();
1156 wid->setObjectName( "noteBook" );
1162 /*!Create preferences.*/
1163 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1165 LightApp_Application::createPreferences(pref);
1170 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1171 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1172 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1173 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1175 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1176 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1178 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1180 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1181 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1182 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1183 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1184 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1185 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1186 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1187 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1188 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1189 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1192 /*!Update desktop title.*/
1193 void SalomeApp_Application::updateDesktopTitle() {
1194 QString aTitle = applicationName();
1195 QString aVer = applicationVersion();
1196 if ( !aVer.isEmpty() )
1197 aTitle += QString( " " ) + aVer;
1199 if ( activeStudy() )
1201 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1202 if ( !sName.isEmpty() ) {
1203 if ( getStudy()->GetProperties()->IsLocked() ) {
1204 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1206 aTitle += QString( " - [%1]" ).arg( sName );
1211 desktop()->setWindowTitle( aTitle );
1214 int SalomeApp_Application::closeChoice( const QString& /*docName*/ )
1216 QStringList buttons;
1217 QMap<int, int> choices;
1219 buttons << tr ("APPCLOSE_SAVE"); // Save & Clear
1220 choices.insert( idx++, CloseSave ); // ...
1221 buttons << tr ("APPCLOSE_CLOSE"); // Clear w/o saving
1222 choices.insert( idx++, CloseDiscard ); // ...
1223 if ( myIsCloseFromExit ) {
1224 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1225 choices.insert( idx++, CloseDisconnectSave ); // ...
1226 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1227 choices.insert( idx++, CloseDisconnect ); // ...
1229 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1230 choices.insert( idx++, CloseCancel ); // ...
1232 if( !activeStudy()->isModified() )
1234 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1235 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1236 return choices[answer];
1239 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1245 if ( activeStudy()->isSaved() )
1247 else if ( !onSaveAsDoc() )
1252 case CloseDisconnectSave:
1253 if ( activeStudy()->isSaved() )
1255 else if ( !onSaveAsDoc() )
1258 case CloseDisconnect:
1259 closeActiveDoc( false );
1260 closePermanently = false;
1269 int SalomeApp_Application::openChoice( const QString& aName )
1271 int choice = LightApp_Application::openChoice( aName );
1273 if ( QFileInfo( aName ).exists() ) {
1274 if ( choice == OpenNew ) { // The document isn't already open.
1276 if ( aName == getStudy()->Name().c_str() )
1278 // The document already exists in the study.
1279 // Do you want to reload it?
1281 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1282 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1283 if ( answer == SUIT_MessageBox::Yes )
1284 choice = OpenRefresh;
1286 choice = OpenCancel;
1289 } else { // file is not exist on disk
1290 SUIT_MessageBox::warning( desktop(),
1291 QObject::tr("WRN_WARNING"),
1292 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toUtf8().data()));
1299 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1302 int choice = aChoice;
1309 res = LightApp_Application::openAction( choice, aName );
1317 \brief Get map of the operations which can be performed
1318 on the module activation.
1320 The method should return the map of the kind \c {<id>:<name>}
1321 where \c <id> is an integer identifier of the operation and
1322 \c <name> is a title for the button to be added to the
1323 dialog box. After user selects the required operation by the
1324 clicking the corresponding button in the dialog box, its identifier
1325 is passed to the moduleActionSelected() method to process
1328 \return map of the operations
1329 \sa moduleActionSelected()
1331 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1333 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1335 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1337 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1342 \brief Called when the used selectes required operation chosen
1343 from "Activate module" dialog box.
1345 Performs the required operation according to the user choice.
1347 \param id operation identifier
1348 \sa activateModuleActions()
1350 void SalomeApp_Application::moduleActionSelected( const int id )
1356 case NewAndScriptId:
1360 LightApp_Application::moduleActionSelected( id );
1365 /*!Gets CORBA::ORB_var*/
1366 CORBA::ORB_var SalomeApp_Application::orb()
1368 static CORBA::ORB_var _orb;
1370 if ( CORBA::is_nil( _orb ) ) {
1371 Qtx::CmdLineArgs args;
1372 SetArgcArgv( args.argc(), args.argv() );
1373 _orb = KERNEL::GetRefToORB();
1379 /*!Create and return SALOMEDS_Study.*/
1380 _PTR(Study) SalomeApp_Application::getStudy()
1382 static _PTR(Study) _study;
1384 CORBA::Object_var aSObject = namingService()->Resolve("/Study");
1385 SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(aSObject);
1386 _study = ClientFactory::Study(aStudy);
1391 /*!Create and return SALOME_NamingService.*/
1392 SALOME_NamingService_Abstract *SalomeApp_Application::namingService()
1397 /*!Create and return SALOME_LifeCycleCORBA.*/
1398 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1400 static SALOME_LifeCycleCORBA _lcc( namingService() );
1404 /*!Private SLOT. On preferences.*/
1405 void SalomeApp_Application::onProperties()
1407 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1411 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1414 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1415 int res = aDlg.exec();
1416 if( res==QDialog::Accepted && aDlg.isChanged() )
1417 SB->CommitCommand();
1421 //study->updateCaptions();
1422 updateDesktopTitle();
1426 /*!Insert items in popup, which necessary for current application*/
1427 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1429 LightApp_SelectionMgr* mgr = selectionMgr();
1430 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1431 mgr->setSelectionCacheEnabled( true );
1433 LightApp_Application::contextMenuPopup( type, thePopup, title );
1435 // temporary commented
1436 /*OB_Browser* ob = objectBrowser();
1437 if ( !ob || type != ob->popupClientType() )
1440 // Get selected objects
1441 SALOME_ListIO aList;
1442 mgr->selectedObjects( aList, QString(), false );
1444 // add GUI state commands: restore, rename
1445 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1446 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1447 thePopup->addSeparator();
1448 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1449 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1450 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1451 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1454 // "Delete reference" item should appear only for invalid references
1456 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1457 bool isInvalidRefs = false;
1459 _PTR(SObject) anObj;
1460 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1462 if( it.Value()->hasEntry() )
1464 _PTR(SObject) aSObject = getStudy()->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1465 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1468 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1469 isInvalidRefs = true;
1473 // Add "Delete reference" item to popup
1474 if ( isInvalidRefs )
1476 thePopup->addSeparator();
1477 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1481 // "Activate module" item should appear only if it's necessary
1482 if ( aList.Extent() == 1 ) {
1484 mgr->selectedObjects( aList );
1486 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1488 // add extra popup menu (defined in XML)
1489 if ( myExtActions.size() > 0 ) {
1490 // Use only first selected object
1491 _PTR(SObject) aSO = getStudy()->FindObjectID( aIObj->getEntry() );
1493 _PTR( GenericAttribute ) anAttr;
1494 std::string auid = "AttributeUserID";
1495 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1496 if ( aSO->FindAttribute( anAttr, auid ) ) {
1497 _PTR(AttributeUserID) aAttrID = anAttr;
1498 QString aId = aAttrID->Value().c_str();
1499 if ( myExtActions.contains( aId ) ) {
1500 thePopup->addAction(myExtActions[aId]);
1506 // check if item is a "GUI state" item (also a first level object)
1507 QString entry( aIObj->getEntry() );
1508 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1509 QString aModuleName( aIObj->getComponentDataType() );
1510 QString aModuleTitle = moduleTitle( aModuleName );
1511 if (aModuleTitle.isEmpty()) {
1512 // use displayer module, if given
1513 aModuleTitle = moduleDisplayer( aModuleName );
1515 CAM_Module* currentModule = activeModule();
1516 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) {
1517 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1522 mgr->setSelectionCacheEnabled( cacheIsOn );
1525 /*!Update obect browser:
1526 1.if 'updateModels' true, update existing data models;
1527 2. update "non-existing" (not loaded yet) data models;
1528 3. update object browser if it exists */
1529 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1531 // update "non-existing" (not loaded yet) data models
1532 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1535 for ( _PTR(SComponentIterator) it ( getStudy()->NewComponentIterator() ); it->More(); it->Next() )
1537 _PTR(SComponent) aComponent ( it->Value() );
1539 #ifndef WITH_SALOMEDS_OBSERVER
1540 // with GUI observers this check is not needed anymore
1541 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1542 continue; // skip the magic "Interface Applicative" component
1544 if ( !objectBrowser() )
1545 getWindow( WT_ObjectBrowser );
1546 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1547 objectBrowser()->setAutoUpdate( false );
1548 SalomeApp_DataModel::synchronize( aComponent, study );
1549 objectBrowser()->setAutoUpdate( isAutoUpdate );
1553 // create data objects that correspond to GUI state save points
1554 if ( study ) updateSavePointDataObjects( study );
1556 // update existing data models (already loaded SComponents)
1557 LightApp_Application::updateObjectBrowser( updateModels );
1560 /*!Display Catalog Genenerator dialog */
1561 void SalomeApp_Application::onCatalogGen()
1563 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1567 /*!Display Registry Display dialog */
1568 void SalomeApp_Application::onRegDisplay()
1570 CORBA::ORB_var anOrb = orb();
1571 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1574 regWnd->activateWindow();
1577 /*!find original object by double click on item */
1578 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1580 // Issue 21379: References are supported at LightApp_DataObject level
1581 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1583 if( obj && obj->isReference() )
1585 QString entry = obj->refEntry();
1587 SUIT_DataOwnerPtrList aList;
1588 aList.append( new LightApp_DataOwner( entry ) );
1589 selectionMgr()->setSelected( aList, false );
1591 SUIT_DataBrowser* ob = objectBrowser();
1593 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1594 if ( !aSelectedIndexes.isEmpty() )
1595 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1597 emit objectDoubleClicked( theObj );
1601 Creates new view manager
1602 \param type - type of view manager
1604 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1606 return createViewManager(type);
1610 /*!Global utility function, returns selected GUI Save point object's ID */
1611 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1613 SALOME_ListIO aList;
1614 selMgr->selectedObjects( aList );
1615 if( aList.Extent() > 0 ) {
1616 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1617 QString entry( aIObj->getEntry() );
1618 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1619 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1621 bool ok; // conversion to integer is ok?
1622 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1623 return ok ? savePoint : -1;
1628 /*!Called on Restore GUI State popup command*/
1629 void SalomeApp_Application::onRestoreGUIState()
1631 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1632 if ( savePoint == -1 )
1634 SalomeApp_VisualState( this ).restoreState( savePoint );
1637 /*!Called on Delete GUI State popup command*/
1638 void SalomeApp_Application::onDeleteGUIState()
1640 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1641 if ( savePoint == -1 )
1643 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1647 study->removeSavePoint( savePoint );
1648 updateSavePointDataObjects( study );
1651 /*!Called on New study operation*/
1652 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1654 LightApp_Application::onStudyCreated( study );
1656 //#ifndef DISABLE_PYCONSOLE
1657 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1658 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1661 loadDockWindowsState();
1663 objectBrowserColumnsVisibility();
1666 /*!Called on Open study operation*/
1667 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1669 LightApp_Application::onStudyOpened( study );
1671 //#ifndef DISABLE_PYCONSOLE
1672 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1673 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1676 loadDockWindowsState();
1678 objectBrowserColumnsVisibility();
1680 // temporary commented
1681 /*if ( objectBrowser() ) {
1682 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1683 objectBrowser()->updateTree( study->root() );
1687 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1688 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1691 SUIT_DataBrowser* ob = objectBrowser();
1692 LightApp_SelectionMgr* selMgr = selectionMgr();
1694 if ( !study || !ob || !selMgr )
1697 // find GUI states root object
1698 SUIT_DataObject* guiRootObj = 0;
1700 study->root()->children( ch );
1701 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1702 for ( ; it != last ; ++it ) {
1703 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1708 std::vector<int> savePoints = study->getSavePoints();
1709 // case 1: no more save points but they existed in study's tree
1710 if ( savePoints.empty() && guiRootObj ) {
1711 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1712 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1713 const bool isAutoUpdate = ob->autoUpdate();
1714 selMgr->clearSelected();
1715 ob->setAutoUpdate(true);
1716 DataObjectList ch = guiRootObj->children();
1717 for( int i = 0; i < ch.size(); i++ )
1720 ob->setAutoUpdate(isAutoUpdate);
1723 // case 2: no more save points but root does not exist either
1724 if ( savePoints.empty() && !guiRootObj )
1726 // case 3: save points but no root for them - create it
1727 if ( !savePoints.empty() && !guiRootObj )
1728 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1729 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1730 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1732 if ( guiRootObj->nextBrother() ) {
1733 study->root()->removeChild(guiRootObj);
1734 study->root()->appendChild(guiRootObj);
1735 //study->root()->dump();
1738 // store data objects in a map id-to-DataObject
1739 QMap<int,SalomeApp_SavePointObject*> mapDO;
1741 guiRootObj->children( ch );
1742 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1743 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1745 mapDO[dobj->getId()] = dobj;
1748 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1749 // if in the map - remove it from map.
1750 for ( size_t i = 0; i < savePoints.size(); i++ )
1751 if ( !mapDO.contains( savePoints[i] ) )
1752 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1754 mapDO.remove( savePoints[i] );
1756 // delete DataObjects that are still in the map -- their IDs were not found in data model
1757 if( mapDO.size() > 0) {
1758 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1759 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1760 selMgr->clearSelected();
1761 const bool isAutoUpdate = ob->autoUpdate();
1762 ob->setAutoUpdate(true);
1763 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1765 ob->setAutoUpdate(isAutoUpdate);
1769 /*! Check data object */
1770 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1779 Opens other study into active Study. If Study is empty - creates it.
1780 \param theName - name of study
1782 bool SalomeApp_Application::useStudy( const QString& theName )
1785 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1788 res = aStudy->loadDocument( theName );
1789 updateDesktopTitle();
1790 updateCommandsStatus();
1794 /*! Show/hide object browser colums according to preferences */
1795 void SalomeApp_Application::objectBrowserColumnsVisibility()
1797 if ( objectBrowser() )
1798 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1800 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1801 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1805 #ifndef DISABLE_PYCONSOLE
1806 /*! Set SalomeApp_NoteBook pointer */
1807 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1809 myNoteBook = theNoteBook;
1812 /*! Return SalomeApp_NoteBook pointer */
1813 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1820 * Define extra actions defined in module definition XML file.
1821 * Additional popup items sections can be defined by parameter "popupitems".
1822 * Supported attributes:
1823 * title - title of menu item,
1824 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1825 * method - method which has to be called when menu item is selected
1827 * <section name="MODULENAME">
1828 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1830 * <section name="importmed">
1831 * <parameter name="title" value="My menu"/>
1832 * <parameter name="objectid" value="VISU.Result"/>
1833 * <parameter name="method" value="nameOfModuleMethod"/>
1836 void SalomeApp_Application::createExtraActions()
1838 myExtActions.clear();
1839 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1841 QStringList aModules;
1842 modules(aModules, false);
1843 foreach(QString aModile, aModules) {
1844 QString aModName = moduleName(aModile);
1845 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1846 if (!aSectionStr.isNull()) {
1847 QStringList aSections = aSectionStr.split(':');
1848 foreach(QString aSection, aSections) {
1849 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1850 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1851 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1852 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1855 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1856 if (aModuleName.isNull())
1857 aModuleName = aModName;
1859 QAction* aAction = new QAction(aTitle, this);
1861 aData<<aModuleName<<aSlot;
1862 aAction->setData(aData);
1863 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1864 myExtActions[aId] = aAction;
1871 * Called when extra action is selected
1873 void SalomeApp_Application::onExtAction()
1875 QAction* aAction = ::qobject_cast<QAction*>(sender());
1879 QVariant aData = aAction->data();
1880 QStringList aDataList = aData.value<QStringList>();
1881 if (aDataList.size() != 2)
1884 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1885 SALOME_ListIO aListIO;
1886 aSelectionMgr->selectedObjects(aListIO);
1887 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1888 if (aListIO.Extent() < 1)
1890 if (!anIO->hasEntry())
1893 QString aEntry(anIO->getEntry());
1895 QApplication::setOverrideCursor( Qt::WaitCursor );
1896 QString aModuleTitle = moduleTitle(aDataList[0]);
1897 activateModule(aModuleTitle);
1898 QApplication::restoreOverrideCursor();
1900 QCoreApplication::processEvents();
1902 CAM_Module* aModule = activeModule();
1906 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1907 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1911 Checks that an object can be renamed.
1912 \param entry entry of the object
1913 \brief Return \c true if object can be renamed
1915 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1917 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1921 Rename object by entry.
1922 \param entry entry of the object
1923 \param name new name of the object
1924 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1926 bool SalomeApp_Application::renameObject( const QString& /*entry*/, const QString& name )
1928 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1930 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1932 if(!aStudy || savePoint == -1)
1935 if ( !name.isNull() && !name.isEmpty() ) {
1936 aStudy->setNameOfSavePoint( savePoint, name );
1937 updateSavePointDataObjects( aStudy );
1939 //Mark study as modified
1946 #ifndef DISABLE_PYCONSOLE
1947 //============================================================================
1948 /*! Function : onUpdateStudy
1949 * Purpose : Slot to update the study.
1951 //============================================================================
1952 void SalomeApp_Application::onUpdateStudy()
1954 QApplication::setOverrideCursor( Qt::WaitCursor );
1956 if( !updateStudy() )
1957 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1959 QApplication::restoreOverrideCursor();
1962 //============================================================================
1963 /*! Function : updateStudy
1964 * Purpose : Update study by dumping the study to Python script and loading it.
1965 * It is used to apply variable modifications done in NoteBook to created objects.
1967 //============================================================================
1968 bool SalomeApp_Application::updateStudy()
1970 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1971 if ( !study || !myNoteBook )
1974 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1975 myNoteBook->setDumpedStudyName( study->studyName() );
1977 // get unique temporary directory name
1978 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1980 if( aTmpDir.isEmpty() )
1983 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1984 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1986 // dump study to the temporary directory
1987 QString aScriptName( "notebook" );
1988 bool toPublish = true;
1989 bool isMultiFile = false;
1990 bool toSaveGUI = true;
1993 _PTR(AttributeParameter) ap;
1994 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1995 if(ip->isDumpPython()) ip->setDumpPython(); //Unset DumpPython flag.
1996 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1997 ip->setDumpPython();
1998 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2000 bool ok = getStudy()->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2002 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2005 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2009 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2010 int anIndex = aList.indexOf( this );
2012 // Disconnect dialog from application desktop in case if:
2013 // 1) Application is not the first application in the session
2014 // 2) Application is the first application in session but not the only.
2015 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2016 if( changeDesktop ) {
2018 SalomeApp_Application* app = this;
2019 if( anIndex > 0 && anIndex < aList.count() )
2020 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2021 else if(anIndex == 0 && aList.count() > 1)
2022 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2027 // creation a new study and restoring will be done in another application
2028 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2029 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2032 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2033 QString aStudyName = myNoteBook->getDumpedStudyName();
2034 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2035 // clear a study (delete all objects)
2036 onCloseDoc( false );
2038 if( !changeDesktop ) {
2039 ok = onRestoreStudy( aDumpScript,
2048 //============================================================================
2049 /*! Function : onRestoreStudy
2050 * Purpose : Load the dumped study from Python script
2052 //============================================================================
2053 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2054 const QString& theStudyName,
2055 bool theIsStudySaved )
2059 // create a new study
2062 // get active application
2063 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2065 // load study from the temporary directory
2066 QFileInfo aScriptInfo = QFileInfo(theDumpScript);
2067 QString command = QString( "exec(open(\"%1\" ,\"rb\").read())" ).arg(aScriptInfo.canonicalFilePath());
2069 #ifndef DISABLE_PYCONSOLE
2070 PyConsole_Console* pyConsole = app->pythonConsole();
2072 PropertyMgr propm( this, "IsLoadedScript", true );
2073 pyConsole->execAndWait( command );
2077 // remove temporary directory
2078 QString aStudyName = aScriptInfo.baseName();
2079 QDir aDir = aScriptInfo.absoluteDir();
2080 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2081 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2082 ok = aDir.remove( *it ) && ok;
2084 ok = aDir.rmdir( aDir.absolutePath() );
2086 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2088 #ifndef DISABLE_PYCONSOLE
2089 if ( app->getNoteBook() )
2090 app->getNoteBook()->Init();
2091 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2092 newStudy->Modified();
2093 updateDesktopTitle();
2104 Close the Application
2106 void SalomeApp_Application::afterCloseDoc()
2108 #ifndef DISABLE_PYCONSOLE
2109 // emit signal to restore study from Python script
2111 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2112 myNoteBook->getDumpedStudyName(),
2113 myNoteBook->isDumpedStudySaved() );
2116 LightApp_Application::afterCloseDoc();
2119 bool SalomeApp_Application::canOpenDoc( const QString& url )
2121 _PTR(Study) aStudyDS = getStudy();
2123 return aStudyDS->CanOpen( url.toUtf8().data() );
2128 Asks to close existing document.
2130 bool SalomeApp_Application::checkExistingDoc()
2132 return LightApp_Application::checkExistingDoc();
2136 #ifndef DISABLE_PYCONSOLE
2138 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2140 return new SalomeApp_PyInterp( resourceMgr() );
2143 #endif // DISABLE_PYCONSOLE
2145 void SalomeApp_Application::ensureShaperIsActivated()
2147 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
2148 _PTR(Study) studyDS = getStudy();
2149 if ( study && studyDS )
2151 _PTR(SObject) shaper = studyDS->FindObjectByPath("/Shaper"); // non null result if shaper data is present in the study
2152 bool shaperIsActive = false;
2153 QList<CAM_DataModel*> models;
2154 study->dataModels( models );
2155 for( int i = 0; i < models.count() && !shaperIsActive; i++ )
2156 shaperIsActive = models[i]->module()->moduleName() == "Shaper";
2158 if (shaper && !shaperIsActive)
2159 onDesktopMessage("register_module_in_study/Shaper");
2163 void SalomeApp_Application::addCatalogue( const QString& moduleName, const QString& catalogue )
2165 CORBA::Object_var obj = namingService()->Resolve( "/Kernel/ModulCatalog" );
2166 SALOME_ModuleCatalog::ModuleCatalog_var moduleCatalogue = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
2167 QFileInfo fi( catalogue );
2168 if ( !CORBA::is_nil( moduleCatalogue ) && fi.isFile() )
2170 SALOME_ModuleCatalog::ListOfComponents_var known = moduleCatalogue->GetComponentList();
2171 bool loaded = false;
2172 for ( int i = 0; i < (int)known->length() && !loaded; i++ )
2173 loaded = QString( known[i].in() ) == moduleName;
2175 moduleCatalogue->ImportXmlCatalogFile( catalogue.toUtf8().constData() );