1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File: SalomeApp_Application.cxx
20 // Created: 10/22/2004 3:23:45 PM
21 // Author: Sergey LITONIN
22 // Copyright (C) CEA 2004
24 #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
26 #include "SalomeApp_Application.h"
28 #include "SalomeApp_Study.h"
29 #include "SalomeApp_DataModel.h"
30 #include "SalomeApp_DataObject.h"
31 #include "SalomeApp_EventFilter.h"
32 #include "SalomeApp_VisualState.h"
33 #include "SalomeApp_ExitDlg.h"
35 #include "SalomeApp_StudyPropertiesDlg.h"
37 #include "LightApp_Application.h"
38 #include "LightApp_Preferences.h"
39 #include "LightApp_WidgetContainer.h"
40 #include "LightApp_SelectionMgr.h"
41 #include "LightApp_NameDlg.h"
43 #include "STD_LoadStudiesDlg.h"
45 #include <SUIT_Tools.h>
46 #include <SUIT_Session.h>
47 #include <SUIT_MsgDlg.h>
49 #include <QtxMRUAction.h>
51 #include <OB_Browser.h>
52 #include <OB_ListItem.h>
54 #include <PythonConsole_PyConsole.h>
56 #include <SUIT_FileDlg.h>
57 #include <SUIT_MessageBox.h>
58 #include <SUIT_ResourceMgr.h>
59 #include <SUIT_ActionOperation.h>
61 #include <Utils_ORB_INIT.hxx>
62 #include <Utils_SINGLETON.hxx>
63 #include <SALOME_ModuleCatalog_impl.hxx>
64 #include <SALOME_LifeCycleCORBA.hxx>
67 #include <qcombobox.h>
70 #include <qcheckbox.h>
71 #include <qpushbutton.h>
73 #include <qmessagebox.h>
75 #include "SALOMEDSClient_ClientFactory.hxx"
76 #include "SALOMEDSClient_IParameters.hxx"
78 #include "SALOME_ListIteratorOfListIO.hxx"
79 #include "SALOME_ListIO.hxx"
81 #include "ToolsGUI_CatalogGeneratorDlg.h"
82 #include "ToolsGUI_RegWidget.h"
84 #include <SALOMEDSClient_ClientFactory.hxx>
87 /*!Internal class that updates object browser item properties */
88 class SalomeApp_Updater : public OB_Updater
91 SalomeApp_Updater() : OB_Updater(){};
92 virtual ~SalomeApp_Updater(){};
93 virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem );
96 void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem )
98 if( !theObj || !theItem )
101 SalomeApp_DataObject* SAObj = dynamic_cast<SalomeApp_DataObject*>( theObj );
105 _PTR(SObject) SObj = SAObj->object();
108 _PTR( GenericAttribute ) anAttr;
111 if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) )
113 _PTR(AttributeSelectable) aAttrSel = anAttr;
114 theItem->setSelectable( aAttrSel->IsSelectable() );
117 if ( SObj->FindAttribute(anAttr, "AttributeExpandable") )
119 _PTR(AttributeExpandable) aAttrExpand = anAttr;
120 theItem->setExpandable( aAttrExpand->IsExpandable() );
123 //this attribute is not supported in the version of SALOME 3.x
124 //if ( SObj->FindAttribute(anAttr, "AttributeOpened") )
126 // _PTR(AttributeOpened) aAttrOpen = anAttr;
127 // theItem->setOpen( aAttrOpen->IsOpened() );
131 /*!Create new instance of SalomeApp_Application.*/
132 extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication()
134 return new SalomeApp_Application();
138 SalomeApp_Application::SalomeApp_Application()
139 : LightApp_Application()
141 connect( desktop(), SIGNAL( message( const QString& ) ),
142 this, SLOT( onDesktopMessage( const QString& ) ) );
146 *\li Destroy event filter.
148 SalomeApp_Application::~SalomeApp_Application()
150 // Do not destroy. It's a singleton !
151 //SalomeApp_EventFilter::Destroy();
154 /*!Start application.*/
155 void SalomeApp_Application::start()
157 LightApp_Application::start();
159 SalomeApp_EventFilter::Init();
161 static bool isFirst = true;
168 for (int i = 1; i < qApp->argc(); i++) {
169 QRegExp rxs ("--study-hdf=(.+)");
170 if ( rxs.search( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) {
171 QString file = rxs.capturedTexts()[1];
172 QFileInfo fi ( file );
173 QString extension = fi.extension( false ).lower();
174 if ( extension == "hdf" && fi.exists() )
175 hdffile = fi.absFilePath();
178 QRegExp rxp ("--pyscript=(.+)");
179 if ( rxp.search( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) {
180 QStringList files = QStringList::split(",",rxp.capturedTexts()[1],false);
186 if ( !hdffile.isEmpty() ) // open hdf file given as parameter
187 onOpenDoc( hdffile );
188 else if ( pyfiles.count() > 0 ) // create new study
191 // import/execute python scripts
192 if ( pyfiles.count() > 0 && activeStudy() ) {
193 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
195 _PTR(Study) aStudy = appStudy->studyDS();
196 if ( !aStudy->GetProperties()->IsLocked() ) {
197 for (uint j = 0; j < pyfiles.count(); j++ ) {
198 QFileInfo fi ( pyfiles[j] );
199 PythonConsole* pyConsole = pythonConsole();
201 QString extension = fi.extension( false ).lower();
203 // execute python script
204 QString command = QString( "execfile(\"%1\")" ).arg( fi.absFilePath() );
205 pyConsole->exec( command );
208 // import python module
209 QString command = QString( "import %1" ).arg( pyfiles[j] );
210 if ( extension == "py" )
211 command = QString( "import %1" ).arg( fi.baseName( true ) );
212 pyConsole->exec( command );
223 void SalomeApp_Application::createActions()
225 LightApp_Application::createActions();
227 SUIT_Desktop* desk = desktop();
230 // "Save GUI State" command is moved to VISU module
231 // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIconSet(),
232 // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ),
233 // 0, desk, false, this, SLOT( onSaveGUIState() ) );
236 createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIconSet(),
237 tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ),
238 CTRL+Key_D, desk, false, this, SLOT( onDumpStudy() ) );
241 createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIconSet(),
242 tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ),
243 CTRL+Key_T, desk, false, this, SLOT( onLoadScript() ) );
246 createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIconSet(),
247 tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ),
248 CTRL+Key_P, desk, false, this, SLOT( onProperties() ) );
250 //! Catalog Generator
251 createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIconSet(),
252 tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ),
253 SHIFT+Key_G, desk, false, this, SLOT( onCatalogGen() ) );
256 createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIconSet(),
257 tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ),
258 /*SHIFT+Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) );
260 //SRN: BugID IPAL9021, add an action "Load"
261 createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ),
262 resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ),
263 tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ),
264 CTRL+Key_L, desk, false, this, SLOT( onLoadDoc() ) );
265 //SRN: BugID IPAL9021: End
268 int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
270 // "Save GUI State" command is renamed to "Save VISU State" and
271 // creation of menu item is moved to VISU
272 // createMenu( SaveGUIStateId, fileMenu, 10, -1 );
274 createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load"
276 createMenu( DumpStudyId, fileMenu, 10, -1 );
277 createMenu( separator(), fileMenu, -1, 15, -1 );
278 createMenu( LoadScriptId, fileMenu, 10, -1 );
279 createMenu( separator(), fileMenu, -1, 15, -1 );
280 createMenu( PropertiesId, fileMenu, 10, -1 );
281 createMenu( separator(), fileMenu, -1, 15, -1 );
283 int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 );
284 createMenu( CatalogGenId, toolsMenu, 10, -1 );
285 createMenu( RegDisplayId, toolsMenu, 10, -1 );
286 createMenu( separator(), toolsMenu, -1, 15, -1 );
289 /*! Purpose : SLOT. Open new document with \a aName.*/
290 bool SalomeApp_Application::onOpenDoc( const QString& aName )
292 bool res = false, toOpen = true, isAlreadyOpen = false;
294 // Look among opened studies
295 if (activeStudy()) { // at least one study is opened
296 SUIT_Session* aSession = SUIT_Session::session();
297 QPtrList<SUIT_Application> aAppList = aSession->applications();
298 QPtrListIterator<SUIT_Application> it (aAppList);
299 SUIT_Application* aApp = 0;
300 // iterate on all applications
301 for (; (aApp = it.current()) && !isAlreadyOpen; ++it) {
302 if (aApp->activeStudy()->studyName() == aName) {
303 isAlreadyOpen = true; // Already opened, ask user what to do
305 // The document ... is already open.
306 // Do you want to reload it?
307 int aAnswer = SUIT_MessageBox::warn2(desktop(), tr("WRN_WARNING"),
308 tr("QUE_DOC_ALREADYOPEN").arg(aName),
309 tr("BUT_YES"), tr("BUT_NO"), 1, 2, 2);
310 if (aAnswer == 1) { // reload
311 if (activeStudy()->studyName() == aName && aAppList.count() > 1) {
312 // Opened in THIS (active) application.
313 STD_Application* app1 = (STD_Application*)aAppList.at(0);
314 STD_Application* app2 = (STD_Application*)aAppList.at(1);
315 if (!app1 || !app2) {
319 if (app1->activeStudy()->studyName() == aName) {
320 // app1 is this application, we need another one
323 // Close document of this application. This application will be destroyed.
324 onCloseDoc(/*ask = */false);
325 // Open the file with another application, as this one will be destroyed.
326 return app1->onOpenDoc(aName);
328 // Opened in another application.
329 STD_Application* app = (STD_Application*)aApp;
331 app->onCloseDoc(/*ask = */false);
333 } else { // do not reload
334 // OK, the study will not be reloaded, but we call
335 // CAM_Application::onOpenDoc( aName ) all the same.
336 // It will activate a desktop of the study <aName>.
342 // Look among unloaded studies
343 if (!isAlreadyOpen) {
344 std::vector<std::string> List = studyMgr()->GetOpenStudies();
347 for (unsigned int ind = 0; ind < List.size() && !isAlreadyOpen; ind++) {
348 studyName = List[ind].c_str();
349 if (aName == studyName) {
350 // Already exists unloaded, ask user what to do
351 isAlreadyOpen = true;
353 // The document ... already exists in the study manager.
354 // Do you want to reload it?
355 int aAnswer = SUIT_MessageBox::warn2(desktop(), tr("WRN_WARNING"),
356 tr("QUE_DOC_ALREADYEXIST").arg(aName),
357 tr("BUT_YES"), tr("BUT_NO"), 1, 2, 2);
359 _PTR(Study) aStudy = studyMgr()->GetStudyByName(aName.latin1());
361 studyMgr()->Close(aStudy);
370 res = CAM_Application::onOpenDoc( aName );
372 QAction* a = action( MRUId );
373 if ( a && a->inherits( "QtxMRUAction" ) )
375 QtxMRUAction* mru = (QtxMRUAction*)a;
377 mru->insert( aName );
379 mru->remove( aName );
384 /*!SLOT. Load document.*/
385 void SalomeApp_Application::onLoadDoc()
387 QString name, studyname, ext;
389 STD_LoadStudiesDlg aDlg( desktop(), TRUE);
391 std::vector<std::string> List = studyMgr()->GetOpenStudies();
393 SUIT_Session* aSession = SUIT_Session::session();
394 QPtrList<SUIT_Application> aAppList = aSession->applications();
395 SUIT_Application* aApp = 0;
397 for (unsigned int ind = 0; ind < List.size(); ind++) {
398 studyname = List[ind].c_str();
399 //Add to list only unloaded studies
400 bool isAlreadyOpen = false;
401 for ( QPtrListIterator<SUIT_Application> it( aAppList ); it.current() && !isAlreadyOpen; ++it )
404 if(!aApp || !aApp->activeStudy()) continue;
405 if ( aApp->activeStudy()->studyName() == studyname ) isAlreadyOpen = true;
408 if ( !isAlreadyOpen ) aDlg.ListComponent->insertItem( studyname );
411 int retVal = aDlg.exec();
412 studyname = aDlg.ListComponent->currentText();
414 if (retVal == QDialog::Rejected)
417 if ( studyname.isNull() || studyname.isEmpty() )
422 //this code replace marker of windows drive and path become invalid therefore
423 // defines placed there
424 name.replace( QRegExp(":"), "/" );
427 if( LightApp_Application::onLoadDoc( name ) )
430 updateViewManagers();
431 updateObjectBrowser(true);
436 \brief Close application.
438 void SalomeApp_Application::onExit()
440 bool killServers = false;
443 if ( exitConfirmation() ) {
444 SalomeApp_ExitDlg dlg( desktop() );
445 result = dlg.exec() == QDialog::Accepted;
446 killServers = dlg.isServersShutdown();
450 SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers );
453 /*!SLOT. Load document with \a aName.*/
454 bool SalomeApp_Application::onLoadDoc( const QString& aName )
456 return LightApp_Application::onLoadDoc( aName );
459 /*!SLOT. Copy objects to study maneger from selection maneger..*/
460 void SalomeApp_Application::onCopy()
463 LightApp_SelectionMgr* mgr = selectionMgr();
464 mgr->selectedObjects(list);
466 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
467 if(study == NULL) return;
469 _PTR(Study) stdDS = study->studyDS();
472 SALOME_ListIteratorOfListIO it( list );
475 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
477 studyMgr()->Copy(so);
478 onSelectionChanged();
485 /*!SLOT. Paste objects to study maneger from selection manager.*/
486 void SalomeApp_Application::onPaste()
489 LightApp_SelectionMgr* mgr = selectionMgr();
490 mgr->selectedObjects(list);
492 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
493 if(study == NULL) return;
495 _PTR(Study) stdDS = study->studyDS();
498 if ( stdDS->GetProperties()->IsLocked() ) {
499 SUIT_MessageBox::warn1 ( desktop(),
500 QObject::tr("WRN_WARNING"),
501 QObject::tr("WRN_STUDY_LOCKED"),
502 QObject::tr("BUT_OK") );
506 SALOME_ListIteratorOfListIO it( list );
509 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
511 studyMgr()->Paste(so);
512 updateObjectBrowser( true );
513 updateActions(); //SRN: BugID IPAL9377, case 3
520 /*! Check if the study is locked */
521 void SalomeApp_Application::onCloseDoc( bool ask )
523 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
526 _PTR(Study) stdDS = study->studyDS();
527 if(stdDS && stdDS->IsStudyLocked()) {
528 if ( SUIT_MessageBox::warn2( desktop(),
529 QObject::tr( "WRN_WARNING" ),
530 QObject::tr( "CLOSE_LOCKED_STUDY" ),
531 QObject::tr( "BUT_YES" ),
532 QObject::tr( "BUT_NO" ),
535 SUIT_NO ) == SUIT_NO ) return;
540 LightApp_Application::onCloseDoc( ask );
543 /*!Sets enable or disable some actions on selection changed.*/
544 void SalomeApp_Application::onSelectionChanged()
547 LightApp_SelectionMgr* mgr = selectionMgr();
548 mgr->selectedObjects(list);
550 bool canCopy = false;
551 bool canPaste = false;
553 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
555 _PTR(Study) stdDS = study->studyDS();
558 SALOME_ListIteratorOfListIO it ( list );
560 if (it.More() && list.Extent() == 1) {
561 _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry());
564 canCopy = studyMgr()->CanCopy(so);
565 canPaste = studyMgr()->CanPaste(so);
571 action(EditCopyId)->setEnabled(canCopy);
572 action(EditPasteId)->setEnabled(canPaste);
575 /*!Delete references.*/
576 void SalomeApp_Application::onDeleteInvalidReferences()
579 LightApp_SelectionMgr* mgr = selectionMgr();
580 mgr->selectedObjects( aList, QString::null, false );
582 if( aList.IsEmpty() )
585 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
586 _PTR(Study) aStudyDS = aStudy->studyDS();
587 _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder();
590 for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
591 if ( it.Value()->hasEntry() )
593 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
594 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
597 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
598 aStudyBuilder->RemoveReference( aSObject );
600 updateObjectBrowser();
604 void SalomeApp_Application::onOpenWith()
606 QApplication::setOverrideCursor( Qt::waitCursor );
608 LightApp_SelectionMgr* mgr = selectionMgr();
609 mgr->selectedObjects(aList);
610 if (aList.Extent() != 1)
612 QApplication::restoreOverrideCursor();
615 Handle(SALOME_InteractiveObject) aIObj = aList.First();
616 QString aModuleName(aIObj->getComponentDataType());
617 QString aModuleTitle = moduleTitle(aModuleName);
618 activateModule(aModuleTitle);
619 QApplication::restoreOverrideCursor();
625 SUIT_Study* SalomeApp_Application::createNewStudy()
627 SalomeApp_Study* aStudy = new SalomeApp_Study( this );
629 // Set up processing of major study-related events
630 connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
631 connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
632 connect( aStudy, SIGNAL( saved ( SUIT_Study* ) ), this, SLOT( onStudySaved ( SUIT_Study* ) ) );
633 connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
639 Enable/Disable menu items and toolbar buttons. Rebuild menu
641 void SalomeApp_Application::updateCommandsStatus()
643 LightApp_Application::updateCommandsStatus();
646 QAction* a = action( DumpStudyId );
648 a->setEnabled( activeStudy() );
651 a = action( LoadScriptId );
653 a->setEnabled( activeStudy() );
656 a = action( PropertiesId );
658 a->setEnabled( activeStudy() );
660 // Save GUI state menu
661 a = action( SaveGUIStateId );
663 a->setEnabled( activeStudy() );
665 // update state of Copy/Paste menu items
666 onSelectionChanged();
670 \class DumpStudyFileDlg
671 Private class used in Dump Study operation. Consists 2 check boxes:
672 "Publish in study" and "Save GUI parameters"
674 class DumpStudyFileDlg : public SUIT_FileDlg
677 DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true )
679 QHBox* hB = new QHBox( this );
680 myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY"), hB );
681 mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE"), hB );
682 QPushButton* pb = new QPushButton(this);
683 addWidgets( new QLabel("", this), hB, pb );
686 QCheckBox* myPublishChk;
687 QCheckBox* mySaveGUIChk;
690 /*!Private SLOT. On dump study.*/
691 void SalomeApp_Application::onDumpStudy( )
693 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
694 if ( !appStudy ) return;
695 _PTR(Study) aStudy = appStudy->studyDS();
697 QStringList aFilters;
698 aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
700 DumpStudyFileDlg* fd = new DumpStudyFileDlg( desktop() );
701 fd->setCaption( tr( "TOT_DESK_FILE_DUMP_STUDY" ) );
702 fd->setFilters( aFilters );
703 fd->myPublishChk->setChecked( true );
704 fd->mySaveGUIChk->setChecked( true );
709 aFileName = fd->selectedFile();
710 if (!aFileName.isEmpty()) {
711 if ( (aFileName.find('-', 0) == -1) && (aFileName.find('!', 0) == -1) && (aFileName.find('?', 0) == -1) &&
712 (aFileName.find('#', 0) == -1) && (aFileName.find('*', 0) == -1) && (aFileName.find('&', 0) == -1)) {
716 SUIT_MessageBox::warn1 ( desktop(),
717 QObject::tr("WRN_WARNING"),
718 tr("WRN_FILE_NAME_BAD"),
719 QObject::tr("BUT_OK") );
726 bool toPublish = fd->myPublishChk->isChecked();
727 bool toSaveGUI = fd->mySaveGUIChk->isChecked();
730 if ( !aFileName.isEmpty() ) {
731 QFileInfo aFileInfo(aFileName);
733 _PTR(AttributeParameter) ap;
734 _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
735 if(ip->isDumpPython(appStudy->studyDS())) ip->setDumpPython(appStudy->studyDS()); //Unset DumpPython flag.
736 if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
737 ip->setDumpPython(appStudy->studyDS());
738 savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
740 bool res = aStudy->DumpStudy( aFileInfo.dirPath( true ).latin1(), aFileInfo.baseName().latin1(), toPublish);
742 appStudy->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
744 SUIT_MessageBox::warn1 ( desktop(),
745 QObject::tr("WRN_WARNING"),
746 tr("WRN_DUMP_STUDY_FAILED"),
747 QObject::tr("BUT_OK") );
751 /*!Private SLOT. On load script.*/
752 void SalomeApp_Application::onLoadScript( )
754 SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( activeStudy() );
755 if ( !appStudy ) return;
756 _PTR(Study) aStudy = appStudy->studyDS();
758 if ( aStudy->GetProperties()->IsLocked() ) {
759 SUIT_MessageBox::warn1 ( desktop(),
760 QObject::tr("WRN_WARNING"),
761 QObject::tr("WRN_STUDY_LOCKED"),
762 QObject::tr("BUT_OK") );
766 QStringList filtersList;
767 filtersList.append(tr("PYTHON_FILES_FILTER"));
768 filtersList.append(tr("ALL_FILES_FILTER"));
770 QString aFile = SUIT_FileDlg::getFileName( desktop(), "", filtersList, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), true, true );
772 if ( !aFile.isEmpty() )
774 QString command = QString("execfile(\"%1\")").arg(aFile);
776 PythonConsole* pyConsole = pythonConsole();
779 pyConsole->exec( command );
783 /*!Private SLOT. On save GUI state.*/
784 void SalomeApp_Application::onSaveGUIState()
786 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
788 SalomeApp_VisualState( this ).storeState();
789 updateSavePointDataObjects( study );
790 objectBrowser()->updateTree( study->root() );
796 *\retval QString "(*.hdf)"
798 QString SalomeApp_Application::getFileFilter() const
804 QWidget* SalomeApp_Application::createWindow( const int flag )
807 if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag);
809 SUIT_ResourceMgr* resMgr = resourceMgr();
811 if ( flag == WT_ObjectBrowser )
813 OB_Browser* ob = (OB_Browser*)wid;
814 ob->setUpdater( new SalomeApp_Updater() );
815 connect( ob->listView(), SIGNAL( doubleClicked( QListViewItem* ) ), this, SLOT( onDblClick( QListViewItem* ) ) );
816 bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false ),
817 autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
818 for ( int i = SalomeApp_DataObject::CT_Value; i <= SalomeApp_DataObject::CT_RefEntry; i++ )
820 ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i );
821 ob->setColumnShown( i, resMgr->booleanValue( "ObjectBrowser",
822 QString().sprintf( "visibility_column_%d", i ), true ) );
824 ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual );
825 ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual );
826 ob->resize( desktop()->width()/3, ob->height() );
828 else if ( flag == WT_PyConsole )
830 PythonConsole* pyCons = new PythonConsole( desktop(), new SalomeApp_PyInterp() );
831 pyCons->setCaption( tr( "PYTHON_CONSOLE" ) );
833 pyCons->resize( pyCons->width(), desktop()->height()/4 );
834 //pyCons->connectPopupRequest(this, SLOT(onConnectPopupRequest(SUIT_PopupClient*, QContextMenuEvent*)));
839 /*!Create preferences.*/
840 void SalomeApp_Application::createPreferences( LightApp_Preferences* pref )
842 LightApp_Application::createPreferences(pref);
847 int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
848 int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
849 int defCols = pref->addPreference( tr( "PREF_GROUP_DEF_COLUMNS" ), obTab );
850 for ( int i = SalomeApp_DataObject::CT_Value; i <= SalomeApp_DataObject::CT_RefEntry; i++ )
852 pref->addPreference( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), defCols,
853 LightApp_Preferences::Bool, "ObjectBrowser", QString().sprintf( "visibility_column_%d", i ) );
855 pref->setItemProperty( defCols, "columns", 1 );
857 // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources..
858 int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat );
859 int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab );
860 pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" );
863 /*!Update desktop title.*/
864 void SalomeApp_Application::updateDesktopTitle() {
865 QString aTitle = applicationName();
866 QString aVer = applicationVersion();
867 if ( !aVer.isEmpty() )
868 aTitle += QString( " " ) + aVer;
872 QString sName = SUIT_Tools::file( activeStudy()->studyName().stripWhiteSpace(), false );
873 if ( !sName.isEmpty() ) {
874 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
876 _PTR(Study) stdDS = study->studyDS();
878 if ( stdDS->GetProperties()->IsLocked() ) {
879 aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) );
881 aTitle += QString( " - [%1]" ).arg( sName );
888 desktop()->setCaption( aTitle );
892 \brief Show dialog box to propose possible user actions when study is closed.
893 \param docName study name
894 \return chosen action ID
897 int SalomeApp_Application::closeChoice( const QString& docName )
899 SUIT_MsgDlg dlg( desktop(), tr( "APPCLOSE_CAPTION" ), tr ( "APPCLOSE_DESCRIPTION" ),
900 QMessageBox::standardIcon( QMessageBox::Information ) );
901 dlg.addButton( tr ( "APPCLOSE_SAVE" ), CloseSave );
902 dlg.addButton( tr ( "APPCLOSE_CLOSE" ), CloseDiscard );
903 dlg.addButton( tr ( "APPCLOSE_UNLOAD" ), CloseUnload );
909 \brief Process user actions selected from the dialog box when study is closed.
910 \param choice chosen action ID
911 \param closePermanently "forced study closing" flag
912 \return operation status
915 bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently )
921 if ( activeStudy()->isSaved() )
923 else if ( !onSaveAsDoc() )
929 closePermanently = false;
939 \brief Get module activation actions
940 \return map <action_id><action_name> where
941 - action_id is unique non-zero action identifier
942 - action_name is action title
943 \sa moduleActionSelected()
945 QMap<int, QString> SalomeApp_Application::activateModuleActions() const
947 QMap<int, QString> opmap = LightApp_Application::activateModuleActions();
948 opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) );
953 \brief Process module activation action.
954 \param id action identifier
955 \sa activateModuleActions()
957 void SalomeApp_Application::moduleActionSelected( const int id )
959 if ( id == LoadStudyId )
962 LightApp_Application::moduleActionSelected( id );
965 /*!Gets CORBA::ORB_var*/
966 CORBA::ORB_var SalomeApp_Application::orb()
968 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
969 static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
973 /*!Create and return SALOMEDS_StudyManager.*/
974 SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr()
976 static _PTR(StudyManager) _sm;
977 if(!_sm) _sm = ClientFactory::StudyManager();
981 /*!Create and return SALOME_NamingService.*/
982 SALOME_NamingService* SalomeApp_Application::namingService()
984 static SALOME_NamingService* _ns = new SALOME_NamingService( orb() );
988 /*!Create and return SALOME_LifeCycleCORBA.*/
989 SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
991 static SALOME_LifeCycleCORBA* _lcc = new SALOME_LifeCycleCORBA( namingService() );
995 /*!Return default engine IOR for light modules*/
996 QString SalomeApp_Application::defaultEngineIOR()
998 /// Look for a default module engine (needed for CORBAless modules to use SALOMEDS persistence)
1000 CORBA::Object_ptr anEngine = namingService()->Resolve( "/SalomeAppEngine" );
1001 if ( !CORBA::is_nil( anEngine ) )
1003 CORBA::String_var objStr = orb()->object_to_string( anEngine );
1004 anIOR = QString( objStr.in() );
1009 /*!Private SLOT. On preferences.*/
1010 void SalomeApp_Application::onProperties()
1012 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1016 _PTR(StudyBuilder) SB = study->studyDS()->NewBuilder();
1019 SalomeApp_StudyPropertiesDlg aDlg( desktop() );
1020 int res = aDlg.exec();
1021 if( res==QDialog::Accepted && aDlg.isChanged() )
1022 SB->CommitCommand();
1026 //study->updateCaptions();
1027 updateDesktopTitle();
1031 /*!Insert items in popup, which necessary for current application*/
1032 void SalomeApp_Application::contextMenuPopup( const QString& type, QPopupMenu* thePopup, QString& title )
1034 LightApp_Application::contextMenuPopup( type, thePopup, title );
1036 OB_Browser* ob = objectBrowser();
1037 if ( !ob || type != ob->popupClientType() )
1040 // Get selected objects
1041 SALOME_ListIO aList;
1042 LightApp_SelectionMgr* mgr = selectionMgr();
1043 mgr->selectedObjects( aList, QString::null, false );
1045 // add GUI state commands: restore, rename
1046 if ( aList.Extent() == 1 && aList.First()->hasEntry() &&
1047 QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) {
1048 thePopup->insertSeparator();
1049 thePopup->insertItem( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) );
1050 thePopup->insertItem( tr( "MEN_RENAME_VS" ), this, SLOT( onRenameGUIState() ) );
1051 thePopup->insertItem( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) );
1054 // "Delete reference" item should appear only for invalid references
1056 // isInvalidRefs will be true, if at least one of selected objects is invalid reference
1057 bool isInvalidRefs = false;
1058 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(activeStudy());
1059 _PTR(Study) aStudyDS = aStudy->studyDS();
1060 _PTR(SObject) anObj;
1062 for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() )
1063 if( it.Value()->hasEntry() )
1065 _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject;
1066 while( aRefObj && aRefObj->ReferencedObject( anObj ) )
1069 if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() )
1070 isInvalidRefs = true;
1073 // Add "Delete reference" item to popup
1074 if ( isInvalidRefs )
1076 thePopup->insertSeparator();
1077 thePopup->insertItem( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) );
1082 mgr->selectedObjects( aList );
1084 // "Activate module" item should appear only if it's necessary
1085 if (aList.Extent() != 1)
1087 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1088 // check if item is a "GUI state" item (also a first level object)
1089 QString entry( aIObj->getEntry() );
1090 if ( entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) )
1092 QString aModuleName(aIObj->getComponentDataType());
1093 QString aModuleTitle = moduleTitle(aModuleName);
1094 CAM_Module* currentModule = activeModule();
1095 if (currentModule && currentModule->moduleName() == aModuleTitle)
1097 if ( !aModuleTitle.isEmpty() )
1098 thePopup->insertItem( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) );
1101 /*!Update obect browser:
1102 1.if 'updateModels' true, update existing data models;
1103 2. update "non-existing" (not loaded yet) data models;
1104 3. update object browser if it exists */
1105 void SalomeApp_Application::updateObjectBrowser( const bool updateModels )
1107 // update "non-existing" (not loaded yet) data models
1108 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>(activeStudy());
1111 _PTR(Study) stdDS = study->studyDS();
1114 for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() )
1116 _PTR(SComponent) aComponent ( it->Value() );
1118 if ( aComponent->ComponentDataType() == "Interface Applicative" )
1119 continue; // skip the magic "Interface Applicative" component
1121 OB_Browser* ob = static_cast<OB_Browser*>( getWindow( WT_ObjectBrowser ));
1122 const bool isAutoUpdate = ob->isAutoUpdate();
1123 ob->setAutoUpdate( false );
1124 SalomeApp_DataModel::synchronize( aComponent, study );
1125 ob->setAutoUpdate( isAutoUpdate );
1126 //SalomeApp_DataModel::BuildTree( aComponent, study->root(), study, /*skipExisitng=*/true );
1131 // create data objects that correspond to GUI state save points
1132 if ( study ) updateSavePointDataObjects( study );
1134 // update existing data models (already loaded SComponents)
1135 LightApp_Application::updateObjectBrowser( updateModels );
1138 /*!Display Catalog Genenerator dialog */
1139 void SalomeApp_Application::onCatalogGen()
1141 ToolsGUI_CatalogGeneratorDlg aDlg( desktop() );
1145 /*!Display Registry Display dialog */
1146 void SalomeApp_Application::onRegDisplay()
1148 CORBA::ORB_var anOrb = orb();
1149 ToolsGUI_RegWidget* regWnd = ToolsGUI_RegWidget::GetRegWidget( anOrb, desktop(), "Registry" );
1152 regWnd->setActiveWindow();
1155 /*!find original object by double click on item */
1156 void SalomeApp_Application::onDblClick( QListViewItem* it )
1158 OB_ListItem* item = dynamic_cast<OB_ListItem*>( it );
1159 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1163 SalomeApp_DataObject* obj = dynamic_cast<SalomeApp_DataObject*>( item->dataObject() );
1167 QString entry = obj->entry();
1168 _PTR(SObject) sobj = study->studyDS()->FindObjectID( entry.latin1() ), ref;
1170 if( sobj && sobj->ReferencedObject( ref ) )
1172 entry = ref->GetID().c_str();
1173 QListViewItemIterator anIt( item->listView() );
1174 for( ; anIt.current(); anIt++ )
1176 OB_ListItem* item = dynamic_cast<OB_ListItem*>( anIt.current() );
1180 SalomeApp_DataObject* original = dynamic_cast<SalomeApp_DataObject*>( item->dataObject() );
1181 if( original->entry()!=entry )
1184 OB_Browser* br = objectBrowser();
1185 br->setSelected( original );
1186 SUIT_DataObject* p = original->parent();
1199 Creates new view manager
1200 \param type - type of view manager
1202 SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type)
1204 return createViewManager(type);
1208 /*!Global utility funciton, returns selected GUI Save point object's ID */
1209 int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr )
1211 SALOME_ListIO aList;
1212 selMgr->selectedObjects( aList );
1213 Handle(SALOME_InteractiveObject) aIObj = aList.First();
1214 QString entry( aIObj->getEntry() );
1215 QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" );
1216 if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object
1218 bool ok; // conversion to integer is ok?
1219 int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok );
1220 return ok ? savePoint : -1;
1223 /*!Called on Restore GUI State popup command*/
1224 void SalomeApp_Application::onRestoreGUIState()
1226 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1227 if ( savePoint == -1 )
1229 SalomeApp_VisualState( this ).restoreState( savePoint );
1232 /*!Called on Rename GUI State popup command*/
1233 void SalomeApp_Application::onRenameGUIState()
1235 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1236 if ( savePoint == -1 )
1238 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1242 QString newName = LightApp_NameDlg::getName( desktop(), study->getNameOfSavePoint( savePoint ) );
1243 if ( !newName.isNull() && !newName.isEmpty() ) {
1244 study->setNameOfSavePoint( savePoint, newName );
1245 updateSavePointDataObjects( study );
1246 objectBrowser()->updateTree( study->root() );
1251 /*!Called on Delete GUI State popup command*/
1252 void SalomeApp_Application::onDeleteGUIState()
1254 int savePoint = ::getSelectedSavePoint( selectionMgr() );
1255 if ( savePoint == -1 )
1257 SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( activeStudy() );
1261 study->removeSavePoint( savePoint );
1262 updateSavePointDataObjects( study );
1265 /*!Called on Save study operation*/
1266 void SalomeApp_Application::onStudySaved( SUIT_Study* study )
1268 LightApp_Application::onStudySaved( study );
1270 if ( objectBrowser() ) {
1271 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1272 objectBrowser()->updateTree( study->root() );
1276 /*!Called on Open study operation*/
1277 void SalomeApp_Application::onStudyOpened( SUIT_Study* study )
1279 LightApp_Application::onStudyOpened( study );
1281 if ( objectBrowser() ) {
1282 updateSavePointDataObjects( dynamic_cast<SalomeApp_Study*>( study ) );
1283 objectBrowser()->updateTree( study->root() );
1287 /*! utility function. returns true if list view item that correspond to given SUIT_DataObject is open.
1288 only first level items are traversed */
1289 bool isListViewItemOpen( QListView* lv, const SUIT_DataObject* dobj )
1294 QListViewItem* item = lv->firstChild();
1296 OB_ListItem* ob_item = dynamic_cast<OB_ListItem*>( item );
1297 if ( ob_item && ob_item->dataObject() == dobj )
1298 return ob_item->isOpen();
1299 item = item->nextSibling();
1304 /*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/
1305 void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study )
1307 OB_Browser* ob = objectBrowser();
1309 if ( !study || !ob )
1312 // find GUI states root object
1313 SUIT_DataObject* guiRootObj = 0;
1315 study->root()->children( ch );
1316 DataObjectList::const_iterator it = ch.begin(), last = ch.end();
1317 for ( ; it != last ; ++it ) {
1318 if ( dynamic_cast<SalomeApp_SavePointRootObject*>( *it ) ) {
1323 std::vector<int> savePoints = study->getSavePoints();
1324 // case 1: no more save points but they existed in study's tree
1325 if ( savePoints.empty() && guiRootObj ) {
1329 // case 2: no more save points but root does not exist either
1330 if ( savePoints.empty() && !guiRootObj )
1332 // case 3: save points but no root for them - create it
1333 if ( !savePoints.empty() && !guiRootObj )
1334 guiRootObj = new SalomeApp_SavePointRootObject( study->root() );
1335 // case 4: everything already exists.. here may be a problem: we want "GUI states" root object
1336 // to be always the last one in the tree. Here we check - if it is not the last one - remove and
1338 if ( guiRootObj->nextBrother() ) {
1339 study->root()->removeChild(guiRootObj);
1340 study->root()->appendChild(guiRootObj);
1341 //study->root()->dump();
1344 // store data objects in a map id-to-DataObject
1345 QMap<int,SalomeApp_SavePointObject*> mapDO;
1347 guiRootObj->children( ch );
1348 for( it = ch.begin(), last = ch.end(); it != last ; ++it ) {
1349 SalomeApp_SavePointObject* dobj = dynamic_cast<SalomeApp_SavePointObject*>( *it );
1351 mapDO[dobj->getId()] = dobj;
1354 // iterate new save points. if DataObject with such ID not found in map - create DataObject
1355 // if in the map - remove it from map.
1356 for ( int i = 0; i < savePoints.size(); i++ )
1357 if ( !mapDO.contains( savePoints[i] ) )
1358 new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study );
1360 mapDO.remove( savePoints[i] );
1362 // delete DataObjects that are still in the map -- their IDs were not found in data model
1363 for ( QMap<int,SalomeApp_SavePointObject*>::Iterator it = mapDO.begin(); it != mapDO.end(); ++it )
1367 /*! Check data object */
1368 bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj)
1376 /*! Process standard messages from desktop */
1377 void SalomeApp_Application::onDesktopMessage( const QString& message )
1379 // update object browser
1380 if ( message.lower() == "updateobjectbrowser" ||
1381 message.lower() == "updateobjbrowser" )
1382 updateObjectBrowser();