1 // Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: SalomeApp_Application.cxx
24 // Created: 10/22/2004 3:23:45 PM
25 // Author: Sergey LITONIN
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
32 #ifndef DISABLE_PYCONSOLE
37 #ifndef DISABLE_PYCONSOLE
38 #include "SalomeApp_PyInterp.h"
39 #include "SalomeApp_NoteBook.h"
40 #include "LightApp_PyEditor.h"
41 #include "PyConsole_Console.h"
43 #include "SalomeApp_Application.h"
44 #include "SalomeApp_Study.h"
45 #include "SalomeApp_DataModel.h"
46 #include "SalomeApp_DataObject.h"
47 #include "SalomeApp_VisualState.h"
48 #include "SalomeApp_StudyPropertiesDlg.h"
49 #include "SalomeApp_LoadStudiesDlg.h"
50 #include "SalomeApp_ExitDlg.h"
52 #include <LightApp_Application.h>
53 #include <LightApp_FileValidator.h>
54 #include <LightApp_Module.h>
55 #include <LightApp_Preferences.h>
56 #include <LightApp_SelectionMgr.h>
57 #include <LightApp_NameDlg.h>
58 #include <LightApp_DataOwner.h>
60 #include <CAM_Module.h>
62 #include <SUIT_Tools.h>
63 #include <SUIT_Session.h>
64 #include <SUIT_Desktop.h>
65 #include <SUIT_DataBrowser.h>
66 #include <SUIT_FileDlg.h>
67 #include <SUIT_MessageBox.h>
68 #include <SUIT_ResourceMgr.h>
69 #include <SUIT_TreeModel.h>
70 #include <SUIT_ViewWindow.h>
71 #include <SUIT_ViewManager.h>
72 #include <SUIT_ViewModel.h>
73 #include <SUIT_OverrideCursor.h>
75 #include <QtxTreeView.h>
77 #include <SALOME_EventFilter.h>
79 // temporary commented
80 //#include <OB_ListItem.h>
83 #include <Utils_ORB_INIT.hxx>
84 #include <Utils_SINGLETON.hxx>
85 #include <SALOME_LifeCycleCORBA.hxx>
87 #include <QApplication>
92 #include <QPushButton>
94 #include <QListWidget>
95 #include <QGridLayout>
99 #include <SALOMEDSClient_ClientFactory.hxx>
100 #include <Basics_Utils.hxx>
102 #include <SALOME_ListIO.hxx>
103 #include <SALOME_Prs.h>
106 #include <ToolsGUI_CatalogGeneratorDlg.h>
107 #include <ToolsGUI_RegWidget.h>
111 #include <SALOMEDS_Tool.hxx>
113 /*!Internal class that updates object browser item properties */
114 // temporary commented
115 /*class SalomeApp_Updater : public OB_Updater
118 SalomeApp_Updater() : OB_Updater(){};
119 virtual ~SalomeApp_Updater(){};
120 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
123 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
125 if( !theObj || !theItem )
128 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
132 _PTR(SObject) SObj = SAObj->object();
135 _PTR( GenericAttribute ) anAttr;
138 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
140 _PTR(AttributeSelectable) aAttrSel = anAttr;
141 theItem->setSelectable( aAttrSel->IsSelectable() );
144 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
146 _PTR(AttributeExpandable) aAttrExpand = anAttr;
147 theItem->setExpandable( aAttrExpand->IsExpandable() );
150 //this attribute is not supported in the version of SALOME 3.x
151 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
153 // _PTR(AttributeOpened) aAttrOpen = anAttr;
154 // theItem->setOpen( aAttrOpen->IsOpened() );
166 //! Constructor. Sets passed boolean flag to \c true.
167 MessageLocker( bool& Lock ) : myPrevState( Lock ), myLock( Lock ) { myLock = true; }
168 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
169 ~MessageLocker() { myLock = myPrevState; }
172 bool& myLock; //! External 'Lock state' boolean flag
176 /*!Create new instance of SalomeApp_Application.*/
177 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
179 return new SalomeApp_Application();
183 SalomeApp_Application::SalomeApp_Application()
184 : LightApp_Application(),
185 myIsCloseFromExit( false ),
186 myToIgnoreMessages( false )
191 *\li Destroy event filter.
193 SalomeApp_Application::~SalomeApp_Application()
195 // Do not destroy. It's a singleton !
196 //SALOME_EventFilter::Destroy();
199 QStringList __getArgsList(QString argsString)
201 // Special process if some items of 'args:' list are themselves lists
202 // Note that an item can be a list, but not a list of lists...
203 // So we can have something like this:
204 // myscript.py args:['file1','file2'],val1,"done",[1,2,3],[True,False],"ok"
205 // With such a call, argsString variable contains the string representing "[file1,file2]", "val1", "done", "[1,2,3]", "[True,False]", "ok"
206 // We have to split argsString to obtain: [[file1,file2],val1,done,[1,2,3],[True,False],ok]
207 argsString.replace("\\\"", "'"); // replace escaped double quotes by simple quotes
208 bool containsList = (QRegExp("(\\[[^\\]]*\\])").indexIn(argsString) >= 0);
210 QStringList sl = argsString.split("\"", QString::SkipEmptyParts);
215 return argsString.split(",", QString::SkipEmptyParts);
218 /*!Start application.*/
219 void SalomeApp_Application::start()
221 // process the command line options before start: to createActions in accordance to the options
222 static bool isFirst = true;
229 QStringList args = QApplication::arguments();
230 for (int i = 1; i < args.count(); i++) {
231 QRegExp rxs ("--study-hdf=(.+)");
232 if ( rxs.indexIn( args[i] ) >= 0 && rxs.capturedTexts().count() > 1 ) {
233 QString file = rxs.capturedTexts()[1];
234 QFileInfo fi ( file );
235 QString extension = fi.suffix().toLower();
236 if ( extension == "hdf" && fi.exists() )
237 hdffile = fi.absoluteFilePath();
240 QRegExp rxp ("--pyscript=\\[(.+)\\]");
241 if ( rxp.indexIn( args[i] ) >= 0 && rxp.capturedTexts().count() > 1 ) {
243 QStringList dictList = rxp.capturedTexts()[1].split("},", QString::SkipEmptyParts);
244 for (int k = 0; k < dictList.count(); ++k) {
245 QRegExp rxd ("[\\s]*\\{?([^\\{\\}]+)\\}?[\\s]*");
246 if ( rxd.indexIn( dictList[k] ) >= 0 && rxd.capturedTexts().count() > 1 ) {
247 for (int m = 1; m < rxd.capturedTexts().count(); ++m) {
248 pyfiles += rxd.capturedTexts()[m];
255 // Here pyfiles elements are: "script_name": [list_of_"arg"s]
256 // For example: "/absolute/path/to/my_script.py": ["1", "2"]
258 LightApp_Application::start();
259 SALOME_EventFilter::Init();
261 setProperty("open_study_from_command_line", true);
262 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
263 onOpenDoc( hdffile );
264 setProperty("open_study_from_command_line", QVariant());
266 #ifndef DISABLE_PYCONSOLE
267 // import/execute python scripts
268 if ( pyfiles.count() > 0 && activeStudy() ) {
269 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
270 PyConsole_Console* pyConsole = pythonConsole();
271 if ( appStudy && pyConsole ) {
272 if ( !getStudy()->GetProperties()->IsLocked() ) {
273 // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]}
274 // Path is absolute, script has .py extension
275 for (int j = 0; j < pyfiles.count(); j++ ) {
276 // Extract scripts and their arguments, if any
277 QRegExp rxp ("\"(.+)\":[\\s]*\\[(.*)\\]");
278 if ( rxp.indexIn( pyfiles[j] ) >= 0 && rxp.capturedTexts().count() == 3 ) {
279 QString script = rxp.capturedTexts()[1];
281 QStringList argList = __getArgsList(rxp.capturedTexts()[2]);
282 for (int k = 0; k < argList.count(); k++ ) {
283 QString arg = argList[k].trimmed();
284 arg.remove( QRegExp("^[\"]") );
285 arg.remove( QRegExp("[\"]$") );
286 args << QString("\"%1\"").arg(arg);
288 if (args.count() == 1)
291 script.remove( QRegExp("^python.*[\\s]+") );
292 QString command = QString( "exec(open(\"%1\", \"rb\").read(), args=(%2))" ).arg(script).arg(args.join(","));
293 pyConsole->exec(command);
295 } // end for loop on pyfiles QStringList
301 LightApp_Application::start();
302 SALOME_EventFilter::Init();
307 void SalomeApp_Application::createActions()
309 LightApp_Application::createActions();
311 SUIT_Desktop* desk = desktop();
314 // "Save GUI State" command is moved to VISU module
315 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIcon(),
316 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
317 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
320 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIcon(),
321 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
322 Qt::CTRL+Qt::Key_D, desk, false, this, SLOT( onDumpStudy() ) );
325 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIcon(),
326 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
327 Qt::CTRL+Qt::Key_T, desk, false, this, SLOT( onLoadScript() ) );
330 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIcon(),
331 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
332 0, desk, false, this, SLOT( onProperties() ) );
334 //! Catalog Generator
335 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIcon(),
336 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
337 Qt::ALT+Qt::SHIFT+Qt::Key_G, desk, false, this, SLOT( onCatalogGen() ) );
340 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIcon(),
341 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
342 /*Qt::SHIFT+Qt::Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
344 createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(),
345 tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ),
346 Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) );
347 //no need at this action for mono-study application because study is always exists
348 action( ConnectId )->setVisible( false );
350 createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(),
351 tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ),
352 Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) );
353 //no need at this action for mono-study application because study is always exists
354 action( DisconnectId )->setVisible( false );
357 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
359 // "Save GUI State" command is renamed to "Save VISU State" and
360 // creation of menu item is moved to VISU
361 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
363 createMenu( ConnectId, fileMenu, 5 );
364 createMenu( DisconnectId, fileMenu, 5 );
365 createMenu( separator(), fileMenu, -1, 5 );
367 createMenu( DumpStudyId, fileMenu, 10, -1 );
368 createMenu( LoadScriptId, fileMenu, 10, -1 );
369 createMenu( separator(), fileMenu, -1, 10, -1 );
370 createMenu( PropertiesId, fileMenu, 10, -1 );
371 createMenu( separator(), fileMenu, -1, 10, -1 );
373 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
374 createMenu( CatalogGenId, toolsMenu, 10, -1 );
375 createMenu( RegDisplayId, toolsMenu, 10, -1 );
376 createMenu( separator(), toolsMenu, -1, 15, -1 );
378 createExtraActions();
380 #ifndef DISABLE_PYCONSOLE
381 #ifndef DISABLE_SALOMEOBJECT
382 // import Python module that manages SALOME plugins
384 PyLockWrapper lck; // acquire GIL
385 PyObjWrapper pluginsmanager = PyImport_ImportModule((char*)"salome_pluginsmanager");
386 PyObjWrapper res = PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",0,"salome",tr("MEN_DESK_TOOLS").toUtf8().data(),tr("MEN_DESK_PLUGINS").toUtf8().data());
390 // end of SALOME plugins loading
397 \brief Close application.
399 void SalomeApp_Application::onExit()
401 //MessageLocker ml( myToIgnoreMessages );
403 bool killServers = false;
406 if ( exitConfirmation() ) {
407 SalomeApp_ExitDlg dlg( desktop() );
408 result = dlg.exec() == QDialog::Accepted;
409 killServers = dlg.isServersShutdown();
413 if ( !killServers ) myIsCloseFromExit = true;
414 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
415 if ( SUIT_Session::session()->applications().count() > 0 ) myIsCloseFromExit = false;
419 /*!SLOT. Create a document.*/
420 void SalomeApp_Application::onNewDoc()
422 MessageLocker ml( myToIgnoreMessages );
424 LightApp_Application::onNewDoc();
427 /*!SLOT. Load document.*/
428 void SalomeApp_Application::onLoadDoc()
430 MessageLocker ml( myToIgnoreMessages );
434 // rnv: According to the single-study approach on the server side
435 // can be only one study. So if it is exists connect to them,
436 // overwise show warning message: "No active study on the server"
439 SUIT_Session* aSession = SUIT_Session::session();
440 QList<SUIT_Application*> aAppList = aSession->applications();
442 QStringList unloadedStudies;
444 for ( unsigned int ind = 0; ind < List.size(); ind++ ) {
445 studyName = List[ind].c_str();
446 // Add to list only unloaded studies
447 bool isAlreadyOpen = false;
448 QListIterator<SUIT_Application*> it( aAppList );
449 while ( it.hasNext() && !isAlreadyOpen ) {
450 SUIT_Application* aApp = it.next();
451 if( !aApp || !aApp->activeStudy() )
453 if ( aApp->activeStudy()->studyName() == studyName )
454 isAlreadyOpen = true;
457 if ( !isAlreadyOpen )
458 unloadedStudies << studyName;
460 studyName = SalomeApp_LoadStudiesDlg::selectStudy( desktop(), unloadedStudies );
461 if ( studyName.isEmpty() )
466 SUIT_MessageBox::warning( desktop(),
467 QObject::tr("WRN_WARNING"),
468 QObject::tr("WRN_NO_STUDY_ON SERV") );
472 studyName = activeStudy()->studyName();
475 // this code replaces marker of windows drive and path become invalid therefore
476 // defines placed there
477 studyName.replace( QRegExp(":"), "/" );
480 if ( onLoadDoc( studyName ) ) {
482 updateViewManagers();
483 updateObjectBrowser( true );
487 /*!SLOT. Unload document.*/
488 void SalomeApp_Application::onUnloadDoc( bool ask )
491 activeStudy()->abortAllOperations();
492 if ( activeStudy()->isModified() ) {
493 QString docName = activeStudy()->studyName().trimmed();
494 int answer = SUIT_MessageBox::question( desktop(), tr( "DISCONNECT_CAPTION" ),
495 tr( "DISCONNECT_DESCRIPTION" ),
496 tr( "DISCONNECT_SAVE" ),
497 tr( "DISCONNECT_WO_SAVE" ),
498 tr( "APPCLOSE_CANCEL" ), 0 );
499 if ( answer == 0 ) { // save before unload
500 if ( activeStudy()->isSaved() )
502 else if ( !onSaveAsDoc() )
505 else if ( answer == 2 ) // Cancel
509 closeActiveDoc( false );
512 /*!SLOT. Create new study and load script*/
513 void SalomeApp_Application::onNewWithScript()
515 QStringList filtersList;
516 filtersList.append(tr("PYTHON_FILES_FILTER"));
517 filtersList.append(tr("ALL_FILES_FILTER"));
519 QString anInitialPath = "";
520 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
521 anInitialPath = QDir::currentPath();
523 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
525 if ( !aFile.isEmpty() )
529 QString command = QString("exec(open(\"%1\", \"rb\").read())").arg(aFile);
531 #ifndef DISABLE_PYCONSOLE
532 PyConsole_Console* pyConsole = pythonConsole();
535 pyConsole->exec( command );
541 /*!SLOT. Load document with \a aName.*/
542 bool SalomeApp_Application::onLoadDoc( const QString& aName )
544 if ( !LightApp_Application::closeDoc() )
548 if ( !activeStudy() ) {
549 // if no study - load in current desktop
550 res = useStudy( aName );
553 // if study exists - load in new desktop. Check: is the same file is loaded?
554 SUIT_Session* aSession = SUIT_Session::session();
555 QList<SUIT_Application*> aAppList = aSession->applications();
556 bool isAlreadyOpen = false;
557 SalomeApp_Application* aApp = 0;
558 for ( QList<SUIT_Application*>::iterator it = aAppList.begin();
559 it != aAppList.end() && !isAlreadyOpen; ++it ) {
560 aApp = dynamic_cast<SalomeApp_Application*>( *it );
561 if ( aApp && aApp->activeStudy()->studyName() == aName )
562 isAlreadyOpen = true;
564 if ( !isAlreadyOpen ) {
565 aApp = dynamic_cast<SalomeApp_Application*>( startApplication( 0, 0 ) );
567 res = aApp->useStudy( aName );
570 aApp->desktop()->activateWindow();
577 /*!SLOT. Parse message for desktop.*/
578 void SalomeApp_Application::onDesktopMessage( const QString& message )
580 if ( myToIgnoreMessages )
581 return; // a message from SALOMEDS is caused by GUI action
583 MessageLocker ml( myToIgnoreMessages );
585 if (message.indexOf("studyCreated") == 0) {
586 if (!activeStudy()) {
588 updateCommandsStatus();
591 if (message.indexOf("studyCleared") == 0) {
592 // Disconnect GUI from active study, because it was closed on DS side.
594 closeActiveDoc( false );
595 // Disable 'Connect' action
596 QAction* a = action( ConnectId );
598 a->setEnabled( false );
601 else if ( message.toLower() == "connect_to_study" ) {
603 useStudy( activeStudy()->studyName() );
605 if (message.indexOf("studyNameChanged") == 0) {
606 updateDesktopTitle();
608 LightApp_Application::onDesktopMessage( message );
611 /*!On module activation action.*/
612 void SalomeApp_Application::onModuleActivation( const QString& modName )
614 if (!activeStudy() && !modName.isEmpty())
617 LightApp_Application::onModuleActivation( modName );
620 /*!SLOT. Copy objects to study maneger from selection maneger..*/
621 void SalomeApp_Application::onCopy()
623 LightApp_Application::onCopy();
626 LightApp_SelectionMgr* mgr = selectionMgr();
627 mgr->selectedObjects(list);
629 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
630 if(study == NULL) return;
632 _PTR(Study) stdDS = getStudy();
635 SALOME_ListIteratorOfListIO it( list );
638 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
643 onSelectionChanged();
651 /*!SLOT. Paste objects to study maneger from selection manager.*/
652 void SalomeApp_Application::onPaste()
654 LightApp_Application::onPaste();
657 LightApp_SelectionMgr* mgr = selectionMgr();
658 mgr->selectedObjects(list);
660 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
661 if(study == NULL) return;
663 _PTR(Study) stdDS = getStudy();
666 if ( stdDS->GetProperties()->IsLocked() ) {
667 SUIT_MessageBox::warning( desktop(),
668 QObject::tr("WRN_WARNING"),
669 QObject::tr("WRN_STUDY_LOCKED") );
673 SALOME_ListIteratorOfListIO it( list );
676 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
681 updateObjectBrowser( true );
682 updateActions(); //SRN: BugID IPAL9377, case 3
690 /*!Check the application on closing.
691 * \retval true if possible, else false
693 bool SalomeApp_Application::isPossibleToClose( bool& closePermanently )
695 return LightApp_Application::isPossibleToClose( closePermanently );
698 /*! Check if the study is locked */
699 void SalomeApp_Application::onCloseDoc( bool ask )
701 if(getStudy()->IsStudyLocked()) {
702 if ( SUIT_MessageBox::question( desktop(),
703 QObject::tr( "WRN_WARNING" ),
704 QObject::tr( "CLOSE_LOCKED_STUDY" ),
705 SUIT_MessageBox::Yes | SUIT_MessageBox::No,
706 SUIT_MessageBox::No) == SUIT_MessageBox::No ) return;
709 MessageLocker ml( myToIgnoreMessages );
711 LightApp_Application::onCloseDoc( ask );
713 // reinitialize study to have empty data
714 //getStudy()->Init();
717 /*!SLOT. Reload document from the file.*/
718 bool SalomeApp_Application::onReopenDoc()
720 MessageLocker ml( myToIgnoreMessages );
722 return LightApp_Application::onReopenDoc();
726 /*!SLOT. Load document.*/
727 void SalomeApp_Application::onOpenDoc()
729 MessageLocker ml( myToIgnoreMessages );
731 LightApp_Application::onOpenDoc();
734 /*!SLOT. Load document.*/
735 bool SalomeApp_Application::onOpenDoc(const QString& name)
737 MessageLocker ml( myToIgnoreMessages );
739 return LightApp_Application::onOpenDoc(name);
742 /*!Sets enable or disable some actions on selection changed.*/
743 void SalomeApp_Application::onSelectionChanged()
746 LightApp_SelectionMgr* mgr = selectionMgr();
747 mgr->selectedObjects(list);
749 bool canCopy = false;
750 bool canPaste = false;
752 LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
755 canCopy = m->canCopy();
756 canPaste = m->canPaste();
759 SALOME_ListIteratorOfListIO it ( list );
761 if (it.More() && list.Extent() == 1) {
762 _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry());
765 canCopy = canCopy || getStudy()->CanCopy(so);
766 canPaste = canPaste || getStudy()->CanPaste(so);
770 action(EditCopyId)->setEnabled(canCopy);
771 action(EditPasteId)->setEnabled(canPaste);
774 /*!Delete references.*/
775 void SalomeApp_Application::onDeleteInvalidReferences()
778 LightApp_SelectionMgr* mgr = selectionMgr();
779 mgr->selectedObjects( aList, QString(), false );
781 if( aList.IsEmpty() )
784 _PTR(Study) aStudyDS = getStudy();
785 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
788 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
789 if ( it.Value()->hasEntry() )
791 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
792 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
795 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
796 aStudyBuilder->RemoveReference( aSObject );
798 updateObjectBrowser();
802 void SalomeApp_Application::onOpenWith()
804 QApplication::setOverrideCursor( Qt::WaitCursor );
806 LightApp_SelectionMgr* mgr = selectionMgr();
807 mgr->selectedObjects(aList);
808 if (aList.Extent() != 1)
810 QApplication::restoreOverrideCursor();
813 Handle(SALOME_InteractiveObject) aIObj = aList.First();
814 QString aModuleName(aIObj->getComponentDataType());
815 QString aModuleTitle = moduleTitle(aModuleName);
816 if (aModuleTitle.isEmpty()) // no gui
817 aModuleTitle = moduleDisplayer(aModuleName);
818 activateModule(aModuleTitle);
819 QApplication::restoreOverrideCursor();
825 SUIT_Study* SalomeApp_Application::createNewStudy()
827 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
829 // Set up processing of major study-related events
830 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
831 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
832 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
833 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
835 #ifndef DISABLE_PYCONSOLE
836 //to receive signal in application that NoteBook's variable was modified
837 connect( aStudy, SIGNAL(notebookVarUpdated(QString)),
838 this, SIGNAL(notebookVarUpdated(QString)) );
847 Enable/Disable menu items and toolbar buttons. Rebuild menu
849 void SalomeApp_Application::updateCommandsStatus()
851 LightApp_Application::updateCommandsStatus();
854 QAction* a = action( DumpStudyId );
856 a->setEnabled( activeStudy() );
858 #ifndef DISABLE_PYCONSOLE
860 a = action( LoadScriptId );
862 a->setEnabled( pythonConsole() );
866 a = action( PropertiesId );
868 a->setEnabled( activeStudy() );
870 // Save GUI state menu
871 a = action( SaveGUIStateId );
873 a->setEnabled( activeStudy() );
875 // Connect study menu
876 a = action( ConnectId );
878 a->setEnabled( !activeStudy() );
880 // Disconnect study menu
881 a = action( DisconnectId );
883 a->setEnabled( activeStudy() );
885 // update state of Copy/Paste menu items
886 onSelectionChanged();
890 \class DumpStudyFileDlg
891 Private class used in Dump Study operation. Consists 2 check boxes:
892 "Publish in study" and "Save GUI parameters"
894 class DumpStudyFileDlg : public SUIT_FileDlg
897 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
899 QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
902 QWidget *hB = new QWidget( this );
903 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY") );
904 myMultiFileChk = new QCheckBox( tr("MULTI_FILE_DUMP") );
905 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE") );
907 QHBoxLayout *layout = new QHBoxLayout;
908 layout->addWidget(myPublishChk);
909 layout->addWidget(myMultiFileChk);
910 layout->addWidget(mySaveGUIChk);
911 hB->setLayout(layout);
913 QPushButton* pb = new QPushButton(this);
915 int row = grid->rowCount();
916 grid->addWidget( new QLabel("", this), row, 0 );
917 grid->addWidget( hB, row, 1, 1, 3 );
918 grid->addWidget( pb, row, 5 );
923 QCheckBox* myPublishChk;
924 QCheckBox* myMultiFileChk;
925 QCheckBox* mySaveGUIChk;
928 /*!Private SLOT. On dump study.*/
929 void SalomeApp_Application::onDumpStudy( )
931 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
932 if ( !appStudy ) return;
934 QStringList aFilters;
935 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
937 bool anIsPublish = true;
938 bool anIsMultiFile = false;
939 bool anIsSaveGUI = true;
941 if ( SUIT_ResourceMgr* aResourceMgr = resourceMgr() ) {
942 anIsPublish = aResourceMgr->booleanValue( "Study", "pydump_publish", anIsPublish );
943 anIsMultiFile = aResourceMgr->booleanValue( "Study", "multi_file_dump", anIsMultiFile );
944 anIsSaveGUI = aResourceMgr->booleanValue( "Study", "pydump_save_gui", anIsSaveGUI );
947 DumpStudyFileDlg fd( desktop() );
948 fd.setValidator( new LightApp_PyFileValidator( &fd ) );
949 fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
950 fd.setNameFilters( aFilters );
951 fd.myPublishChk->setChecked( anIsPublish );
952 fd.myMultiFileChk->setChecked( anIsMultiFile );
953 fd.mySaveGUIChk->setChecked( anIsSaveGUI );
954 if ( fd.exec() == QDialog::Accepted )
956 QString aFileName = fd.selectedFile();
958 bool toPublish = fd.myPublishChk->isChecked();
959 bool isMultiFile = fd.myMultiFileChk->isChecked();
960 bool toSaveGUI = fd.mySaveGUIChk->isChecked();
962 if ( !aFileName.isEmpty() ) {
963 QFileInfo aFileInfo(aFileName);
964 if( aFileInfo.isDir() ) // IPAL19257
967 // Issue 21377 - dump study implementation moved to SalomeApp_Study class
970 SUIT_OverrideCursor wc;
971 ensureShaperIsActivated();
972 res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
975 SUIT_MessageBox::warning( desktop(),
976 QObject::tr("WRN_WARNING"),
977 tr("WRN_DUMP_STUDY_FAILED") );
982 /*!Private SLOT. On load script.*/
983 void SalomeApp_Application::onLoadScript( )
985 if ( getStudy()->GetProperties()->IsLocked() ) {
986 SUIT_MessageBox::warning( desktop(),
987 QObject::tr("WRN_WARNING"),
988 QObject::tr("WRN_STUDY_LOCKED") );
992 QStringList filtersList;
993 filtersList.append(tr("PYTHON_FILES_FILTER"));
994 filtersList.append(tr("ALL_FILES_FILTER"));
996 QString anInitialPath = "";
997 if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() )
998 anInitialPath = QDir::currentPath();
1000 QString aFile = SUIT_FileDlg::getFileName( desktop(), anInitialPath, filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
1002 if ( !aFile.isEmpty() )
1005 QString command = QString("exec(compile(open('%1', 'rb').read(), '%1', 'exec'))").arg(aFile);
1007 #ifndef DISABLE_PYCONSOLE
1008 PyConsole_Console* pyConsole = pythonConsole();
1011 pyConsole->exec( command );
1016 /*!Private SLOT. On save GUI state.*/
1017 void SalomeApp_Application::onSaveGUIState()
1019 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1021 SalomeApp_VisualState( this ).storeState();
1022 updateSavePointDataObjects( study );
1023 updateObjectBrowser();
1028 /*!Public SLOT. Performs some actions when dockable windows are triggered.*/
1029 void SalomeApp_Application::onDockWindowVisibilityChanged( bool theIsVisible )
1031 LightApp_Application::onDockWindowVisibilityChanged( theIsVisible );
1032 QAction* send = ::qobject_cast<QAction*>( sender() );
1035 QString aWinName = send->data().toString();
1036 if ( theIsVisible && aWinName == "objectBrowser" )
1037 objectBrowserColumnsVisibility();
1041 QWidget* SalomeApp_Application::createWindow( const int flag )
1044 #ifndef DISABLE_PYCONSOLE
1045 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
1047 wid = LightApp_Application::createWindow(flag);
1050 SUIT_ResourceMgr* resMgr = resourceMgr();
1052 if ( flag == WT_ObjectBrowser )
1054 SUIT_DataBrowser* ob = qobject_cast<SUIT_DataBrowser*>( wid );
1056 // temporary commented
1057 //ob->setUpdater( new SalomeApp_Updater() );
1059 #ifdef WITH_SALOMEDS_OBSERVER
1060 //do not activate the automatic update of Qt tree through signal/slot
1061 ob->setAutoUpdate(false);
1062 //activate update of modified objects only
1063 ob->setUpdateModified(true);
1066 connect( ob, SIGNAL( doubleClicked( SUIT_DataObject* ) ), this, SLOT( onDblClick( SUIT_DataObject* ) ) );
1069 ValueCol = QObject::tr( "VALUE_COLUMN" ),
1070 IORCol = QObject::tr( "IOR_COLUMN" ),
1071 RefCol = QObject::tr( "REFENTRY_COLUMN" ),
1072 EntryCol = QObject::tr( "ENTRY_COLUMN" );
1074 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
1075 treeModel->registerColumn( 0, EntryCol, SalomeApp_DataObject::EntryId );
1076 treeModel->registerColumn( 0, ValueCol, SalomeApp_DataObject::ValueId );
1077 treeModel->registerColumn( 0, IORCol, SalomeApp_DataObject::IORId );
1078 treeModel->registerColumn( 0, RefCol, SalomeApp_DataObject::RefEntryId );
1079 treeModel->setAppropriate( EntryCol, Qtx::Toggled );
1080 treeModel->setAppropriate( ValueCol, Qtx::Toggled );
1081 treeModel->setAppropriate( IORCol, Qtx::Toggled );
1082 treeModel->setAppropriate( RefCol, Qtx::Toggled );
1084 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
1085 bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
1086 bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", true );
1088 ob->setAutoSizeFirstColumn(autoSizeFirst);
1089 ob->setAutoSizeColumns(autoSize);
1090 ob->setResizeOnExpandItem(resizeOnExpandItem);
1091 ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
1093 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1095 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1096 ob->treeView()->setColumnHidden( i, !shown );
1099 // temporary commented
1101 for ( int i = SalomeApp_DataObject::ValueIdx; i <= SalomeApp_DataObject::RefEntryIdx; i++ )
1103 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
1104 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
1105 QString().sprintf( "visibility_column_%d", i ), true ) );
1109 // temporary commented
1111 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
1112 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
1113 ob->resize( desktop()->width()/3, ob->height() );
1117 #ifndef DISABLE_PYCONSOLE
1118 else if ( flag == WT_PyConsole )
1120 PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
1121 pyCons->setObjectName( "pythonConsole" );
1122 pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
1123 pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
1124 pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
1125 pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
1126 pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
1129 else if ( flag == WT_NoteBook )
1131 setNoteBook( new SalomeApp_NoteBook( desktop() ) );
1132 //to receive signal in NoteBook that it's variable was modified
1133 connect( this, SIGNAL( notebookVarUpdated( QString ) ),
1134 getNoteBook(), SLOT( onVarUpdate( QString ) ) );
1136 wid = getNoteBook();
1137 wid->setObjectName( "noteBook" );
1143 /*!Create preferences.*/
1144 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
1146 LightApp_Application::createPreferences(pref);
1151 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
1152 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
1153 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
1154 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1156 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i-SalomeApp_DataObject::EntryId ).toLatin1() ), defCols,
1157 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_id_%d", i-1 ) );
1159 pref->setItemProperty( "orientation", Qt::Vertical, defCols );
1161 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
1162 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
1163 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
1164 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
1165 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1166 pref->addPreference( tr( "PREF_PYDUMP_PUBLISH" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_publish" );
1167 pref->addPreference( tr( "PREF_PYDUMP_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file_dump" );
1168 pref->addPreference( tr( "PREF_PYDUMP_SAVE_GUI" ), studyGroup, LightApp_Preferences::Bool, "Study", "pydump_save_gui" );
1169 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1170 pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
1173 /*!Update desktop title.*/
1174 void SalomeApp_Application::updateDesktopTitle() {
1175 QString aTitle = applicationName();
1176 QString aVer = applicationVersion();
1177 if ( !aVer.isEmpty() )
1178 aTitle += QString( " " ) + aVer;
1180 if ( activeStudy() )
1182 QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
1183 if ( !sName.isEmpty() ) {
1184 if ( getStudy()->GetProperties()->IsLocked() ) {
1185 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
1187 aTitle += QString( " - [%1]" ).arg( sName );
1192 desktop()->setWindowTitle( aTitle );
1195 int SalomeApp_Application::closeChoice( const QString& /*docName*/ )
1197 QStringList buttons;
1198 QMap<int, int> choices;
1200 buttons << tr ("APPCLOSE_SAVE"); // Save & Clear
1201 choices.insert( idx++, CloseSave ); // ...
1202 buttons << tr ("APPCLOSE_CLOSE"); // Clear w/o saving
1203 choices.insert( idx++, CloseDiscard ); // ...
1204 if ( myIsCloseFromExit ) {
1205 buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect
1206 choices.insert( idx++, CloseDisconnectSave ); // ...
1207 buttons << tr ("APPCLOSE_UNLOAD"); // Disconnect
1208 choices.insert( idx++, CloseDisconnect ); // ...
1210 buttons << tr ("APPCLOSE_CANCEL"); // Cancel
1211 choices.insert( idx++, CloseCancel ); // ...
1213 if( !activeStudy()->isModified() )
1215 int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ),
1216 tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 );
1217 return choices[answer];
1220 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
1226 if ( activeStudy()->isSaved() )
1228 else if ( !onSaveAsDoc() )
1233 case CloseDisconnectSave:
1234 if ( activeStudy()->isSaved() )
1236 else if ( !onSaveAsDoc() )
1239 case CloseDisconnect:
1240 closeActiveDoc( false );
1241 closePermanently = false;
1250 int SalomeApp_Application::openChoice( const QString& aName )
1252 int choice = LightApp_Application::openChoice( aName );
1254 if ( QFileInfo( aName ).exists() ) {
1255 if ( choice == OpenNew ) { // The document isn't already open.
1257 if ( aName == getStudy()->Name().c_str() )
1259 // The document already exists in the study.
1260 // Do you want to reload it?
1262 int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ),
1263 SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No );
1264 if ( answer == SUIT_MessageBox::Yes )
1265 choice = OpenRefresh;
1267 choice = OpenCancel;
1270 } else { // file is not exist on disk
1271 SUIT_MessageBox::warning( desktop(),
1272 QObject::tr("WRN_WARNING"),
1273 QObject::tr("WRN_FILE_NOT_EXIST").arg(aName.toUtf8().data()));
1280 bool SalomeApp_Application::openAction( const int aChoice, const QString& aName )
1283 int choice = aChoice;
1290 res = LightApp_Application::openAction( choice, aName );
1298 \brief Get map of the operations which can be performed
1299 on the module activation.
1301 The method should return the map of the kind \c {<id>:<name>}
1302 where \c <id> is an integer identifier of the operation and
1303 \c <name> is a title for the button to be added to the
1304 dialog box. After user selects the required operation by the
1305 clicking the corresponding button in the dialog box, its identifier
1306 is passed to the moduleActionSelected() method to process
1309 \return map of the operations
1310 \sa moduleActionSelected()
1312 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
1314 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
1316 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
1318 opmap.insert( NewAndScriptId, tr( "ACTIVATE_MODULE_OP_SCRIPT" ) );
1323 \brief Called when the used selectes required operation chosen
1324 from "Activate module" dialog box.
1326 Performs the required operation according to the user choice.
1328 \param id operation identifier
1329 \sa activateModuleActions()
1331 void SalomeApp_Application::moduleActionSelected( const int id )
1337 case NewAndScriptId:
1341 LightApp_Application::moduleActionSelected( id );
1346 /*!Gets CORBA::ORB_var*/
1347 CORBA::ORB_var SalomeApp_Application::orb()
1349 static CORBA::ORB_var _orb;
1351 if ( CORBA::is_nil( _orb ) ) {
1352 Qtx::CmdLineArgs args;
1353 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
1354 _orb = init( args.argc(), args.argv() );
1360 /*!Create and return SALOMEDS_Study.*/
1361 _PTR(Study) SalomeApp_Application::getStudy()
1363 static _PTR(Study) _study;
1365 CORBA::Object_var aSObject = namingService()->Resolve("/Study");
1366 SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(aSObject);
1367 _study = ClientFactory::Study(aStudy);
1372 /*!Create and return SALOME_NamingService.*/
1373 SALOME_NamingService* SalomeApp_Application::namingService()
1375 static SALOME_NamingService _ns(orb());
1379 /*!Create and return SALOME_LifeCycleCORBA.*/
1380 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
1382 static SALOME_LifeCycleCORBA _lcc( namingService() );
1386 /*!Private SLOT. On preferences.*/
1387 void SalomeApp_Application::onProperties()
1389 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1393 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1396 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1397 int res = aDlg.exec();
1398 if( res==QDialog::Accepted && aDlg.isChanged() )
1399 SB->CommitCommand();
1403 //study->updateCaptions();
1404 updateDesktopTitle();
1408 /*!Insert items in popup, which necessary for current application*/
1409 void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
1411 LightApp_SelectionMgr* mgr = selectionMgr();
1412 bool cacheIsOn = mgr->isSelectionCacheEnabled();
1413 mgr->setSelectionCacheEnabled( true );
1415 LightApp_Application::contextMenuPopup( type, thePopup, title );
1417 // temporary commented
1418 /*OB_Browser* ob = objectBrowser();
1419 if ( !ob || type != ob->popupClientType() )
1422 // Get selected objects
1423 SALOME_ListIO aList;
1424 mgr->selectedObjects( aList, QString(), false );
1426 // add GUI state commands: restore, rename
1427 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1428 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1429 thePopup->addSeparator();
1430 thePopup->addAction( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1431 thePopup->addAction( tr( "MEN_RENAME_VS" ), objectBrowser(),
1432 SLOT( onStartEditing() ), objectBrowser()->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
1433 thePopup->addAction( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1436 // "Delete reference" item should appear only for invalid references
1438 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1439 bool isInvalidRefs = false;
1441 _PTR(SObject) anObj;
1442 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1444 if( it.Value()->hasEntry() )
1446 _PTR(SObject) aSObject = getStudy()->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1447 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1450 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1451 isInvalidRefs = true;
1455 // Add "Delete reference" item to popup
1456 if ( isInvalidRefs )
1458 thePopup->addSeparator();
1459 thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1463 // "Activate module" item should appear only if it's necessary
1464 if ( aList.Extent() == 1 ) {
1466 mgr->selectedObjects( aList );
1468 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1470 // add extra popup menu (defined in XML)
1471 if ( myExtActions.size() > 0 ) {
1472 // Use only first selected object
1473 _PTR(SObject) aSO = getStudy()->FindObjectID( aIObj->getEntry() );
1475 _PTR( GenericAttribute ) anAttr;
1476 std::string auid = "AttributeUserID";
1477 auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID);
1478 if ( aSO->FindAttribute( anAttr, auid ) ) {
1479 _PTR(AttributeUserID) aAttrID = anAttr;
1480 QString aId = aAttrID->Value().c_str();
1481 if ( myExtActions.contains( aId ) ) {
1482 thePopup->addAction(myExtActions[aId]);
1488 // check if item is a "GUI state" item (also a first level object)
1489 QString entry( aIObj->getEntry() );
1490 if ( !entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1491 QString aModuleName( aIObj->getComponentDataType() );
1492 QString aModuleTitle = moduleTitle( aModuleName );
1493 if (aModuleTitle.isEmpty()) {
1494 // use displayer module, if given
1495 aModuleTitle = moduleDisplayer( aModuleName );
1497 CAM_Module* currentModule = activeModule();
1498 if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) {
1499 thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1504 mgr->setSelectionCacheEnabled( cacheIsOn );
1507 /*!Update obect browser:
1508 1.if 'updateModels' true, update existing data models;
1509 2. update "non-existing" (not loaded yet) data models;
1510 3. update object browser if it exists */
1511 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1513 // update "non-existing" (not loaded yet) data models
1514 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1517 for ( _PTR(SComponentIterator) it ( getStudy()->NewComponentIterator() ); it->More(); it->Next() )
1519 _PTR(SComponent) aComponent ( it->Value() );
1521 #ifndef WITH_SALOMEDS_OBSERVER
1522 // with GUI observers this check is not needed anymore
1523 if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() )
1524 continue; // skip the magic "Interface Applicative" component
1526 if ( !objectBrowser() )
1527 getWindow( WT_ObjectBrowser );
1528 const bool isAutoUpdate = objectBrowser()->autoUpdate();
1529 objectBrowser()->setAutoUpdate( false );
1530 SalomeApp_DataModel::synchronize( aComponent, study );
1531 objectBrowser()->setAutoUpdate( isAutoUpdate );
1535 // create data objects that correspond to GUI state save points
1536 if ( study ) updateSavePointDataObjects( study );
1538 // update existing data models (already loaded SComponents)
1539 LightApp_Application::updateObjectBrowser( updateModels );
1542 /*!Display Catalog Genenerator dialog */
1543 void SalomeApp_Application::onCatalogGen()
1545 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1549 /*!Display Registry Display dialog */
1550 void SalomeApp_Application::onRegDisplay()
1552 CORBA::ORB_var anOrb = orb();
1553 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop() );
1556 regWnd->activateWindow();
1559 /*!find original object by double click on item */
1560 void SalomeApp_Application::onDblClick( SUIT_DataObject* theObj )
1562 // Issue 21379: References are supported at LightApp_DataObject level
1563 LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( theObj );
1565 if( obj && obj->isReference() )
1567 QString entry = obj->refEntry();
1569 SUIT_DataOwnerPtrList aList;
1570 aList.append( new LightApp_DataOwner( entry ) );
1571 selectionMgr()->setSelected( aList, false );
1573 SUIT_DataBrowser* ob = objectBrowser();
1575 QModelIndexList aSelectedIndexes = ob->selectedIndexes();
1576 if ( !aSelectedIndexes.isEmpty() )
1577 ob->treeView()->scrollTo( aSelectedIndexes.first() );
1579 emit objectDoubleClicked( theObj );
1583 Creates new view manager
1584 \param type - type of view manager
1586 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1588 return createViewManager(type);
1592 /*!Global utility function, returns selected GUI Save point object's ID */
1593 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1595 SALOME_ListIO aList;
1596 selMgr->selectedObjects( aList );
1597 if( aList.Extent() > 0 ) {
1598 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1599 QString entry( aIObj->getEntry() );
1600 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1601 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1603 bool ok; // conversion to integer is ok?
1604 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1605 return ok ? savePoint : -1;
1610 /*!Called on Restore GUI State popup command*/
1611 void SalomeApp_Application::onRestoreGUIState()
1613 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1614 if ( savePoint == -1 )
1616 SalomeApp_VisualState( this ).restoreState( savePoint );
1619 /*!Called on Delete GUI State popup command*/
1620 void SalomeApp_Application::onDeleteGUIState()
1622 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1623 if ( savePoint == -1 )
1625 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1629 study->removeSavePoint( savePoint );
1630 updateSavePointDataObjects( study );
1633 /*!Called on New study operation*/
1634 void SalomeApp_Application::onStudyCreated( SUIT_Study* study )
1636 LightApp_Application::onStudyCreated( study );
1638 //#ifndef DISABLE_PYCONSOLE
1639 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1640 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1643 loadDockWindowsState();
1645 objectBrowserColumnsVisibility();
1648 /*!Called on Open study operation*/
1649 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1651 LightApp_Application::onStudyOpened( study );
1653 //#ifndef DISABLE_PYCONSOLE
1654 // desktop()->tabifyDockWidget( windowDock( getWindow( WT_NoteBook ) ),
1655 // windowDock( getWindow( WT_ObjectBrowser ) ) );
1658 loadDockWindowsState();
1660 objectBrowserColumnsVisibility();
1662 // temporary commented
1663 /*if ( objectBrowser() ) {
1664 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1665 objectBrowser()->updateTree( study->root() );
1669 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1670 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1673 SUIT_DataBrowser* ob = objectBrowser();
1674 LightApp_SelectionMgr* selMgr = selectionMgr();
1676 if ( !study || !ob || !selMgr )
1679 // find GUI states root object
1680 SUIT_DataObject* guiRootObj = 0;
1682 study->root()->children( ch );
1683 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1684 for ( ; it != last ; ++it ) {
1685 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1690 std::vector<int> savePoints = study->getSavePoints();
1691 // case 1: no more save points but they existed in study's tree
1692 if ( savePoints.empty() && guiRootObj ) {
1693 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1694 // : set auto update to true for removing SalomeApp_SavePointRootObject from the SUIT_TreeModel
1695 const bool isAutoUpdate = ob->autoUpdate();
1696 selMgr->clearSelected();
1697 ob->setAutoUpdate(true);
1698 DataObjectList ch = guiRootObj->children();
1699 for( int i = 0; i < ch.size(); i++ )
1702 ob->setAutoUpdate(isAutoUpdate);
1705 // case 2: no more save points but root does not exist either
1706 if ( savePoints.empty() && !guiRootObj )
1708 // case 3: save points but no root for them - create it
1709 if ( !savePoints.empty() && !guiRootObj )
1710 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1711 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1712 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1714 if ( guiRootObj->nextBrother() ) {
1715 study->root()->removeChild(guiRootObj);
1716 study->root()->appendChild(guiRootObj);
1717 //study->root()->dump();
1720 // store data objects in a map id-to-DataObject
1721 QMap<int,SalomeApp_SavePointObject*> mapDO;
1723 guiRootObj->children( ch );
1724 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1725 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1727 mapDO[dobj->getId()] = dobj;
1730 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1731 // if in the map - remove it from map.
1732 for ( size_t i = 0; i < savePoints.size(); i++ )
1733 if ( !mapDO.contains( savePoints[i] ) )
1734 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1736 mapDO.remove( savePoints[i] );
1738 // delete DataObjects that are still in the map -- their IDs were not found in data model
1739 if( mapDO.size() > 0) {
1740 //rnv : to fix bug "IPAL22450 TC6.3.0: sigsegv loop deleting the GUI state"
1741 // : set auto update to true for removing SalomeApp_SavePointObject from the SUIT_TreeModel
1742 selMgr->clearSelected();
1743 const bool isAutoUpdate = ob->autoUpdate();
1744 ob->setAutoUpdate(true);
1745 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1747 ob->setAutoUpdate(isAutoUpdate);
1751 /*! Check data object */
1752 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1761 Opens other study into active Study. If Study is empty - creates it.
1762 \param theName - name of study
1764 bool SalomeApp_Application::useStudy( const QString& theName )
1767 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1770 res = aStudy->loadDocument( theName );
1771 updateDesktopTitle();
1772 updateCommandsStatus();
1776 /*! Show/hide object browser colums according to preferences */
1777 void SalomeApp_Application::objectBrowserColumnsVisibility()
1779 if ( objectBrowser() )
1780 for ( int i = SalomeApp_DataObject::EntryId; i < SalomeApp_DataObject::LastId; i++ )
1782 bool shown = resourceMgr()->booleanValue( "ObjectBrowser", QString( "visibility_column_id_%1" ).arg( i-1 ), true );
1783 objectBrowser()->treeView()->setColumnHidden( i, !shown );
1787 #ifndef DISABLE_PYCONSOLE
1788 /*! Set SalomeApp_NoteBook pointer */
1789 void SalomeApp_Application::setNoteBook( SalomeApp_NoteBook* theNoteBook )
1791 myNoteBook = theNoteBook;
1794 /*! Return SalomeApp_NoteBook pointer */
1795 SalomeApp_NoteBook* SalomeApp_Application::getNoteBook() const
1802 * Define extra actions defined in module definition XML file.
1803 * Additional popup items sections can be defined by parameter "popupitems".
1804 * Supported attributes:
1805 * title - title of menu item,
1806 * attributelocalid - AttributeLocalId defined for selected data item where menu command has to be applied,
1807 * method - method which has to be called when menu item is selected
1809 * <section name="MODULENAME">
1810 * <parameter name="popupitems" value="menuitem1:menuitem2:..."/>
1812 * <section name="importmed">
1813 * <parameter name="title" value="My menu"/>
1814 * <parameter name="objectid" value="VISU.Result"/>
1815 * <parameter name="method" value="nameOfModuleMethod"/>
1818 void SalomeApp_Application::createExtraActions()
1820 myExtActions.clear();
1821 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
1823 QStringList aModules;
1824 modules(aModules, false);
1825 foreach(QString aModile, aModules) {
1826 QString aModName = moduleName(aModile);
1827 QString aSectionStr = resMgr->stringValue(aModName, "popupitems", QString());
1828 if (!aSectionStr.isNull()) {
1829 QStringList aSections = aSectionStr.split(':');
1830 foreach(QString aSection, aSections) {
1831 QString aTitle = resMgr->stringValue(aSection, "title", QString());
1832 QString aId = resMgr->stringValue(aSection, "objectid", QString());
1833 QString aSlot = resMgr->stringValue(aSection, "method", QString());
1834 if (aTitle.isEmpty() || aSlot.isEmpty() || aId.isEmpty())
1837 QString aModuleName = resMgr->stringValue(aSection, "module", QString());
1838 if (aModuleName.isNull())
1839 aModuleName = aModName;
1841 QAction* aAction = new QAction(aTitle, this);
1843 aData<<aModuleName<<aSlot;
1844 aAction->setData(aData);
1845 connect(aAction, SIGNAL(triggered()), this, SLOT(onExtAction()));
1846 myExtActions[aId] = aAction;
1853 * Called when extra action is selected
1855 void SalomeApp_Application::onExtAction()
1857 QAction* aAction = ::qobject_cast<QAction*>(sender());
1861 QVariant aData = aAction->data();
1862 QStringList aDataList = aData.value<QStringList>();
1863 if (aDataList.size() != 2)
1866 LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
1867 SALOME_ListIO aListIO;
1868 aSelectionMgr->selectedObjects(aListIO);
1869 const Handle(SALOME_InteractiveObject)& anIO = aListIO.First();
1870 if (aListIO.Extent() < 1)
1872 if (!anIO->hasEntry())
1875 QString aEntry(anIO->getEntry());
1877 QApplication::setOverrideCursor( Qt::WaitCursor );
1878 QString aModuleTitle = moduleTitle(aDataList[0]);
1879 activateModule(aModuleTitle);
1880 QApplication::restoreOverrideCursor();
1882 QCoreApplication::processEvents();
1884 CAM_Module* aModule = activeModule();
1888 if (!QMetaObject::invokeMethod(aModule, qPrintable(aDataList[1]), Q_ARG(QString, aEntry)))
1889 printf("Error: Can't Invoke method %s\n", qPrintable(aDataList[1]));
1893 Checks that an object can be renamed.
1894 \param entry entry of the object
1895 \brief Return \c true if object can be renamed
1897 bool SalomeApp_Application::renameAllowed( const QString& entry) const
1899 return entry.startsWith( tr( "SAVE_POINT_DEF_NAME") );
1903 Rename object by entry.
1904 \param entry entry of the object
1905 \param name new name of the object
1906 \brief Return \c true if rename operation finished successfully, \c false otherwise.
1908 bool SalomeApp_Application::renameObject( const QString& /*entry*/, const QString& name )
1910 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1912 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1914 if(!aStudy || savePoint == -1)
1917 if ( !name.isNull() && !name.isEmpty() ) {
1918 aStudy->setNameOfSavePoint( savePoint, name );
1919 updateSavePointDataObjects( aStudy );
1921 //Mark study as modified
1928 #ifndef DISABLE_PYCONSOLE
1929 //============================================================================
1930 /*! Function : onUpdateStudy
1931 * Purpose : Slot to update the study.
1933 //============================================================================
1934 void SalomeApp_Application::onUpdateStudy()
1936 QApplication::setOverrideCursor( Qt::WaitCursor );
1938 if( !updateStudy() )
1939 SUIT_MessageBox::warning( desktop(), tr( "ERROR" ), tr( "ERR_UPDATE_STUDY_FAILED" ) );
1941 QApplication::restoreOverrideCursor();
1944 //============================================================================
1945 /*! Function : updateStudy
1946 * Purpose : Update study by dumping the study to Python script and loading it.
1947 * It is used to apply variable modifications done in NoteBook to created objects.
1949 //============================================================================
1950 bool SalomeApp_Application::updateStudy()
1952 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1953 if ( !study || !myNoteBook )
1956 myNoteBook->setIsDumpedStudySaved( study->isSaved() );
1957 myNoteBook->setDumpedStudyName( study->studyName() );
1959 // get unique temporary directory name
1960 QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() );
1962 if( aTmpDir.isEmpty() )
1965 if( aTmpDir.right( 1 ).compare( QDir::separator() ) == 0 )
1966 aTmpDir.remove( aTmpDir.length() - 1, 1 );
1968 // dump study to the temporary directory
1969 QString aScriptName( "notebook" );
1970 bool toPublish = true;
1971 bool isMultiFile = false;
1972 bool toSaveGUI = true;
1975 _PTR(AttributeParameter) ap;
1976 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
1977 if(ip->isDumpPython()) ip->setDumpPython(); //Unset DumpPython flag.
1978 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
1979 ip->setDumpPython();
1980 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
1982 bool ok = getStudy()->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile );
1984 study->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
1987 myNoteBook->setDumpedStudyScript( aTmpDir + QDir::separator() + aScriptName + ".py" );
1991 QList<SUIT_Application*> aList = SUIT_Session::session()->applications();
1992 int anIndex = aList.indexOf( this );
1994 // Disconnect dialog from application desktop in case if:
1995 // 1) Application is not the first application in the session
1996 // 2) Application is the first application in session but not the only.
1997 bool changeDesktop = ((anIndex > 0) || (anIndex == 0 && aList.count() > 1));
1998 if( changeDesktop ) {
2000 SalomeApp_Application* app = this;
2001 if( anIndex > 0 && anIndex < aList.count() )
2002 app = dynamic_cast<SalomeApp_Application*>( aList[ anIndex - 1 ] );
2003 else if(anIndex == 0 && aList.count() > 1)
2004 app = dynamic_cast<SalomeApp_Application*>( aList[ 1 ] );
2009 // creation a new study and restoring will be done in another application
2010 connect( this, SIGNAL( dumpedStudyClosed( const QString&, const QString&, bool ) ),
2011 app, SLOT( onRestoreStudy( const QString&, const QString&, bool ) ), Qt::UniqueConnection );
2014 QString aDumpScript = myNoteBook->getDumpedStudyScript();
2015 QString aStudyName = myNoteBook->getDumpedStudyName();
2016 bool isStudySaved = myNoteBook->isDumpedStudySaved();
2017 // clear a study (delete all objects)
2018 onCloseDoc( false );
2020 if( !changeDesktop ) {
2021 ok = onRestoreStudy( aDumpScript,
2030 //============================================================================
2031 /*! Function : onRestoreStudy
2032 * Purpose : Load the dumped study from Python script
2034 //============================================================================
2035 bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript,
2036 const QString& theStudyName,
2037 bool theIsStudySaved )
2041 // create a new study
2044 // get active application
2045 SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
2047 // load study from the temporary directory
2048 QFileInfo aScriptInfo = QFileInfo(theDumpScript);
2049 QString command = QString( "exec(open(\"%1\" ,\"rb\").read())" ).arg(aScriptInfo.canonicalFilePath());
2051 #ifndef DISABLE_PYCONSOLE
2052 PyConsole_Console* pyConsole = app->pythonConsole();
2054 pyConsole->execAndWait( command );
2057 // remove temporary directory
2058 QString aStudyName = aScriptInfo.baseName();
2059 QDir aDir = aScriptInfo.absoluteDir();
2060 QStringList aFiles = aDir.entryList( QStringList( "*.py*" ) );
2061 for( QStringList::iterator it = aFiles.begin(), itEnd = aFiles.end(); it != itEnd; ++it )
2062 ok = aDir.remove( *it ) && ok;
2064 ok = aDir.rmdir( aDir.absolutePath() );
2066 if( SalomeApp_Study* newStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() ) )
2068 #ifndef DISABLE_PYCONSOLE
2069 if ( app->getNoteBook() )
2070 app->getNoteBook()->Init();
2071 newStudy->updateFromNotebook(theStudyName, theIsStudySaved);
2072 newStudy->Modified();
2073 updateDesktopTitle();
2084 Close the Application
2086 void SalomeApp_Application::afterCloseDoc()
2088 #ifndef DISABLE_PYCONSOLE
2089 // emit signal to restore study from Python script
2091 emit dumpedStudyClosed( myNoteBook->getDumpedStudyScript(),
2092 myNoteBook->getDumpedStudyName(),
2093 myNoteBook->isDumpedStudySaved() );
2096 LightApp_Application::afterCloseDoc();
2099 bool SalomeApp_Application::canOpenDoc( const QString& url )
2101 _PTR(Study) aStudyDS = getStudy();
2103 return aStudyDS->CanOpen( url.toUtf8().data() );
2108 Asks to close existing document.
2110 bool SalomeApp_Application::checkExistingDoc()
2112 return LightApp_Application::checkExistingDoc();
2116 #ifndef DISABLE_PYCONSOLE
2118 PyConsole_Interp* SalomeApp_Application::createPyInterp()
2120 return new SalomeApp_PyInterp;
2123 #endif // DISABLE_PYCONSOLE
2125 void SalomeApp_Application::ensureShaperIsActivated()
2127 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
2128 _PTR(Study) studyDS = getStudy();
2129 if ( study && studyDS )
2131 _PTR(SObject) shaper = studyDS->FindObjectByPath("/Shaper"); // non null result if shaper data is present in the study
2132 bool shaperIsActive = false;
2133 QList<CAM_DataModel*> models;
2134 study->dataModels( models );
2135 for( int i = 0; i < models.count() && !shaperIsActive; i++ )
2136 shaperIsActive = models[i]->module()->moduleName() == "Shaper";
2138 if (shaper && !shaperIsActive)
2139 onDesktopMessage("register_module_in_study/Shaper");