1 // Copyright (C) 2007-2024 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
38 #ifndef DISABLE_PYCONSOLE
39 #include "SalomeApp_PyInterp.h"
40 #include "SalomeApp_NoteBook.h"
41 #include "LightApp_PyEditor.h"
42 #include "PyConsole_Console.h"
44 #include "SalomeApp_Application.h"
45 #include "SalomeApp_Study.h"
46 #include "SalomeApp_DataModel.h"
47 #include "SalomeApp_DataObject.h"
48 #include "SalomeApp_VisualState.h"
49 #include "SalomeApp_StudyPropertiesDlg.h"
50 #include "SalomeApp_LoadStudiesDlg.h"
51 #include "SalomeApp_ExitDlg.h"
53 #include <LightApp_Application.h>
54 #include <LightApp_FileValidator.h>
55 #include <LightApp_Module.h>
56 #include <LightApp_Preferences.h>
57 #include <LightApp_SelectionMgr.h>
58 #include <LightApp_NameDlg.h>
59 #include <LightApp_DataOwner.h>
61 #include <CAM_Module.h>
63 #include <SUIT_Tools.h>
64 #include <SUIT_Session.h>
65 #include <SUIT_Desktop.h>
66 #include <SUIT_DataBrowser.h>
67 #include <SUIT_FileDlg.h>
68 #include <SUIT_MessageBox.h>
69 #include <SUIT_ResourceMgr.h>
70 #include <SUIT_TreeModel.h>
71 #include <SUIT_ViewWindow.h>
72 #include <SUIT_ViewManager.h>
73 #include <SUIT_ViewModel.h>
74 #include <SUIT_OverrideCursor.h>
76 #include <QtxTreeView.h>
78 #include <SALOME_EventFilter.h>
80 // temporary commented
81 //#include <OB_ListItem.h>
84 #include <SALOME_LifeCycleCORBA.hxx>
86 #include <QApplication>
91 #include <QPushButton>
93 #include <QListWidget>
94 #include <QGridLayout>
98 #include <SALOMEDSClient_ClientFactory.hxx>
99 #include <ArgvKeeper.hxx>
100 #include <Basics_Utils.hxx>
101 #include <OpUtil.hxx>
103 #include <SALOME_ListIO.hxx>
104 #include <SALOME_Prs.h>
107 #include <ToolsGUI_CatalogGeneratorDlg.h>
108 #include <ToolsGUI_RegWidget.h>
112 #include <SALOMEDS_Tool.hxx>
114 #include <SALOMEconfig.h>
115 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
117 std::unique_ptr<SALOME_NamingService_Abstract> SalomeApp_Application::_ns;
119 /*!Internal class that updates object browser item properties */
120 // temporary commented
121 /*class SalomeApp_Updater : public OB_Updater
124 SalomeApp_Updater() : OB_Updater(){};
125 virtual ~SalomeApp_Updater(){};
126 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
129 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
131 if( !theObj || !theItem )
134 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
138 _PTR(SObject) SObj = SAObj->object();
141 _PTR( GenericAttribute ) anAttr;
144 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
146 _PTR(AttributeSelectable) aAttrSel = anAttr;
147 theItem->setSelectable( aAttrSel->IsSelectable() );
150 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
152 _PTR(AttributeExpandable) aAttrExpand = anAttr;
153 theItem->setExpandable( aAttrExpand->IsExpandable() );
156 //this attribute is not supported in the version of SALOME 3.x
157 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
159 // _PTR(AttributeOpened) aAttrOpen = anAttr;
160 // theItem->setOpen( aAttrOpen->IsOpened() );
172 //! Constructor. Sets passed boolean flag to \c true.
173 MessageLocker( bool& Lock ) : myPrevState( Lock ), myLock( Lock ) { myLock = true; }
174 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
175 ~MessageLocker() { myLock = myPrevState; }
178 bool& myLock; //! External 'Lock state' boolean flag
182 \brief Dynamic property manager
189 PropertyMgr(QObject* object, const QString& property, const QVariant& value)
190 : myObject(object), myProperty(property)
192 myObject->setProperty(qPrintable(myProperty), value);
196 myObject->setProperty(qPrintable(myProperty), QVariant());
202 SalomeApp_Application::SalomeApp_Application(SALOME_NamingService_Abstract *ns):myIsCloseFromExit( false ),myToIgnoreMessages( false )
205 _ns.reset(new SALOME_NamingService(orb()));
211 *\li Destroy event filter.
213 SalomeApp_Application::~SalomeApp_Application()
215 // Do not destroy. It's a singleton !
216 //SALOME_EventFilter::Destroy();
219 QStringList __getArgsList(QString argsString)
221 // Special process if some items of 'args:' list are themselves lists
222 // Note that an item can be a list, but not a list of lists...
223 // So we can have something like this:
224 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
225 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
226 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
227 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
228 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
230 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
235 return argsString.split(",", QString::SkipEmptyParts);
238 /*!Start application.*/
239 void SalomeApp_Application::start()
241 // process the command line options before start: to createActions in accordance to the options
242 static bool isFirst = true;
249 QStringList args = QApplication::arguments();
250 for (int i = 1; i < args.count(); i++) {
251 QRegExp rxs ("--study-hdf=(.+)");
252 if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
253 QString file = rxs.capturedTexts()[1];
254 QFileInfo fi ( file );
255 QString extension = fi.suffix().toLower();
256 if ( extension == "hdf" && fi.exists() )
257 hdffile = fi.absoluteFilePath();
260 QRegExp rxp ("--pyscript=\\[(.+)\\]");
261 if ( rxp.indexIn( args[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
263 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
264 for (int k = 0; k < dictList.count(); ++k) {
265 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
266 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
267 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
268 pyfiles += rxd.capturedTexts()[m];
275 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
276 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
278 LightApp_Application::start();
279 SALOME_EventFilter::Init();
281 if ( !hdffile.isEmpty() )
283 // open hdf file given as parameter
284 PropertyMgr propm( this, "open_study_from_command_line", true );
285 onOpenDoc( hdffile );
288 #ifndef DISABLE_PYCONSOLE
289 // import/execute python scripts
290 if ( pyfiles.count() > 0 && activeStudy() ) {
291 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
292 PyConsole_Console* pyConsole = pythonConsole();
293 if ( appStudy && pyConsole ) {
294 if ( !getStudy()->GetProperties()->IsLocked() ) {
295 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
296 // Path is absolute, script has .py extension
297 for (int j = 0; j < pyfiles.count(); j++ ) {
298 // Extract scripts and their arguments, if any
299 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
300 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
301 QString script = rxp.capturedTexts()[1];
303 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
304 for (int k = 0; k < argList.count(); k++ ) {
305 QString arg = argList[k].trimmed();
306 arg.remove( QRegExp("^[\"]") );
307 arg.remove( QRegExp("[\"]$") );
308 args << QString("\"%1\"").arg(arg);
310 if (args.count() == 1)
313 script.remove( QRegExp("^python.*[\\s]+") );
314 QString command = QString( "exec(open(\"%1\", \"rb\").read(), args=(%2))" ).arg(script).arg(args.join(","));
315 PropertyMgr propm( this, "IsLoadedScript", true );
316 pyConsole->exec(command);
318 } // end for loop on pyfiles QStringList
324 LightApp_Application::start();
325 SALOME_EventFilter::Init();
330 void SalomeApp_Application::createActions()
332 LightApp_Application::createActions();
334 SUIT_Desktop* desk = desktop();
337 // "Save GUI State" command is moved to VISU module
338 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
339 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
340 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
343 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
344 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
345 QKeySequence::UnknownKey, desk, false, this, SLOT( onDumpStudy() ), "/PRP_DESK_FILE_DUMP_STUDY" );
348 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
349 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
350 QKeySequence::UnknownKey, desk, false, this, SLOT( onLoadScript() ), "/PRP_DESK_FILE_LOAD_SCRIPT" );
353 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
354 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
355 0, desk, false, this, SLOT( onProperties() ) );
357 //! Catalog Generator
358 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
359 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
360 QKeySequence::UnknownKey, desk, false, this, SLOT( onCatalogGen() ), "/PRP_DESK_CATALOG_GENERATOR" );
363 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
364 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
365 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
367 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
368 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
369 QKeySequence::UnknownKey, desk, false, this, SLOT( onLoadDoc() ), "/PRP_DESK_CONNECT" );
370 //no need at this action for mono-study application because study is always exists
371 action( ConnectId )->setVisible( false );
373 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
374 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
375 QKeySequence::UnknownKey, desk, false, this, SLOT( onUnloadDoc() ), "/PRP_DESK_DISCONNECT" );
376 //no need at this action for mono-study application because study is always exists
377 action( DisconnectId )->setVisible( false );
380 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
382 // "Save GUI State" command is renamed to "Save VISU State" and
383 // creation of menu item is moved to VISU
384 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
386 createMenu( ConnectId, fileMenu, 5 );
387 createMenu( DisconnectId, fileMenu, 5 );
388 createMenu( separator(), fileMenu, -1, 5 );
390 createMenu( DumpStudyId, fileMenu, 10, -1 );
391 createMenu( LoadScriptId, fileMenu, 10, -1 );
392 createMenu( separator(), fileMenu, -1, 10, -1 );
393 createMenu( PropertiesId, fileMenu, 10, -1 );
394 createMenu( separator(), fileMenu, -1, 10, -1 );
396 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
397 createMenu( CatalogGenId, toolsMenu, 10, -1 );
398 createMenu( RegDisplayId, toolsMenu, 10, -1 );
399 createMenu( separator(), toolsMenu, -1, 15, -1 );
401 createExtraActions();
403 #ifndef DISABLE_PYCONSOLE
404 #ifndef DISABLE_SALOMEOBJECT
405 // import Python module that manages SALOME plugins
407 PyLockWrapper lck; // acquire GIL
408 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
409 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
413 // end of SALOME plugins loading
420 \brief Close application.
422 void SalomeApp_Application::onExit()
424 //MessageLocker ml( myToIgnoreMessages );
426 bool killServers = false;
429 if ( exitConfirmation() ) {
430 SalomeApp_ExitDlg dlg( desktop() );
431 result = dlg.exec() == QDialog::Accepted;
432 killServers = dlg.isServersShutdown();
436 if ( !killServers ) myIsCloseFromExit = true;
437 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
438 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
442 /*!SLOT. Create a document.*/
443 void SalomeApp_Application::onNewDoc()
445 MessageLocker ml( myToIgnoreMessages );
447 LightApp_Application::onNewDoc();
450 /*!SLOT. Load document.*/
451 void SalomeApp_Application::onLoadDoc()
453 MessageLocker ml( myToIgnoreMessages );
457 // rnv: According to the single-study approach on the server side
458 // can be only one study. So if it is exists connect to them,
459 // overwise show warning message: "No active study on the server"
462 SUIT_Session* aSession = SUIT_Session::session();
463 QList<SUIT_Application*> aAppList = aSession->applications();
465 QStringList unloadedStudies;
467 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
468 studyName = List[ind].c_str();
469 // Add to list only unloaded studies
470 bool isAlreadyOpen = false;
471 QListIterator<SUIT_Application*> it( aAppList );
472 while ( it.hasNext() && !isAlreadyOpen ) {
473 SUIT_Application* aApp = it.next();
474 if( !aApp || !aApp->activeStudy() )
476 if ( aApp->activeStudy()->studyName() == studyName )
477 isAlreadyOpen = true;
480 if ( !isAlreadyOpen )
481 unloadedStudies << studyName;
483 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
484 if ( studyName.isEmpty() )
489 SUIT_MessageBox::warning( desktop(),
490 QObject::tr("WRN_WARNING"),
491 QObject::tr("WRN_NO_STUDY_ON SERV") );
495 studyName = activeStudy()->studyName();
498 // this code replaces marker of windows drive and path become invalid therefore
499 // defines placed there
500 studyName.replace( QRegExp(":"), "/" );
503 if ( onLoadDoc( studyName ) ) {
505 updateViewManagers();
506 updateObjectBrowser( true );
510 /*!SLOT. Unload document.*/
511 void SalomeApp_Application::onUnloadDoc( bool ask )
514 activeStudy()->abortAllOperations();
515 if ( activeStudy()->isModified() ) {
516 QString docName = activeStudy()->studyName().trimmed();
517 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
518 tr( "DISCONNECT_DESCRIPTION" ),
519 tr( "DISCONNECT_SAVE" ),
520 tr( "DISCONNECT_WO_SAVE" ),
521 tr( "APPCLOSE_CANCEL" ), 0 );
522 if ( answer == 0 ) { // save before unload
523 if ( activeStudy()->isSaved() )
525 else if ( !onSaveAsDoc() )
528 else if ( answer == 2 ) // Cancel
532 closeActiveDoc( false );
535 /*!SLOT. Create new study and load script*/
536 void SalomeApp_Application::onNewWithScript()
538 QStringList filtersList;
539 filtersList.append(tr("PYTHON_FILES_FILTER"));
540 filtersList.append(tr("ALL_FILES_FILTER"));
542 QString anInitialPath = "";
543 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
544 anInitialPath = QDir::currentPath();
546 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
548 if ( !aFile.isEmpty() )
552 #ifndef DISABLE_PYCONSOLE
553 QString command = QString("exec(open(\"%1\", \"rb\").read())").arg(aFile);
554 PyConsole_Console* pyConsole = pythonConsole();
555 PropertyMgr propm( this, "IsLoadedScript", true );
557 pyConsole->exec( command );
563 /*!SLOT. Load document with \a aName.*/
564 bool SalomeApp_Application::onLoadDoc( const QString& aName )
566 if ( !LightApp_Application::closeDoc() )
570 if ( !activeStudy() ) {
571 // if no study - load in current desktop
572 res = useStudy( aName );
575 // if study exists - load in new desktop. Check: is the same file is loaded?
576 SUIT_Session* aSession = SUIT_Session::session();
577 QList<SUIT_Application*> aAppList = aSession->applications();
578 bool isAlreadyOpen = false;
579 SalomeApp_Application* aApp = 0;
580 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
581 it != aAppList.end() && !isAlreadyOpen; ++it ) {
582 aApp = dynamic_cast<SalomeApp_Application*>( *it );
583 if ( aApp && aApp->activeStudy()->studyName() == aName )
584 isAlreadyOpen = true;
586 if ( !isAlreadyOpen ) {
587 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
589 res = aApp->useStudy( aName );
592 aApp->desktop()->activateWindow();
599 /*!SLOT. Parse message for desktop.*/
600 void SalomeApp_Application::onDesktopMessage( const QString& message )
602 if ( myToIgnoreMessages )
603 return; // a message from SALOMEDS is caused by GUI action
605 MessageLocker ml( myToIgnoreMessages );
607 if (message.indexOf("studyCreated") == 0) {
608 if (!activeStudy()) {
610 updateCommandsStatus();
613 if (message.indexOf("studyCleared") == 0) {
614 // Disconnect GUI from active study, because it was closed on DS side.
616 closeActiveDoc( false );
617 // Disable 'Connect' action
618 QAction* a = action( ConnectId );
620 a->setEnabled( false );
623 else if ( message.toLower() == "connect_to_study" ) {
625 useStudy( activeStudy()->studyName() );
627 if (message.indexOf("studyNameChanged") == 0) {
628 updateDesktopTitle();
630 LightApp_Application::onDesktopMessage( message );
633 /*!On module activation action.*/
634 void SalomeApp_Application::onModuleActivation( const QString& modName )
636 if (!activeStudy() && !modName.isEmpty())
639 LightApp_Application::onModuleActivation( modName );
642 /*!SLOT. Copy objects to study maneger from selection maneger..*/
643 void SalomeApp_Application::onCopy()
645 LightApp_Application::onCopy();
648 LightApp_SelectionMgr* mgr = selectionMgr();
649 mgr->selectedObjects(list);
651 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
652 if(study == NULL) return;
654 _PTR(Study) stdDS = getStudy();
657 SALOME_ListIteratorOfListIO it( list );
660 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
665 onSelectionChanged();
673 /*!SLOT. Paste objects to study maneger from selection manager.*/
674 void SalomeApp_Application::onPaste()
676 LightApp_Application::onPaste();
679 LightApp_SelectionMgr* mgr = selectionMgr();
680 mgr->selectedObjects(list);
682 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
683 if(study == NULL) return;
685 _PTR(Study) stdDS = getStudy();
688 if ( stdDS->GetProperties()->IsLocked() ) {
689 SUIT_MessageBox::warning( desktop(),
690 QObject::tr("WRN_WARNING"),
691 QObject::tr("WRN_STUDY_LOCKED") );
695 SALOME_ListIteratorOfListIO it( list );
698 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
703 updateObjectBrowser( true );
704 updateActions(); //SRN: BugID IPAL9377, case 3
712 /*!Check the application on closing.
713 * \retval true if possible, else false
715 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
717 return LightApp_Application::isPossibleToClose( closePermanently );
720 /*! Check if the study is locked */
721 void SalomeApp_Application::onCloseDoc( bool ask )
723 if(getStudy()->IsStudyLocked()) {
724 if ( SUIT_MessageBox::question( desktop(),
725 QObject::tr( "WRN_WARNING" ),
726 QObject::tr( "CLOSE_LOCKED_STUDY" ),
727 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
728 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
731 MessageLocker ml( myToIgnoreMessages );
733 LightApp_Application::onCloseDoc( ask );
735 // reinitialize study to have empty data
736 //getStudy()->Init();
739 /*!SLOT. Reload document from the file.*/
740 bool SalomeApp_Application::onReopenDoc()
742 MessageLocker ml( myToIgnoreMessages );
744 return LightApp_Application::onReopenDoc();
748 /*!SLOT. Load document.*/
749 void SalomeApp_Application::onOpenDoc()
751 MessageLocker ml( myToIgnoreMessages );
753 LightApp_Application::onOpenDoc();
756 /*!SLOT. Load document.*/
757 bool SalomeApp_Application::onOpenDoc(const QString& name)
759 MessageLocker ml( myToIgnoreMessages );
761 return LightApp_Application::onOpenDoc(name);
764 /*!Sets enable or disable some actions on selection changed.*/
765 void SalomeApp_Application::onSelectionChanged()
768 LightApp_SelectionMgr* mgr = selectionMgr();
769 mgr->selectedObjects(list);
771 bool canCopy = false;
772 bool canPaste = false;
774 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
777 canCopy = m->canCopy();
778 canPaste = m->canPaste();
781 SALOME_ListIteratorOfListIO it ( list );
783 if (it.More() && list.Extent() == 1) {
784 _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry());
787 canCopy = canCopy || getStudy()->CanCopy(so);
788 canPaste = canPaste || getStudy()->CanPaste(so);
792 action(EditCopyId)->setEnabled(canCopy);
793 action(EditPasteId)->setEnabled(canPaste);
796 /*!Delete references.*/
797 void SalomeApp_Application::onDeleteInvalidReferences()
800 LightApp_SelectionMgr* mgr = selectionMgr();
801 mgr->selectedObjects( aList, QString(), false );
803 if( aList.IsEmpty() )
806 _PTR(Study) aStudyDS = getStudy();
807 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
810 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
811 if ( it.Value()->hasEntry() )
813 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
814 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
817 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
818 aStudyBuilder->RemoveReference( aSObject );
820 updateObjectBrowser();
824 void SalomeApp_Application::onOpenWith()
826 QApplication::setOverrideCursor( Qt::WaitCursor );
828 LightApp_SelectionMgr* mgr = selectionMgr();
829 mgr->selectedObjects(aList);
830 if (aList.Extent() != 1)
832 QApplication::restoreOverrideCursor();
835 Handle(SALOME_InteractiveObject) aIObj = aList.First();
836 QString aModuleName(aIObj->getComponentDataType());
837 QString aModuleTitle = moduleTitle(aModuleName);
838 if (aModuleTitle.isEmpty()) // no gui
839 aModuleTitle = moduleDisplayer(aModuleName);
840 activateModule(aModuleTitle);
841 QApplication::restoreOverrideCursor();
847 SUIT_Study* SalomeApp_Application::createNewStudy()
849 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
851 // Set up processing of major study-related events
852 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
853 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
854 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
855 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
857 #ifndef DISABLE_PYCONSOLE
858 //to receive signal in application that NoteBook's variable was modified
859 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
860 this, SIGNAL(notebookVarUpdated(QString)) );
869 Enable/Disable menu items and toolbar buttons. Rebuild menu
871 void SalomeApp_Application::updateCommandsStatus()
873 LightApp_Application::updateCommandsStatus();
876 QAction* a = action( DumpStudyId );
878 a->setEnabled( activeStudy() );
880 #ifndef DISABLE_PYCONSOLE
882 a = action( LoadScriptId );
884 a->setEnabled( pythonConsole() );
888 a = action( PropertiesId );
890 a->setEnabled( activeStudy() );
892 // Save GUI state menu
893 a = action( SaveGUIStateId );
895 a->setEnabled( activeStudy() );
897 // Connect study menu
898 a = action( ConnectId );
900 a->setEnabled( !activeStudy() );
902 // Disconnect study menu
903 a = action( DisconnectId );
905 a->setEnabled( activeStudy() );
907 // update state of Copy/Paste menu items
908 onSelectionChanged();
912 \class DumpStudyFileDlg
913 Private class used in Dump Study operation. Consists 2 check boxes:
914 "Publish in study" and "Save GUI parameters"
916 class DumpStudyFileDlg : public SUIT_FileDlg
919 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
921 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
924 QWidget *hB = new QWidget( this );
925 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
926 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
927 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
929 QHBoxLayout *layout = new QHBoxLayout;
930 layout->addWidget(myPublishChk);
931 layout->addWidget(myMultiFileChk);
932 layout->addWidget(mySaveGUIChk);
933 hB->setLayout(layout);
935 QPushButton* pb = new QPushButton(this);
937 int row = grid->rowCount();
938 grid->addWidget( new QLabel("", this), row, 0 );
939 grid->addWidget( hB, row, 1, 1, 3 );
940 grid->addWidget( pb, row, 5 );
945 QCheckBox* myPublishChk;
946 QCheckBox* myMultiFileChk;
947 QCheckBox* mySaveGUIChk;
950 /*!Private SLOT. On dump study.*/
951 void SalomeApp_Application::onDumpStudy( )
953 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
954 if ( !appStudy ) return;
956 QStringList aFilters;
957 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
959 bool anIsPublish = true;
960 bool anIsMultiFile = false;
961 bool anIsSaveGUI = true;
963 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
964 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
965 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
966 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
969 DumpStudyFileDlg fd( desktop() );
970 fd.setValidator( new LightApp_PyFileValidator( &fd ) );
971 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
972 fd.setNameFilters( aFilters );
973 fd.myPublishChk->setChecked( anIsPublish );
974 fd.myMultiFileChk->setChecked( anIsMultiFile );
975 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
976 if ( fd.exec() == QDialog::Accepted )
978 QString aFileName = fd.selectedFile();
980 bool toPublish = fd.myPublishChk->isChecked();
981 bool isMultiFile = fd.myMultiFileChk->isChecked();
982 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
984 if ( !aFileName.isEmpty() ) {
985 QFileInfo aFileInfo(aFileName);
986 if( aFileInfo.isDir() ) // IPAL19257
989 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
992 SUIT_OverrideCursor wc;
993 ensureShaperIsActivated();
994 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
997 SUIT_MessageBox::warning( desktop(),
998 QObject::tr("WRN_WARNING"),
999 tr("WRN_DUMP_STUDY_FAILED") );
1004 /*!Private SLOT. On load script.*/
1005 void SalomeApp_Application::onLoadScript( )
1007 if ( getStudy()->GetProperties()->IsLocked() ) {
1008 SUIT_MessageBox::warning( desktop(),
1009 QObject::tr("WRN_WARNING"),
1010 QObject::tr("WRN_STUDY_LOCKED") );
1014 QStringList filtersList;
1015 filtersList.append(tr("PYTHON_FILES_FILTER"));
1016 filtersList.append(tr("ALL_FILES_FILTER"));
1018 QString anInitialPath = "";
1019 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
1020 anInitialPath = QDir::currentPath();
1022 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
1024 if ( !aFile.isEmpty() )
1026 #ifndef DISABLE_PYCONSOLE
1027 QString command = QString("exec(compile(open('%1', 'rb').read(), '%1', 'exec'))").arg(aFile);
1028 PyConsole_Console* pyConsole = pythonConsole();
1029 PropertyMgr propm( this, "IsLoadedScript", true );
1031 pyConsole->exec(command);
1036 /*!Private SLOT. On save GUI state.*/
1037 void SalomeApp_Application::onSaveGUIState()
1039 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1041 SalomeApp_VisualState( this ).storeState();
1042 updateSavePointDataObjects( study );
1043 updateObjectBrowser();
1048 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1049 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1051 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1052 QAction* send = ::qobject_cast<QAction*>( sender() );
1055 QString aWinName = send->data().toString();
1056 if ( theIsVisible && aWinName == "objectBrowser" )
1057 objectBrowserColumnsVisibility();
1061 QWidget* SalomeApp_Application::createWindow( const int flag )
1064 #ifndef DISABLE_PYCONSOLE
1065 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1067 wid = LightApp_Application::createWindow(flag);
1070 SUIT_ResourceMgr* resMgr = resourceMgr();
1072 if ( flag == WT_ObjectBrowser )
1074 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1076 // temporary commented
1077 //ob->setUpdater( new SalomeApp_Updater() );
1079 #ifdef WITH_SALOMEDS_OBSERVER
1080 //do not activate the automatic update of Qt tree through signal/slot
1081 ob->setAutoUpdate(false);
1082 //activate update of modified objects only
1083 ob->setUpdateModified(true);
1086 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1089 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1090 IORCol = QObject::tr( "IOR_COLUMN" ),
1091 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1092 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1094 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1095 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1096 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1097 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1098 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1099 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1100 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1101 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1102 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1104 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1105 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1106 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1108 ob->setAutoSizeFirstColumn(autoSizeFirst);
1109 ob->setAutoSizeColumns(autoSize);
1110 ob->setResizeOnExpandItem(resizeOnExpandItem);
1111 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1113 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1115 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1116 ob->treeView()->setColumnHidden( i, !shown );
1119 // temporary commented
1121 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1123 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1124 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1125 QString().sprintf( "visibility_column_%d", i ), true ) );
1129 // temporary commented
1131 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1132 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1133 ob->resize( desktop()->width()/3, ob->height() );
1137 #ifndef DISABLE_PYCONSOLE
1138 else if ( flag == WT_PyConsole )
1140 PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
1141 pyCons->setObjectName( "pythonConsole" );
1142 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1143 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1144 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1145 pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
1146 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1149 else if ( flag == WT_NoteBook )
1151 setNoteBook( new SalomeApp_NoteBook( desktop() ) );
1152 //to receive signal in NoteBook that it's variable was modified
1153 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1154 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1156 wid = getNoteBook();
1157 wid->setObjectName( "noteBook" );
1163 /*!Create preferences.*/
1164 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1166 LightApp_Application::createPreferences(pref);
1171 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1172 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1173 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1174 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1176 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1177 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1179 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1181 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1182 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1183 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1184 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1185 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1186 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1187 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1188 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1189 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1190 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1193 /*!Update desktop title.*/
1194 void SalomeApp_Application::updateDesktopTitle() {
1195 QString aTitle = applicationName();
1196 QString aVer = applicationVersion();
1197 if ( !aVer.isEmpty() )
1198 aTitle += QString( " " ) + aVer;
1200 if ( activeStudy() )
1202 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1203 if ( !sName.isEmpty() ) {
1204 if ( getStudy()->GetProperties()->IsLocked() ) {
1205 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1207 aTitle += QString( " - [%1]" ).arg( sName );
1212 desktop()->setWindowTitle( aTitle );
1215 int SalomeApp_Application::closeChoice( const QString& /*docName*/ )
1217 QStringList buttons;
1218 QMap<int, int> choices;
1220 buttons << tr ("APPCLOSE_SAVE"); // Save & Clear
1221 choices.insert( idx++, CloseSave ); // ...
1222 buttons << tr ("APPCLOSE_CLOSE"); // Clear w/o saving
1223 choices.insert( idx++, CloseDiscard ); // ...
1224 if ( myIsCloseFromExit ) {
1225 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1226 choices.insert( idx++, CloseDisconnectSave ); // ...
1227 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1228 choices.insert( idx++, CloseDisconnect ); // ...
1230 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1231 choices.insert( idx++, CloseCancel ); // ...
1233 if( !activeStudy()->isModified() )
1235 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1236 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1237 return choices[answer];
1240 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1246 if ( activeStudy()->isSaved() )
1248 else if ( !onSaveAsDoc() )
1253 case CloseDisconnectSave:
1254 if ( activeStudy()->isSaved() )
1256 else if ( !onSaveAsDoc() )
1259 case CloseDisconnect:
1260 closeActiveDoc( false );
1261 closePermanently = false;
1270 int SalomeApp_Application::openChoice( const QString& aName )
1272 int choice = LightApp_Application::openChoice( aName );
1274 if ( QFileInfo( aName ).exists() ) {
1275 if ( choice == OpenNew ) { // The document isn't already open.
1277 if ( aName == getStudy()->Name().c_str() )
1279 // The document already exists in the study.
1280 // Do you want to reload it?
1282 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1283 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1284 if ( answer == SUIT_MessageBox::Yes )
1285 choice = OpenRefresh;
1287 choice = OpenCancel;
1290 } else { // file is not exist on disk
1291 SUIT_MessageBox::warning( desktop(),
1292 QObject::tr("WRN_WARNING"),
1293 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toUtf8().data()));
1300 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1303 int choice = aChoice;
1310 res = LightApp_Application::openAction( choice, aName );
1318 \brief Get map of the operations which can be performed
1319 on the module activation.
1321 The method should return the map of the kind \c {<id>:<name>}
1322 where \c <id> is an integer identifier of the operation and
1323 \c <name> is a title for the button to be added to the
1324 dialog box. After user selects the required operation by the
1325 clicking the corresponding button in the dialog box, its identifier
1326 is passed to the moduleActionSelected() method to process
1329 \return map of the operations
1330 \sa moduleActionSelected()
1332 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1334 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1336 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1338 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1343 \brief Called when the used selectes required operation chosen
1344 from "Activate module" dialog box.
1346 Performs the required operation according to the user choice.
1348 \param id operation identifier
1349 \sa activateModuleActions()
1351 void SalomeApp_Application::moduleActionSelected( const int id )
1357 case NewAndScriptId:
1361 LightApp_Application::moduleActionSelected( id );
1366 /*!Gets CORBA::ORB_var*/
1367 CORBA::ORB_var SalomeApp_Application::orb()
1369 static CORBA::ORB_var _orb;
1371 if ( CORBA::is_nil( _orb ) ) {
1372 Qtx::CmdLineArgs args;
1373 SetArgcArgv( args.argc(), args.argv() );
1374 _orb = KERNEL::GetRefToORB();
1380 /*!Create and return SALOMEDS_Study.*/
1381 _PTR(Study) SalomeApp_Application::getStudy()
1383 static _PTR(Study) _study;
1385 CORBA::Object_var aSObject = namingService()->Resolve("/Study");
1386 SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(aSObject);
1387 _study = ClientFactory::Study(aStudy);
1392 /*!Create and return SALOME_NamingService.*/
1393 SALOME_NamingService_Abstract *SalomeApp_Application::namingService()
1398 /*!Create and return SALOME_LifeCycleCORBA.*/
1399 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1401 static SALOME_LifeCycleCORBA _lcc( namingService() );
1405 /*!Private SLOT. On preferences.*/
1406 void SalomeApp_Application::onProperties()
1408 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1412 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1415 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1416 int res = aDlg.exec();
1417 if( res==QDialog::Accepted && aDlg.isChanged() )
1418 SB->CommitCommand();
1422 //study->updateCaptions();
1423 updateDesktopTitle();
1427 /*!Insert items in popup, which necessary for current application*/
1428 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1430 LightApp_SelectionMgr* mgr = selectionMgr();
1431 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1432 mgr->setSelectionCacheEnabled( true );
1434 LightApp_Application::contextMenuPopup( type, thePopup, title );
1436 // temporary commented
1437 /*OB_Browser* ob = objectBrowser();
1438 if ( !ob || type != ob->popupClientType() )
1441 // Get selected objects
1442 SALOME_ListIO aList;
1443 mgr->selectedObjects( aList, QString(), false );
1445 // add GUI state commands: restore, rename
1446 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1447 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1448 thePopup->addSeparator();
1449 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1450 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1451 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1452 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1455 // "Delete reference" item should appear only for invalid references
1457 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1458 bool isInvalidRefs = false;
1460 _PTR(SObject) anObj;
1461 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1463 if( it.Value()->hasEntry() )
1465 _PTR(SObject) aSObject = getStudy()->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1466 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1469 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1470 isInvalidRefs = true;
1474 // Add "Delete reference" item to popup
1475 if ( isInvalidRefs )
1477 thePopup->addSeparator();
1478 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1482 // "Activate module" item should appear only if it's necessary
1483 if ( aList.Extent() == 1 ) {
1485 mgr->selectedObjects( aList );
1487 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1489 // add extra popup menu (defined in XML)
1490 if ( myExtActions.size() > 0 ) {
1491 // Use only first selected object
1492 _PTR(SObject) aSO = getStudy()->FindObjectID( aIObj->getEntry() );
1494 _PTR( GenericAttribute ) anAttr;
1495 std::string auid = "AttributeUserID";
1496 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1497 if ( aSO->FindAttribute( anAttr, auid ) ) {
1498 _PTR(AttributeUserID) aAttrID = anAttr;
1499 QString aId = aAttrID->Value().c_str();
1500 if ( myExtActions.contains( aId ) ) {
1501 thePopup->addAction(myExtActions[aId]);
1507 // check if item is a "GUI state" item (also a first level object)
1508 QString entry( aIObj->getEntry() );
1509 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1510 QString aModuleName( aIObj->getComponentDataType() );
1511 QString aModuleTitle = moduleTitle( aModuleName );
1512 if (aModuleTitle.isEmpty()) {
1513 // use displayer module, if given
1514 aModuleTitle = moduleDisplayer( aModuleName );
1516 CAM_Module* currentModule = activeModule();
1517 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) {
1518 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1523 mgr->setSelectionCacheEnabled( cacheIsOn );
1526 /*!Update obect browser:
1527 1.if 'updateModels' true, update existing data models;
1528 2. update "non-existing" (not loaded yet) data models;
1529 3. update object browser if it exists */
1530 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1532 // update "non-existing" (not loaded yet) data models
1533 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1536 for ( _PTR(SComponentIterator) it ( getStudy()->NewComponentIterator() ); it->More(); it->Next() )
1538 _PTR(SComponent) aComponent ( it->Value() );
1540 #ifndef WITH_SALOMEDS_OBSERVER
1541 // with GUI observers this check is not needed anymore
1542 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1543 continue; // skip the magic "Interface Applicative" component
1545 if ( !objectBrowser() )
1546 getWindow( WT_ObjectBrowser );
1547 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1548 objectBrowser()->setAutoUpdate( false );
1549 SalomeApp_DataModel::synchronize( aComponent, study );
1550 objectBrowser()->setAutoUpdate( isAutoUpdate );
1554 // create data objects that correspond to GUI state save points
1555 if ( study ) updateSavePointDataObjects( study );
1557 // update existing data models (already loaded SComponents)
1558 LightApp_Application::updateObjectBrowser( updateModels );
1561 /*!Display Catalog Genenerator dialog */
1562 void SalomeApp_Application::onCatalogGen()
1564 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1568 /*!Display Registry Display dialog */
1569 void SalomeApp_Application::onRegDisplay()
1571 CORBA::ORB_var anOrb = orb();
1572 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1575 regWnd->activateWindow();
1578 /*!find original object by double click on item */
1579 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1581 // Issue 21379: References are supported at LightApp_DataObject level
1582 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1584 if( obj && obj->isReference() )
1586 QString entry = obj->refEntry();
1588 SUIT_DataOwnerPtrList aList;
1589 aList.append( new LightApp_DataOwner( entry ) );
1590 selectionMgr()->setSelected( aList, false );
1592 SUIT_DataBrowser* ob = objectBrowser();
1594 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1595 if ( !aSelectedIndexes.isEmpty() )
1596 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1598 emit objectDoubleClicked( theObj );
1602 Creates new view manager
1603 \param type - type of view manager
1605 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1607 return createViewManager(type);
1611 /*!Global utility function, returns selected GUI Save point object's ID */
1612 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1614 SALOME_ListIO aList;
1615 selMgr->selectedObjects( aList );
1616 if( aList.Extent() > 0 ) {
1617 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1618 QString entry( aIObj->getEntry() );
1619 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1620 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1622 bool ok; // conversion to integer is ok?
1623 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1624 return ok ? savePoint : -1;
1629 /*!Called on Restore GUI State popup command*/
1630 void SalomeApp_Application::onRestoreGUIState()
1632 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1633 if ( savePoint == -1 )
1635 SalomeApp_VisualState( this ).restoreState( savePoint );
1638 /*!Called on Delete GUI State popup command*/
1639 void SalomeApp_Application::onDeleteGUIState()
1641 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1642 if ( savePoint == -1 )
1644 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1648 study->removeSavePoint( savePoint );
1649 updateSavePointDataObjects( study );
1652 /*!Called on New study operation*/
1653 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1655 LightApp_Application::onStudyCreated( study );
1657 //#ifndef DISABLE_PYCONSOLE
1658 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1659 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1662 loadDockWindowsState();
1664 objectBrowserColumnsVisibility();
1667 /*!Called on Open study operation*/
1668 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1670 LightApp_Application::onStudyOpened( study );
1672 //#ifndef DISABLE_PYCONSOLE
1673 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1674 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1677 loadDockWindowsState();
1679 objectBrowserColumnsVisibility();
1681 // temporary commented
1682 /*if ( objectBrowser() ) {
1683 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1684 objectBrowser()->updateTree( study->root() );
1688 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1689 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1692 SUIT_DataBrowser* ob = objectBrowser();
1693 LightApp_SelectionMgr* selMgr = selectionMgr();
1695 if ( !study || !ob || !selMgr )
1698 // find GUI states root object
1699 SUIT_DataObject* guiRootObj = 0;
1701 study->root()->children( ch );
1702 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1703 for ( ; it != last ; ++it ) {
1704 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1709 std::vector<int> savePoints = study->getSavePoints();
1710 // case 1: no more save points but they existed in study's tree
1711 if ( savePoints.empty() && guiRootObj ) {
1712 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1713 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1714 const bool isAutoUpdate = ob->autoUpdate();
1715 selMgr->clearSelected();
1716 ob->setAutoUpdate(true);
1717 DataObjectList ch = guiRootObj->children();
1718 for( int i = 0; i < ch.size(); i++ )
1721 ob->setAutoUpdate(isAutoUpdate);
1724 // case 2: no more save points but root does not exist either
1725 if ( savePoints.empty() && !guiRootObj )
1727 // case 3: save points but no root for them - create it
1728 if ( !savePoints.empty() && !guiRootObj )
1729 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1730 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1731 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1733 if ( guiRootObj->nextBrother() ) {
1734 study->root()->removeChild(guiRootObj);
1735 study->root()->appendChild(guiRootObj);
1736 //study->root()->dump();
1739 // store data objects in a map id-to-DataObject
1740 QMap<int,SalomeApp_SavePointObject*> mapDO;
1742 guiRootObj->children( ch );
1743 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1744 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1746 mapDO[dobj->getId()] = dobj;
1749 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1750 // if in the map - remove it from map.
1751 for ( size_t i = 0; i < savePoints.size(); i++ )
1752 if ( !mapDO.contains( savePoints[i] ) )
1753 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1755 mapDO.remove( savePoints[i] );
1757 // delete DataObjects that are still in the map -- their IDs were not found in data model
1758 if( mapDO.size() > 0) {
1759 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1760 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1761 selMgr->clearSelected();
1762 const bool isAutoUpdate = ob->autoUpdate();
1763 ob->setAutoUpdate(true);
1764 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1766 ob->setAutoUpdate(isAutoUpdate);
1770 /*! Check data object */
1771 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1780 Opens other study into active Study. If Study is empty - creates it.
1781 \param theName - name of study
1783 bool SalomeApp_Application::useStudy( const QString& theName )
1786 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1789 res = aStudy->loadDocument( theName );
1790 updateDesktopTitle();
1791 updateCommandsStatus();
1795 /*! Show/hide object browser colums according to preferences */
1796 void SalomeApp_Application::objectBrowserColumnsVisibility()
1798 if ( objectBrowser() )
1799 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1801 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1802 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1806 #ifndef DISABLE_PYCONSOLE
1807 /*! Set SalomeApp_NoteBook pointer */
1808 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1810 myNoteBook = theNoteBook;
1813 /*! Return SalomeApp_NoteBook pointer */
1814 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1821 * Define extra actions defined in module definition XML file.
1822 * Additional popup items sections can be defined by parameter "popupitems".
1823 * Supported attributes:
1824 * title - title of menu item,
1825 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1826 * method - method which has to be called when menu item is selected
1828 * <section name="MODULENAME">
1829 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1831 * <section name="importmed">
1832 * <parameter name="title" value="My menu"/>
1833 * <parameter name="objectid" value="VISU.Result"/>
1834 * <parameter name="method" value="nameOfModuleMethod"/>
1837 void SalomeApp_Application::createExtraActions()
1839 myExtActions.clear();
1840 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1842 QStringList aModules;
1843 modules(aModules, false);
1844 foreach(QString aModile, aModules) {
1845 QString aModName = moduleName(aModile);
1846 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1847 if (!aSectionStr.isNull()) {
1848 QStringList aSections = aSectionStr.split(':');
1849 foreach(QString aSection, aSections) {
1850 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1851 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1852 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1853 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1856 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1857 if (aModuleName.isNull())
1858 aModuleName = aModName;
1860 QAction* aAction = new QAction(aTitle, this);
1862 aData<<aModuleName<<aSlot;
1863 aAction->setData(aData);
1864 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1865 myExtActions[aId] = aAction;
1872 * Called when extra action is selected
1874 void SalomeApp_Application::onExtAction()
1876 QAction* aAction = ::qobject_cast<QAction*>(sender());
1880 QVariant aData = aAction->data();
1881 QStringList aDataList = aData.value<QStringList>();
1882 if (aDataList.size() != 2)
1885 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1886 SALOME_ListIO aListIO;
1887 aSelectionMgr->selectedObjects(aListIO);
1888 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1889 if (aListIO.Extent() < 1)
1891 if (!anIO->hasEntry())
1894 QString aEntry(anIO->getEntry());
1896 QApplication::setOverrideCursor( Qt::WaitCursor );
1897 QString aModuleTitle = moduleTitle(aDataList[0]);
1898 activateModule(aModuleTitle);
1899 QApplication::restoreOverrideCursor();
1901 QCoreApplication::processEvents();
1903 CAM_Module* aModule = activeModule();
1907 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1908 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1912 Checks that an object can be renamed.
1913 \param entry entry of the object
1914 \brief Return \c true if object can be renamed
1916 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1918 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1922 Rename object by entry.
1923 \param entry entry of the object
1924 \param name new name of the object
1925 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1927 bool SalomeApp_Application::renameObject( const QString& /*entry*/, const QString& name )
1929 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1931 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1933 if(!aStudy || savePoint == -1)
1936 if ( !name.isNull() && !name.isEmpty() ) {
1937 aStudy->setNameOfSavePoint( savePoint, name );
1938 updateSavePointDataObjects( aStudy );
1940 //Mark study as modified
1947 #ifndef DISABLE_PYCONSOLE
1948 //============================================================================
1949 /*! Function : onUpdateStudy
1950 * Purpose : Slot to update the study.
1952 //============================================================================
1953 void SalomeApp_Application::onUpdateStudy()
1955 QApplication::setOverrideCursor( Qt::WaitCursor );
1957 if( !updateStudy() )
1958 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1960 QApplication::restoreOverrideCursor();
1963 //============================================================================
1964 /*! Function : updateStudy
1965 * Purpose : Update study by dumping the study to Python script and loading it.
1966 * It is used to apply variable modifications done in NoteBook to created objects.
1968 //============================================================================
1969 bool SalomeApp_Application::updateStudy()
1971 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1972 if ( !study || !myNoteBook )
1975 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1976 myNoteBook->setDumpedStudyName( study->studyName() );
1978 // get unique temporary directory name
1979 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1981 if( aTmpDir.isEmpty() )
1984 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1985 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1987 // dump study to the temporary directory
1988 QString aScriptName( "notebook" );
1989 bool toPublish = true;
1990 bool isMultiFile = false;
1991 bool toSaveGUI = true;
1994 _PTR(AttributeParameter) ap;
1995 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1996 if(ip->isDumpPython()) ip->setDumpPython(); //Unset DumpPython flag.
1997 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1998 ip->setDumpPython();
1999 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2001 bool ok = getStudy()->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2003 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2006 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2010 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2011 int anIndex = aList.indexOf( this );
2013 // Disconnect dialog from application desktop in case if:
2014 // 1) Application is not the first application in the session
2015 // 2) Application is the first application in session but not the only.
2016 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2017 if( changeDesktop ) {
2019 SalomeApp_Application* app = this;
2020 if( anIndex > 0 && anIndex < aList.count() )
2021 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2022 else if(anIndex == 0 && aList.count() > 1)
2023 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2028 // creation a new study and restoring will be done in another application
2029 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2030 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2033 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2034 QString aStudyName = myNoteBook->getDumpedStudyName();
2035 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2036 // clear a study (delete all objects)
2037 onCloseDoc( false );
2039 if( !changeDesktop ) {
2040 ok = onRestoreStudy( aDumpScript,
2049 //============================================================================
2050 /*! Function : onRestoreStudy
2051 * Purpose : Load the dumped study from Python script
2053 //============================================================================
2054 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2055 const QString& theStudyName,
2056 bool theIsStudySaved )
2060 // create a new study
2063 // get active application
2064 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2066 // load study from the temporary directory
2067 QFileInfo aScriptInfo = QFileInfo(theDumpScript);
2068 QString command = QString( "exec(open(\"%1\" ,\"rb\").read())" ).arg(aScriptInfo.canonicalFilePath());
2070 #ifndef DISABLE_PYCONSOLE
2071 PyConsole_Console* pyConsole = app->pythonConsole();
2073 PropertyMgr propm( this, "IsLoadedScript", true );
2074 pyConsole->execAndWait( command );
2078 // remove temporary directory
2079 QString aStudyName = aScriptInfo.baseName();
2080 QDir aDir = aScriptInfo.absoluteDir();
2081 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2082 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2083 ok = aDir.remove( *it ) && ok;
2085 ok = aDir.rmdir( aDir.absolutePath() );
2087 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2089 #ifndef DISABLE_PYCONSOLE
2090 if ( app->getNoteBook() )
2091 app->getNoteBook()->Init();
2092 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2093 newStudy->Modified();
2094 updateDesktopTitle();
2105 Close the Application
2107 void SalomeApp_Application::afterCloseDoc()
2109 #ifndef DISABLE_PYCONSOLE
2110 // emit signal to restore study from Python script
2112 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2113 myNoteBook->getDumpedStudyName(),
2114 myNoteBook->isDumpedStudySaved() );
2117 LightApp_Application::afterCloseDoc();
2120 bool SalomeApp_Application::canOpenDoc( const QString& url )
2122 _PTR(Study) aStudyDS = getStudy();
2124 return aStudyDS->CanOpen( url.toUtf8().data() );
2129 Asks to close existing document.
2131 bool SalomeApp_Application::checkExistingDoc()
2133 return LightApp_Application::checkExistingDoc();
2137 #ifndef DISABLE_PYCONSOLE
2139 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2141 return new SalomeApp_PyInterp( resourceMgr() );
2144 #endif // DISABLE_PYCONSOLE
2146 void SalomeApp_Application::ensureShaperIsActivated()
2148 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
2149 _PTR(Study) studyDS = getStudy();
2150 if ( study && studyDS )
2152 _PTR(SObject) shaper = studyDS->FindObjectByPath("/Shaper"); // non null result if shaper data is present in the study
2153 bool shaperIsActive = false;
2154 QList<CAM_DataModel*> models;
2155 study->dataModels( models );
2156 for( int i = 0; i < models.count() && !shaperIsActive; i++ )
2157 shaperIsActive = models[i]->module()->moduleName() == "Shaper";
2159 if (shaper && !shaperIsActive)
2160 onDesktopMessage("register_module_in_study/Shaper");
2164 void SalomeApp_Application::addCatalogue( const QString& moduleName, const QString& catalogue )
2166 CORBA::Object_var obj = namingService()->Resolve( "/Kernel/ModulCatalog" );
2167 SALOME_ModuleCatalog::ModuleCatalog_var moduleCatalogue = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
2168 QFileInfo fi( catalogue );
2169 if ( !CORBA::is_nil( moduleCatalogue ) && fi.isFile() )
2171 SALOME_ModuleCatalog::ListOfComponents_var known = moduleCatalogue->GetComponentList();
2172 bool loaded = false;
2173 for ( int i = 0; i < (int)known->length() && !loaded; i++ )
2174 loaded = QString( known[i].in() ) == moduleName;
2176 moduleCatalogue->ImportXmlCatalogFile( catalogue.toUtf8().constData() );