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_Real.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>
75 #include <SUIT_FindActionDialog.h>
77 #include <QtxTreeView.h>
79 #include <SALOME_EventFilter.h>
81 // temporary commented
82 //#include <OB_ListItem.h>
85 #include <SALOME_LifeCycleCORBA.hxx>
87 #include <QApplication>
92 #include <QPushButton>
94 #include <QListWidget>
95 #include <QGridLayout>
99 #include <SALOMEDSClient_ClientFactory.hxx>
100 #include <ArgvKeeper.hxx>
101 #include <Basics_Utils.hxx>
102 #include <OpUtil.hxx>
104 #include <SALOME_ListIO.hxx>
105 #include <SALOME_Prs.h>
108 #include <ToolsGUI_CatalogGeneratorDlg.h>
109 #include <ToolsGUI_RegWidget.h>
114 #include <SALOMEDS_Tool.hxx>
116 #include <SALOMEconfig.h>
117 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
119 std::unique_ptr<SALOME_NamingService_Abstract> SalomeApp_Application::_ns;
121 /*!Internal class that updates object browser item properties */
122 // temporary commented
123 /*class SalomeApp_Updater : public OB_Updater
126 SalomeApp_Updater() : OB_Updater(){};
127 virtual ~SalomeApp_Updater(){};
128 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
131 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
133 if( !theObj || !theItem )
136 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
140 _PTR(SObject) SObj = SAObj->object();
143 _PTR( GenericAttribute ) anAttr;
146 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
148 _PTR(AttributeSelectable) aAttrSel = anAttr;
149 theItem->setSelectable( aAttrSel->IsSelectable() );
152 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
154 _PTR(AttributeExpandable) aAttrExpand = anAttr;
155 theItem->setExpandable( aAttrExpand->IsExpandable() );
158 //this attribute is not supported in the version of SALOME 3.x
159 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
161 // _PTR(AttributeOpened) aAttrOpen = anAttr;
162 // theItem->setOpen( aAttrOpen->IsOpened() );
174 //! Constructor. Sets passed boolean flag to \c true.
175 MessageLocker( bool& Lock ) : myPrevState( Lock ), myLock( Lock ) { myLock = true; }
176 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
177 ~MessageLocker() { myLock = myPrevState; }
180 bool& myLock; //! External 'Lock state' boolean flag
184 \brief Dynamic property manager
191 PropertyMgr(QObject* object, const QString& property, const QVariant& value)
192 : myObject(object), myProperty(property)
194 myObject->setProperty(qPrintable(myProperty), value);
198 myObject->setProperty(qPrintable(myProperty), QVariant());
204 SalomeApp_Application::SalomeApp_Application(SALOME_NamingService_Abstract *ns):myIsCloseFromExit( false ),myToIgnoreMessages( false )
207 _ns.reset(new SALOME_NamingService(orb()));
213 *\li Destroy event filter.
215 SalomeApp_Application::~SalomeApp_Application()
217 // Do not destroy. It's a singleton !
218 //SALOME_EventFilter::Destroy();
221 QStringList __getArgsList(QString argsString)
223 // Special process if some items of 'args:' list are themselves lists
224 // Note that an item can be a list, but not a list of lists...
225 // So we can have something like this:
226 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
227 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
228 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
229 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
230 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
232 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
237 return argsString.split(",", QString::SkipEmptyParts);
240 /*!Start application.*/
241 void SalomeApp_Application::start()
243 // process the command line options before start: to createActions in accordance to the options
244 static bool isFirst = true;
251 QStringList args = QApplication::arguments();
252 for (int i = 1; i < args.count(); i++) {
253 QRegExp rxs ("--study-hdf=(.+)");
254 if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
255 QString file = rxs.capturedTexts()[1];
256 QFileInfo fi ( file );
257 QString extension = fi.suffix().toLower();
258 if ( extension == "hdf" && fi.exists() )
259 hdffile = fi.absoluteFilePath();
262 QRegExp rxp ("--pyscript=\\[(.+)\\]");
263 if ( rxp.indexIn( args[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
265 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
266 for (int k = 0; k < dictList.count(); ++k) {
267 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
268 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
269 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
270 pyfiles += rxd.capturedTexts()[m];
277 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
278 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
280 LightApp_Application::start();
281 SALOME_EventFilter::Init();
283 if ( !hdffile.isEmpty() )
285 // open hdf file given as parameter
286 PropertyMgr propm( this, "open_study_from_command_line", true );
287 onOpenDoc( hdffile );
290 #ifndef DISABLE_PYCONSOLE
291 // import/execute python scripts
292 if ( pyfiles.count() > 0 && activeStudy() ) {
293 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
294 PyConsole_Console* pyConsole = pythonConsole();
295 if ( appStudy && pyConsole ) {
296 if ( !getStudy()->GetProperties()->IsLocked() ) {
297 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
298 // Path is absolute, script has .py extension
299 for (int j = 0; j < pyfiles.count(); j++ ) {
300 // Extract scripts and their arguments, if any
301 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
302 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
303 QString script = rxp.capturedTexts()[1];
305 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
306 for (int k = 0; k < argList.count(); k++ ) {
307 QString arg = argList[k].trimmed();
308 arg.remove( QRegExp("^[\"]") );
309 arg.remove( QRegExp("[\"]$") );
310 args << QString("\"%1\"").arg(arg);
312 if (args.count() == 1)
315 script.remove( QRegExp("^python.*[\\s]+") );
316 QString command = QString( "exec(open(\"%1\", \"rb\").read(), args=(%2))" ).arg(script).arg(args.join(","));
317 PropertyMgr propm( this, "IsLoadedScript", true );
318 pyConsole->exec(command);
320 } // end for loop on pyfiles QStringList
326 LightApp_Application::start();
327 SALOME_EventFilter::Init();
332 void SalomeApp_Application::createActions()
334 LightApp_Application::createActions();
336 SUIT_Desktop* desk = desktop();
339 // "Save GUI State" command is moved to VISU module
340 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
341 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
342 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
345 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
346 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
347 QKeySequence::UnknownKey, desk, false, this, SLOT( onDumpStudy() ), "/PRP_DESK_FILE_DUMP_STUDY" );
350 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
351 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
352 QKeySequence::UnknownKey, desk, false, this, SLOT( onLoadScript() ), "/PRP_DESK_FILE_LOAD_SCRIPT" );
355 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
356 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
357 0, desk, false, this, SLOT( onProperties() ) );
359 //! Catalog Generator
360 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
361 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
362 QKeySequence::UnknownKey, desk, false, this, SLOT( onCatalogGen() ), "/PRP_DESK_CATALOG_GENERATOR" );
365 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
366 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
367 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
369 //! Find action dialog
370 createAction( FindActionId, tr( "TOT_DESK_FIND_ACTION" ), QIcon(),
371 tr( "MEN_DESK_FIND_ACTION" ), tr( "PRP_DESK_FIND_ACTION" ),
372 QKeySequence::UnknownKey, desk, false, this, SLOT( onFindAction() ), "/PRP_DESK_FIND_ACTION" );
374 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
375 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
376 QKeySequence::UnknownKey, desk, false, this, SLOT( onLoadDoc() ), "/PRP_DESK_CONNECT" );
377 //no need at this action for mono-study application because study is always exists
378 action( ConnectId )->setVisible( false );
380 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
381 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
382 QKeySequence::UnknownKey, desk, false, this, SLOT( onUnloadDoc() ), "/PRP_DESK_DISCONNECT" );
383 //no need at this action for mono-study application because study is always exists
384 action( DisconnectId )->setVisible( false );
387 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
389 // "Save GUI State" command is renamed to "Save VISU State" and
390 // creation of menu item is moved to VISU
391 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
393 createMenu( ConnectId, fileMenu, 5 );
394 createMenu( DisconnectId, fileMenu, 5 );
395 createMenu( separator(), fileMenu, -1, 5 );
397 createMenu( DumpStudyId, fileMenu, 10, -1 );
398 createMenu( LoadScriptId, fileMenu, 10, -1 );
399 createMenu( separator(), fileMenu, -1, 10, -1 );
400 createMenu( PropertiesId, fileMenu, 10, -1 );
401 createMenu( separator(), fileMenu, -1, 10, -1 );
403 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
404 createMenu( CatalogGenId, toolsMenu, 10, -1 );
405 createMenu( RegDisplayId, toolsMenu, 10, -1 );
406 createMenu( FindActionId, toolsMenu, 10, -1 );
407 createMenu( separator(), toolsMenu, -1, 15, -1 );
409 createExtraActions();
411 #ifndef DISABLE_PYCONSOLE
412 #ifndef DISABLE_SALOMEOBJECT
413 // import Python module that manages SALOME plugins
415 PyLockWrapper lck; // acquire GIL
416 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
417 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
421 // end of SALOME plugins loading
428 \brief Close application.
430 void SalomeApp_Application::onExit()
432 //MessageLocker ml( myToIgnoreMessages );
434 bool killServers = false;
437 if ( exitConfirmation() ) {
438 SalomeApp_ExitDlg dlg( desktop() );
439 result = dlg.exec() == QDialog::Accepted;
440 killServers = dlg.isServersShutdown();
444 if ( !killServers ) myIsCloseFromExit = true;
445 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
446 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
450 /*!SLOT. Create a document.*/
451 void SalomeApp_Application::onNewDoc()
453 MessageLocker ml( myToIgnoreMessages );
455 LightApp_Application::onNewDoc();
458 /*!SLOT. Load document.*/
459 void SalomeApp_Application::onLoadDoc()
461 MessageLocker ml( myToIgnoreMessages );
465 // rnv: According to the single-study approach on the server side
466 // can be only one study. So if it is exists connect to them,
467 // overwise show warning message: "No active study on the server"
470 SUIT_Session* aSession = SUIT_Session::session();
471 QList<SUIT_Application*> aAppList = aSession->applications();
473 QStringList unloadedStudies;
475 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
476 studyName = List[ind].c_str();
477 // Add to list only unloaded studies
478 bool isAlreadyOpen = false;
479 QListIterator<SUIT_Application*> it( aAppList );
480 while ( it.hasNext() && !isAlreadyOpen ) {
481 SUIT_Application* aApp = it.next();
482 if( !aApp || !aApp->activeStudy() )
484 if ( aApp->activeStudy()->studyName() == studyName )
485 isAlreadyOpen = true;
488 if ( !isAlreadyOpen )
489 unloadedStudies << studyName;
491 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
492 if ( studyName.isEmpty() )
497 SUIT_MessageBox::warning( desktop(),
498 QObject::tr("WRN_WARNING"),
499 QObject::tr("WRN_NO_STUDY_ON SERV") );
503 studyName = activeStudy()->studyName();
506 // this code replaces marker of windows drive and path become invalid therefore
507 // defines placed there
508 studyName.replace( QRegExp(":"), "/" );
511 if ( onLoadDoc( studyName ) ) {
513 updateViewManagers();
514 updateObjectBrowser( true );
518 /*!SLOT. Unload document.*/
519 void SalomeApp_Application::onUnloadDoc( bool ask )
522 activeStudy()->abortAllOperations();
523 if ( activeStudy()->isModified() ) {
524 QString docName = activeStudy()->studyName().trimmed();
525 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
526 tr( "DISCONNECT_DESCRIPTION" ),
527 tr( "DISCONNECT_SAVE" ),
528 tr( "DISCONNECT_WO_SAVE" ),
529 tr( "APPCLOSE_CANCEL" ), 0 );
530 if ( answer == 0 ) { // save before unload
531 if ( activeStudy()->isSaved() )
533 else if ( !onSaveAsDoc() )
536 else if ( answer == 2 ) // Cancel
540 closeActiveDoc( false );
543 /*!SLOT. Create new study and load script*/
544 void SalomeApp_Application::onNewWithScript()
546 QStringList filtersList;
547 filtersList.append(tr("PYTHON_FILES_FILTER"));
548 filtersList.append(tr("ALL_FILES_FILTER"));
550 QString anInitialPath = "";
551 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
552 anInitialPath = QDir::currentPath();
554 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
556 if ( !aFile.isEmpty() )
560 #ifndef DISABLE_PYCONSOLE
561 QString command = QString("exec(open(\"%1\", \"rb\").read())").arg(aFile);
562 PyConsole_Console* pyConsole = pythonConsole();
563 PropertyMgr propm( this, "IsLoadedScript", true );
565 pyConsole->exec( command );
571 /*!SLOT. Load document with \a aName.*/
572 bool SalomeApp_Application::onLoadDoc( const QString& aName )
574 if ( !LightApp_Application::closeDoc() )
578 if ( !activeStudy() ) {
579 // if no study - load in current desktop
580 res = useStudy( aName );
583 // if study exists - load in new desktop. Check: is the same file is loaded?
584 SUIT_Session* aSession = SUIT_Session::session();
585 QList<SUIT_Application*> aAppList = aSession->applications();
586 bool isAlreadyOpen = false;
587 SalomeApp_Application* aApp = 0;
588 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
589 it != aAppList.end() && !isAlreadyOpen; ++it ) {
590 aApp = dynamic_cast<SalomeApp_Application*>( *it );
591 if ( aApp && aApp->activeStudy()->studyName() == aName )
592 isAlreadyOpen = true;
594 if ( !isAlreadyOpen ) {
595 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
597 res = aApp->useStudy( aName );
600 aApp->desktop()->activateWindow();
607 /*!SLOT. Parse message for desktop.*/
608 void SalomeApp_Application::onDesktopMessage( const QString& message )
610 if ( myToIgnoreMessages )
611 return; // a message from SALOMEDS is caused by GUI action
613 MessageLocker ml( myToIgnoreMessages );
615 if (message.indexOf("studyCreated") == 0) {
616 if (!activeStudy()) {
618 updateCommandsStatus();
621 if (message.indexOf("studyCleared") == 0) {
622 // Disconnect GUI from active study, because it was closed on DS side.
624 closeActiveDoc( false );
625 // Disable 'Connect' action
626 QAction* a = action( ConnectId );
628 a->setEnabled( false );
631 else if ( message.toLower() == "connect_to_study" ) {
633 useStudy( activeStudy()->studyName() );
635 if (message.indexOf("studyNameChanged") == 0) {
636 updateDesktopTitle();
638 LightApp_Application::onDesktopMessage( message );
641 /*!On module activation action.*/
642 void SalomeApp_Application::onModuleActivation( const QString& modName )
644 if (!activeStudy() && !modName.isEmpty())
647 LightApp_Application::onModuleActivation( modName );
650 /*!SLOT. Copy objects to study maneger from selection maneger..*/
651 void SalomeApp_Application::onCopy()
653 LightApp_Application::onCopy();
656 LightApp_SelectionMgr* mgr = selectionMgr();
657 mgr->selectedObjects(list);
659 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
660 if(study == NULL) return;
662 _PTR(Study) stdDS = getStudy();
665 SALOME_ListIteratorOfListIO it( list );
668 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
673 onSelectionChanged();
681 /*!SLOT. Paste objects to study maneger from selection manager.*/
682 void SalomeApp_Application::onPaste()
684 LightApp_Application::onPaste();
687 LightApp_SelectionMgr* mgr = selectionMgr();
688 mgr->selectedObjects(list);
690 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
691 if(study == NULL) return;
693 _PTR(Study) stdDS = getStudy();
696 if ( stdDS->GetProperties()->IsLocked() ) {
697 SUIT_MessageBox::warning( desktop(),
698 QObject::tr("WRN_WARNING"),
699 QObject::tr("WRN_STUDY_LOCKED") );
703 SALOME_ListIteratorOfListIO it( list );
706 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
711 updateObjectBrowser( true );
712 updateActions(); //SRN: BugID IPAL9377, case 3
720 /*!Check the application on closing.
721 * \retval true if possible, else false
723 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
725 return LightApp_Application::isPossibleToClose( closePermanently );
728 /*! Check if the study is locked */
729 void SalomeApp_Application::onCloseDoc( bool ask )
731 if(getStudy()->IsStudyLocked()) {
732 if ( SUIT_MessageBox::question( desktop(),
733 QObject::tr( "WRN_WARNING" ),
734 QObject::tr( "CLOSE_LOCKED_STUDY" ),
735 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
736 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
739 MessageLocker ml( myToIgnoreMessages );
741 LightApp_Application::onCloseDoc( ask );
743 // reinitialize study to have empty data
744 //getStudy()->Init();
747 /*!SLOT. Reload document from the file.*/
748 bool SalomeApp_Application::onReopenDoc()
750 MessageLocker ml( myToIgnoreMessages );
752 return LightApp_Application::onReopenDoc();
756 /*!SLOT. Load document.*/
757 void SalomeApp_Application::onOpenDoc()
759 MessageLocker ml( myToIgnoreMessages );
761 LightApp_Application::onOpenDoc();
764 /*!SLOT. Load document.*/
765 bool SalomeApp_Application::onOpenDoc(const QString& name)
767 MessageLocker ml( myToIgnoreMessages );
769 return LightApp_Application::onOpenDoc(name);
772 /*!Sets enable or disable some actions on selection changed.*/
773 void SalomeApp_Application::onSelectionChanged()
776 LightApp_SelectionMgr* mgr = selectionMgr();
777 mgr->selectedObjects(list);
779 bool canCopy = false;
780 bool canPaste = false;
782 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
785 canCopy = m->canCopy();
786 canPaste = m->canPaste();
789 SALOME_ListIteratorOfListIO it ( list );
791 if (it.More() && list.Extent() == 1) {
792 _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry());
795 canCopy = canCopy || getStudy()->CanCopy(so);
796 canPaste = canPaste || getStudy()->CanPaste(so);
800 action(EditCopyId)->setEnabled(canCopy);
801 action(EditPasteId)->setEnabled(canPaste);
804 /*!Delete references.*/
805 void SalomeApp_Application::onDeleteInvalidReferences()
808 LightApp_SelectionMgr* mgr = selectionMgr();
809 mgr->selectedObjects( aList, QString(), false );
811 if( aList.IsEmpty() )
814 _PTR(Study) aStudyDS = getStudy();
815 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
818 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
819 if ( it.Value()->hasEntry() )
821 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
822 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
825 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
826 aStudyBuilder->RemoveReference( aSObject );
828 updateObjectBrowser();
832 void SalomeApp_Application::onOpenWith()
834 QApplication::setOverrideCursor( Qt::WaitCursor );
836 LightApp_SelectionMgr* mgr = selectionMgr();
837 mgr->selectedObjects(aList);
838 if (aList.Extent() != 1)
840 QApplication::restoreOverrideCursor();
843 Handle(SALOME_InteractiveObject) aIObj = aList.First();
844 QString aModuleName(aIObj->getComponentDataType());
845 QString aModuleTitle = moduleTitle(aModuleName);
846 if (aModuleTitle.isEmpty()) // no gui
847 aModuleTitle = moduleDisplayer(aModuleName);
848 activateModule(aModuleTitle);
849 QApplication::restoreOverrideCursor();
855 SUIT_Study* SalomeApp_Application::createNewStudy()
857 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
859 // Set up processing of major study-related events
860 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
861 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
862 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
863 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
865 #ifndef DISABLE_PYCONSOLE
866 //to receive signal in application that NoteBook's variable was modified
867 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
868 this, SIGNAL(notebookVarUpdated(QString)) );
877 Enable/Disable menu items and toolbar buttons. Rebuild menu
879 void SalomeApp_Application::updateCommandsStatus()
881 LightApp_Application::updateCommandsStatus();
884 QAction* a = action( DumpStudyId );
886 a->setEnabled( activeStudy() );
888 #ifndef DISABLE_PYCONSOLE
890 a = action( LoadScriptId );
892 a->setEnabled( pythonConsole() );
896 a = action( PropertiesId );
898 a->setEnabled( activeStudy() );
900 // Save GUI state menu
901 a = action( SaveGUIStateId );
903 a->setEnabled( activeStudy() );
905 // Connect study menu
906 a = action( ConnectId );
908 a->setEnabled( !activeStudy() );
910 // Disconnect study menu
911 a = action( DisconnectId );
913 a->setEnabled( activeStudy() );
915 // update state of Copy/Paste menu items
916 onSelectionChanged();
920 \class DumpStudyFileDlg
921 Private class used in Dump Study operation. Consists 2 check boxes:
922 "Publish in study" and "Save GUI parameters"
924 class DumpStudyFileDlg : public SUIT_FileDlg
927 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
929 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
932 QWidget *hB = new QWidget( this );
933 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
934 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
935 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
937 QHBoxLayout *layout = new QHBoxLayout;
938 layout->addWidget(myPublishChk);
939 layout->addWidget(myMultiFileChk);
940 layout->addWidget(mySaveGUIChk);
941 hB->setLayout(layout);
943 QPushButton* pb = new QPushButton(this);
945 int row = grid->rowCount();
946 grid->addWidget( new QLabel("", this), row, 0 );
947 grid->addWidget( hB, row, 1, 1, 3 );
948 grid->addWidget( pb, row, 5 );
953 QCheckBox* myPublishChk;
954 QCheckBox* myMultiFileChk;
955 QCheckBox* mySaveGUIChk;
958 /*!Private SLOT. On dump study.*/
959 void SalomeApp_Application::onDumpStudy( )
961 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
962 if ( !appStudy ) return;
964 QStringList aFilters;
965 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
967 bool anIsPublish = true;
968 bool anIsMultiFile = false;
969 bool anIsSaveGUI = true;
971 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
972 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
973 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
974 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
977 DumpStudyFileDlg fd( desktop() );
978 fd.setValidator( new LightApp_PyFileValidator( &fd ) );
979 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
980 fd.setNameFilters( aFilters );
981 fd.myPublishChk->setChecked( anIsPublish );
982 fd.myMultiFileChk->setChecked( anIsMultiFile );
983 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
984 if ( fd.exec() == QDialog::Accepted )
986 QString aFileName = fd.selectedFile();
988 bool toPublish = fd.myPublishChk->isChecked();
989 bool isMultiFile = fd.myMultiFileChk->isChecked();
990 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
992 if ( !aFileName.isEmpty() ) {
993 QFileInfo aFileInfo(aFileName);
994 if( aFileInfo.isDir() ) // IPAL19257
997 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
1000 SUIT_OverrideCursor wc;
1001 ensureShaperIsActivated();
1002 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
1005 SUIT_MessageBox::warning( desktop(),
1006 QObject::tr("WRN_WARNING"),
1007 tr("WRN_DUMP_STUDY_FAILED") );
1012 /*!Private SLOT. On load script.*/
1013 void SalomeApp_Application::onLoadScript( )
1015 if ( getStudy()->GetProperties()->IsLocked() ) {
1016 SUIT_MessageBox::warning( desktop(),
1017 QObject::tr("WRN_WARNING"),
1018 QObject::tr("WRN_STUDY_LOCKED") );
1022 QStringList filtersList;
1023 filtersList.append(tr("PYTHON_FILES_FILTER"));
1024 filtersList.append(tr("ALL_FILES_FILTER"));
1026 QString anInitialPath = "";
1027 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
1028 anInitialPath = QDir::currentPath();
1030 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
1032 if ( !aFile.isEmpty() )
1034 #ifndef DISABLE_PYCONSOLE
1035 QString command = QString("exec(compile(open('%1', 'rb').read(), '%1', 'exec'))").arg(aFile);
1036 PyConsole_Console* pyConsole = pythonConsole();
1037 PropertyMgr propm( this, "IsLoadedScript", true );
1039 pyConsole->exec(command);
1044 /*!Private SLOT. On save GUI state.*/
1045 void SalomeApp_Application::onSaveGUIState()
1047 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1049 SalomeApp_VisualState( this ).storeState();
1050 updateSavePointDataObjects( study );
1051 updateObjectBrowser();
1056 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1057 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1059 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1060 QAction* send = ::qobject_cast<QAction*>( sender() );
1063 QString aWinName = send->data().toString();
1064 if ( theIsVisible && aWinName == "objectBrowser" )
1065 objectBrowserColumnsVisibility();
1069 QWidget* SalomeApp_Application::createWindow( const int flag )
1072 #ifndef DISABLE_PYCONSOLE
1073 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1075 wid = LightApp_Application::createWindow(flag);
1078 SUIT_ResourceMgr* resMgr = resourceMgr();
1080 if ( flag == WT_ObjectBrowser )
1082 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1084 // temporary commented
1085 //ob->setUpdater( new SalomeApp_Updater() );
1087 #ifdef WITH_SALOMEDS_OBSERVER
1088 //do not activate the automatic update of Qt tree through signal/slot
1089 ob->setAutoUpdate(false);
1090 //activate update of modified objects only
1091 ob->setUpdateModified(true);
1094 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1097 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1098 IORCol = QObject::tr( "IOR_COLUMN" ),
1099 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1100 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1102 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1103 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1104 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1105 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1106 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1107 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1108 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1109 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1110 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1112 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1113 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1114 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1116 ob->setAutoSizeFirstColumn(autoSizeFirst);
1117 ob->setAutoSizeColumns(autoSize);
1118 ob->setResizeOnExpandItem(resizeOnExpandItem);
1119 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1121 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1123 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1124 ob->treeView()->setColumnHidden( i, !shown );
1127 // temporary commented
1129 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1131 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1132 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1133 QString().sprintf( "visibility_column_%d", i ), true ) );
1137 // temporary commented
1139 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1140 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1141 ob->resize( desktop()->width()/3, ob->height() );
1145 #ifndef DISABLE_PYCONSOLE
1146 else if ( flag == WT_PyConsole )
1148 PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
1149 pyCons->setObjectName( "pythonConsole" );
1150 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1151 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1152 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1153 pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
1154 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1157 else if ( flag == WT_NoteBook )
1159 setNoteBook( new SalomeApp_NoteBook( desktop() ) );
1160 //to receive signal in NoteBook that it's variable was modified
1161 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1162 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1164 wid = getNoteBook();
1165 wid->setObjectName( "noteBook" );
1171 /*!Create preferences.*/
1172 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1174 LightApp_Application::createPreferences(pref);
1179 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1180 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1181 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1182 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1184 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1185 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1187 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1189 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1190 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1191 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1192 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1193 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1194 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1195 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1196 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1197 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1198 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1201 /*!Update desktop title.*/
1202 void SalomeApp_Application::updateDesktopTitle() {
1203 QString aTitle = applicationName();
1204 QString aVer = applicationVersion();
1205 if ( !aVer.isEmpty() )
1206 aTitle += QString( " " ) + aVer;
1208 if ( activeStudy() )
1210 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1211 if ( !sName.isEmpty() ) {
1212 if ( getStudy()->GetProperties()->IsLocked() ) {
1213 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1215 aTitle += QString( " - [%1]" ).arg( sName );
1220 desktop()->setWindowTitle( aTitle );
1223 int SalomeApp_Application::closeChoice( const QString& /*docName*/ )
1225 QStringList buttons;
1226 QMap<int, int> choices;
1228 buttons << tr ("APPCLOSE_SAVE"); // Save & Clear
1229 choices.insert( idx++, CloseSave ); // ...
1230 buttons << tr ("APPCLOSE_CLOSE"); // Clear w/o saving
1231 choices.insert( idx++, CloseDiscard ); // ...
1232 if ( myIsCloseFromExit ) {
1233 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1234 choices.insert( idx++, CloseDisconnectSave ); // ...
1235 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1236 choices.insert( idx++, CloseDisconnect ); // ...
1238 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1239 choices.insert( idx++, CloseCancel ); // ...
1241 if( !activeStudy()->isModified() )
1243 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1244 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1245 return choices[answer];
1248 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1254 if ( activeStudy()->isSaved() )
1256 else if ( !onSaveAsDoc() )
1261 case CloseDisconnectSave:
1262 if ( activeStudy()->isSaved() )
1264 else if ( !onSaveAsDoc() )
1267 case CloseDisconnect:
1268 closeActiveDoc( false );
1269 closePermanently = false;
1278 int SalomeApp_Application::openChoice( const QString& aName )
1280 int choice = LightApp_Application::openChoice( aName );
1282 if ( QFileInfo( aName ).exists() ) {
1283 if ( choice == OpenNew ) { // The document isn't already open.
1285 if ( aName == getStudy()->Name().c_str() )
1287 // The document already exists in the study.
1288 // Do you want to reload it?
1290 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1291 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1292 if ( answer == SUIT_MessageBox::Yes )
1293 choice = OpenRefresh;
1295 choice = OpenCancel;
1298 } else { // file is not exist on disk
1299 SUIT_MessageBox::warning( desktop(),
1300 QObject::tr("WRN_WARNING"),
1301 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toUtf8().data()));
1308 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1311 int choice = aChoice;
1318 res = LightApp_Application::openAction( choice, aName );
1326 \brief Get map of the operations which can be performed
1327 on the module activation.
1329 The method should return the map of the kind \c {<id>:<name>}
1330 where \c <id> is an integer identifier of the operation and
1331 \c <name> is a title for the button to be added to the
1332 dialog box. After user selects the required operation by the
1333 clicking the corresponding button in the dialog box, its identifier
1334 is passed to the moduleActionSelected() method to process
1337 \return map of the operations
1338 \sa moduleActionSelected()
1340 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1342 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1344 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1346 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1351 \brief Called when the used selectes required operation chosen
1352 from "Activate module" dialog box.
1354 Performs the required operation according to the user choice.
1356 \param id operation identifier
1357 \sa activateModuleActions()
1359 void SalomeApp_Application::moduleActionSelected( const int id )
1365 case NewAndScriptId:
1369 LightApp_Application::moduleActionSelected( id );
1374 /*!Gets CORBA::ORB_var*/
1375 CORBA::ORB_var SalomeApp_Application::orb()
1377 static CORBA::ORB_var _orb;
1379 if ( CORBA::is_nil( _orb ) ) {
1380 Qtx::CmdLineArgs args;
1381 SetArgcArgv( args.argc(), args.argv() );
1382 _orb = KERNEL::GetRefToORB();
1388 /*!Create and return SALOMEDS_Study.*/
1389 _PTR(Study) SalomeApp_Application::getStudy()
1391 static _PTR(Study) _study;
1393 CORBA::Object_var aSObject = namingService()->Resolve("/Study");
1394 SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(aSObject);
1395 _study = ClientFactory::Study(aStudy);
1400 /*!Create and return SALOME_NamingService.*/
1401 SALOME_NamingService_Abstract *SalomeApp_Application::namingService()
1406 /*!Create and return SALOME_LifeCycleCORBA.*/
1407 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1409 static SALOME_LifeCycleCORBA _lcc( namingService() );
1413 /*!Private SLOT. On preferences.*/
1414 void SalomeApp_Application::onProperties()
1416 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1420 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1423 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1424 int res = aDlg.exec();
1425 if( res==QDialog::Accepted && aDlg.isChanged() )
1426 SB->CommitCommand();
1430 //study->updateCaptions();
1431 updateDesktopTitle();
1435 /*!Insert items in popup, which necessary for current application*/
1436 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1438 LightApp_SelectionMgr* mgr = selectionMgr();
1439 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1440 mgr->setSelectionCacheEnabled( true );
1442 LightApp_Application::contextMenuPopup( type, thePopup, title );
1444 // temporary commented
1445 /*OB_Browser* ob = objectBrowser();
1446 if ( !ob || type != ob->popupClientType() )
1449 // Get selected objects
1450 SALOME_ListIO aList;
1451 mgr->selectedObjects( aList, QString(), false );
1453 // add GUI state commands: restore, rename
1454 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1455 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1456 thePopup->addSeparator();
1457 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1458 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1459 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1460 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1463 // "Delete reference" item should appear only for invalid references
1465 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1466 bool isInvalidRefs = false;
1468 _PTR(SObject) anObj;
1469 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1471 if( it.Value()->hasEntry() )
1473 _PTR(SObject) aSObject = getStudy()->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1474 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1477 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1478 isInvalidRefs = true;
1482 // Add "Delete reference" item to popup
1483 if ( isInvalidRefs )
1485 thePopup->addSeparator();
1486 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1490 // "Activate module" item should appear only if it's necessary
1491 if ( aList.Extent() == 1 ) {
1493 mgr->selectedObjects( aList );
1495 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1497 // add extra popup menu (defined in XML)
1498 if ( myExtActions.size() > 0 ) {
1499 // Use only first selected object
1500 _PTR(SObject) aSO = getStudy()->FindObjectID( aIObj->getEntry() );
1502 _PTR( GenericAttribute ) anAttr;
1503 std::string auid = "AttributeUserID";
1504 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1505 if ( aSO->FindAttribute( anAttr, auid ) ) {
1506 _PTR(AttributeUserID) aAttrID = anAttr;
1507 QString aId = aAttrID->Value().c_str();
1508 if ( myExtActions.contains( aId ) ) {
1509 thePopup->addAction(myExtActions[aId]);
1515 // check if item is a "GUI state" item (also a first level object)
1516 QString entry( aIObj->getEntry() );
1517 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1518 QString aModuleName( aIObj->getComponentDataType() );
1519 QString aModuleTitle = moduleTitle( aModuleName );
1520 if (aModuleTitle.isEmpty()) {
1521 // use displayer module, if given
1522 aModuleTitle = moduleDisplayer( aModuleName );
1524 CAM_Module* currentModule = activeModule();
1525 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) {
1526 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1531 mgr->setSelectionCacheEnabled( cacheIsOn );
1534 /*!Update obect browser:
1535 1.if 'updateModels' true, update existing data models;
1536 2. update "non-existing" (not loaded yet) data models;
1537 3. update object browser if it exists */
1538 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1540 // update "non-existing" (not loaded yet) data models
1541 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1544 for ( _PTR(SComponentIterator) it ( getStudy()->NewComponentIterator() ); it->More(); it->Next() )
1546 _PTR(SComponent) aComponent ( it->Value() );
1548 #ifndef WITH_SALOMEDS_OBSERVER
1549 // with GUI observers this check is not needed anymore
1550 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1551 continue; // skip the magic "Interface Applicative" component
1553 if ( !objectBrowser() )
1554 getWindow( WT_ObjectBrowser );
1555 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1556 objectBrowser()->setAutoUpdate( false );
1557 SalomeApp_DataModel::synchronize( aComponent, study );
1558 objectBrowser()->setAutoUpdate( isAutoUpdate );
1562 // create data objects that correspond to GUI state save points
1563 if ( study ) updateSavePointDataObjects( study );
1565 // update existing data models (already loaded SComponents)
1566 LightApp_Application::updateObjectBrowser( updateModels );
1569 /*!Display Catalog Genenerator dialog */
1570 void SalomeApp_Application::onCatalogGen()
1572 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1576 /*!Display Registry Display dialog */
1577 void SalomeApp_Application::onRegDisplay()
1579 CORBA::ORB_var anOrb = orb();
1580 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1583 regWnd->activateWindow();
1586 /*!Display Action Search dialog */
1587 void SalomeApp_Application::onFindAction()
1589 const auto pActiveModule = activeModule();
1590 if (pActiveModule && pActiveModule->name() == "PARAVIS") {
1592 // ParaViS module has its own action search dialog (Quick Launch dialog).
1593 // Keep this conditional block until ParaViS's actions are not added to ShortcutMgr resource and asset files.
1596 SUIT_FindActionDialog aDlg( desktop() );
1598 aDlg.setActiveModuleID(pActiveModule->name());
1600 aDlg.setActiveModuleID();
1605 /*!find original object by double click on item */
1606 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1608 // Issue 21379: References are supported at LightApp_DataObject level
1609 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1611 if( obj && obj->isReference() )
1613 QString entry = obj->refEntry();
1615 SUIT_DataOwnerPtrList aList;
1616 aList.append( new LightApp_DataOwner( entry ) );
1617 selectionMgr()->setSelected( aList, false );
1619 SUIT_DataBrowser* ob = objectBrowser();
1621 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1622 if ( !aSelectedIndexes.isEmpty() )
1623 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1625 emit objectDoubleClicked( theObj );
1629 Creates new view manager
1630 \param type - type of view manager
1632 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1634 return createViewManager(type);
1638 /*!Global utility function, returns selected GUI Save point object's ID */
1639 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1641 SALOME_ListIO aList;
1642 selMgr->selectedObjects( aList );
1643 if( aList.Extent() > 0 ) {
1644 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1645 QString entry( aIObj->getEntry() );
1646 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1647 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1649 bool ok; // conversion to integer is ok?
1650 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1651 return ok ? savePoint : -1;
1656 /*!Called on Restore GUI State popup command*/
1657 void SalomeApp_Application::onRestoreGUIState()
1659 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1660 if ( savePoint == -1 )
1662 SalomeApp_VisualState( this ).restoreState( savePoint );
1665 /*!Called on Delete GUI State popup command*/
1666 void SalomeApp_Application::onDeleteGUIState()
1668 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1669 if ( savePoint == -1 )
1671 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1675 study->removeSavePoint( savePoint );
1676 updateSavePointDataObjects( study );
1679 /*!Called on New study operation*/
1680 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1682 LightApp_Application::onStudyCreated( study );
1684 //#ifndef DISABLE_PYCONSOLE
1685 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1686 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1689 loadDockWindowsState();
1691 objectBrowserColumnsVisibility();
1694 /*!Called on Open study operation*/
1695 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1697 LightApp_Application::onStudyOpened( study );
1699 //#ifndef DISABLE_PYCONSOLE
1700 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1701 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1704 loadDockWindowsState();
1706 objectBrowserColumnsVisibility();
1708 // temporary commented
1709 /*if ( objectBrowser() ) {
1710 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1711 objectBrowser()->updateTree( study->root() );
1715 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1716 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1719 SUIT_DataBrowser* ob = objectBrowser();
1720 LightApp_SelectionMgr* selMgr = selectionMgr();
1722 if ( !study || !ob || !selMgr )
1725 // find GUI states root object
1726 SUIT_DataObject* guiRootObj = 0;
1728 study->root()->children( ch );
1729 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1730 for ( ; it != last ; ++it ) {
1731 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1736 std::vector<int> savePoints = study->getSavePoints();
1737 // case 1: no more save points but they existed in study's tree
1738 if ( savePoints.empty() && guiRootObj ) {
1739 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1740 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1741 const bool isAutoUpdate = ob->autoUpdate();
1742 selMgr->clearSelected();
1743 ob->setAutoUpdate(true);
1744 DataObjectList ch = guiRootObj->children();
1745 for( int i = 0; i < ch.size(); i++ )
1748 ob->setAutoUpdate(isAutoUpdate);
1751 // case 2: no more save points but root does not exist either
1752 if ( savePoints.empty() && !guiRootObj )
1754 // case 3: save points but no root for them - create it
1755 if ( !savePoints.empty() && !guiRootObj )
1756 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1757 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1758 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1760 if ( guiRootObj->nextBrother() ) {
1761 study->root()->removeChild(guiRootObj);
1762 study->root()->appendChild(guiRootObj);
1763 //study->root()->dump();
1766 // store data objects in a map id-to-DataObject
1767 QMap<int,SalomeApp_SavePointObject*> mapDO;
1769 guiRootObj->children( ch );
1770 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1771 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1773 mapDO[dobj->getId()] = dobj;
1776 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1777 // if in the map - remove it from map.
1778 for ( size_t i = 0; i < savePoints.size(); i++ )
1779 if ( !mapDO.contains( savePoints[i] ) )
1780 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1782 mapDO.remove( savePoints[i] );
1784 // delete DataObjects that are still in the map -- their IDs were not found in data model
1785 if( mapDO.size() > 0) {
1786 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1787 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1788 selMgr->clearSelected();
1789 const bool isAutoUpdate = ob->autoUpdate();
1790 ob->setAutoUpdate(true);
1791 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1793 ob->setAutoUpdate(isAutoUpdate);
1797 /*! Check data object */
1798 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1807 Opens other study into active Study. If Study is empty - creates it.
1808 \param theName - name of study
1810 bool SalomeApp_Application::useStudy( const QString& theName )
1813 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1816 res = aStudy->loadDocument( theName );
1817 updateDesktopTitle();
1818 updateCommandsStatus();
1822 /*! Show/hide object browser colums according to preferences */
1823 void SalomeApp_Application::objectBrowserColumnsVisibility()
1825 if ( objectBrowser() )
1826 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1828 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1829 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1833 #ifndef DISABLE_PYCONSOLE
1834 /*! Set SalomeApp_NoteBook pointer */
1835 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1837 myNoteBook = theNoteBook;
1840 /*! Return SalomeApp_NoteBook pointer */
1841 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1848 * Define extra actions defined in module definition XML file.
1849 * Additional popup items sections can be defined by parameter "popupitems".
1850 * Supported attributes:
1851 * title - title of menu item,
1852 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1853 * method - method which has to be called when menu item is selected
1855 * <section name="MODULENAME">
1856 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1858 * <section name="importmed">
1859 * <parameter name="title" value="My menu"/>
1860 * <parameter name="objectid" value="VISU.Result"/>
1861 * <parameter name="method" value="nameOfModuleMethod"/>
1864 void SalomeApp_Application::createExtraActions()
1866 myExtActions.clear();
1867 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1869 QStringList aModules;
1870 modules(aModules, false);
1871 foreach(QString aModile, aModules) {
1872 QString aModName = moduleName(aModile);
1873 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1874 if (!aSectionStr.isNull()) {
1875 QStringList aSections = aSectionStr.split(':');
1876 foreach(QString aSection, aSections) {
1877 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1878 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1879 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1880 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1883 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1884 if (aModuleName.isNull())
1885 aModuleName = aModName;
1887 QAction* aAction = new QAction(aTitle, this);
1889 aData<<aModuleName<<aSlot;
1890 aAction->setData(aData);
1891 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1892 myExtActions[aId] = aAction;
1899 * Called when extra action is selected
1901 void SalomeApp_Application::onExtAction()
1903 QAction* aAction = ::qobject_cast<QAction*>(sender());
1907 QVariant aData = aAction->data();
1908 QStringList aDataList = aData.value<QStringList>();
1909 if (aDataList.size() != 2)
1912 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1913 SALOME_ListIO aListIO;
1914 aSelectionMgr->selectedObjects(aListIO);
1915 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1916 if (aListIO.Extent() < 1)
1918 if (!anIO->hasEntry())
1921 QString aEntry(anIO->getEntry());
1923 QApplication::setOverrideCursor( Qt::WaitCursor );
1924 QString aModuleTitle = moduleTitle(aDataList[0]);
1925 activateModule(aModuleTitle);
1926 QApplication::restoreOverrideCursor();
1928 QCoreApplication::processEvents();
1930 CAM_Module* aModule = activeModule();
1934 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1935 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1939 Checks that an object can be renamed.
1940 \param entry entry of the object
1941 \brief Return \c true if object can be renamed
1943 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1945 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1949 Rename object by entry.
1950 \param entry entry of the object
1951 \param name new name of the object
1952 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1954 bool SalomeApp_Application::renameObject( const QString& /*entry*/, const QString& name )
1956 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1958 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1960 if(!aStudy || savePoint == -1)
1963 if ( !name.isNull() && !name.isEmpty() ) {
1964 aStudy->setNameOfSavePoint( savePoint, name );
1965 updateSavePointDataObjects( aStudy );
1967 //Mark study as modified
1974 #ifndef DISABLE_PYCONSOLE
1975 //============================================================================
1976 /*! Function : onUpdateStudy
1977 * Purpose : Slot to update the study.
1979 //============================================================================
1980 void SalomeApp_Application::onUpdateStudy()
1982 QApplication::setOverrideCursor( Qt::WaitCursor );
1984 if( !updateStudy() )
1985 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1987 QApplication::restoreOverrideCursor();
1990 //============================================================================
1991 /*! Function : updateStudy
1992 * Purpose : Update study by dumping the study to Python script and loading it.
1993 * It is used to apply variable modifications done in NoteBook to created objects.
1995 //============================================================================
1996 bool SalomeApp_Application::updateStudy()
1998 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1999 if ( !study || !myNoteBook )
2002 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
2003 myNoteBook->setDumpedStudyName( study->studyName() );
2005 // get unique temporary directory name
2006 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
2008 if( aTmpDir.isEmpty() )
2011 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
2012 aTmpDir.remove( aTmpDir.length() - 1, 1 );
2014 // dump study to the temporary directory
2015 QString aScriptName( "notebook" );
2016 bool toPublish = true;
2017 bool isMultiFile = false;
2018 bool toSaveGUI = true;
2021 _PTR(AttributeParameter) ap;
2022 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
2023 if(ip->isDumpPython()) ip->setDumpPython(); //Unset DumpPython flag.
2024 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
2025 ip->setDumpPython();
2026 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
2028 bool ok = getStudy()->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
2030 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
2033 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
2037 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
2038 int anIndex = aList.indexOf( this );
2040 // Disconnect dialog from application desktop in case if:
2041 // 1) Application is not the first application in the session
2042 // 2) Application is the first application in session but not the only.
2043 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
2044 if( changeDesktop ) {
2046 SalomeApp_Application* app = this;
2047 if( anIndex > 0 && anIndex < aList.count() )
2048 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2049 else if(anIndex == 0 && aList.count() > 1)
2050 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2055 // creation a new study and restoring will be done in another application
2056 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2057 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2060 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2061 QString aStudyName = myNoteBook->getDumpedStudyName();
2062 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2063 // clear a study (delete all objects)
2064 onCloseDoc( false );
2066 if( !changeDesktop ) {
2067 ok = onRestoreStudy( aDumpScript,
2076 //============================================================================
2077 /*! Function : onRestoreStudy
2078 * Purpose : Load the dumped study from Python script
2080 //============================================================================
2081 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2082 const QString& theStudyName,
2083 bool theIsStudySaved )
2087 // create a new study
2090 // get active application
2091 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2093 // load study from the temporary directory
2094 QFileInfo aScriptInfo = QFileInfo(theDumpScript);
2095 QString command = QString( "exec(open(\"%1\" ,\"rb\").read())" ).arg(aScriptInfo.canonicalFilePath());
2097 #ifndef DISABLE_PYCONSOLE
2098 PyConsole_Console* pyConsole = app->pythonConsole();
2100 PropertyMgr propm( this, "IsLoadedScript", true );
2101 pyConsole->execAndWait( command );
2105 // remove temporary directory
2106 QString aStudyName = aScriptInfo.baseName();
2107 QDir aDir = aScriptInfo.absoluteDir();
2108 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2109 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2110 ok = aDir.remove( *it ) && ok;
2112 ok = aDir.rmdir( aDir.absolutePath() );
2114 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2116 #ifndef DISABLE_PYCONSOLE
2117 if ( app->getNoteBook() )
2118 app->getNoteBook()->Init();
2119 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2120 newStudy->Modified();
2121 updateDesktopTitle();
2132 Close the Application
2134 void SalomeApp_Application::afterCloseDoc()
2136 #ifndef DISABLE_PYCONSOLE
2137 // emit signal to restore study from Python script
2139 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2140 myNoteBook->getDumpedStudyName(),
2141 myNoteBook->isDumpedStudySaved() );
2144 LightApp_Application::afterCloseDoc();
2147 bool SalomeApp_Application::canOpenDoc( const QString& url )
2149 _PTR(Study) aStudyDS = getStudy();
2151 return aStudyDS->CanOpen( url.toUtf8().data() );
2156 Asks to close existing document.
2158 bool SalomeApp_Application::checkExistingDoc()
2160 return LightApp_Application::checkExistingDoc();
2164 #ifndef DISABLE_PYCONSOLE
2166 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2168 return new SalomeApp_PyInterp( resourceMgr() );
2171 #endif // DISABLE_PYCONSOLE
2173 void SalomeApp_Application::ensureShaperIsActivated()
2175 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
2176 _PTR(Study) studyDS = getStudy();
2177 if ( study && studyDS )
2179 _PTR(SObject) shaper = studyDS->FindObjectByPath("/Shaper"); // non null result if shaper data is present in the study
2180 bool shaperIsActive = false;
2181 QList<CAM_DataModel*> models;
2182 study->dataModels( models );
2183 for( int i = 0; i < models.count() && !shaperIsActive; i++ )
2184 shaperIsActive = models[i]->module()->moduleName() == "Shaper";
2186 if (shaper && !shaperIsActive)
2187 onDesktopMessage("register_module_in_study/Shaper");
2191 void SalomeApp_Application::addCatalogue( const QString& moduleName, const QString& catalogue )
2193 CORBA::Object_var obj = namingService()->Resolve( "/Kernel/ModulCatalog" );
2194 SALOME_ModuleCatalog::ModuleCatalog_var moduleCatalogue = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
2195 QFileInfo fi( catalogue );
2196 if ( !CORBA::is_nil( moduleCatalogue ) && fi.isFile() )
2198 SALOME_ModuleCatalog::ListOfComponents_var known = moduleCatalogue->GetComponentList();
2199 bool loaded = false;
2200 for ( int i = 0; i < (int)known->length() && !loaded; i++ )
2201 loaded = QString( known[i].in() ) == moduleName;
2203 moduleCatalogue->ImportXmlCatalogFile( catalogue.toUtf8().constData() );