X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSalomeApp%2FSalomeApp_Application.cxx;h=802d7d7b0fd5ea10fc7d4ff3161750f9ff73592f;hb=f830c97c748d8f8a6a7eccc8e3a58e19066a1181;hp=bddff0e9cc2febae9e15b793ca9457e649144f4e;hpb=bb6b081c02274bf1cf6f196d1373d8fb5850eb02;p=modules%2Fgui.git diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index bddff0e9c..802d7d7b0 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -1,3 +1,21 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// // File: SalomeApp_Application.cxx // Created: 10/22/2004 3:23:45 PM // Author: Sergey LITONIN @@ -11,20 +29,22 @@ #include "SalomeApp_DataModel.h" #include "SalomeApp_DataObject.h" #include "SalomeApp_EventFilter.h" +#include "SalomeApp_VisualState.h" +#include "SalomeApp_ExitDlg.h" #include "SalomeApp_StudyPropertiesDlg.h" -#include "SalomeApp_CheckFileDlg.h" - #include "LightApp_Application.h" #include "LightApp_Preferences.h" #include "LightApp_WidgetContainer.h" #include "LightApp_SelectionMgr.h" +#include "LightApp_NameDlg.h" #include "STD_LoadStudiesDlg.h" #include #include +#include #include @@ -43,14 +63,17 @@ #include #include -#include #include #include #include #include +#include +#include +#include +#include -#include "SALOMEDS_StudyManager.hxx" -#include "SALOMEDS_SObject.hxx" +#include "SALOMEDSClient_ClientFactory.hxx" +#include "SALOMEDSClient_IParameters.hxx" #include "SALOME_ListIteratorOfListIO.hxx" #include "SALOME_ListIO.hxx" @@ -58,21 +81,65 @@ #include "ToolsGUI_CatalogGeneratorDlg.h" #include "ToolsGUI_RegWidget.h" +#include + +#include +/*!Internal class that updates object browser item properties */ +class SalomeApp_Updater : public OB_Updater +{ +public: + SalomeApp_Updater() : OB_Updater(){}; + virtual ~SalomeApp_Updater(){}; + virtual void update( SUIT_DataObject* theObj, OB_ListItem* theItem ); +}; + +void SalomeApp_Updater::update( SUIT_DataObject* theObj, OB_ListItem* theItem ) +{ + if( !theObj || !theItem ) + return; + + SalomeApp_DataObject* SAObj = dynamic_cast( theObj ); + if( !SAObj ) + return; + + _PTR(SObject) SObj = SAObj->object(); + if( !SObj ) + return; + _PTR( GenericAttribute ) anAttr; + + // Selectable + if ( SObj->FindAttribute( anAttr, "AttributeSelectable" ) ) + { + _PTR(AttributeSelectable) aAttrSel = anAttr; + theItem->setSelectable( aAttrSel->IsSelectable() ); + } + // Expandable + if ( SObj->FindAttribute(anAttr, "AttributeExpandable") ) + { + _PTR(AttributeExpandable) aAttrExpand = anAttr; + theItem->setExpandable( aAttrExpand->IsExpandable() ); + } + // Opened + //this attribute is not supported in the version of SALOME 3.x + //if ( SObj->FindAttribute(anAttr, "AttributeOpened") ) + //{ + // _PTR(AttributeOpened) aAttrOpen = anAttr; + // theItem->setOpen( aAttrOpen->IsOpened() ); + //} +} + /*!Create new instance of SalomeApp_Application.*/ extern "C" SALOMEAPP_EXPORT SUIT_Application* createApplication() { return new SalomeApp_Application(); } -/* - Class : SalomeApp_Application - Description : Application containing SalomeApp module or LightApp module -*/ - /*!Constructor.*/ SalomeApp_Application::SalomeApp_Application() : LightApp_Application() { + connect( desktop(), SIGNAL( message( const QString& ) ), + this, SLOT( onDesktopMessage( const QString& ) ) ); } /*!Destructor. @@ -80,7 +147,8 @@ SalomeApp_Application::SalomeApp_Application() */ SalomeApp_Application::~SalomeApp_Application() { - SalomeApp_EventFilter::Destroy(); + // Do not destroy. It's a singleton ! + //SalomeApp_EventFilter::Destroy(); } /*!Start application.*/ @@ -89,6 +157,66 @@ void SalomeApp_Application::start() LightApp_Application::start(); SalomeApp_EventFilter::Init(); + + static bool isFirst = true; + if ( isFirst ) { + isFirst = false; + + QString hdffile; + QStringList pyfiles; + + for (int i = 1; i < qApp->argc(); i++) { + QRegExp rxs ("--study-hdf=(.+)"); + if ( rxs.search( QString(qApp->argv()[i]) ) >= 0 && rxs.capturedTexts().count() > 1 ) { + QString file = rxs.capturedTexts()[1]; + QFileInfo fi ( file ); + QString extension = fi.extension( false ).lower(); + if ( extension == "hdf" && fi.exists() ) + hdffile = fi.absFilePath(); + } + else { + QRegExp rxp ("--pyscript=(.+)"); + if ( rxp.search( QString(qApp->argv()[i]) ) >= 0 && rxp.capturedTexts().count() > 1 ) { + QStringList files = QStringList::split(",",rxp.capturedTexts()[1],false); + pyfiles += files; + } + } + } + + if ( !hdffile.isEmpty() ) // open hdf file given as parameter + onOpenDoc( hdffile ); + else if ( pyfiles.count() > 0 ) // create new study + onNewDoc(); + + // import/execute python scripts + if ( pyfiles.count() > 0 && activeStudy() ) { + SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); + if ( appStudy ) { + _PTR(Study) aStudy = appStudy->studyDS(); + if ( !aStudy->GetProperties()->IsLocked() ) { + for (uint j = 0; j < pyfiles.count(); j++ ) { + QFileInfo fi ( pyfiles[j] ); + PythonConsole* pyConsole = pythonConsole(); + if ( pyConsole ) { + QString extension = fi.extension( false ).lower(); + if ( fi.exists() ) { + // execute python script + QString command = QString( "execfile(\"%1\")" ).arg( fi.absFilePath() ); + pyConsole->exec( command ); + } + else { + // import python module + QString command = QString( "import %1" ).arg( pyfiles[j] ); + if ( extension == "py" ) + command = QString( "import %1" ).arg( fi.baseName( true ) ); + pyConsole->exec( command ); + } + } + } + } + } + } + } } /*!Create actions:*/ @@ -98,33 +226,53 @@ void SalomeApp_Application::createActions() SUIT_Desktop* desk = desktop(); + //! Save GUI state + // "Save GUI State" command is moved to VISU module + // createAction( SaveGUIStateId, tr( "TOT_DESK_FILE_SAVE_GUI_STATE" ), QIconSet(), + // tr( "MEN_DESK_FILE_SAVE_GUI_STATE" ), tr( "PRP_DESK_FILE_SAVE_GUI_STATE" ), + // 0, desk, false, this, SLOT( onSaveGUIState() ) ); + //! Dump study createAction( DumpStudyId, tr( "TOT_DESK_FILE_DUMP_STUDY" ), QIconSet(), tr( "MEN_DESK_FILE_DUMP_STUDY" ), tr( "PRP_DESK_FILE_DUMP_STUDY" ), - 0, desk, false, this, SLOT( onDumpStudy() ) ); + CTRL+Key_D, desk, false, this, SLOT( onDumpStudy() ) ); //! Load script createAction( LoadScriptId, tr( "TOT_DESK_FILE_LOAD_SCRIPT" ), QIconSet(), tr( "MEN_DESK_FILE_LOAD_SCRIPT" ), tr( "PRP_DESK_FILE_LOAD_SCRIPT" ), - 0, desk, false, this, SLOT( onLoadScript() ) ); + CTRL+Key_T, desk, false, this, SLOT( onLoadScript() ) ); //! Properties createAction( PropertiesId, tr( "TOT_DESK_PROPERTIES" ), QIconSet(), tr( "MEN_DESK_PROPERTIES" ), tr( "PRP_DESK_PROPERTIES" ), - 0, desk, false, this, SLOT( onProperties() ) ); + CTRL+Key_P, desk, false, this, SLOT( onProperties() ) ); //! Catalog Generator createAction( CatalogGenId, tr( "TOT_DESK_CATALOG_GENERATOR" ), QIconSet(), tr( "MEN_DESK_CATALOG_GENERATOR" ), tr( "PRP_DESK_CATALOG_GENERATOR" ), - 0, desk, false, this, SLOT( onCatalogGen() ) ); + SHIFT+Key_G, desk, false, this, SLOT( onCatalogGen() ) ); //! Registry Display createAction( RegDisplayId, tr( "TOT_DESK_REGISTRY_DISPLAY" ), QIconSet(), tr( "MEN_DESK_REGISTRY_DISPLAY" ), tr( "PRP_DESK_REGISTRY_DISPLAY" ), - 0, desk, false, this, SLOT( onRegDisplay() ) ); + /*SHIFT+Key_D*/0, desk, false, this, SLOT( onRegDisplay() ) ); + + //SRN: BugID IPAL9021, add an action "Load" + createAction( FileLoadId, tr( "TOT_DESK_FILE_LOAD" ), + resourceMgr()->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ), + tr( "MEN_DESK_FILE_LOAD" ), tr( "PRP_DESK_FILE_LOAD" ), + CTRL+Key_L, desk, false, this, SLOT( onLoadDoc() ) ); + //SRN: BugID IPAL9021: End + int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 ); + // "Save GUI State" command is renamed to "Save VISU State" and + // creation of menu item is moved to VISU + // createMenu( SaveGUIStateId, fileMenu, 10, -1 ); + + createMenu( FileLoadId, fileMenu, 0 ); //SRN: BugID IPAL9021, add a menu item "Load" + createMenu( DumpStudyId, fileMenu, 10, -1 ); createMenu( separator(), fileMenu, -1, 15, -1 ); createMenu( LoadScriptId, fileMenu, 10, -1 ); @@ -132,7 +280,7 @@ void SalomeApp_Application::createActions() createMenu( PropertiesId, fileMenu, 10, -1 ); createMenu( separator(), fileMenu, -1, 15, -1 ); - int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, -1, 50 ); + int toolsMenu = createMenu( tr( "MEN_DESK_TOOLS" ), -1, MenuToolsId, 50 ); createMenu( CatalogGenId, toolsMenu, 10, -1 ); createMenu( RegDisplayId, toolsMenu, 10, -1 ); createMenu( separator(), toolsMenu, -1, 15, -1 ); @@ -270,7 +418,11 @@ void SalomeApp_Application::onLoadDoc() return; name = studyname; +#ifndef WNT + //this code replace marker of windows drive and path become invalid therefore + // defines placed there name.replace( QRegExp(":"), "/" ); +#endif if( LightApp_Application::onLoadDoc( name ) ) { @@ -280,6 +432,23 @@ void SalomeApp_Application::onLoadDoc() } } +/*! + \brief Close application. +*/ +void SalomeApp_Application::onExit() +{ + bool killServers = false; + bool result = true; + + if ( exitConfirmation() ) { + SalomeApp_ExitDlg dlg( desktop() ); + result = dlg.exec() == QDialog::Accepted; + killServers = dlg.isServersShutdown(); + } + + if ( result ) + SUIT_Session::session()->closeSession( SUIT_Session::ASK, killServers ); +} /*!SLOT. Load document with \a aName.*/ bool SalomeApp_Application::onLoadDoc( const QString& aName ) @@ -326,6 +495,14 @@ void SalomeApp_Application::onPaste() _PTR(Study) stdDS = study->studyDS(); if(!stdDS) return; + if ( stdDS->GetProperties()->IsLocked() ) { + SUIT_MessageBox::warn1 ( desktop(), + QObject::tr("WRN_WARNING"), + QObject::tr("WRN_STUDY_LOCKED"), + QObject::tr("BUT_OK") ); + return; + } + SALOME_ListIteratorOfListIO it( list ); if(it.More()) { @@ -340,6 +517,29 @@ void SalomeApp_Application::onPaste() } } +/*! Check if the study is locked */ +void SalomeApp_Application::onCloseDoc( bool ask ) +{ + SalomeApp_Study* study = dynamic_cast(activeStudy()); + + if (study != NULL) { + _PTR(Study) stdDS = study->studyDS(); + if(stdDS && stdDS->IsStudyLocked()) { + if ( SUIT_MessageBox::warn2( desktop(), + QObject::tr( "WRN_WARNING" ), + QObject::tr( "CLOSE_LOCKED_STUDY" ), + QObject::tr( "BUT_YES" ), + QObject::tr( "BUT_NO" ), + SUIT_YES, + SUIT_NO, + SUIT_NO ) == SUIT_NO ) return; + + } + } + + LightApp_Application::onCloseDoc( ask ); +} + /*!Sets enable or disable some actions on selection changed.*/ void SalomeApp_Application::onSelectionChanged() { @@ -347,67 +547,56 @@ void SalomeApp_Application::onSelectionChanged() LightApp_SelectionMgr* mgr = selectionMgr(); mgr->selectedObjects(list); - SalomeApp_Study* study = dynamic_cast(activeStudy()); - if(study == NULL) return; + bool canCopy = false; + bool canPaste = false; - _PTR(Study) stdDS = study->studyDS(); - if(!stdDS) return; + SalomeApp_Study* study = dynamic_cast(activeStudy()); + if (study != NULL) { + _PTR(Study) stdDS = study->studyDS(); - QAction* qaction; + if (stdDS) { + SALOME_ListIteratorOfListIO it ( list ); - SALOME_ListIteratorOfListIO it( list ); - if(it.More() && list.Extent() == 1) - { - _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); + if (it.More() && list.Extent() == 1) { + _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); - qaction = action(EditCopyId); - if( so ) { - SALOMEDS_SObject* aSO = dynamic_cast(so.get()); - if ( aSO && studyMgr()->CanCopy(so) ) qaction->setEnabled(true); - else qaction->setEnabled(false); - } - else qaction->setEnabled(false); - - qaction = action(EditPasteId); - if( so ) { - SALOMEDS_SObject* aSO = dynamic_cast(so.get()); - if( aSO && studyMgr()->CanPaste(so) ) qaction->setEnabled(true); - qaction->setEnabled(false); - } - else qaction->setEnabled(false); - } - else { - qaction = action(EditCopyId); - qaction->setEnabled(false); - qaction = action(EditPasteId); - qaction->setEnabled(false); + if ( so ) { + canCopy = studyMgr()->CanCopy(so); + canPaste = studyMgr()->CanPaste(so); + } + } + } } + + action(EditCopyId)->setEnabled(canCopy); + action(EditPasteId)->setEnabled(canPaste); } /*!Delete references.*/ -void SalomeApp_Application::onDeleteReferences() +void SalomeApp_Application::onDeleteInvalidReferences() { SALOME_ListIO aList; LightApp_SelectionMgr* mgr = selectionMgr(); - mgr->selectedObjects(aList); + mgr->selectedObjects( aList, QString::null, false ); - if (aList.Extent() < 1) return; + if( aList.IsEmpty() ) + return; SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); _PTR(Study) aStudyDS = aStudy->studyDS(); _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder(); _PTR(SObject) anObj; - for ( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() ) + for( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() ) + if ( it.Value()->hasEntry() ) { - if ( it.Value()->hasEntry() ) - { - _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ); - if ( aSObject->ReferencedObject(anObj) ) - aStudyBuilder->RemoveReference(aSObject); - } - } + _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject; + while( aRefObj && aRefObj->ReferencedObject( anObj ) ) + aRefObj = anObj; + if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() ) + aStudyBuilder->RemoveReference( aSObject ); + } updateObjectBrowser(); } @@ -430,10 +619,9 @@ void SalomeApp_Application::onOpenWith() QApplication::restoreOverrideCursor(); } -//======================================================================= -// name : createNewStudy -/*! Purpose : Create new study*/ -//======================================================================= +/*! + Creates new study +*/ SUIT_Study* SalomeApp_Application::createNewStudy() { SalomeApp_Study* aStudy = new SalomeApp_Study( this ); @@ -447,10 +635,9 @@ SUIT_Study* SalomeApp_Application::createNewStudy() return aStudy; } -//======================================================================= -// name : updateCommandsStatus -/*! Purpose : Enable/Disable menu items and toolbar buttons. Rebuild menu*/ -//======================================================================= +/*! + Enable/Disable menu items and toolbar buttons. Rebuild menu +*/ void SalomeApp_Application::updateCommandsStatus() { LightApp_Application::updateCommandsStatus(); @@ -465,16 +652,41 @@ void SalomeApp_Application::updateCommandsStatus() if ( a ) a->setEnabled( activeStudy() ); + // Properties menu a = action( PropertiesId ); if( a ) a->setEnabled( activeStudy() ); - a = action(EditCopyId); - a->setEnabled(false); - a = action(EditPasteId); - a->setEnabled(false); + // Save GUI state menu + a = action( SaveGUIStateId ); + if( a ) + a->setEnabled( activeStudy() ); + + // update state of Copy/Paste menu items + onSelectionChanged(); } +/*! + \class DumpStudyFileDlg + Private class used in Dump Study operation. Consists 2 check boxes: + "Publish in study" and "Save GUI parameters" +*/ +class DumpStudyFileDlg : public SUIT_FileDlg +{ +public: + DumpStudyFileDlg( QWidget* parent ) : SUIT_FileDlg( parent, false, true, true ) + { + QHBox* hB = new QHBox( this ); + myPublishChk = new QCheckBox( tr("PUBLISH_IN_STUDY"), hB ); + mySaveGUIChk = new QCheckBox( tr("SAVE_GUI_STATE"), hB ); + QPushButton* pb = new QPushButton(this); + addWidgets( new QLabel("", this), hB, pb ); + pb->hide(); + } + QCheckBox* myPublishChk; + QCheckBox* mySaveGUIChk; +}; + /*!Private SLOT. On dump study.*/ void SalomeApp_Application::onDumpStudy( ) { @@ -485,18 +697,54 @@ void SalomeApp_Application::onDumpStudy( ) QStringList aFilters; aFilters.append( tr( "PYTHON_FILES_FILTER" ) ); - SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg( desktop(), false, tr("PUBLISH_IN_STUDY"), true, true); + DumpStudyFileDlg* fd = new DumpStudyFileDlg( desktop() ); fd->setCaption( tr( "TOT_DESK_FILE_DUMP_STUDY" ) ); fd->setFilters( aFilters ); - fd->SetChecked(true); - fd->exec(); - QString aFileName = fd->selectedFile(); - bool toPublish = fd->IsChecked(); + fd->myPublishChk->setChecked( true ); + fd->mySaveGUIChk->setChecked( true ); + QString aFileName; + while (1) { + fd->exec(); + fd->raise(); + aFileName = fd->selectedFile(); + if (!aFileName.isEmpty()) { + if ( (aFileName.find('-', 0) == -1) && (aFileName.find('!', 0) == -1) && (aFileName.find('?', 0) == -1) && + (aFileName.find('#', 0) == -1) && (aFileName.find('*', 0) == -1) && (aFileName.find('&', 0) == -1)) { + break; + } + else { + SUIT_MessageBox::warn1 ( desktop(), + QObject::tr("WRN_WARNING"), + tr("WRN_FILE_NAME_BAD"), + QObject::tr("BUT_OK") ); + } + } + else { + break; + } + } + bool toPublish = fd->myPublishChk->isChecked(); + bool toSaveGUI = fd->mySaveGUIChk->isChecked(); delete fd; - if(!aFileName.isEmpty()) { + if ( !aFileName.isEmpty() ) { QFileInfo aFileInfo(aFileName); - aStudy->DumpStudy( aFileInfo.dirPath( true ).latin1(), aFileInfo.baseName().latin1(), toPublish ); + int savePoint; + _PTR(AttributeParameter) ap; + _PTR(IParameters) ip = ClientFactory::getIParameters(ap); + if(ip->isDumpPython(appStudy->studyDS())) ip->setDumpPython(appStudy->studyDS()); //Unset DumpPython flag. + if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method + ip->setDumpPython(appStudy->studyDS()); + savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point + } + bool res = aStudy->DumpStudy( aFileInfo.dirPath( true ).latin1(), aFileInfo.baseName().latin1(), toPublish); + if ( toSaveGUI ) + appStudy->removeSavePoint(savePoint); //SRN: remove the created temporary save point. + if ( !res ) + SUIT_MessageBox::warn1 ( desktop(), + QObject::tr("WRN_WARNING"), + tr("WRN_DUMP_STUDY_FAILED"), + QObject::tr("BUT_OK") ); } } @@ -532,6 +780,18 @@ void SalomeApp_Application::onLoadScript( ) } } +/*!Private SLOT. On save GUI state.*/ +void SalomeApp_Application::onSaveGUIState() +{ + SalomeApp_Study* study = dynamic_cast( activeStudy() ); + if ( study ) { + SalomeApp_VisualState( this ).storeState(); + updateSavePointDataObjects( study ); + objectBrowser()->updateTree( study->root() ); + } + updateActions(); +} + /*!Gets file filter. *\retval QString "(*.hdf)" */ @@ -543,15 +803,18 @@ QString SalomeApp_Application::getFileFilter() const /*!Create window.*/ QWidget* SalomeApp_Application::createWindow( const int flag ) { - QWidget* wid = LightApp_Application::createWindow(flag); + QWidget* wid = 0; + if ( flag != WT_PyConsole ) wid = LightApp_Application::createWindow(flag); SUIT_ResourceMgr* resMgr = resourceMgr(); if ( flag == WT_ObjectBrowser ) { OB_Browser* ob = (OB_Browser*)wid; + ob->setUpdater( new SalomeApp_Updater() ); connect( ob->listView(), SIGNAL( doubleClicked( QListViewItem* ) ), this, SLOT( onDblClick( QListViewItem* ) ) ); - bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false ); + bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false ), + autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true ); for ( int i = SalomeApp_DataObject::CT_Value; i <= SalomeApp_DataObject::CT_RefEntry; i++ ) { ob->addColumn( tr( QString().sprintf( "OBJ_BROWSER_COLUMN_%d", i ) ), i ); @@ -559,15 +822,16 @@ QWidget* SalomeApp_Application::createWindow( const int flag ) QString().sprintf( "visibility_column_%d", i ), true ) ); } ob->setWidthMode( autoSize ? QListView::Maximum : QListView::Manual ); + ob->listView()->setColumnWidthMode( 0, autoSizeFirst ? QListView::Maximum : QListView::Manual ); + ob->resize( desktop()->width()/3, ob->height() ); } else if ( flag == WT_PyConsole ) { - delete wid; - wid = 0; PythonConsole* pyCons = new PythonConsole( desktop(), new SalomeApp_PyInterp() ); pyCons->setCaption( tr( "PYTHON_CONSOLE" ) ); wid = pyCons; - // pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); + pyCons->resize( pyCons->width(), desktop()->height()/4 ); + //pyCons->connectPopupRequest(this, SLOT(onConnectPopupRequest(SUIT_PopupClient*, QContextMenuEvent*))); } return wid; } @@ -590,8 +854,10 @@ void SalomeApp_Application::createPreferences( LightApp_Preferences* pref ) } pref->setItemProperty( defCols, "columns", 1 ); - int objSetGroup = pref->addPreference( tr( "PREF_OBJ_BROWSER_SETTINGS" ), obTab ); - pref->addPreference( tr( "PREF_AUTO_SIZE" ), objSetGroup, LightApp_Preferences::Bool, "ObjectBrowser", "auto_size" ); + // adding preference to LightApp_Application handled preferences.. a bit of hacking with resources.. + int genTab = pref->addPreference( LightApp_Application::tr( "PREF_TAB_GENERAL" ), salomeCat ); + int studyGroup = pref->addPreference( LightApp_Application::tr( "PREF_GROUP_STUDY" ), genTab ); + pref->addPreference( tr( "PREF_STORE_VISUAL_STATE" ), studyGroup, LightApp_Preferences::Bool, "Study", "store_visual_state" ); } /*!Update desktop title.*/ @@ -622,6 +888,80 @@ void SalomeApp_Application::updateDesktopTitle() { desktop()->setCaption( aTitle ); } +/*! + \brief Show dialog box to propose possible user actions when study is closed. + \param docName study name + \return chosen action ID + \sa closeAction() +*/ +int SalomeApp_Application::closeChoice( const QString& docName ) +{ + SUIT_MsgDlg dlg( desktop(), tr( "APPCLOSE_CAPTION" ), tr ( "APPCLOSE_DESCRIPTION" ), + QMessageBox::standardIcon( QMessageBox::Information ) ); + dlg.addButton( tr ( "APPCLOSE_SAVE" ), CloseSave ); + dlg.addButton( tr ( "APPCLOSE_CLOSE" ), CloseDiscard ); + dlg.addButton( tr ( "APPCLOSE_UNLOAD" ), CloseUnload ); + + return dlg.exec(); +} + +/*! + \brief Process user actions selected from the dialog box when study is closed. + \param choice chosen action ID + \param closePermanently "forced study closing" flag + \return operation status + \sa closeChoice() +*/ +bool SalomeApp_Application::closeAction( const int choice, bool& closePermanently ) +{ + bool res = true; + switch( choice ) + { + case CloseSave: + if ( activeStudy()->isSaved() ) + onSaveDoc(); + else if ( !onSaveAsDoc() ) + res = false; + break; + case CloseDiscard: + break; + case CloseUnload: + closePermanently = false; + break; + case CloseCancel: + default: + res = false; + } + return res; +} + +/*! + \brief Get module activation actions + \return map where + - action_id is unique non-zero action identifier + - action_name is action title + \sa moduleActionSelected() +*/ +QMap SalomeApp_Application::activateModuleActions() const +{ + QMap opmap = LightApp_Application::activateModuleActions(); + opmap.insert( LoadStudyId, tr( "ACTIVATE_MODULE_OP_LOAD" ) ); + return opmap; +} + +/*! + \brief Process module activation action. + \param id action identifier + \sa activateModuleActions() +*/ +void SalomeApp_Application::moduleActionSelected( const int id ) +{ + if ( id == LoadStudyId ) + onLoadDoc(); + else + LightApp_Application::moduleActionSelected( id ); +} + /*!Gets CORBA::ORB_var*/ CORBA::ORB_var SalomeApp_Application::orb() { @@ -633,8 +973,9 @@ CORBA::ORB_var SalomeApp_Application::orb() /*!Create and return SALOMEDS_StudyManager.*/ SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr() { - static SALOMEDSClient_StudyManager* _sm = new SALOMEDS_StudyManager(); - return _sm; + static _PTR(StudyManager) _sm; + if(!_sm) _sm = ClientFactory::StudyManager(); + return _sm.get(); } /*!Create and return SALOME_NamingService.*/ @@ -658,7 +999,10 @@ QString SalomeApp_Application::defaultEngineIOR() QString anIOR( "" ); CORBA::Object_ptr anEngine = namingService()->Resolve( "/SalomeAppEngine" ); if ( !CORBA::is_nil( anEngine ) ) - anIOR = orb()->object_to_string( anEngine ); + { + CORBA::String_var objStr = orb()->object_to_string( anEngine ); + anIOR = QString( objStr.in() ); + } return anIOR; } @@ -696,65 +1040,70 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QPopupMenu* t // Get selected objects SALOME_ListIO aList; LightApp_SelectionMgr* mgr = selectionMgr(); - mgr->selectedObjects(aList); + mgr->selectedObjects( aList, QString::null, false ); + + // add GUI state commands: restore, rename + if ( aList.Extent() == 1 && aList.First()->hasEntry() && + QString( aList.First()->getEntry() ).startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) { + thePopup->insertSeparator(); + thePopup->insertItem( tr( "MEN_RESTORE_VS" ), this, SLOT( onRestoreGUIState() ) ); + thePopup->insertItem( tr( "MEN_RENAME_VS" ), this, SLOT( onRenameGUIState() ) ); + thePopup->insertItem( tr( "MEN_DELETE_VS" ), this, SLOT( onDeleteGUIState() ) ); + } // "Delete reference" item should appear only for invalid references - // Check if selected objects is invalid references - bool isInvalidRefs = true; - - if ( aList.Extent() < 1 ) - isInvalidRefs = false; + // isInvalidRefs will be true, if at least one of selected objects is invalid reference + bool isInvalidRefs = false; + SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); + _PTR(Study) aStudyDS = aStudy->studyDS(); + _PTR(SObject) anObj; - if ( isInvalidRefs ) + for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() ) + if( it.Value()->hasEntry() ) { - SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); - _PTR(Study) aStudyDS = aStudy->studyDS(); - _PTR(SObject) anObj; + _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject; + while( aRefObj && aRefObj->ReferencedObject( anObj ) ) + aRefObj = anObj; - for ( SALOME_ListIteratorOfListIO it( aList ); it.More() && isInvalidRefs; it.Next() ) - { - if ( it.Value()->hasEntry() ) - { - _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ); - SALOMEDS_SObject* aSO = dynamic_cast(aSObject.get()); - if( aSO ) - if ( aSObject->ReferencedObject(anObj) == false || !QString(anObj->GetName().c_str()).isEmpty() ) - isInvalidRefs = false; - } - } + if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() ) + isInvalidRefs = true; } - // Add "Delete refrence" item to popup + // Add "Delete reference" item to popup if ( isInvalidRefs ) - { - thePopup->insertSeparator(); - thePopup->insertItem( tr( "MEN_DELETE_REFERENCE" ), this, SLOT( onDeleteReferences() ) ); - return; - } + { + thePopup->insertSeparator(); + thePopup->insertItem( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) ); + return; + } + + aList.Clear(); + mgr->selectedObjects( aList ); // "Activate module" item should appear only if it's necessary if (aList.Extent() != 1) return; Handle(SALOME_InteractiveObject) aIObj = aList.First(); + // check if item is a "GUI state" item (also a first level object) + QString entry( aIObj->getEntry() ); + if ( entry.startsWith( tr( "SAVE_POINT_DEF_NAME" ) ) ) + return; QString aModuleName(aIObj->getComponentDataType()); QString aModuleTitle = moduleTitle(aModuleName); CAM_Module* currentModule = activeModule(); if (currentModule && currentModule->moduleName() == aModuleTitle) return; - thePopup->insertItem( tr( "MEN_OPENWITH" ), this, SLOT( onOpenWith() ) ); - + if ( !aModuleTitle.isEmpty() ) + thePopup->insertItem( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) ); } /*!Update obect browser: 1.if 'updateModels' true, update existing data models; 2. update "non-existing" (not loaded yet) data models; - 3. update object browser if it existing */ + 3. update object browser if it exists */ void SalomeApp_Application::updateObjectBrowser( const bool updateModels ) { - // update existing data models (already loaded SComponents) - LightApp_Application::updateObjectBrowser(updateModels); - // update "non-existing" (not loaded yet) data models SalomeApp_Study* study = dynamic_cast(activeStudy()); if ( study ) @@ -769,16 +1118,21 @@ void SalomeApp_Application::updateObjectBrowser( const bool updateModels ) if ( aComponent->ComponentDataType() == "Interface Applicative" ) continue; // skip the magic "Interface Applicative" component - SalomeApp_DataModel::BuildTree( aComponent, study->root(), study, /*skipExisitng=*/true ); + OB_Browser* ob = static_cast( getWindow( WT_ObjectBrowser )); + const bool isAutoUpdate = ob->isAutoUpdate(); + ob->setAutoUpdate( false ); + SalomeApp_DataModel::synchronize( aComponent, study ); + ob->setAutoUpdate( isAutoUpdate ); + //SalomeApp_DataModel::BuildTree( aComponent, study->root(), study, /*skipExisitng=*/true ); } } } - if ( objectBrowser() ) - { - objectBrowser()->updateGeometry(); - objectBrowser()->updateTree(); - } + // create data objects that correspond to GUI state save points + if ( study ) updateSavePointDataObjects( study ); + + // update existing data models (already loaded SComponents) + LightApp_Application::updateObjectBrowser( updateModels ); } /*!Display Catalog Genenerator dialog */ @@ -840,3 +1194,191 @@ void SalomeApp_Application::onDblClick( QListViewItem* it ) } } } + +/*! + Creates new view manager + \param type - type of view manager +*/ +SUIT_ViewManager* SalomeApp_Application::newViewManager(const QString& type) +{ + return createViewManager(type); +} + + +/*!Global utility funciton, returns selected GUI Save point object's ID */ +int getSelectedSavePoint( const LightApp_SelectionMgr* selMgr ) +{ + SALOME_ListIO aList; + selMgr->selectedObjects( aList ); + Handle(SALOME_InteractiveObject) aIObj = aList.First(); + QString entry( aIObj->getEntry() ); + QString startStr = QObject::tr( "SAVE_POINT_DEF_NAME" ); + if ( !entry.startsWith( startStr ) ) // it's a "GUI state" object + return -1; + bool ok; // conversion to integer is ok? + int savePoint = entry.right( entry.length() - startStr.length() ).toInt( &ok ); + return ok ? savePoint : -1; +} + +/*!Called on Restore GUI State popup command*/ +void SalomeApp_Application::onRestoreGUIState() +{ + int savePoint = ::getSelectedSavePoint( selectionMgr() ); + if ( savePoint == -1 ) + return; + SalomeApp_VisualState( this ).restoreState( savePoint ); +} + +/*!Called on Rename GUI State popup command*/ +void SalomeApp_Application::onRenameGUIState() +{ + int savePoint = ::getSelectedSavePoint( selectionMgr() ); + if ( savePoint == -1 ) + return; + SalomeApp_Study* study = dynamic_cast( activeStudy() ); + if ( !study ) + return; + + QString newName = LightApp_NameDlg::getName( desktop(), study->getNameOfSavePoint( savePoint ) ); + if ( !newName.isNull() && !newName.isEmpty() ) { + study->setNameOfSavePoint( savePoint, newName ); + updateSavePointDataObjects( study ); + objectBrowser()->updateTree( study->root() ); + } +} + + +/*!Called on Delete GUI State popup command*/ +void SalomeApp_Application::onDeleteGUIState() +{ + int savePoint = ::getSelectedSavePoint( selectionMgr() ); + if ( savePoint == -1 ) + return; + SalomeApp_Study* study = dynamic_cast( activeStudy() ); + if ( !study ) + return; + + study->removeSavePoint( savePoint ); + updateSavePointDataObjects( study ); +} + +/*!Called on Save study operation*/ +void SalomeApp_Application::onStudySaved( SUIT_Study* study ) +{ + LightApp_Application::onStudySaved( study ); + + if ( objectBrowser() ) { + updateSavePointDataObjects( dynamic_cast( study ) ); + objectBrowser()->updateTree( study->root() ); + } +} + +/*!Called on Open study operation*/ +void SalomeApp_Application::onStudyOpened( SUIT_Study* study ) +{ + LightApp_Application::onStudyOpened( study ); + + if ( objectBrowser() ) { + updateSavePointDataObjects( dynamic_cast( study ) ); + objectBrowser()->updateTree( study->root() ); + } +} + +/*! utility function. returns true if list view item that correspond to given SUIT_DataObject is open. + only first level items are traversed */ +bool isListViewItemOpen( QListView* lv, const SUIT_DataObject* dobj ) +{ + if ( !lv || !dobj ) + return false; + + QListViewItem* item = lv->firstChild(); + while ( item ) { + OB_ListItem* ob_item = dynamic_cast( item ); + if ( ob_item && ob_item->dataObject() == dobj ) + return ob_item->isOpen(); + item = item->nextSibling(); + } + return false; +} + +/*! updateSavePointDataObjects: syncronize data objects that correspond to save points (gui states)*/ +void SalomeApp_Application::updateSavePointDataObjects( SalomeApp_Study* study ) +{ + OB_Browser* ob = objectBrowser(); + + if ( !study || !ob ) + return; + + // find GUI states root object + SUIT_DataObject* guiRootObj = 0; + DataObjectList ch; + study->root()->children( ch ); + DataObjectList::const_iterator it = ch.begin(), last = ch.end(); + for ( ; it != last ; ++it ) { + if ( dynamic_cast( *it ) ) { + guiRootObj = *it; + break; + } + } + std::vector savePoints = study->getSavePoints(); + // case 1: no more save points but they existed in study's tree + if ( savePoints.empty() && guiRootObj ) { + delete guiRootObj; + return; + } + // case 2: no more save points but root does not exist either + if ( savePoints.empty() && !guiRootObj ) + return; + // case 3: save points but no root for them - create it + if ( !savePoints.empty() && !guiRootObj ) + guiRootObj = new SalomeApp_SavePointRootObject( study->root() ); + // case 4: everything already exists.. here may be a problem: we want "GUI states" root object + // to be always the last one in the tree. Here we check - if it is not the last one - remove and + // re-create it. + if ( guiRootObj->nextBrother() ) { + study->root()->removeChild(guiRootObj); + study->root()->appendChild(guiRootObj); + //study->root()->dump(); + } + + // store data objects in a map id-to-DataObject + QMap mapDO; + ch.clear(); + guiRootObj->children( ch ); + for( it = ch.begin(), last = ch.end(); it != last ; ++it ) { + SalomeApp_SavePointObject* dobj = dynamic_cast( *it ); + if ( dobj ) + mapDO[dobj->getId()] = dobj; + } + + // iterate new save points. if DataObject with such ID not found in map - create DataObject + // if in the map - remove it from map. + for ( int i = 0; i < savePoints.size(); i++ ) + if ( !mapDO.contains( savePoints[i] ) ) + new SalomeApp_SavePointObject( guiRootObj, savePoints[i], study ); + else + mapDO.remove( savePoints[i] ); + + // delete DataObjects that are still in the map -- their IDs were not found in data model + for ( QMap::Iterator it = mapDO.begin(); it != mapDO.end(); ++it ) + delete it.data(); +} + +/*! Check data object */ +bool SalomeApp_Application::checkDataObject(LightApp_DataObject* theObj) +{ + if (theObj) + return true; + + return false; +} + +/*! Process standard messages from desktop */ +void SalomeApp_Application::onDesktopMessage( const QString& message ) +{ + // update object browser + if ( message.lower() == "updateobjectbrowser" || + message.lower() == "updateobjbrowser" ) + updateObjectBrowser(); +} +