From: rnv Date: Thu, 22 Jun 2017 14:32:06 +0000 (+0300) Subject: Merge Python 3 porting. X-Git-Tag: V9_0_0~7 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=7e5424a12a7f6894a5b9a029fd8251f2cb5780b8;hp=78fc24036a8974ff6d4c05d4b7e156393211d1a8;p=modules%2Fgui.git Merge Python 3 porting. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a6313fb7..087ee04b9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ SET(${PROJECT_NAME_UC}_MINOR_VERSION 3) SET(${PROJECT_NAME_UC}_PATCH_VERSION 0) SET(${PROJECT_NAME_UC}_VERSION ${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION}) -SET(${PROJECT_NAME_UC}_VERSION_DEV 0) +SET(${PROJECT_NAME_UC}_VERSION_DEV 1) # Common CMake macros # =================== @@ -89,12 +89,10 @@ OPTION(SALOME_USE_PVVIEWER "Enable ParaView visualization (Mandatory in classic CMAKE_DEPENDENT_OPTION(SALOME_USE_SALOMEOBJECT "Enable Salome Object (Mandatory in classic configurations)" ON "SALOME_LIGHT_ONLY" ON) -OPTION(SALOME_USE_SINGLE_DESKTOP "Enable multiple document interface" ON) MARK_AS_ADVANCED(SALOME_LIGHT_ONLY SALOME_USE_VTKVIEWER SALOME_USE_GRAPHICSVIEW SALOME_USE_PVVIEWER) MARK_AS_ADVANCED(SALOME_USE_SALOMEOBJECT SALOME_USE_OCCVIEWER SALOME_USE_GLVIEWER SALOME_USE_PLOT2DVIEWER) MARK_AS_ADVANCED(SALOME_USE_PYCONSOLE SALOME_USE_QXGRAPHVIEWER SALOME_USE_PYVIEWER) -MARK_AS_ADVANCED(SALOME_USE_SINGLE_DESKTOP) # Prerequisites # ============= @@ -146,11 +144,6 @@ IF(SALOME_GUI_USE_OBSERVERS) ADD_DEFINITIONS(-DWITH_SALOMEDS_OBSERVER) ENDIF() -# Single-study GUI -IF(SALOME_USE_SINGLE_DESKTOP) - ADD_DEFINITIONS(-DSINGLE_DESKTOP) -ENDIF() - # OCCT FIND_PACKAGE(SalomeCAS REQUIRED) diff --git a/SalomeGUIConfig.cmake.in b/SalomeGUIConfig.cmake.in index 74af92640..bcd7e3c24 100644 --- a/SalomeGUIConfig.cmake.in +++ b/SalomeGUIConfig.cmake.in @@ -63,16 +63,12 @@ SET(SALOME_USE_PVVIEWER @SALOME_USE_PVVIEWER@) SET(SALOME_USE_PYVIEWER @SALOME_USE_PYVIEWER@) SET(SALOME_USE_PYCONSOLE @SALOME_USE_PYCONSOLE@) SET(SALOME_USE_SALOMEOBJECT @SALOME_USE_SALOMEOBJECT@) -SET(SALOME_USE_SINGLE_DESKTOP @SALOME_USE_SINGLE_DESKTOP@) SET(SALOME_GUI_USE_OBSERVERS @SALOME_GUI_USE_OBSERVERS@) SET(SALOME_GUI_USE_OPENGL2 @SALOME_GUI_USE_OPENGL2@) IF(SALOME_GUI_LIGHT_ONLY) LIST(APPEND GUI_DEFINITIONS "-DGUI_DISABLE_CORBA") ENDIF() -IF(SALOME_USE_SINGLE_DESKTOP) - LIST(APPEND GUI_DEFINITIONS "-DSINGLE_DESKTOP") -ENDIF() IF(SALOME_GUI_USE_OBSERVERS) LIST(APPEND GUI_DEFINITIONS "-DWITH_SALOMEDS_OBSERVER") ENDIF() diff --git a/doc/salome/gui/input/howtos_and_best_practives.doc b/doc/salome/gui/input/howtos_and_best_practives.doc index e064bf281..bb32f91cb 100644 --- a/doc/salome/gui/input/howtos_and_best_practives.doc +++ b/doc/salome/gui/input/howtos_and_best_practives.doc @@ -159,12 +159,12 @@ useCaseIter->UnRegister(); useCaseBuilder->UnRegister(); \endcode -\section use_case_compatibility Remark about compatibility with existing studies +\section use_case_compatibility Remark about compatibility with existing study If you decide to switch your module to the use case builder approach to provide customization for the data tree representation, you must take care of compatibility with existing SALOME studies. Basically it means that you have to add -a simple code to \c Load() (and \c LoadASCII() if necessary) method +a simple code to \c Load() method of your module, which adds tree node attributes to all data entities in the data tree of your module. The simplest way to do this is to iterate through all data items and recursively add them to @@ -416,7 +416,7 @@ void MyModule::copyOrMove( const MYMODULE_ORB::object_list& what, { if ( CORBA::is_nil( where ) ) return; // bad parent - SALOMEDS::Study_var study = where->GetStudy(); // study + SALOMEDS::Study_var study = GUI::getStudyServant(); // study SALOMEDS::StudyBuilder_var studyBuilder = study->NewBuilder(); // study builder SALOMEDS::UseCaseBuilder_var useCaseBuilder = study->GetUseCaseBuilder(); // use case builder SALOMEDS::SComponent_var father = where->GetFatherComponent(); // father component diff --git a/doc/salome/gui/input/text_user_interface.doc b/doc/salome/gui/input/text_user_interface.doc index 5501c21ce..0e9984bfa 100644 --- a/doc/salome/gui/input/text_user_interface.doc +++ b/doc/salome/gui/input/text_user_interface.doc @@ -12,10 +12,7 @@ console (since SWIG library is linked directly to the GUI library). The example of usage: \code # update Object browser contents -salome.sg.updateObjBrowser(True) - -# get the active study ID -studyId = salome.sg.getActiveStudyId() +salome.sg.updateObjBrowser() # get the active study name studyName = salome.sg.getActiveStudyName() diff --git a/doc/salome/gui/input/using_pluginsmanager.doc b/doc/salome/gui/input/using_pluginsmanager.doc index bff116f05..71302d2bb 100644 --- a/doc/salome/gui/input/using_pluginsmanager.doc +++ b/doc/salome/gui/input/using_pluginsmanager.doc @@ -100,7 +100,7 @@ training course): import salome import GEOM from salome.geom import geomBuilder -geompy = geomBuilder.New(salome.myStudy) +geompy = geomBuilder.New() # Create the objects Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) @@ -122,10 +122,10 @@ import salome_pluginsmanager def trihedron(context): import GEOM from salome.geom import geomBuilder - geompy = geomBuilder.New(salome.myStudy) + geompy = geomBuilder.New() # Intialize the geompy factory with the active study activeStudy = context.study - geompy.init_geom(activeStudy) + geompy.init_geom() # Create the objects Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) Vy = geompy.MakeVectorDXDYDZ(0, 10, 0) diff --git a/doc/salome/gui/static/footer.html b/doc/salome/gui/static/footer.html index 91afd6cc8..7cf11feba 100755 --- a/doc/salome/gui/static/footer.html +++ b/doc/salome/gui/static/footer.html @@ -4,7 +4,7 @@ diff --git a/doc/salome/tui/static/footer.html b/doc/salome/tui/static/footer.html index 91afd6cc8..7cf11feba 100755 --- a/doc/salome/tui/static/footer.html +++ b/doc/salome/tui/static/footer.html @@ -4,7 +4,7 @@ diff --git a/src/CAM/CAM_Module.cxx b/src/CAM/CAM_Module.cxx index 6a8e49f36..b886d8f55 100755 --- a/src/CAM/CAM_Module.cxx +++ b/src/CAM/CAM_Module.cxx @@ -1027,7 +1027,9 @@ int CAM_Module::registerAction( const int id, QAction* a ) if ( toolMgr() ) toolMgr()->registerAction( a ); - if ( application() && application()->desktop() ) + if ( application() && application()->desktop() && + a->shortcutContext() != Qt::WidgetShortcut && + a->shortcutContext() != Qt::WidgetWithChildrenShortcut ) application()->desktop()->addAction( a ); return ident; diff --git a/src/CAM/CAM_Study.cxx b/src/CAM/CAM_Study.cxx index 91aff4c34..f252617cb 100755 --- a/src/CAM/CAM_Study.cxx +++ b/src/CAM/CAM_Study.cxx @@ -163,7 +163,7 @@ void CAM_Study::dataModelInserted( const CAM_DataModel* dModel ) { CAM_DataModel* dm = (CAM_DataModel*)dModel; - if ( isSaved() ) // need to load data model from an exisitng file? + if ( isSaved() ) // need to load data model from an existing file? openDataModel( studyName(), dm ); else // no, just need to update data model's connection to study tree //(some application may want to show model's root in a study tree even if a model is empty) diff --git a/src/GUI_PY/helper.py b/src/GUI_PY/helper.py index 670cc5ecb..890367e7c 100644 --- a/src/GUI_PY/helper.py +++ b/src/GUI_PY/helper.py @@ -53,23 +53,6 @@ sgPyQt=SalomePyQt.SalomePyQt() import libSALOME_Swig SalomeGUI = libSALOME_Swig.SALOMEGUI_Swig() -# -# ================================================================== -# General helper function for GUI programming actions -# ================================================================== -# -# Get the active study -# -def getActiveStudy(): - """ - This returns a study object that corresponds to the active - study. The active study is a GUI concept: it's the study currently - active on the desktop. - """ - studyId = sgPyQt.getStudyId() - study = services.getStudyManager().GetStudyByID( studyId ) - return study - # # ================================================================== # Functions to manipulate the objects in the browser (generic) @@ -84,7 +67,7 @@ def getSObjectSelected(): ''' sobj = None entry = None - study = getActiveStudy() + study = salome.myStudy if SalomeGUI.SelectedCount() == 1: # We only considere the first element of the list. If you need # something else, create another function in your own context. @@ -112,10 +95,10 @@ def deleteSObjectSelected(): ''' sobj, entry = getSObjectSelected() if ( sobj ): - study = getActiveStudy() + study = salome.myStudy builder = study.NewBuilder() builder.RemoveObject( sobj ) - SalomeGUI.updateObjBrowser(True) + SalomeGUI.updateObjBrowser() pass # @@ -130,7 +113,7 @@ def deleteSObjectSelected(): # # Definitions: -# - the SObject is an item in the active study (Study Object). +# - the SObject is an item in the study (Study Object). # - the entry is the identifier of an item. # - the object (geom object or smesh object) is a CORBA servant # embedded in the SALOME component container and with a reference in diff --git a/src/GuiHelpers/SALOME_AppStudyEditor.cxx b/src/GuiHelpers/SALOME_AppStudyEditor.cxx index 1252bc431..d024287ff 100644 --- a/src/GuiHelpers/SALOME_AppStudyEditor.cxx +++ b/src/GuiHelpers/SALOME_AppStudyEditor.cxx @@ -20,6 +20,7 @@ // Author: Guillaume Boulant (EDF/R&D) #include "SALOME_AppStudyEditor.hxx" +#include "SALOME_GuiServices.hxx" #include #include @@ -29,34 +30,12 @@ SALOME_AppStudyEditor::SALOME_AppStudyEditor(SalomeApp_Application * salomeApp) : SALOME_StudyEditor() { _salomeApp = salomeApp; - updateActiveStudy(); -} - -/** - * This updates the editor with the current active study. If the - * active study id is identical to the study id currently associated - * to this object, then no update is performed. - */ -int SALOME_AppStudyEditor::updateActiveStudy() { - int activeStudyId = SALOME_AppStudyEditor::getActiveStudyId(_salomeApp); - if ( activeStudyId != this->getStudyId() ) { - this->setStudyById(activeStudyId); - } - return activeStudyId; -} - -// GUI context only -int SALOME_AppStudyEditor::getActiveStudyId(SalomeApp_Application * salomeApp) { - SalomeApp_Study* appStudy = dynamic_cast (salomeApp->activeStudy()); - _PTR(Study) aCStudy = appStudy->studyDS(); - int studyId = aCStudy->StudyId(); - return studyId; } SALOMEDS::SObject_ptr SALOME_AppStudyEditor::IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject) { if (!iobject.IsNull()) { if (iobject->hasEntry()) { - SALOMEDS::SObject_var sobject = _study->FindObjectID(iobject->getEntry()); + SALOMEDS::SObject_var sobject = GUI::getStudyServant()->FindObjectID(iobject->getEntry()); return sobject._retn(); } } diff --git a/src/GuiHelpers/SALOME_AppStudyEditor.hxx b/src/GuiHelpers/SALOME_AppStudyEditor.hxx index 19ceb182c..804ad6df1 100644 --- a/src/GuiHelpers/SALOME_AppStudyEditor.hxx +++ b/src/GuiHelpers/SALOME_AppStudyEditor.hxx @@ -37,13 +37,10 @@ class SALOMEGUIHELPERS_EXPORT SALOME_AppStudyEditor: public SALOME_StudyEditor { public: SALOME_AppStudyEditor(SalomeApp_Application * salomeApp); - int updateActiveStudy(); SALOMEDS::SObject_ptr IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject); SALOME_StudyEditor::SObjectList * getSelectedObjects(); - static int getActiveStudyId(SalomeApp_Application * salomeApp); - private: SalomeApp_Application * _salomeApp; diff --git a/src/GuiHelpers/SALOME_GuiServices.cxx b/src/GuiHelpers/SALOME_GuiServices.cxx index 76d1dc081..59d77362e 100644 --- a/src/GuiHelpers/SALOME_GuiServices.cxx +++ b/src/GuiHelpers/SALOME_GuiServices.cxx @@ -68,31 +68,14 @@ namespace GUI { // SALOME application using the resourceMgr() method: // - /** - * This returns the current active study id if an active study is - * defined in the SALOME session, returns -1 otherwise. Note that - * the active study doesn't make sense outside of the GUI SALOME - * process, i.e. the SALOME_SessionServer embedding the - * SalomeApp_Application. - */ - int getActiveStudyId() { - SALOME::Session_var aSession = KERNEL::getSalomeSession(); - if ( CORBA::is_nil(aSession) ) { - INFOS("ERR: can't request for active study because the session is NULL"); - return -1; - } - return aSession->GetActiveStudyId(); - } - /** * This returns the current active study if an active study is * defined in the SALOME session, returns null otherwise. */ - SALOMEDS::Study_ptr getActiveStudy() { - return KERNEL::getStudyById(getActiveStudyId()); + SALOMEDS::Study_ptr getStudyServant() { + return SALOMEDS::Study::_duplicate(KERNEL::getStudyServant()); } - // __GBO__ Question: what is the difference between a // SALOMEDS::Study and a SalomeApp_Study? SalomeApp_Study* getSalomeAppActiveStudy() { @@ -120,9 +103,7 @@ namespace GUI { // retrieve the SALOMEDS::Study servant first and the to // request this servant to get the SObject given its entry. // - _PTR(Study) studyClient = appStudy->studyDS(); - SALOMEDS::Study_var study = KERNEL::getStudyManager()->GetStudyByID(studyClient->StudyId()); - SALOMEDS::SObject_ptr sobject = study->FindObjectID(iobject->getEntry()); + SALOMEDS::SObject_ptr sobject = KERNEL::getStudyServant()->FindObjectID(iobject->getEntry()); return sobject; } } diff --git a/src/GuiHelpers/SALOME_GuiServices.hxx b/src/GuiHelpers/SALOME_GuiServices.hxx index 73661bb98..a7565ff9d 100644 --- a/src/GuiHelpers/SALOME_GuiServices.hxx +++ b/src/GuiHelpers/SALOME_GuiServices.hxx @@ -58,8 +58,7 @@ namespace GUI { // depends of the SALOME module technical choices). In general, on // of the attribute of a SObject is a CORBA servant that handles the // data to work with - SALOMEGUIHELPERS_EXPORT SALOMEDS::Study_ptr getActiveStudy(); - SALOMEGUIHELPERS_EXPORT int getActiveStudyId(); + SALOMEGUIHELPERS_EXPORT SALOMEDS::Study_ptr getStudyServant(); // Another way to get the active study (to be converted in // SALOMEDS::Study): diff --git a/src/GuiHelpers/StandardApp_Module.cxx b/src/GuiHelpers/StandardApp_Module.cxx index e969ed113..051958daa 100644 --- a/src/GuiHelpers/StandardApp_Module.cxx +++ b/src/GuiHelpers/StandardApp_Module.cxx @@ -20,6 +20,8 @@ #include "StandardApp_Module.hxx" +#include "SALOME_GuiServices.hxx" + #include #include #include @@ -279,7 +281,7 @@ bool StandardApp_Module::activateModule( SUIT_Study* theStudy ) setToolShown( true ); if ( this->createStudyComponentAtActivation() ) { - this->createStudyComponent(theStudy); + this->createStudyComponent(); } return bOk; @@ -301,12 +303,9 @@ bool StandardApp_Module::createStudyComponentAtActivation() { * the module. This component is associated to the engine (return by * getEngine()) if the engine is a SALOMEDS::Driver. */ -void StandardApp_Module::createStudyComponent(SUIT_Study* theStudy) { +void StandardApp_Module::createStudyComponent() { - SALOME_NamingService *aNamingService = SalomeApp_Application::namingService(); - CORBA::Object_var aSMObject = aNamingService->Resolve("/myStudyManager"); - SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow(aSMObject); - SALOMEDS::Study_var aDSStudy = aStudyManager->GetStudyByID(theStudy->id()); + SALOMEDS::Study_var aDSStudy = GUI::getStudyServant(); SALOMEDS::SComponent_var aFather = aDSStudy->FindComponent(QCHARSTAR(moduleName())); if (aFather->_is_nil()) diff --git a/src/GuiHelpers/StandardApp_Module.hxx b/src/GuiHelpers/StandardApp_Module.hxx index 62dad7d0e..acf1a4c19 100644 --- a/src/GuiHelpers/StandardApp_Module.hxx +++ b/src/GuiHelpers/StandardApp_Module.hxx @@ -103,7 +103,7 @@ protected: virtual void createModuleActions(); /* Use this to create a root entry in the study for this module */ - void createStudyComponent(SUIT_Study*); + void createStudyComponent(); /* Implement this to say if study component entry should be created at activation step */ virtual bool createStudyComponentAtActivation(); diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx index 24c8f40ff..afda2bbef 100644 --- a/src/LightApp/LightApp_Application.cxx +++ b/src/LightApp/LightApp_Application.cxx @@ -230,8 +230,6 @@ static const char* imageEmptyIcon[] = { "....................", "...................."}; -int LightApp_Application::lastStudyId = 0; - // Markers used to parse array with dockable windows and toolbars state. // For more details please see the qdockarealayout.cpp && qtoolbararealayout.cpp // in the Qt source code. @@ -295,14 +293,6 @@ namespace } } -/*! - \return last global id of study -*/ -int LightApp_Application::studyId() -{ - return LightApp_Application::lastStudyId; -} - /*!Create new instance of LightApp_Application.*/ extern "C" LIGHTAPP_EXPORT SUIT_Application* createApplication() { @@ -454,6 +444,8 @@ void LightApp_Application::start() desktop()->statusBar()->showMessage( "" ); LightApp_EventFilter::Init(); + + onNewDoc(); } /*!Closeapplication.*/ @@ -932,10 +924,8 @@ void LightApp_Application::onNewWindow() */ void LightApp_Application::onNewDoc() { -#ifdef SINGLE_DESKTOP if ( !checkExistingDoc() ) return; -#endif //asl: fix for 0020515 saveDockWindowsState(); @@ -950,10 +940,8 @@ void LightApp_Application::onOpenDoc() { SUIT_Study* study = activeStudy(); -#ifdef SINGLE_DESKTOP if ( !checkExistingDoc() ) return; -#endif CAM_Application::onOpenDoc(); @@ -970,10 +958,8 @@ void LightApp_Application::onOpenDoc() */ bool LightApp_Application::onOpenDoc( const QString& aName ) { -#ifdef SINGLE_DESKTOP if ( !checkExistingDoc() ) return false; -#endif saveDockWindowsState(); @@ -1357,10 +1343,9 @@ void LightApp_Application::placeDockWindow( const int id, Qt::DockWidgetArea pla /*! Gets window. \param flag - key for window - \param studyId - study id Flag used how identificator of window in windows list. */ -QWidget* LightApp_Application::getWindow( const int flag, const int ) +QWidget* LightApp_Application::getWindow( const int flag) { QWidget* wid = dockWindow( flag ); if ( !wid ) @@ -1999,8 +1984,6 @@ void LightApp_Application::updateActions() */ SUIT_Study* LightApp_Application::createNewStudy() { - LightApp_Application::lastStudyId++; - LightApp_Study* aStudy = new LightApp_Study( this ); // Set up processing of major study-related events @@ -2932,6 +2915,20 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref ) pref->addPreference( tr( "PREF_PY_LINE_NUMBS_AREA" ), pyDispGroup, LightApp_Preferences::Bool, "PyEditor", "LineNumberArea" ); // ... "Display settings" group <> + + // ... "Editor settings" group <> + int pyEditGroup = pref->addPreference( tr( "PREF_GROUP_PY_EDITOR" ), pyeditTab ); + // ... -> navigation mode + int pyCompletion = pref->addPreference( tr( "PREF_PY_COMPLETION_MODE" ), pyEditGroup, + LightApp_Preferences::Selector, "PyEditor", "CompletionPolicy" ); + aValuesList.clear(); + anIndicesList.clear(); + aValuesList << tr("PREF_PY_NONE") << tr("PREF_PY_AUTO") << tr("PREF_PY_MANUAL") << tr("PREF_PY_ALWAYS"); + anIndicesList << 0 << 1 << 2 << 3 ; + pref->setItemProperty( "strings", aValuesList, pyCompletion ); + pref->setItemProperty( "indexes", anIndicesList, pyCompletion ); + // ... "Editor settings" group <> + // ... "Tab settings" group <> int pyTabGroup = pref->addPreference( tr( "PREF_GROUP_PY_TAB" ), pyeditTab ); pref->setItemProperty( "columns", 2, pyTabGroup ); @@ -5133,19 +5130,20 @@ bool LightApp_Application::checkExistingDoc() { bool result = true; if( activeStudy() ) { - int answer = SUIT_MessageBox::question( desktop(), - tr( "APPCLOSE_CAPTION" ), - tr( "STUDYCLOSE_DESCRIPTION" ), - tr( "APPCLOSE_SAVE" ), - tr( "APPCLOSE_CLOSE" ), - tr( "APPCLOSE_CANCEL" ), 0 ); + int answer = !activeStudy()->isModified() ? 1 : + SUIT_MessageBox::question( desktop(), + tr( "APPCLOSE_CAPTION" ), + tr( "STUDYCLOSE_DESCRIPTION" ), + tr( "APPCLOSE_SAVE" ), + tr( "APPCLOSE_CLOSE" ), + tr( "APPCLOSE_CANCEL" ), 0 ); if(answer == 0) { if ( activeStudy()->isSaved() ) { onSaveDoc(); closeDoc( false ); } else if ( onSaveAsDoc() ) { - if( !closeDoc( false ) ) { - result = false; + if( !closeDoc( false ) ) { + result = false; } } else { result = false; diff --git a/src/LightApp/LightApp_Application.h b/src/LightApp/LightApp_Application.h index 4d26aef25..767509dfe 100644 --- a/src/LightApp/LightApp_Application.h +++ b/src/LightApp/LightApp_Application.h @@ -135,7 +135,7 @@ public: virtual SUIT_ViewManager* createViewManager( const QString& vmType, QWidget* w ); virtual SUIT_ViewManager* createViewManager( SUIT_ViewModel* ); - QWidget* getWindow( const int, const int = -1 ); + QWidget* getWindow( const int ); QWidget* dockWindow( const int ) const; void removeDockWindow( const int ); void insertDockWindow( const int, QWidget* ); @@ -154,8 +154,6 @@ public: void setDefaultStudyName( const QString& theName ); - static int studyId(); - virtual bool event( QEvent* ); virtual bool checkDataObject( LightApp_DataObject* theObj ); @@ -248,7 +246,7 @@ protected slots: virtual void onWindowActivated( SUIT_ViewWindow* theViewWindow ); void onNewWindow(); - void onModuleActivation( const QString& ); + virtual void onModuleActivation( const QString& ); void onCloseView( SUIT_ViewManager* ); virtual void onStudyCreated( SUIT_Study* ); @@ -341,7 +339,6 @@ protected: static LightApp_Preferences* _prefs_; - static int lastStudyId; QStringList myUserWmTypes; }; diff --git a/src/LightApp/LightApp_Study.cxx b/src/LightApp/LightApp_Study.cxx index 9a3d5dfb7..debdb25b4 100644 --- a/src/LightApp/LightApp_Study.cxx +++ b/src/LightApp/LightApp_Study.cxx @@ -60,8 +60,6 @@ LightApp_Study::~LightApp_Study() */ bool LightApp_Study::createDocument( const QString& theStr ) { - setStudyName( QString( "Study%1" ).arg( LightApp_Application::studyId() ) ); - // create myRoot setRoot( new LightApp_RootObject( this ) ); diff --git a/src/LightApp/resources/LightApp.xml b/src/LightApp/resources/LightApp.xml index ace4c880f..3f74985a9 100644 --- a/src/LightApp/resources/LightApp.xml +++ b/src/LightApp/resources/LightApp.xml @@ -237,6 +237,7 @@ +
diff --git a/src/LightApp/resources/LightApp_msg_en.ts b/src/LightApp/resources/LightApp_msg_en.ts index 63fc8258b..62c8b8d1e 100644 --- a/src/LightApp/resources/LightApp_msg_en.ts +++ b/src/LightApp/resources/LightApp_msg_en.ts @@ -9,7 +9,7 @@ ABOUT_COPYRIGHT - Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE + Copyright (C) 2007-2017 CEA/DEN, EDF R&D, OPEN CASCADE Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -56,15 +56,15 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS STUDYCLOSE_DESCRIPTION - You already have an active study in your session. It has to be closed before working with another study. + The current study has unsaved changes. Would you like to save before closing it? APPCLOSE_SAVE - &Save && Close + &Yes APPCLOSE_CLOSE - Close &w/o saving + &No APPCLOSE_CANCEL @@ -1041,6 +1041,30 @@ File does not exist PREF_PY_LINE_NUMBS_AREA Display line numbers area + + PREF_GROUP_PY_EDITOR + Editor settings + + + PREF_PY_COMPLETION_MODE + Completion mode + + + PREF_PY_NONE + None + + + PREF_PY_AUTO + Auto + + + PREF_PY_MANUAL + Manual + + + PREF_PY_ALWAYS + Always + PREF_GROUP_PY_TAB Tab settings diff --git a/src/LightApp/resources/LightApp_msg_fr.ts b/src/LightApp/resources/LightApp_msg_fr.ts index 88a208a03..6cd92b3d4 100755 --- a/src/LightApp/resources/LightApp_msg_fr.ts +++ b/src/LightApp/resources/LightApp_msg_fr.ts @@ -9,7 +9,7 @@ ABOUT_COPYRIGHT - Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE + Copyright (C) 2007-2017 CEA/DEN, EDF R&D, OPEN CASCADE Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -56,15 +56,15 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS STUDYCLOSE_DESCRIPTION - Une étude est déjà ouverte. Elle doit être fermée avant d'en ouvrir une autre. + Une étude a des modifications non enregistrées. Voulez-vous les sauvegarder avant de fermer? APPCLOSE_SAVE - &Sauvegarder && Fermer + &Oui APPCLOSE_CLOSE - &Fermer sans sauvegarder + &Non APPCLOSE_CANCEL @@ -1041,6 +1041,30 @@ Le fichier n'existe pas PREF_PY_LINE_NUMBS_AREA Affiche les numéros de ligne + + PREF_GROUP_PY_EDITOR + Editor settings + + + PREF_PY_COMPLETION_MODE + Completion mode + + + PREF_PY_NONE + None + + + PREF_PY_AUTO + Auto + + + PREF_PY_MANUAL + Manual + + + PREF_PY_ALWAYS + Always + PREF_GROUP_PY_TAB Indentation diff --git a/src/LightApp/resources/LightApp_msg_ja.ts b/src/LightApp/resources/LightApp_msg_ja.ts index b294bed04..21df7e366 100644 --- a/src/LightApp/resources/LightApp_msg_ja.ts +++ b/src/LightApp/resources/LightApp_msg_ja.ts @@ -9,7 +9,7 @@ ABOUT_COPYRIGHT - Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE + Copyright (C) 2007-2017 CEA/DEN, EDF R&D, OPEN CASCADE Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -56,16 +56,15 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS STUDYCLOSE_DESCRIPTION - 既存のスタディを閉じる必要があります。閉じますか? - + The current study has unsaved changes. Would you like to save before closing it? APPCLOSE_SAVE - 保存して閉じる(&S) + はい(&Y) APPCLOSE_CLOSE - 保存せずに閉じる(&C) + いいえ(&N) APPCLOSE_CANCEL @@ -1040,6 +1039,30 @@ Pythonファイルは、文字、数字、アンダースコアが含まれて PREF_PY_LINE_NUMBS_AREA ライン数エリアの表示 + + PREF_GROUP_PY_EDITOR + Editor settings + + + PREF_PY_COMPLETION_MODE + Completion mode + + + PREF_PY_NONE + None + + + PREF_PY_AUTO + Auto + + + PREF_PY_MANUAL + Manual + + + PREF_PY_ALWAYS + Always + PREF_GROUP_PY_TAB 設定タブ diff --git a/src/OCCViewer/OCCViewer_ViewModel.cxx b/src/OCCViewer/OCCViewer_ViewModel.cxx index 3285f015e..0b0ce6a97 100644 --- a/src/OCCViewer/OCCViewer_ViewModel.cxx +++ b/src/OCCViewer/OCCViewer_ViewModel.cxx @@ -120,7 +120,8 @@ OCCViewer_Viewer::OCCViewer_Viewer( bool DisplayTrihedron) myIsRelative(true), myTopLayerId( 0 ), myTrihedronSize(100), - myClippingDlg (NULL) + myClippingDlg (NULL), + myIsUseLocalSelection(false) { // init CasCade viewers myV3dViewer = OCCViewer_VService::CreateViewer( TCollection_ExtendedString("Viewer3d").ToExtString() ); @@ -454,7 +455,7 @@ void OCCViewer_Viewer::onKeyPress(SUIT_ViewWindow* theWindow, QKeyEvent* theEven break; case Qt::Key_N: if ( isPreselectionEnabled() ) { - if ( getAISContext()->HasOpenedContext() ) + if ( useLocalSelection() ) getAISContext()->HilightNextDetected( aView->getViewPort()->getView() ); } break; @@ -1355,6 +1356,27 @@ OCCViewer_ViewWindow* OCCViewer_Viewer::createSubWindow() return new OCCViewer_ViewWindow(0, this); } +/*! + Sets using local selection state + \param theIsUseLocalSelection - state +*/ +void OCCViewer_Viewer::setUseLocalSelection(bool theIsUseLocalSelection) +{ + myIsUseLocalSelection = theIsUseLocalSelection; +} + +/* + * Returns true if local context is opened or view model local state is set + */ +bool OCCViewer_Viewer::useLocalSelection() const +{ + if (myIsUseLocalSelection) + return true; + + Handle(AIS_InteractiveContext) ic = getAISContext(); + return !ic.IsNull() && ic->HasOpenedContext(); +} + // obsolete QColor OCCViewer_Viewer::backgroundColor( int theViewId ) const { diff --git a/src/OCCViewer/OCCViewer_ViewModel.h b/src/OCCViewer/OCCViewer_ViewModel.h index 63db7700b..329bb05bd 100755 --- a/src/OCCViewer/OCCViewer_ViewModel.h +++ b/src/OCCViewer/OCCViewer_ViewModel.h @@ -132,6 +132,9 @@ public: virtual OCCViewer_ViewWindow* createSubWindow(); + void setUseLocalSelection(bool theIsUseLocalSelection); + bool useLocalSelection() const; + public: Handle(V3d_Viewer) getViewer3d() const { return myV3dViewer;} Handle(AIS_InteractiveContext) getAISContext() const { return myAISContext; } @@ -279,7 +282,7 @@ protected: QString myClippingTexture; bool myTextureModulated; double myClippingTextureScale; - + bool myIsUseLocalSelection; }; #ifdef WIN32 diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx index a4bce4220..b7d38eab4 100644 --- a/src/OCCViewer/OCCViewer_ViewWindow.cxx +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -393,7 +393,7 @@ bool OCCViewer_ViewWindow::eventFilter( QObject* watched, QEvent* e ) if ( aEvent->modifiers().testFlag(Qt::ControlModifier) ) { Handle(AIS_InteractiveContext) ic = myModel->getAISContext(); - if ( isPreselectionEnabled() && ic->HasOpenedContext() ) { + if ( isPreselectionEnabled() && myModel->useLocalSelection() ) { if ( aEvent->delta() > 0 ) { ic->HilightNextDetected( myViewPort->getView() ); } else { diff --git a/src/PyViewer/CMakeLists.txt b/src/PyViewer/CMakeLists.txt index bc4fbe352..85bcc87ee 100644 --- a/src/PyViewer/CMakeLists.txt +++ b/src/PyViewer/CMakeLists.txt @@ -69,12 +69,14 @@ SET(_other_RESOURCES ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_copy.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_cut.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_delete.png + ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_find.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_help.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_new.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_open.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_paste.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_preferences.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_redo.png + ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_replace.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_save.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_save_as.png ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_select_all.png diff --git a/src/PyViewer/PyViewer_Settings.cxx b/src/PyViewer/PyViewer_Settings.cxx index d86c8373e..90259e380 100644 --- a/src/PyViewer/PyViewer_Settings.cxx +++ b/src/PyViewer/PyViewer_Settings.cxx @@ -50,6 +50,8 @@ void PyViewer_Settings::load() setTabSpaceVisible( myResMgr->booleanValue( group, option( snTabSpaceVisible ), tabSpaceVisible() ) ); setTabSize( myResMgr->integerValue( group, option( snTabSize ), tabSize() ) ); setFont( myResMgr->fontValue( group, option( snFont ), font() ) ); + setCompletionPolicy( myResMgr->integerValue( group, option( snCompletionPolicy ), + completionPolicy() ) ); } void PyViewer_Settings::save() @@ -65,4 +67,5 @@ void PyViewer_Settings::save() myResMgr->setValue( group, option( snTabSpaceVisible ), tabSpaceVisible() ); myResMgr->setValue( group, option( snTabSize ), tabSize() ); myResMgr->setValue( group, option( snFont ), font() ); + myResMgr->setValue( group, option( snCompletionPolicy ), completionPolicy() ); } diff --git a/src/PyViewer/PyViewer_ViewWindow.cxx b/src/PyViewer/PyViewer_ViewWindow.cxx index f7c37be7e..a9e6c79c2 100644 --- a/src/PyViewer/PyViewer_ViewWindow.cxx +++ b/src/PyViewer/PyViewer_ViewWindow.cxx @@ -22,7 +22,7 @@ #include "PyViewer_ViewWindow.h" -#include "PyEditor_Editor.h" +#include "PyEditor_Widget.h" #include "PyEditor_SettingsDlg.h" #include "SUIT_Session.h" @@ -32,9 +32,11 @@ #include "QtxActionToolMgr.h" #include +#include #include #include #include +#include /*! \class PyViewer_ViewWindow @@ -48,9 +50,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : SUIT_ViewWindow( desktop ) { - // Create editor and set it as a central widget. - myTextEditor = new PyEditor_Editor( this ); - setCentralWidget( myTextEditor ); + // Create central widget. + myEditor = new PyEditor_Widget( this ); + setCentralWidget( myEditor ); // Create actions. SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); @@ -82,7 +84,7 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : action->setShortcut( QKeySequence::Save ); connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) ); action->setEnabled( false ); - connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ), + connect( myEditor, SIGNAL( modificationChanged( bool ) ), action, SLOT( setEnabled( bool ) ) ); toolMgr()->registerAction( action, SaveId ); @@ -101,9 +103,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_UNDO" ), 0, this ); action->setStatusTip( tr( "DSC_UNDO" ) ); action->setShortcut( QKeySequence::Undo ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( undo() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( undo() ) ); action->setEnabled( false ); - connect( myTextEditor->document(), SIGNAL( undoAvailable( bool ) ), + connect( myEditor, SIGNAL( undoAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); toolMgr()->registerAction( action, UndoId ); @@ -113,9 +115,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_REDO" ), 0, this ); action->setStatusTip( tr( "DSC_REDO" ) ); action->setShortcut( QKeySequence::Redo ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( redo() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( redo() ) ); action->setEnabled( false ); - connect( myTextEditor->document(), SIGNAL( redoAvailable( bool ) ), + connect( myEditor, SIGNAL( redoAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); toolMgr()->registerAction( action, RedoId ); @@ -125,9 +127,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_CUT" ), 0, this ); action->setStatusTip( tr( "DSC_CUT" ) ); action->setShortcut( QKeySequence::Cut ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( cut() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( cut() ) ); action->setEnabled( false ); - connect( myTextEditor, SIGNAL( copyAvailable( bool ) ), + connect( myEditor, SIGNAL( copyAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); toolMgr()->registerAction( action, CutId ); @@ -137,9 +139,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_COPY" ), 0, this ); action->setStatusTip( tr( "DSC_COPY" ) ); action->setShortcut( QKeySequence::Copy ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( copy() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) ); action->setEnabled( false ); - connect( myTextEditor, SIGNAL( copyAvailable( bool ) ), + connect( myEditor, SIGNAL( copyAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); toolMgr()->registerAction( action, CopyId ); @@ -149,7 +151,7 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_PASTE" ), 0, this ); action->setStatusTip( tr( "DSC_PASTE" ) ); action->setShortcut( QKeySequence::Paste ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( paste() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) ); toolMgr()->registerAction( action, PasteId ); // . Delete @@ -158,9 +160,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_DELETE" ), 0, this ); action->setStatusTip( tr( "DSC_DELETE" ) ); action->setShortcut( QKeySequence::Delete ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( deleteSelected() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( deleteSelected() ) ); action->setEnabled( false ); - connect( myTextEditor, SIGNAL( copyAvailable( bool ) ), + connect( myEditor, SIGNAL( copyAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); toolMgr()->registerAction( action, DeleteId ); @@ -170,9 +172,29 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : tr( "ACT_SELECT_ALL" ), 0, this ); action->setStatusTip( tr( "DSC_SELECT_ALL" ) ); action->setShortcut( QKeySequence::SelectAll ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( selectAll() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) ); toolMgr()->registerAction( action, SelectAllId ); + // . Find + action = new QtxAction( tr( "TTP_FIND" ), + resMgr->loadPixmap( "PyViewer", tr( "ICON_FIND" ) ), + tr( "ACT_FIND" ), 0, this ); + action->setStatusTip( tr( "DSC_FIND" ) ); + action->setShortcut( QKeySequence::Find ); + action->setShortcutContext( Qt::WidgetShortcut ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( find() ) ); + toolMgr()->registerAction( action, FindId ); + + // . Replace + action = new QtxAction( tr( "TTP_REPLACE" ), + resMgr->loadPixmap( "PyViewer", tr( "ICON_REPLACE" ) ), + tr( "ACT_REPLACE" ), 0, this ); + action->setStatusTip( tr( "DSC_REPLACE" ) ); + action->setShortcut( QKeySequence::Replace ); + action->setShortcutContext( Qt::WidgetShortcut ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( replace() ) ); + toolMgr()->registerAction( action, ReplaceId ); + // . Preferences action = new QtxAction( tr( "TTP_PREFERENCES" ), resMgr->loadPixmap( "PyViewer", tr( "ICON_PREFERENCES" ) ), @@ -205,6 +227,9 @@ PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) : toolMgr()->append( DeleteId, idTB ); toolMgr()->append( SelectAllId, idTB ); toolMgr()->append( toolMgr()->separator(), idTB ); + toolMgr()->append( FindId, idTB ); + toolMgr()->append( ReplaceId, idTB ); + toolMgr()->append( toolMgr()->separator(), idTB ); toolMgr()->append( PreferencesId, idTB ); toolMgr()->append( toolMgr()->separator(), idTB ); toolMgr()->append( HelpId, idTB ); @@ -239,7 +264,7 @@ void PyViewer_ViewWindow::onNew() { if ( whetherSave() ) { - myTextEditor->clear(); + myEditor->clear(); setCurrentFile( QString() ); } } @@ -299,7 +324,7 @@ bool PyViewer_ViewWindow::onSaveAs() */ void PyViewer_ViewWindow::onPreferences() { - PyEditor_SettingsDlg dlg( myTextEditor, true, this ); + PyEditor_SettingsDlg dlg( myEditor->editor(), true, this ); connect( &dlg, SIGNAL( help() ), this, SLOT( onHelp() ) ); dlg.exec(); } @@ -311,7 +336,7 @@ void PyViewer_ViewWindow::onPreferences() void PyViewer_ViewWindow::setCurrentFile( const QString& filePath ) { myURL = filePath; - myTextEditor->document()->setModified( false ); + myEditor->setModified( false ); } /*! @@ -321,7 +346,7 @@ void PyViewer_ViewWindow::setCurrentFile( const QString& filePath ) */ bool PyViewer_ViewWindow::whetherSave() { - if ( myTextEditor->document()->isModified() ) + if ( myEditor->isModified() ) { QMessageBox::StandardButton answer = QMessageBox::warning( this, tr( "NAME_PYEDITOR" ), @@ -358,7 +383,7 @@ void PyViewer_ViewWindow::loadFile( const QString& filePath ) QTextStream anInput( &aFile ); QApplication::setOverrideCursor( Qt::WaitCursor ); - myTextEditor->setPlainText( anInput.readAll() ); + myEditor->setText( anInput.readAll() ); QApplication::restoreOverrideCursor(); setCurrentFile( filePath ); @@ -382,7 +407,7 @@ bool PyViewer_ViewWindow::saveFile( const QString& filePath ) QTextStream anOutput( &aFile ); QApplication::setOverrideCursor( Qt::WaitCursor ); - anOutput << myTextEditor->toPlainText(); + anOutput << myEditor->text(); QApplication::restoreOverrideCursor(); setCurrentFile( filePath ); diff --git a/src/PyViewer/PyViewer_ViewWindow.h b/src/PyViewer/PyViewer_ViewWindow.h index b96ea8b2c..229721d68 100644 --- a/src/PyViewer/PyViewer_ViewWindow.h +++ b/src/PyViewer/PyViewer_ViewWindow.h @@ -27,7 +27,7 @@ #include -class PyEditor_Editor; +class PyEditor_Widget; class PYVIEWER_EXPORT PyViewer_ViewWindow : public SUIT_ViewWindow { @@ -36,6 +36,7 @@ class PYVIEWER_EXPORT PyViewer_ViewWindow : public SUIT_ViewWindow public: enum { NewId, OpenId, SaveId, SaveAsId, UndoId, RedoId, CutId, CopyId, PasteId, DeleteId, SelectAllId, + FindId, ReplaceId, PreferencesId, HelpId }; PyViewer_ViewWindow( SUIT_Desktop* = 0 ); @@ -61,7 +62,7 @@ private: QString defaultName() const; private: - PyEditor_Editor* myTextEditor; + PyEditor_Widget* myEditor; QString myURL; }; diff --git a/src/PyViewer/resources/PyViewer_images.ts b/src/PyViewer/resources/PyViewer_images.ts index 639f1b584..6ac464e6c 100644 --- a/src/PyViewer/resources/PyViewer_images.ts +++ b/src/PyViewer/resources/PyViewer_images.ts @@ -47,6 +47,14 @@ ICON_SELECT_ALL py_select_all.png + + ICON_FIND + py_find.png + + + ICON_REPLACE + py_replace.png + ICON_PREFERENCES py_preferences.png diff --git a/src/PyViewer/resources/PyViewer_msg_en.ts b/src/PyViewer/resources/PyViewer_msg_en.ts index 0f4355ee3..20e989a1a 100644 --- a/src/PyViewer/resources/PyViewer_msg_en.ts +++ b/src/PyViewer/resources/PyViewer_msg_en.ts @@ -146,6 +146,30 @@ DSC_SELECT_ALL Select all the contents + + ACT_FIND + Find + + + TTP_FIND + Find + + + DSC_FIND + Find text + + + ACT_REPLACE + Replace + + + TTP_REPLACE + Find & Replace + + + DSC_REPLACE + Find and replace text + ACT_PREFERENCES Pre&ferences diff --git a/src/PyViewer/resources/PyViewer_msg_fr.ts b/src/PyViewer/resources/PyViewer_msg_fr.ts index c0fc973cd..7a52883c0 100644 --- a/src/PyViewer/resources/PyViewer_msg_fr.ts +++ b/src/PyViewer/resources/PyViewer_msg_fr.ts @@ -146,6 +146,30 @@ DSC_SELECT_ALL Sélectionne tout le contenu + + ACT_FIND + Find + + + TTP_FIND + Find + + + DSC_FIND + Find text + + + ACT_REPLACE + Replace + + + TTP_REPLACE + Find & Replace + + + DSC_REPLACE + Find and replace text + ACT_PREFERENCES Préférences diff --git a/src/PyViewer/resources/PyViewer_msg_ja.ts b/src/PyViewer/resources/PyViewer_msg_ja.ts index 6b8691da3..35c4e054e 100644 --- a/src/PyViewer/resources/PyViewer_msg_ja.ts +++ b/src/PyViewer/resources/PyViewer_msg_ja.ts @@ -146,6 +146,30 @@ DSC_SELECT_ALL 全選択 + + ACT_FIND + Find + + + TTP_FIND + Find + + + DSC_FIND + Find text + + + ACT_REPLACE + Replace + + + TTP_REPLACE + Find & Replace + + + DSC_REPLACE + Find and replace text + ACT_PREFERENCES 環境設定 (&f) diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx index 459839a9b..4264610e4 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx @@ -609,7 +609,6 @@ void PyModuleHelper::XmlHandler::insertPopupItems( QDomNode& parentNode, QMenu* SALOME GUI modules. */ -PyModuleHelper::InterpMap PyModuleHelper::myInterpMap; LightApp_Module* PyModuleHelper::myInitModule = 0; /*! @@ -1731,31 +1730,15 @@ QString PyModuleHelper::engineIOR() const /*! \brief Initialize python subinterpreter (one per study). \internal - \param studyId study ID */ -void PyModuleHelper::initInterp( int studyId ) +void PyModuleHelper::initInterp() { FuncMsg fmsg( "--- PyModuleHelper::initInterp()" ); - // check study Id - if ( !studyId ) { - // Error! Study Id must not be 0! - myInterp = 0; - return; - } - QMutexLocker ml( &myInitMutex ); - // try to find the subinterpreter - if ( myInterpMap.contains( studyId ) ) { - // found! - myInterp = myInterpMap[ studyId ]; - return; - } - myInterp = new SALOME_PYQT_PyInterp(); myInterp->initialize(); - myInterpMap[ studyId ] = myInterp; #ifndef GUI_DISABLE_CORBA if ( !SUIT_PYTHON::initialized ) { @@ -1772,7 +1755,7 @@ void PyModuleHelper::initInterp( int studyId ) } // ... then call a method int embedded = 1; - PyObjWrapper aRes( PyObject_CallMethod( aMod, (char*)"salome_init", (char*)"ii", studyId, embedded ) ); + PyObjWrapper aRes( PyObject_CallMethod( aMod, (char*)"salome_init", (char*)"i", embedded ) ); if ( !aRes ) { // Error! PyErr_Print(); @@ -1905,10 +1888,9 @@ void PyModuleHelper::internalInitialize( CAM_Application* app ) LightApp_Study* aStudy = dynamic_cast( app->activeStudy() ); if ( !aStudy ) return; - int aStudyId = aStudy ? aStudy->id() : 0; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( aStudyId ); + initInterp(); if ( !myInterp ) return; // Error @@ -2006,10 +1988,11 @@ void PyModuleHelper::internalActivate( SUIT_Study* study ) // get study Id LightApp_Study* aStudy = dynamic_cast( study ); - int aStudyId = aStudy ? aStudy->id() : 0; + if ( !aStudy ) + return; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( aStudyId ); + initInterp(); if ( !myInterp ) { myLastActivateStatus = false; return; // Error @@ -2058,10 +2041,11 @@ void PyModuleHelper::internalCustomize( SUIT_Study* study ) // get study Id LightApp_Study* aStudy = dynamic_cast( study ); - int aStudyId = aStudy ? aStudy->id() : 0; + if ( !aStudy ) + return; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( aStudyId ); + initInterp(); if ( !myInterp ) { myLastActivateStatus = false; return; // Error @@ -2134,7 +2118,8 @@ void PyModuleHelper::internalClosedStudy( SUIT_Study* theStudy ) // Get study Id // get study Id LightApp_Study* aStudy = dynamic_cast( theStudy ); - int aStudyId = aStudy ? aStudy->id() : 0; + if ( !aStudy ) + return; // check that Python subinterpreter is initialized and Python module is imported if ( !myInterp || !myPyModule ) { @@ -2143,7 +2128,7 @@ void PyModuleHelper::internalClosedStudy( SUIT_Study* theStudy ) } // then call Python module's deactivate() method if ( PyObject_HasAttrString( myPyModule , (char*)"closeStudy" ) ) { - PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"closeStudy", (char*)"i", aStudyId ) ); + PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"closeStudy", (char*)"i" ) ); if( !res ) { PyErr_Print(); } @@ -2202,12 +2187,11 @@ void PyModuleHelper::internalStudyChanged( SUIT_Study* study ) // get study Id LightApp_Study* aStudy = dynamic_cast( study ); - int id = aStudy ? aStudy->id() : 0; - - fmsg.message( QString( "study id = %1" ).arg( id ) ); + if ( !aStudy ) + return; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( id ); + initInterp(); if ( !myInterp ) return; // Error @@ -2224,7 +2208,7 @@ void PyModuleHelper::internalStudyChanged( SUIT_Study* study ) // call Python module's activeStudyChanged() method if ( PyObject_HasAttrString( myPyModule, (char*)"activeStudyChanged" ) ) { - PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"activeStudyChanged", (char*)"i", id ) ); + PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"activeStudyChanged", (char*)"i" ) ); if( !res ) { PyErr_Print(); } diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h index e25fc9ab0..c4d1ca9fe 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.h @@ -54,9 +54,6 @@ private: class XmlHandler; class InitLocker; - typedef QMap InterpMap; - - static InterpMap myInterpMap; //!< study to Python subinterpreter map static LightApp_Module* myInitModule; //!< Python GUI being initialized (not zero only during the initialization) LightApp_Module* myModule; //!< GUI module @@ -110,7 +107,7 @@ public slots: void onObjectBrowserClicked(SUIT_DataObject*, int); private: - void initInterp( int ); + void initInterp(); void importModule(); void setWorkSpace(); diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx index 4748bde69..aea4aa2d5 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx @@ -67,8 +67,10 @@ #include #include #include +#include #include + namespace { /*! @@ -329,6 +331,90 @@ void SALOME_Selection::ClearFilters() ProcessVoidEvent( new TEvent( mySelMgr ) ); } +/*! + \class UserDefinedContent + \brief The class represents base class for user defined widget that + can be inserted to the Preferences dialog. +*/ + +/*! + \brief Constructor +*/ +UserDefinedContent::UserDefinedContent() + : QWidget() +{ +} + +/*! + \brief Called from Preferences dialog to store settings to the resource file. +*/ +void UserDefinedContent::store() +{ +} + +/*! + \brief Called from Preferences dialog to restore settings from the resource file. +*/ +void UserDefinedContent::retrieve() +{ +} + +/*! + \class SgPyQtUserDefinedContent + \brief A Wrapper for UserDefinedContent class. + \internal +*/ +class SgPyQtUserDefinedContent: public QtxUserDefinedContent +{ +public: + SgPyQtUserDefinedContent(UserDefinedContent*); + virtual ~SgPyQtUserDefinedContent(); + + void store( QtxResourceMgr*, QtxPreferenceMgr* ); + void retrieve( QtxResourceMgr*, QtxPreferenceMgr* ); + +private: + UserDefinedContent* myContent; +}; + +/*! + \brief Create custom item for Preferences dialog wrapping widget passed from Python. + \internal +*/ +SgPyQtUserDefinedContent::SgPyQtUserDefinedContent(UserDefinedContent* content) + : QtxUserDefinedContent( 0 ), myContent( content ) +{ + QVBoxLayout* l = new QVBoxLayout( this ); + l->setContentsMargins( 0, 0, 0, 0 ); + l->addWidget( myContent ); +} + +/*! + \brief Destructor. + \internal +*/ +SgPyQtUserDefinedContent::~SgPyQtUserDefinedContent() +{ +} + +/*! + \brief Called from Preferences dialog to store settings to the resource file. + \internal +*/ +void SgPyQtUserDefinedContent::store( QtxResourceMgr*, QtxPreferenceMgr* ) +{ + myContent->store(); +} + +/*! + \brief Called from Preferences dialog to restore settings from the resource file. + \internal +*/ +void SgPyQtUserDefinedContent::retrieve( QtxResourceMgr*, QtxPreferenceMgr* ) +{ + myContent->retrieve(); +} + /*! \class SalomePyQt \brief The class provides utility functions which can be used in the Python @@ -512,30 +598,6 @@ QTreeView* SalomePyQt::getObjectBrowser() return ProcessEvent( new TGetObjectBrowserEvent() ); } -/*! - \fn int SalomePyQt::getStudyId(); - \brief Get active study's identifier. - \return active study ID or 0 if there is no active study -*/ - -class TGetStudyIdEvent: public SALOME_Event -{ -public: - typedef int TResult; - TResult myResult; - TGetStudyIdEvent() : myResult( 0 ) {} - virtual void Execute() - { - if ( LightApp_Study* aStudy = getActiveStudy() ) { - myResult = aStudy->id(); - } - } -}; -int SalomePyQt::getStudyId() -{ - return ProcessEvent( new TGetStudyIdEvent() ); -} - /*! \fn SALOME_Selection* SalomePyQt::getSelection(); \brief Get the selection object for the current study. @@ -738,37 +800,23 @@ bool SalomePyQt::activateModule( const QString& modName ) } /*! - \brief Update an Object Browser of the specified (by identifier) study. - - If \a studyId <= 0 the active study's object browser is updated. - The \a updateSelection parameter is obsolete and currently is not used. - This parameter will be removed in future, so try to avoid its usage in - your code. - - \brief studyId study identifier - \brief updateSelection update selection flag (not used) - \sa getActiveStudy() + \brief Update an Object Browser of the study. */ -void SalomePyQt::updateObjBrowser( const int studyId, bool updateSelection ) +void SalomePyQt::updateObjBrowser() { class TEvent: public SALOME_Event { - int myStudyId; - bool myUpdateSelection; public: - TEvent( const int studyId, bool updateSelection ) - : myStudyId( studyId ), myUpdateSelection( updateSelection ) {} + TEvent() {} virtual void Execute() { if ( SUIT_Session::session() ) { - if ( getActiveStudy() && myStudyId <= 0 ) - myStudyId = getActiveStudy()->id(); - if ( myStudyId > 0 ) { + if ( getActiveStudy() ) { QList apps = SUIT_Session::session()->applications(); QList::Iterator it; for( it = apps.begin(); it != apps.end(); ++it ) { LightApp_Application* anApp = dynamic_cast( *it ); - if ( anApp && anApp->activeStudy() && anApp->activeStudy()->id() == myStudyId ) { + if ( anApp && anApp->activeStudy() ) { anApp->updateObjectBrowser(); return; } @@ -777,7 +825,7 @@ void SalomePyQt::updateObjBrowser( const int studyId, bool updateSelection ) } } }; - ProcessVoidEvent( new TEvent( studyId, updateSelection ) ); + ProcessVoidEvent( new TEvent() ); } @@ -2440,7 +2488,39 @@ void SalomePyQt::setPreferenceProperty( const int id, } } }; - ProcessVoidEvent( new TEvent( id, prop, var) ); + ProcessVoidEvent( new TEvent( id, prop, var ) ); +} + +/*! + \brief Set specific widget as a custom preferences item. + \param id preferences identifier + \param prop preferences property name + \param widget custom widget +*/ +void SalomePyQt::setPreferencePropertyWg( const int id, + const QString& prop, + UserDefinedContent* widget ) +{ + class TEvent: public SALOME_Event + { + int myId; + QString myProp; + UserDefinedContent* myWidget; + public: + TEvent( const int id, const QString& prop, UserDefinedContent* widget ) + : myId( id ), myProp( prop ), myWidget( widget ) {} + virtual void Execute() + { + LightApp_Module* module = getActiveModule(); + if ( module ) { + LightApp_Preferences* pref = module->getApp()->preferences(); + if ( pref ) { + pref->setItemProperty( myProp, (qint64) new SgPyQtUserDefinedContent( myWidget ), myId ); + } + } + } + }; + ProcessVoidEvent( new TEvent( id, prop, widget ) ); } /*! diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h index d31a8600f..8b749800e 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.h @@ -114,6 +114,23 @@ enum { PT_Font = LightApp_Preferences::Font, PT_DirList = LightApp_Preferences::DirList, PT_File = LightApp_Preferences::File, + PT_Slider = LightApp_Preferences::Slider, + PT_Shortcut = LightApp_Preferences::Shortcut, + PT_ShortcutTree = LightApp_Preferences::ShortcutTree, + PT_BiColor = LightApp_Preferences::BiColor, + PT_Background = LightApp_Preferences::Background, + PT_UserDefined = LightApp_Preferences::UserDefined, +}; + +class UserDefinedContent: public QWidget +{ + Q_OBJECT + +public: + explicit UserDefinedContent(); + + virtual void store(); + virtual void retrieve(); }; //! Orientation @@ -172,12 +189,11 @@ public: static void disableSelector(); static SALOME_Selection* getSelection(); static void setSelection( const QStringList& ); - static int getStudyId(); static void putInfo( const QString&, const int = 0 ); static const QString getActiveComponent(); static PyObject* getActivePythonModule(); static bool activateModule( const QString& ); - static void updateObjBrowser( const int = 0, bool = true ); + static void updateObjBrowser(); static bool isModified(); static void setModified( bool ); @@ -277,6 +293,7 @@ public: const QString& = QString() ); static QVariant preferenceProperty( const int, const QString& ); static void setPreferenceProperty( const int, const QString&, const QVariant& ); + static void setPreferencePropertyWg( const int, const QString&, UserDefinedContent* ); static void addPreferenceProperty( const int, const QString&, const int, const QVariant& ); static void message( const QString&, bool = true ); diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip index 59309bcfd..a80a8403a 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip @@ -102,6 +102,12 @@ enum PrefType { PT_Font, PT_DirList, PT_File, + PT_Slider, + PT_Shortcut, + PT_ShortcutTree, + PT_BiColor, + PT_Background, + PT_UserDefined }; enum Orientation { @@ -237,6 +243,26 @@ private: QtxTreeView( const QtxTreeView& ); }; +class UserDefinedContent : public QWidget +{ +%TypeHeaderCode +#include +%End + +%ConvertToSubClassCode + if ( qobject_cast( sipCpp ) ) + sipClass = sipClass_UserDefinedContent; + else + sipClass = NULL; +%End + +public: + explicit UserDefinedContent(); + + virtual void store(); + virtual void retrieve(); +}; + enum VisibilityState { ShownState, @@ -273,13 +299,11 @@ public: static void enableSelector() /ReleaseGIL/ ; static void disableSelector() /ReleaseGIL/ ; static SALOME_Selection* getSelection() /Factory,ReleaseGIL/ ; - static void setSelection( const QStringList& ) /ReleaseGIL/ ; - static int getStudyId() /ReleaseGIL/ ; static void putInfo( const QString&, const int = 0 ) /ReleaseGIL/ ; static const QString getActiveComponent() /ReleaseGIL/ ; static SIP_PYOBJECT getActivePythonModule() /ReleaseGIL/ ; static bool activateModule( const QString& ) /ReleaseGIL/ ; - static void updateObjBrowser( const int = 0, bool = true ) /ReleaseGIL/ ; + static void updateObjBrowser() /ReleaseGIL/ ; static bool isModified() /ReleaseGIL/ ; static void setModified( bool ) /ReleaseGIL/ ; @@ -391,6 +415,9 @@ public: static void setPreferenceProperty( const int, const QString&, const QVariant& ) /ReleaseGIL/ ; + static void setPreferencePropertyWg( const int, + const QString&, + UserDefinedContent* ) /ReleaseGIL/ ; static void addPreferenceProperty( const int, const QString&, const int, diff --git a/src/SALOME_SWIG/SALOMEGUI_Swig.cxx b/src/SALOME_SWIG/SALOMEGUI_Swig.cxx index bcd1e54ad..184ad8f63 100644 --- a/src/SALOME_SWIG/SALOMEGUI_Swig.cxx +++ b/src/SALOME_SWIG/SALOMEGUI_Swig.cxx @@ -71,7 +71,7 @@ This module provides an access to the SALOME GUI implementing set of functions which can be used from Python. This module is implemented using SWIG wrappings for some GUI functionality: - - getActiveStudyId(), getActiveStudyName() : get active study identifier and name + - getActiveStudyName() : get active study name - updateObjBrowser() : update contents of the Object Browser - SelectedCount() : get number of currently selected items - getSelected() : get entry of the speicified selected item @@ -173,9 +173,8 @@ bool SALOMEGUI_Swig::hasDesktop() /*! \brief Update active study's Object Browser. - \param updateSelection this parameter is obsolete */ -void SALOMEGUI_Swig::updateObjBrowser( bool /*updateSelection*/ ) +void SALOMEGUI_Swig::updateObjBrowser() { class TEvent: public SALOME_Event { @@ -192,30 +191,6 @@ void SALOMEGUI_Swig::updateObjBrowser( bool /*updateSelection*/ ) ProcessVoidEvent( new TEvent() ); } -/*! - \fn int SALOMEGUI_Swig::getActiveStudyId() - \brief Get active study identifier - \return active study's ID or 0 if there is no active study -*/ - -class TGetActiveStudyIdEvent: public SALOME_Event -{ -public: - typedef int TResult; - TResult myResult; - TGetActiveStudyIdEvent() : myResult( 0 ) {} - virtual void Execute() - { - if ( LightApp_Study* aStudy = getActiveStudy() ) { - myResult = aStudy->id(); - } - } -}; -int SALOMEGUI_Swig::getActiveStudyId() -{ - return ProcessEvent( new TGetActiveStudyIdEvent() ); -} - /*! \fn const char* SALOMEGUI_Swig::getActiveStudyName() \brief Get active study name diff --git a/src/SALOME_SWIG/SALOMEGUI_Swig.hxx b/src/SALOME_SWIG/SALOMEGUI_Swig.hxx index 6b537c8c9..f5d2227ee 100644 --- a/src/SALOME_SWIG/SALOMEGUI_Swig.hxx +++ b/src/SALOME_SWIG/SALOMEGUI_Swig.hxx @@ -35,9 +35,8 @@ public: bool hasDesktop(); - void updateObjBrowser( bool ); + void updateObjBrowser(); - int getActiveStudyId(); const char* getActiveStudyName(); const char* getComponentName( const char* ); diff --git a/src/SALOME_SWIG/SALOMEGUI_Swig.i b/src/SALOME_SWIG/SALOMEGUI_Swig.i index 10631d881..c77f14a6a 100644 --- a/src/SALOME_SWIG/SALOMEGUI_Swig.i +++ b/src/SALOME_SWIG/SALOMEGUI_Swig.i @@ -57,10 +57,9 @@ public: bool hasDesktop(); /* update object browser*/ - void updateObjBrowser(bool); + void updateObjBrowser(); /* get active study */ - int getActiveStudyId(); const char *getActiveStudyName(); /* get component name/username */ diff --git a/src/SALOME_SWIG/test_big_table.py b/src/SALOME_SWIG/test_big_table.py index 73a881a10..a2b032fd8 100755 --- a/src/SALOME_SWIG/test_big_table.py +++ b/src/SALOME_SWIG/test_big_table.py @@ -66,6 +66,6 @@ for i in range(1,myVerNb+1): ARealTable.SetTitle("Very useful data") # >>> Updating Object Browser ================================================ -salome.sg.updateObjBrowser(True) +salome.sg.updateObjBrowser() # ============================================================================ diff --git a/src/SALOME_SWIG/test_many_objects.py b/src/SALOME_SWIG/test_many_objects.py index 94df01f83..42897dace 100755 --- a/src/SALOME_SWIG/test_many_objects.py +++ b/src/SALOME_SWIG/test_many_objects.py @@ -84,7 +84,7 @@ for i in range(0,myNb1): myBuilder.Addreference(myRefObject,myObject3); # >>> Updating Object Browser ================================================ -salome.sg.updateObjBrowser(True) +salome.sg.updateObjBrowser() # ============================================================================ diff --git a/src/SALOME_SWIG/test_table.py b/src/SALOME_SWIG/test_table.py index 21b934e9e..812b21e47 100755 --- a/src/SALOME_SWIG/test_table.py +++ b/src/SALOME_SWIG/test_table.py @@ -109,7 +109,7 @@ ACmt = myBuilder.FindOrCreateAttribute(myCmtObject, "AttributeComment") ACmt.SetValue("Just a comment") # >>> Updating Object Browser ================================================ -salome.sg.updateObjBrowser(True) +salome.sg.updateObjBrowser() # ============================================================================ diff --git a/src/SOCC/SOCC_ViewModel.cxx b/src/SOCC/SOCC_ViewModel.cxx index 03825c7a4..3981d50cb 100755 --- a/src/SOCC/SOCC_ViewModel.cxx +++ b/src/SOCC/SOCC_ViewModel.cxx @@ -44,45 +44,11 @@ #include #include -// Temporarily commented to avoid awful dependecy on SALOMEDS -// TODO: better mechanism of storing display/erse status in a study -// should be provided... -//#include -//#include -//#include -//#include - -//#include "SALOMEDSClient.hxx" -//#include "SALOMEDS_StudyManager.hxx" - #include #include #include -// in order NOT TO link with SalomeApp, here the code returns SALOMEDS_Study. -// SalomeApp_Study::studyDS() does it as well, but -- here it is retrieved from -// SALOMEDS::StudyManager - no linkage with SalomeApp. - -// Temporarily commented to avoid awful dependecy on SALOMEDS -// TODO: better mechanism of storing display/erse status in a study -// should be provided... -//static _PTR(Study) getStudyDS() -//{ -// SALOMEDSClient_Study* aStudy = NULL; -// _PTR(StudyManager) aMgr( new SALOMEDS_StudyManager() ); - - // get id of SUIT_Study, if it's a SalomeApp_Study, it will return - // id of its underlying SALOMEDS::Study -// SUIT_Application* app = SUIT_Session::session()->activeApplication(); -// if ( !app ) return _PTR(Study)(aStudy); -// SUIT_Study* stud = app->activeStudy(); -// if ( !stud ) return _PTR(Study)(aStudy); -// const int id = stud->id(); // virtual method, must return SALOMEDS_Study id - // get SALOMEDS_Study with this id from StudyMgr -// return aMgr->GetStudyByID( id ); -//} - /*! Constructor \param DisplayTrihedron - is trihedron displayed @@ -320,12 +286,6 @@ void SOCC_Viewer::Display( const SALOME_OCCPrs* prs ) if ( !anOCCPrs || anOCCPrs->IsNull() ) return; - // get SALOMEDS Study - // Temporarily commented to avoid awful dependecy on SALOMEDS - // TODO: better mechanism of storing display/erse status in a study - // should be provided... - // _PTR(Study) study(getStudyDS()); - // get context Handle (AIS_InteractiveContext) ic = getAISContext(); @@ -401,8 +361,7 @@ void SOCC_Viewer::Display( const SALOME_OCCPrs* prs ) // Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() ); //if ( !anObj.IsNull() && anObj->hasEntry() ) //{ - // if ( study ) - // ToolsGUI::SetVisibility( study, anObj->getEntry(), true, this ); + // ToolsGUI::SetVisibility( anObj->getEntry(), true, this ); //} // Deactivate object if necessary @@ -426,12 +385,6 @@ void SOCC_Viewer::Erase( const SALOME_OCCPrs* prs, const bool forced ) if ( !anOCCPrs || anOCCPrs->IsNull() ) return; - // get SALOMEDS Study - // Temporarily commented to avoid awful dependecy on SALOMEDS - // TODO: better mechanism of storing display/erse status in a study - // should be provided... - // _PTR(Study) study(getStudyDS()); - // get context Handle(AIS_InteractiveContext) ic = getAISContext(); @@ -455,8 +408,7 @@ void SOCC_Viewer::Erase( const SALOME_OCCPrs* prs, const bool forced ) // Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() ); // if ( !anObj.IsNull() && anObj->hasEntry() ) // { - // if ( study ) - // ToolsGUI::SetVisibility( study, anObj->getEntry(), true, this ); + // ToolsGUI::SetVisibility( anObj->getEntry(), true, this ); // } //} } @@ -471,12 +423,6 @@ void SOCC_Viewer::Erase( const SALOME_OCCPrs* prs, const bool forced ) */ void SOCC_Viewer::EraseAll( SALOME_Displayer* d, const bool forced ) { - // get SALOMEDS Study - // Temporarily commented to avoid awful dependecy on SALOMEDS - // TODO: better mechanism of storing display/erse status in a study - // should be provided... - // _PTR(Study) study(getStudyDS()); - // get context Handle(AIS_InteractiveContext) ic = getAISContext(); @@ -504,8 +450,7 @@ void SOCC_Viewer::EraseAll( SALOME_Displayer* d, const bool forced ) // Handle(SALOME_InteractiveObject)::DownCast( anIO->GetOwner() ); // if ( !anObj.IsNull() && anObj->hasEntry() ) { - // if ( study ) - // ToolsGUI::SetVisibility( study, anObj->getEntry(), true, this ); + // ToolsGUI::SetVisibility( anObj->getEntry(), true, this ); // } //} } diff --git a/src/SPlot2d/SPlot2d_ViewModel.cxx b/src/SPlot2d/SPlot2d_ViewModel.cxx index abe70294a..f890ca74c 100644 --- a/src/SPlot2d/SPlot2d_ViewModel.cxx +++ b/src/SPlot2d/SPlot2d_ViewModel.cxx @@ -47,31 +47,6 @@ #include #include -//ASL: Temporary commented in order to avoir dependency on SALOMEDS - -//#include "SALOMEDSClient.hxx" -//#include "SALOMEDS_StudyManager.hxx" - -// in order NOT TO link with SalomeApp, here the code returns SALOMEDS_Study. -// SalomeApp_Study::studyDS() does it as well, but -- here it is retrieved from -// SALOMEDS::StudyManager - no linkage with SalomeApp. - -/*static _PTR(Study) getStudyDS() -{ - SALOMEDSClient_Study* aStudy = NULL; - _PTR(StudyManager) aMgr( new SALOMEDS_StudyManager() ); - - // get id of SUIT_Study, if it's a SalomeApp_Study, it will return - // id of its underlying SALOMEDS::Study - SUIT_Application* app = SUIT_Session::session()->activeApplication(); - if ( !app ) return _PTR(Study)(aStudy); - SUIT_Study* stud = app->activeStudy(); - if ( !stud ) return _PTR(Study)(aStudy); - const int id = stud->id(); // virtual method, must return SALOMEDS_Study id - // get SALOMEDS_Study with this id from StudyMgr - return aMgr->GetStudyByID( id ); -} */ - /*! Constructor */ diff --git a/src/STD/STD_Application.cxx b/src/STD/STD_Application.cxx index d5751cf34..1dcd838cf 100755 --- a/src/STD/STD_Application.cxx +++ b/src/STD/STD_Application.cxx @@ -156,6 +156,8 @@ void STD_Application::createActions() resMgr->loadPixmap( "STD", tr( "ICON_FILE_NEW" ) ), tr( "MEN_DESK_FILE_NEW" ), tr( "PRP_DESK_FILE_NEW" ), Qt::CTRL+Qt::Key_N, desk, false, this, SLOT( onNewDoc() ) ); + //no need at this action for mono-study application because study is always exists + action( FileNewId )->setVisible( false ); createAction( FileOpenId, tr( "TOT_DESK_FILE_OPEN" ), resMgr->loadPixmap( "STD", tr( "ICON_FILE_OPEN" ) ), @@ -367,16 +369,11 @@ bool STD_Application::onReopenDoc() // post closing actions afterCloseDoc(); - int aNbStudies = 0; - QList apps = SUIT_Session::session()->applications(); - for ( int i = 0; i < apps.count(); i++ ) - aNbStudies += apps.at( i )->getNbStudies(); - // reload study from the file res = useFile( studyName ) && activeStudy(); // if reloading is failed, close the desktop - if ( aNbStudies && !res ) + if ( activeStudy() && !res ) closeApplication(); else { diff --git a/src/SUIT/SUIT_Application.cxx b/src/SUIT/SUIT_Application.cxx index 75d32cfc6..06d9180ed 100644 --- a/src/SUIT/SUIT_Application.cxx +++ b/src/SUIT/SUIT_Application.cxx @@ -693,7 +693,8 @@ int SUIT_Application::registerAction( const int id, QAction* a ) if ( desktop() && desktop()->toolMgr() ) desktop()->toolMgr()->registerAction( a ); - if ( desktop() ) + if ( desktop() && a->shortcutContext() != Qt::WidgetShortcut && + a->shortcutContext() != Qt::WidgetWithChildrenShortcut ) desktop()->addAction( a ); return ident; diff --git a/src/SVTK/SVTK_ViewModel.cxx b/src/SVTK/SVTK_ViewModel.cxx index 28bc07177..eb5c339a8 100644 --- a/src/SVTK/SVTK_ViewModel.cxx +++ b/src/SVTK/SVTK_ViewModel.cxx @@ -50,29 +50,6 @@ // VSR: Uncomment below line to allow texture background support in VTK viewer #define VTK_ENABLE_TEXTURED_BACKGROUND - -// in order NOT TO link with SalomeApp, here the code returns SALOMEDS_Study. -// SalomeApp_Study::studyDS() does it as well, but -- here it is retrieved from -// SALOMEDS::StudyManager - no linkage with SalomeApp. - -// Temporarily commented to avoid awful dependecy on SALOMEDS -// TODO: better mechanism of storing display/erse status in a study -// should be provided... -//static _PTR(Study) getStudyDS() -//{ -// SALOMEDSClient_Study* aStudy = NULL; -// _PTR(StudyManager) aMgr( new SALOMEDS_StudyManager() ); - // get id of SUIT_Study, if it's a SalomeApp_Study, it will return - // id of its underlying SALOMEDS::Study -// SUIT_Application* app = SUIT_Session::session()->activeApplication(); -// if ( !app ) return _PTR(Study)(aStudy); -// SUIT_Study* stud = app->activeStudy(); -// if ( !stud ) return _PTR(Study)(aStudy); -// const int id = stud->id(); // virtual method, must return SALOMEDS_Study id - // get SALOMEDS_Study with this id from StudyMgr -// return aMgr->GetStudyByID( id ); -//} - /*! Constructor */ @@ -688,11 +665,6 @@ void SVTK_Viewer::Display( const SALOME_VTKPrs* prs ) if(aPrs->IsNull()) return; if(vtkActorCollection* anActorCollection = aPrs->GetObjects()){ - // get SALOMEDS Study - // Temporarily commented to avoid awful dependecy on SALOMEDS - // TODO: better mechanism of storing display/erse status in a study - // should be provided... - // _PTR(Study) aStudy(getStudyDS()); anActorCollection->InitTraversal(); while(vtkActor* anActor = anActorCollection->GetNextActor()){ if(SALOME_Actor* anAct = SALOME_Actor::SafeDownCast(anActor)){ @@ -703,8 +675,8 @@ void SVTK_Viewer::Display( const SALOME_VTKPrs* prs ) // TODO: better mechanism of storing display/erse status in a study // should be provided... //Handle(SALOME_InteractiveObject) anObj = anAct->getIO(); - //if(!anObj.IsNull() && anObj->hasEntry() && aStudy){ - // ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),true,this); + //if(!anObj.IsNull() && anObj->hasEntry()){ + // ToolsGUI::SetVisibility(anObj->getEntry(),true,this); //} // just display the object QVector aViews = myViewManager->getViews(); @@ -737,11 +709,6 @@ void SVTK_Viewer::Erase( const SALOME_VTKPrs* prs, const bool forced ) if(aPrs->IsNull()) return; if(vtkActorCollection* anActorCollection = aPrs->GetObjects()){ - // get SALOMEDS Study - // Temporarily commented to avoid awful dependecy on SALOMEDS - // TODO: better mechanism of storing display/erase status in a study - // should be provided... - //_PTR(Study) aStudy(getStudyDS()); anActorCollection->InitTraversal(); while(vtkActor* anActor = anActorCollection->GetNextActor()) if(SALOME_Actor* anAct = SALOME_Actor::SafeDownCast(anActor)){ @@ -750,8 +717,8 @@ void SVTK_Viewer::Erase( const SALOME_VTKPrs* prs, const bool forced ) // TODO: better mechanism of storing display/erase status in a study // should be provided... //Handle(SALOME_InteractiveObject) anObj = anAct->getIO(); - //if(!anObj.IsNull() && anObj->hasEntry() && aStudy){ - // ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),false,this); + //if(!anObj.IsNull() && anObj->hasEntry()){ + // ToolsGUI::SetVisibility(anObj->getEntry(),false,this); //} // just display the object QVector aViews = myViewManager->getViews(); @@ -776,10 +743,6 @@ void SVTK_Viewer::Erase( const SALOME_VTKPrs* prs, const bool forced ) */ void SVTK_Viewer::EraseAll( SALOME_Displayer* d, const bool forced ) { - // Temporarily commented to avoid awful dependecy on SALOMEDS - // TODO: better mechanism of storing display/erse status in a study - // should be provided... - //_PTR(Study) aStudy(getStudyDS()); QVector aViews = myViewManager->getViews(); for(int i = 0, iEnd = aViews.size(); i < iEnd; i++){ if(SVTK_ViewWindow* aViewWindow = dynamic_cast(aViews.at(i))) @@ -795,8 +758,8 @@ void SVTK_Viewer::EraseAll( SALOME_Displayer* d, const bool forced ) // TODO: better mechanism of storing display/erse status in a study // should be provided... //Handle(SALOME_InteractiveObject) anObj = anAct->getIO(); - //if(!anObj.IsNull() && anObj->hasEntry() && aStudy) - // ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),false,this); + //if(!anObj.IsNull() && anObj->hasEntry()) + // ToolsGUI::SetVisibility(anObj->getEntry(),false,this); if(forced){ if(SVTK_Renderer* aRnd = aView->GetRenderer()) aRnd->RemoveActor(anAct); diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index 70646990f..2dec08198 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -206,7 +206,6 @@ void SalomeApp_Application::start() QString hdffile; QStringList pyfiles; - QString loadStudy; for (int i = 1; i < qApp->arguments().size(); i++) { QRegExp rxs ("--study-hdf=(.+)"); @@ -240,14 +239,8 @@ void SalomeApp_Application::start() SALOME_EventFilter::Init(); setProperty("open_study_from_command_line", true); - if ( !hdffile.isEmpty() ) // open hdf file given as parameter + if ( !hdffile.isEmpty() ) // open hdf file given as parameter onOpenDoc( hdffile ); - else if ( pyfiles.count() > 0 ) // create new study - onNewDoc(); - else if (!loadStudy.isEmpty()) {// load study by name - if (onLoadDoc(loadStudy)) - updateObjectBrowser(true); - } setProperty("open_study_from_command_line", QVariant()); #ifndef DISABLE_PYCONSOLE @@ -256,8 +249,7 @@ void SalomeApp_Application::start() SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); PyConsole_Console* pyConsole = pythonConsole(); if ( appStudy && pyConsole ) { - _PTR(Study) aStudy = appStudy->studyDS(); - if ( !aStudy->GetProperties()->IsLocked() ) { + if ( !getStudy()->GetProperties()->IsLocked() ) { // pyfiles[j] is a dictionary: {"/absolute/path/to/script.py": [script_args]} // Path is absolute, script has .py extension for (uint j = 0; j < pyfiles.count(); j++ ) { @@ -335,10 +327,14 @@ void SalomeApp_Application::createActions() createAction( ConnectId, tr( "TOT_DESK_CONNECT_STUDY" ), QIcon(), tr( "MEN_DESK_CONNECT" ), tr( "PRP_DESK_CONNECT" ), Qt::CTRL+Qt::Key_L, desk, false, this, SLOT( onLoadDoc() ) ); + //no need at this action for mono-study application because study is always exists + action( ConnectId )->setVisible( false ); createAction( DisconnectId, tr( "TOT_DESK_DISCONNECT_STUDY" ), QIcon(), tr( "MEN_DESK_DISCONNECT" ), tr( "PRP_DESK_DISCONNECT" ), Qt::CTRL+Qt::Key_U, desk, false, this, SLOT( onUnloadDoc() ) ); + //no need at this action for mono-study application because study is always exists + action( DisconnectId )->setVisible( false ); int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 ); @@ -406,8 +402,6 @@ void SalomeApp_Application::onLoadDoc() { QString studyName; - std::vector List = studyMgr()->GetOpenStudies(); - // rnv: According to the single-study approach on the server side // can be only one study. So if it is exists connect to them, // overwise show warning message: "No active study on the server" @@ -439,14 +433,14 @@ void SalomeApp_Application::onLoadDoc() return; */ - if(List.size() <= 0) { + if(!activeStudy()) { SUIT_MessageBox::warning( desktop(), QObject::tr("WRN_WARNING"), QObject::tr("WRN_NO_STUDY_ON SERV") ); return; } - studyName = List[0].c_str(); + studyName = activeStudy()->studyName(); #ifndef WIN32 // this code replaces marker of windows drive and path become invalid therefore @@ -518,10 +512,9 @@ void SalomeApp_Application::onNewWithScript() /*!SLOT. Load document with \a aName.*/ bool SalomeApp_Application::onLoadDoc( const QString& aName ) { -#ifdef SINGLE_DESKTOP if ( !LightApp_Application::closeDoc() ) return false; -#endif + bool res = true; if ( !activeStudy() ) { // if no study - load in current desktop @@ -555,28 +548,40 @@ bool SalomeApp_Application::onLoadDoc( const QString& aName ) /*!SLOT. Parse message for desktop.*/ void SalomeApp_Application::onDesktopMessage( const QString& message ) { - if (message.indexOf("studyCreated:") == 0) { - // Enable 'Connect' action - updateCommandsStatus(); + if (message.indexOf("studyCreated") == 0) { + if (!activeStudy()) { + onNewDoc(); + updateCommandsStatus(); + } } - else if (message.indexOf("studyClosed:") == 0) { - /* message also contains ID of the closed study, - but as soon as SALOME is mono-study application for the moment, - this ID is not needed now.*/ - //long aStudyId = message.section(':', 1).toLong(); + if (message.indexOf("studyCleared") == 0) { // Disconnect GUI from active study, because it was closed on DS side. - closeActiveDoc( false ); - // Disable 'Connect' action - QAction* a = action( ConnectId ); - if ( a ) - a->setEnabled( false ); + if (activeStudy()) { + closeActiveDoc( false ); + // Disable 'Connect' action + QAction* a = action( ConnectId ); + if ( a ) + a->setEnabled( false ); + } } else if ( message.toLower() == "connect_to_study" ) { onLoadDoc(); } + if (message.indexOf("studyNameChanged") == 0) { + updateDesktopTitle(); + } LightApp_Application::onDesktopMessage( message ); } +/*!On module activation action.*/ +void SalomeApp_Application::onModuleActivation( const QString& modName ) +{ + if (!activeStudy() && !modName.isEmpty()) + getStudy()->Init(); + + LightApp_Application::onModuleActivation( modName ); +} + /*!SLOT. Copy objects to study maneger from selection maneger..*/ void SalomeApp_Application::onCopy() { @@ -587,7 +592,7 @@ void SalomeApp_Application::onCopy() SalomeApp_Study* study = dynamic_cast(activeStudy()); if(study == NULL) return; - _PTR(Study) stdDS = study->studyDS(); + _PTR(Study) stdDS = getStudy(); if(!stdDS) return; SALOME_ListIteratorOfListIO it( list ); @@ -595,7 +600,7 @@ void SalomeApp_Application::onCopy() { _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); try { - studyMgr()->Copy(so); + stdDS->Copy(so); onSelectionChanged(); } catch(...) { @@ -613,7 +618,7 @@ void SalomeApp_Application::onPaste() SalomeApp_Study* study = dynamic_cast(activeStudy()); if(study == NULL) return; - _PTR(Study) stdDS = study->studyDS(); + _PTR(Study) stdDS = getStudy(); if(!stdDS) return; if ( stdDS->GetProperties()->IsLocked() ) { @@ -628,7 +633,7 @@ void SalomeApp_Application::onPaste() { _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); try { - studyMgr()->Paste(so); + stdDS->Paste(so); updateObjectBrowser( true ); updateActions(); //SRN: BugID IPAL9377, case 3 } @@ -648,20 +653,18 @@ bool SalomeApp_Application::isPossibleToClose( bool& closePermanently ) /*! 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::question( desktop(), - QObject::tr( "WRN_WARNING" ), - QObject::tr( "CLOSE_LOCKED_STUDY" ), - SUIT_MessageBox::Yes | SUIT_MessageBox::No, - SUIT_MessageBox::No) == SUIT_MessageBox::No ) return; + if(getStudy()->IsStudyLocked()) { + if ( SUIT_MessageBox::question( desktop(), + QObject::tr( "WRN_WARNING" ), + QObject::tr( "CLOSE_LOCKED_STUDY" ), + SUIT_MessageBox::Yes | SUIT_MessageBox::No, + SUIT_MessageBox::No) == SUIT_MessageBox::No ) return; - } } LightApp_Application::onCloseDoc( ask ); + + // reinitialize study to have empty data + getStudy()->Init(); } /*!Sets enable or disable some actions on selection changed.*/ @@ -681,21 +684,14 @@ void SalomeApp_Application::onSelectionChanged() canPaste = m->canPaste(); } - SalomeApp_Study* study = dynamic_cast(activeStudy()); - if (study) { - _PTR(Study) stdDS = study->studyDS(); + SALOME_ListIteratorOfListIO it ( list ); - if (stdDS) { - SALOME_ListIteratorOfListIO it ( list ); + if (it.More() && list.Extent() == 1) { + _PTR(SObject) so = getStudy()->FindObjectID(it.Value()->getEntry()); - if (it.More() && list.Extent() == 1) { - _PTR(SObject) so = stdDS->FindObjectID(it.Value()->getEntry()); - - if ( so ) { - canCopy = canCopy || studyMgr()->CanCopy(so); - canPaste = canPaste || studyMgr()->CanPaste(so); - } - } + if ( so ) { + canCopy = canCopy || getStudy()->CanCopy(so); + canPaste = canPaste || getStudy()->CanPaste(so); } } @@ -713,8 +709,7 @@ void SalomeApp_Application::onDeleteInvalidReferences() if( aList.IsEmpty() ) return; - SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); - _PTR(Study) aStudyDS = aStudy->studyDS(); + _PTR(Study) aStudyDS = getStudy(); _PTR(StudyBuilder) aStudyBuilder = aStudyDS->NewBuilder(); _PTR(SObject) anObj; @@ -804,7 +799,7 @@ void SalomeApp_Application::updateCommandsStatus() // Connect study menu a = action( ConnectId ); if( a ) - a->setEnabled( !activeStudy() && studyMgr()->GetOpenStudies().size() > 0 ); + a->setEnabled( !activeStudy() ); // Disconnect study menu a = action( DisconnectId ); @@ -859,7 +854,6 @@ void SalomeApp_Application::onDumpStudy( ) { SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); if ( !appStudy ) return; - _PTR(Study) aStudy = appStudy->studyDS(); QStringList aFilters; aFilters.append( tr( "PYTHON_FILES_FILTER" ) ); @@ -911,15 +905,11 @@ void SalomeApp_Application::onDumpStudy( ) /*!Private SLOT. On load script.*/ void SalomeApp_Application::onLoadScript( ) { - SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); - if ( appStudy ) { - _PTR(Study) aStudy = appStudy->studyDS(); - if ( aStudy->GetProperties()->IsLocked() ) { - SUIT_MessageBox::warning( desktop(), - QObject::tr("WRN_WARNING"), - QObject::tr("WRN_STUDY_LOCKED") ); - return; - } + if ( getStudy()->GetProperties()->IsLocked() ) { + SUIT_MessageBox::warning( desktop(), + QObject::tr("WRN_WARNING"), + QObject::tr("WRN_STUDY_LOCKED") ); + return; } QStringList filtersList; @@ -1060,14 +1050,11 @@ QWidget* SalomeApp_Application::createWindow( const int flag ) } else if ( flag == WT_NoteBook ) { - SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); - if ( appStudy ) { - _PTR(Study) aStudy = appStudy->studyDS(); - setNoteBook( new SalomeApp_NoteBook( desktop(), aStudy ) ); - //to receive signal in NoteBook that it's variable was modified - connect( this, SIGNAL( notebookVarUpdated( QString ) ), - getNoteBook(), SLOT( onVarUpdate( QString ) ) ); - } + setNoteBook( new SalomeApp_NoteBook( desktop() ) ); + //to receive signal in NoteBook that it's variable was modified + connect( this, SIGNAL( notebookVarUpdated( QString ) ), + getNoteBook(), SLOT( onVarUpdate( QString ) ) ); + wid = getNoteBook(); wid->setObjectName( "noteBook" ); } @@ -1116,16 +1103,10 @@ void SalomeApp_Application::updateDesktopTitle() { { QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false ); if ( !sName.isEmpty() ) { - SalomeApp_Study* study = dynamic_cast(activeStudy()); - if ( study ) { - _PTR(Study) stdDS = study->studyDS(); - if(stdDS) { - if ( stdDS->GetProperties()->IsLocked() ) { - aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) ); - } else { - aTitle += QString( " - [%1]" ).arg( sName ); - } - } + if ( getStudy()->GetProperties()->IsLocked() ) { + aTitle += QString( " - [%1 (%2)]").arg( sName ).arg( tr( "STUDY_LOCKED" ) ); + } else { + aTitle += QString( " - [%1]" ).arg( sName ); } } } @@ -1138,9 +1119,9 @@ int SalomeApp_Application::closeChoice( const QString& docName ) QStringList buttons; QMap choices; int idx = 0; - buttons << tr ("APPCLOSE_SAVE"); // Save & Close + buttons << tr ("APPCLOSE_SAVE"); // Save & Clear choices.insert( idx++, CloseSave ); // ... - buttons << tr ("APPCLOSE_CLOSE"); // Close w/o saving + buttons << tr ("APPCLOSE_CLOSE"); // Clear w/o saving choices.insert( idx++, CloseDiscard ); // ... if ( myIsCloseFromExit ) { buttons << tr ("APPCLOSE_UNLOAD_SAVE"); // Save & Disconnect @@ -1151,6 +1132,8 @@ int SalomeApp_Application::closeChoice( const QString& docName ) buttons << tr ("APPCLOSE_CANCEL"); // Cancel choices.insert( idx++, CloseCancel ); // ... + if( !activeStudy()->isModified() ) + return CloseCancel; int answer = SUIT_MessageBox::question( desktop(), tr( "APPCLOSE_CAPTION" ), tr( "APPCLOSE_DESCRIPTION" ), buttons, 0 ); return choices[answer]; @@ -1192,12 +1175,9 @@ int SalomeApp_Application::openChoice( const QString& aName ) if ( QFileInfo( aName ).exists() ) { if ( choice == OpenNew ) { // The document isn't already open. bool exist = false; - std::vector lst = studyMgr()->GetOpenStudies(); - for ( uint i = 0; i < lst.size() && !exist; i++ ) { - if ( aName == QString( lst[i].c_str() ) ) - exist = true; - } - // The document already exists in the study manager. + if ( aName == getStudy()->Name().c_str() ) + exist = true; + // The document already exists in the study. // Do you want to reload it? if ( exist ) { int answer = SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYEXIST" ).arg( aName ), @@ -1226,12 +1206,7 @@ bool SalomeApp_Application::openAction( const int aChoice, const QString& aName { case OpenRefresh: { - _PTR(Study) aStudy = studyMgr()->GetStudyByName( aName.toStdString() ); - if ( aStudy ) - { - studyMgr()->Close( aStudy ); - choice = OpenNew; - } + choice = OpenNew; } default: res = LightApp_Application::openAction( choice, aName ); @@ -1304,12 +1279,16 @@ CORBA::ORB_var SalomeApp_Application::orb() return _orb; } -/*!Create and return SALOMEDS_StudyManager.*/ -SALOMEDSClient_StudyManager* SalomeApp_Application::studyMgr() +/*!Create and return SALOMEDS_Study.*/ +_PTR(Study) SalomeApp_Application::getStudy() { - static _PTR(StudyManager) _sm; - if(!_sm) _sm = ClientFactory::StudyManager(); - return _sm.get(); + static _PTR(Study) _study; + if(!_study) { + CORBA::Object_var aSObject = namingService()->Resolve("/Study"); + SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(aSObject); + _study = ClientFactory::Study(aStudy); + } + return _study; } /*!Create and return SALOME_NamingService.*/ @@ -1380,72 +1359,62 @@ void SalomeApp_Application::contextMenuPopup( const QString& type, QMenu* thePop // isInvalidRefs will be true, if at least one of selected objects is invalid reference bool isInvalidRefs = false; - SalomeApp_Study* aStudy = dynamic_cast(activeStudy()); - if ( aStudy ) { - _PTR(Study) aStudyDS = aStudy->studyDS(); - _PTR(SObject) anObj; - for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() ) + _PTR(SObject) anObj; + for( SALOME_ListIteratorOfListIO it( aList ); it.More() && !isInvalidRefs; it.Next() ) + { + if( it.Value()->hasEntry() ) { - if( it.Value()->hasEntry() ) - { - _PTR(SObject) aSObject = aStudyDS->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject; - while( aRefObj && aRefObj->ReferencedObject( anObj ) ) - aRefObj = anObj; + _PTR(SObject) aSObject = getStudy()->FindObjectID( it.Value()->getEntry() ), aRefObj = aSObject; + while( aRefObj && aRefObj->ReferencedObject( anObj ) ) + aRefObj = anObj; - if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() ) - isInvalidRefs = true; - } + if( aRefObj && aRefObj!=aSObject && QString( aRefObj->GetName().c_str() ).isEmpty() ) + isInvalidRefs = true; } + } - // Add "Delete reference" item to popup - if ( isInvalidRefs ) - { - thePopup->addSeparator(); - thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) ); - return; - } + // Add "Delete reference" item to popup + if ( isInvalidRefs ) + { + thePopup->addSeparator(); + thePopup->addAction( tr( "MEN_DELETE_INVALID_REFERENCE" ), this, SLOT( onDeleteInvalidReferences() ) ); + return; + } - // "Activate module" item should appear only if it's necessary - if ( aList.Extent() == 1 ) { - aList.Clear(); - mgr->selectedObjects( aList ); - - Handle(SALOME_InteractiveObject) aIObj = aList.First(); - - // add extra popup menu (defined in XML) - if ( myExtActions.size() > 0 ) { - // Use only first selected object - SalomeApp_Study* study = dynamic_cast( activeStudy() ); - if ( study ) { - _PTR(Study) stdDS = study->studyDS(); - if ( stdDS ) { - _PTR(SObject) aSO = stdDS->FindObjectID( aIObj->getEntry() ); - if ( aSO ) { - _PTR( GenericAttribute ) anAttr; - std::string auid = "AttributeUserID"; - auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID); - if ( aSO->FindAttribute( anAttr, auid ) ) { - _PTR(AttributeUserID) aAttrID = anAttr; - QString aId = aAttrID->Value().c_str(); - if ( myExtActions.contains( aId ) ) { - thePopup->addAction(myExtActions[aId]); - } - } - } + // "Activate module" item should appear only if it's necessary + if ( aList.Extent() == 1 ) { + aList.Clear(); + mgr->selectedObjects( aList ); + + Handle(SALOME_InteractiveObject) aIObj = aList.First(); + + // add extra popup menu (defined in XML) + if ( myExtActions.size() > 0 ) { + // Use only first selected object + _PTR(SObject) aSO = getStudy()->FindObjectID( aIObj->getEntry() ); + if ( aSO ) { + _PTR( GenericAttribute ) anAttr; + std::string auid = "AttributeUserID"; + auid += Kernel_Utils::GetGUID(Kernel_Utils::ObjectdID); + if ( aSO->FindAttribute( anAttr, auid ) ) { + _PTR(AttributeUserID) aAttrID = anAttr; + QString aId = aAttrID->Value().c_str(); + if ( myExtActions.contains( aId ) ) { + thePopup->addAction(myExtActions[aId]); } } } + } - // 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" ) ) ) { - QString aModuleName( aIObj->getComponentDataType() ); - QString aModuleTitle = moduleTitle( aModuleName ); - CAM_Module* currentModule = activeModule(); - if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) - thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) ); - } + // 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" ) ) ) { + QString aModuleName( aIObj->getComponentDataType() ); + QString aModuleTitle = moduleTitle( aModuleName ); + CAM_Module* currentModule = activeModule(); + if ( ( !currentModule || currentModule->moduleName() != aModuleTitle ) && !aModuleTitle.isEmpty() ) + thePopup->addAction( tr( "MEN_OPENWITH" ).arg( aModuleTitle ), this, SLOT( onOpenWith() ) ); } } @@ -1462,25 +1431,21 @@ void SalomeApp_Application::updateObjectBrowser( const bool updateModels ) SalomeApp_Study* study = dynamic_cast(activeStudy()); if ( study ) { - _PTR(Study) stdDS = study->studyDS(); - if( stdDS ) + for ( _PTR(SComponentIterator) it ( getStudy()->NewComponentIterator() ); it->More(); it->Next() ) { - for ( _PTR(SComponentIterator) it ( stdDS->NewComponentIterator() ); it->More(); it->Next() ) - { - _PTR(SComponent) aComponent ( it->Value() ); + _PTR(SComponent) aComponent ( it->Value() ); #ifndef WITH_SALOMEDS_OBSERVER - // with GUI observers this check is not needed anymore - if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() ) - continue; // skip the magic "Interface Applicative" component + // with GUI observers this check is not needed anymore + if ( aComponent->ComponentDataType() == study->getVisualComponentName().toLatin1().constData() ) + continue; // skip the magic "Interface Applicative" component #endif - if ( !objectBrowser() ) - getWindow( WT_ObjectBrowser ); - const bool isAutoUpdate = objectBrowser()->autoUpdate(); - objectBrowser()->setAutoUpdate( false ); - SalomeApp_DataModel::synchronize( aComponent, study ); - objectBrowser()->setAutoUpdate( isAutoUpdate ); - } + if ( !objectBrowser() ) + getWindow( WT_ObjectBrowser ); + const bool isAutoUpdate = objectBrowser()->autoUpdate(); + objectBrowser()->setAutoUpdate( false ); + SalomeApp_DataModel::synchronize( aComponent, study ); + objectBrowser()->setAutoUpdate( isAutoUpdate ); } } @@ -1908,8 +1873,6 @@ bool SalomeApp_Application::updateStudy() myNoteBook->setIsDumpedStudySaved( study->isSaved() ); myNoteBook->setDumpedStudyName( study->studyName() ); - _PTR(Study) studyDS = study->studyDS(); - // get unique temporary directory name QString aTmpDir = QString::fromStdString( SALOMEDS_Tool::GetTmpDir() ); if( aTmpDir.isEmpty() ) @@ -1927,12 +1890,12 @@ bool SalomeApp_Application::updateStudy() int savePoint; _PTR(AttributeParameter) ap; _PTR(IParameters) ip = ClientFactory::getIParameters(ap); - if(ip->isDumpPython(studyDS)) ip->setDumpPython(studyDS); //Unset DumpPython flag. + if(ip->isDumpPython()) ip->setDumpPython(); //Unset DumpPython flag. if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method - ip->setDumpPython(studyDS); + ip->setDumpPython(); savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point } - bool ok = studyDS->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile ); + bool ok = getStudy()->DumpStudy( aTmpDir.toStdString(), aScriptName.toStdString(), toPublish, isMultiFile ); if ( toSaveGUI ) study->removeSavePoint(savePoint); //SRN: remove the created temporary save point. @@ -1991,9 +1954,6 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript, { bool ok = true; - // create a new study - onNewDoc(); - // get active application SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ); @@ -2019,9 +1979,8 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript, if( SalomeApp_Study* newStudy = dynamic_cast( app->activeStudy() ) ) { #ifndef DISABLE_PYCONSOLE - _PTR(Study) aStudyDS = newStudy->studyDS(); if ( app->getNoteBook() ) - app->getNoteBook()->Init( aStudyDS ); + app->getNoteBook()->Init(); newStudy->updateFromNotebook(theStudyName, theIsStudySaved); newStudy->Modified(); updateDesktopTitle(); @@ -2055,18 +2014,7 @@ void SalomeApp_Application::afterCloseDoc() */ bool SalomeApp_Application::checkExistingDoc() { - bool result = LightApp_Application::checkExistingDoc(); - if ( result && !activeStudy() ) { - SALOMEDSClient_StudyManager* aMgr = studyMgr(); - if ( aMgr ) { - std::vector List = studyMgr()->GetOpenStudies(); - if( List.size() > 0 ) { - SUIT_MessageBox::critical( desktop(), tr( "WRN_WARNING" ), tr( "ERR_ACTIVEDOC_LOAD" )); - result = false; - } - } - } - return result; + return LightApp_Application::checkExistingDoc(); } diff --git a/src/SalomeApp/SalomeApp_Application.h b/src/SalomeApp/SalomeApp_Application.h index ae6775ea7..cf112abbf 100644 --- a/src/SalomeApp/SalomeApp_Application.h +++ b/src/SalomeApp/SalomeApp_Application.h @@ -96,7 +96,7 @@ public: virtual bool checkExistingDoc(); static CORBA::ORB_var orb(); - static SALOMEDSClient_StudyManager* studyMgr(); + static _PTR(Study) getStudy(); static SALOME_NamingService* namingService(); static SALOME_LifeCycleCORBA* lcc(); @@ -141,6 +141,8 @@ protected slots: void onStudyOpened( SUIT_Study* ); void onDesktopMessage( const QString& ); + virtual void onModuleActivation( const QString& ); + protected: virtual void createActions(); virtual SUIT_Study* createNewStudy(); diff --git a/src/SalomeApp/SalomeApp_DataModel.cxx b/src/SalomeApp/SalomeApp_DataModel.cxx index bebd38e64..77a1ea824 100644 --- a/src/SalomeApp/SalomeApp_DataModel.cxx +++ b/src/SalomeApp/SalomeApp_DataModel.cxx @@ -286,8 +286,7 @@ bool SalomeApp_DataModel::open( const QString& name, CAM_Study* study, QStringLi if ( anId.isEmpty() ) return true; // Probably nothing to load - _PTR(Study) aStudy ( aDoc->studyDS() ); // shared_ptr cannot be used here - _PTR(SComponent) aSComp ( aStudy->FindComponentID( std::string( anId.toLatin1() ) ) ); + _PTR(SComponent) aSComp ( SalomeApp_Application::getStudy()->FindComponentID( std::string( anId.toLatin1() ) ) ); if ( aSComp ) updateTree( aSComp, aDoc ); @@ -321,8 +320,7 @@ void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study ) studyRoot = dynamic_cast( aSStudy->root() ); QString anId = getRootEntry( aSStudy ); if ( !anId.isEmpty() ){ // if nothing is published in the study for this module -> do nothing - _PTR(Study) aStudy ( aSStudy->studyDS() ); - sobj = aStudy->FindComponentID( std::string( anId.toLatin1() ) ); + sobj = SalomeApp_Application::getStudy()->FindComponentID( std::string( anId.toLatin1() ) ); } } } @@ -331,9 +329,8 @@ void SalomeApp_DataModel::update( LightApp_DataObject*, LightApp_Study* study ) if ( studyRoot ) { aSStudy = dynamic_cast( studyRoot->study() ); // value should not change here theoretically, but just to make sure if ( aSStudy ) { - _PTR(Study) aStudy ( aSStudy->studyDS() ); // modelRoot->object() cannot be reused here: it is about to be deleted by buildTree() soon - sobj = aStudy->FindComponentID( std::string( modelRoot->entry().toLatin1() ) ); + sobj = SalomeApp_Application::getStudy()->FindComponentID( std::string( modelRoot->entry().toLatin1() ) ); } } } diff --git a/src/SalomeApp/SalomeApp_DataObject.cxx b/src/SalomeApp/SalomeApp_DataObject.cxx index a6fd9c005..ba1afa068 100644 --- a/src/SalomeApp/SalomeApp_DataObject.cxx +++ b/src/SalomeApp/SalomeApp_DataObject.cxx @@ -291,7 +291,7 @@ QString SalomeApp_DataObject::toolTip( const int /*id*/ ) const if ( !CORBA::is_nil(aComponent) && aComponent->hasObjectInfo() ) { LightApp_RootObject* aRoot = dynamic_cast( root() ); if ( aRoot && aRoot->study() ) { - CORBA::String_var data = aComponent->getObjectInfo( aRoot->study()->id(), entry().toLatin1().constData()); + CORBA::String_var data = aComponent->getObjectInfo( entry().toLatin1().constData()); QString objInfo = data.in(); QStringList l; l << name(); @@ -405,13 +405,13 @@ bool SalomeApp_DataObject::hasChildren() const bool ok = false; // tmp?? - _PTR(UseCaseBuilder) aUseCaseBuilder = myObject->GetStudy()->GetUseCaseBuilder(); + _PTR(UseCaseBuilder) aUseCaseBuilder = SalomeApp_Application::getStudy()->GetUseCaseBuilder(); if (aUseCaseBuilder->IsUseCaseNode(myObject)) { ok = aUseCaseBuilder->HasChildren(myObject); // TODO: check name as below? } else { - _PTR(ChildIterator) it ( myObject->GetStudy()->NewChildIterator( myObject ) ); + _PTR(ChildIterator) it ( SalomeApp_Application::getStudy()->NewChildIterator( myObject ) ); for ( ; it->More() && !ok; it->Next() ) { _PTR(SObject) obj = it->Value(); if ( obj ) { @@ -548,36 +548,28 @@ QString SalomeApp_DataObject::value( const _PTR(SObject)& obj ) const QString aStrings = fromUtf8( str ); //Special case to show NoteBook variables in the "Value" column of the OB - if ( LightApp_RootObject* aRoot = dynamic_cast( root() ) ) + bool ok = false; + QStringList aSectionList = aStrings.split( "|" ); + if ( !aSectionList.isEmpty() ) { - if ( SalomeApp_Study* aStudy = dynamic_cast( aRoot->study() ) ) + QString aLastSection = aSectionList.last(); + QStringList aStringList = aLastSection.split( ":" ); + if ( !aStringList.isEmpty() ) { - _PTR(Study) studyDS( aStudy->studyDS() ); - - bool ok = false; - QStringList aSectionList = aStrings.split( "|" ); - if ( !aSectionList.isEmpty() ) + ok = true; + for ( int i = 0, n = aStringList.size(); i < n; i++ ) { - QString aLastSection = aSectionList.last(); - QStringList aStringList = aLastSection.split( ":" ); - if ( !aStringList.isEmpty() ) - { - ok = true; - for ( int i = 0, n = aStringList.size(); i < n; i++ ) - { - QString aStr = aStringList[i]; - if ( studyDS->IsVariable( aStr.toStdString() ) ) - val.append( aStr + ", " ); - } - - if ( !val.isEmpty() ) - val.remove( val.length() - 2, 2 ); - } + QString aStr = aStringList[i]; + if ( SalomeApp_Application::getStudy()->IsVariable( aStr.toStdString() ) ) + val.append( aStr + ", " ); } - if( !ok ) - val = aStrings; + + if ( !val.isEmpty() ) + val.remove( val.length() - 2, 2 ); } } + if( !ok ) + val = aStrings; } else if ( obj->FindAttribute( attr, "AttributeInteger" ) ) { diff --git a/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx b/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx index 9bdda7525..216b107cd 100644 --- a/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx +++ b/src/SalomeApp/SalomeApp_DoubleSpinBox.cxx @@ -425,38 +425,35 @@ SalomeApp_DoubleSpinBox::SearchState SalomeApp_DoubleSpinBox::findVariable( cons value = 0; if( SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ) ) { - if( SalomeApp_Study* study = dynamic_cast( app->activeStudy() ) ) - { - _PTR(Study) studyDS = study->studyDS(); + _PTR(Study) studyDS = SalomeApp_Application::getStudy(); - std::string aName = name.toStdString(); - if( studyDS->IsVariable( aName ) ) + std::string aName = name.toStdString(); + if( studyDS->IsVariable( aName ) ) + { + if( studyDS->IsReal( aName ) || studyDS->IsInteger( aName ) || studyDS->IsString( aName ) ) { - if( studyDS->IsReal( aName ) || studyDS->IsInteger( aName ) || studyDS->IsString( aName ) ) + if( studyDS->IsString( aName ) ) { - if( studyDS->IsString( aName ) ) - { #ifndef DISABLE_PYCONSOLE - PyConsole_Interp* pyInterp = app->getPyInterp(); - PyLockWrapper aLock; // Acquire GIL - std::string command; - command = "import salome_notebook ; "; - command += "salome_notebook.notebook.setAsReal(\""; - command += aName; - command += "\")"; - bool aResult; - aResult = pyInterp->run(command.c_str()); - if(aResult) - { - return IncorrectType; - } + PyConsole_Interp* pyInterp = app->getPyInterp(); + PyLockWrapper aLock; // Acquire GIL + std::string command; + command = "import salome_notebook ; "; + command += "salome_notebook.notebook.setAsReal(\""; + command += aName; + command += "\")"; + bool aResult; + aResult = pyInterp->run(command.c_str()); + if(aResult) + { + return IncorrectType; + } #endif - } - value = studyDS->GetReal( aName ); - return Found; } - return IncorrectType; + value = studyDS->GetReal( aName ); + return Found; } + return IncorrectType; } } return NotFound; diff --git a/src/SalomeApp/SalomeApp_Engine_i.cxx b/src/SalomeApp/SalomeApp_Engine_i.cxx index 16c1fcc29..108cee699 100644 --- a/src/SalomeApp/SalomeApp_Engine_i.cxx +++ b/src/SalomeApp/SalomeApp_Engine_i.cxx @@ -65,43 +65,37 @@ SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theCompone { SALOMEDS::TMPFile_var aStreamFile = new SALOMEDS::TMPFile; - if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy())) + if (CORBA::is_nil(theComponent)) return aStreamFile._retn(); - const int studyId = theComponent->GetStudy()->StudyId(); - // Get a temporary directory to store a file //std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir(); - if (myMap.count(studyId)) { - std::string componentName (theComponent->ComponentDataType()); - - // Error somewhere outside - Save() called with - // wrong SComponent instance - if ( myComponentName != componentName ) - return aStreamFile._retn(); + std::string componentName (theComponent->ComponentDataType()); - const ListOfFiles& listOfFiles = myMap[studyId]; + // Error somewhere outside - Save() called with + // wrong SComponent instance + if ( myComponentName != componentName ) + return aStreamFile._retn(); - // listOfFiles must contain temporary directory name in its first item - // and names of files (relatively the temporary directory) in the others - const int n = listOfFiles.size() - 1; + // listOfFiles must contain temporary directory name in its first item + // and names of files (relatively the temporary directory) in the others + const int n = myListOfFiles.size() - 1; - if (n > 0) { // there are some files, containing persistent data of the component - std::string aTmpDir = listOfFiles[0]; + if (n > 0) { // there are some files, containing persistent data of the component + std::string aTmpDir = myListOfFiles[0]; - // Create a list to store names of created files - SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames; - aSeq->length(n); - for (int i = 0; i < n; i++) - aSeq[i] = CORBA::string_dup(listOfFiles[i + 1].c_str()); + // Create a list to store names of created files + ListOfFiles aSeq; + aSeq.reserve(n); + for (int i = 0; i < n; i++) + aSeq.push_back(CORBA::string_dup(myListOfFiles[i + 1].c_str())); - // Convert a file to the byte stream - aStreamFile = SALOMEDS_Tool::PutFilesToStream(aTmpDir.c_str(), aSeq.in(), isMultiFile); + // Convert a file to the byte stream + aStreamFile = SALOMEDS_Tool::PutFilesToStream(aTmpDir.c_str(), aSeq, isMultiFile); - // Remove the files and tmp directory, created by the component storage procedure - if (!isMultiFile) SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true); - } + // Remove the files and tmp directory, created by the component storage procedure + if (!isMultiFile) SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq, true); } return aStreamFile._retn(); @@ -113,7 +107,7 @@ CORBA::Boolean SalomeApp_Engine_i::Load (SALOMEDS::SComponent_ptr theComponent, bool isMultiFile) { std::cout << "SalomeApp_Engine_i::Load() isMultiFile = " << isMultiFile << std::endl; - if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy())) + if (CORBA::is_nil(theComponent)) return false; // Error somewhere outside - Load() called with @@ -122,53 +116,42 @@ CORBA::Boolean SalomeApp_Engine_i::Load (SALOMEDS::SComponent_ptr theComponent, if ( myComponentName != componentName ) return false; - const int studyId = theComponent->GetStudy()->StudyId(); - // Create a temporary directory for the component's data files std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir(); // Convert the byte stream theStream to a files and place them in the tmp directory. // The files and temporary directory must be deleted by the component loading procedure. - SALOMEDS::ListOfFileNames_var aSeq = + ListOfFiles aSeq = SALOMEDS_Tool::PutStreamToFiles(theFile, aTmpDir.c_str(), isMultiFile); // Store list of file names to be used by the component loading procedure - const int n = aSeq->length() + 1; + const int n = aSeq.size() + 1; ListOfFiles listOfFiles (n); listOfFiles[0] = aTmpDir; for (int i = 1; i < n; i++) listOfFiles[i] = std::string(aSeq[i - 1]); - SetListOfFiles(listOfFiles, studyId); + SetListOfFiles(listOfFiles); return true; } -SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles (const int theStudyId) +SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles() { - ListOfFiles aListOfFiles; - - if (myMap.find(theStudyId) != myMap.end()) - { - aListOfFiles = myMap[theStudyId]; - } - - return aListOfFiles; + return myListOfFiles; } -void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles& theListOfFiles, - const int theStudyId) +void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles& theListOfFiles) { - myMap[theStudyId] = theListOfFiles; + myListOfFiles = theListOfFiles; } /*! * DumpPython implementation for light modules */ -Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Object_ptr theStudy, - CORBA::Boolean isPublished, - CORBA::Boolean isMultiFile, - CORBA::Boolean& isValidScript) +Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Boolean isPublished, + CORBA::Boolean isMultiFile, + CORBA::Boolean& isValidScript) { MESSAGE("SalomeApp_Engine_i::DumpPython(): myComponentName = "<< myComponentName << ", this = " << this); @@ -182,24 +165,13 @@ Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Object_ptr theStudy, aStreamFile[0] = '\0'; isValidScript = true; - if (CORBA::is_nil(theStudy)) - return aStreamFile._retn(); - - SALOMEDS::Study_var studyDS = SALOMEDS::Study::_narrow( theStudy ); - const int studyId = studyDS->StudyId(); - - if (!myMap.count(studyId)) - return aStreamFile._retn(); - - ListOfFiles listOfFiles = myMap[studyId]; - // listOfFiles must contain temporary directory name in its first item // and names of files (relatively the temporary directory) in the others - if ( listOfFiles.size() < 2 ) + if ( myListOfFiles.size() < 2 ) return aStreamFile._retn(); // there are some files, containing persistent data of the component - QString aTmpPath( listOfFiles.front().c_str() ); + QString aTmpPath( myListOfFiles.front().c_str() ); QDir aTmpDir( aTmpPath ); if ( !aTmpDir.exists() ) return aStreamFile._retn(); @@ -208,8 +180,8 @@ Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Object_ptr theStudy, QStringList aFilePaths; QList aFileSizes; qint64 aBuffSize = 0; - ListOfFiles::const_iterator aFIt = listOfFiles.begin(); - ListOfFiles::const_iterator aFEnd = listOfFiles.end(); + ListOfFiles::const_iterator aFIt = myListOfFiles.begin(); + ListOfFiles::const_iterator aFEnd = myListOfFiles.end(); aFIt++; for (; aFIt != aFEnd; aFIt++){ QString aFileName( (*aFIt).c_str() ); diff --git a/src/SalomeApp/SalomeApp_Engine_i.h b/src/SalomeApp/SalomeApp_Engine_i.h index ec2641913..98412512b 100644 --- a/src/SalomeApp/SalomeApp_Engine_i.h +++ b/src/SalomeApp/SalomeApp_Engine_i.h @@ -55,17 +55,15 @@ public: const char* theURL, bool isMultiFile ); - virtual Engines::TMPFile* DumpPython(CORBA::Object_ptr theStudy, - CORBA::Boolean isPublished, + virtual Engines::TMPFile* DumpPython(CORBA::Boolean isPublished, CORBA::Boolean isMultiFile, CORBA::Boolean& isValidScript); public: typedef std::vector ListOfFiles; - ListOfFiles GetListOfFiles (const int theStudyId); - void SetListOfFiles (const ListOfFiles& theListOfFiles, - const int theStudyId); + ListOfFiles GetListOfFiles (); + void SetListOfFiles (const ListOfFiles& theListOfFiles); static std::string EngineIORForComponent( const char* theComponentName, bool toCreate ); @@ -85,7 +83,7 @@ public: char* IORToLocalPersistentID( SALOMEDS::SObject_ptr, const char*, CORBA::Boolean, CORBA::Boolean ) {return 0;} char* LocalPersistentIDToIOR( SALOMEDS::SObject_ptr, const char*, CORBA::Boolean, CORBA::Boolean ) {return 0;} bool CanPublishInStudy( CORBA::Object_ptr ) {return 0;} - SALOMEDS::SObject_ptr PublishInStudy(SALOMEDS::Study_ptr, SALOMEDS::SObject_ptr, CORBA::Object_ptr, const char* ) throw (SALOME::SALOME_Exception) {return 0;} + SALOMEDS::SObject_ptr PublishInStudy( SALOMEDS::SObject_ptr, CORBA::Object_ptr, const char* ) throw (SALOME::SALOME_Exception) {return 0;} CORBA::Boolean CanCopy( SALOMEDS::SObject_ptr ) {return 0;} SALOMEDS::TMPFile* CopyFrom( SALOMEDS::SObject_ptr, CORBA::Long& ) {return 0;} CORBA::Boolean CanPaste( const char*, CORBA::Long ) {return 0;} @@ -98,8 +96,7 @@ private: static PortableServer::POA_var poa(); static SALOME_NamingService* namingService(); private: - typedef std::map MapOfListOfFiles; - MapOfListOfFiles myMap; + ListOfFiles myListOfFiles; std::string myComponentName; }; diff --git a/src/SalomeApp/SalomeApp_IntSpinBox.cxx b/src/SalomeApp/SalomeApp_IntSpinBox.cxx index 64bf5a306..bb4e01b88 100644 --- a/src/SalomeApp/SalomeApp_IntSpinBox.cxx +++ b/src/SalomeApp/SalomeApp_IntSpinBox.cxx @@ -373,38 +373,35 @@ SalomeApp_IntSpinBox::SearchState SalomeApp_IntSpinBox::findVariable( const QStr value = 0; if( SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ) ) { - if( SalomeApp_Study* study = dynamic_cast( app->activeStudy() ) ) - { - _PTR(Study) studyDS = study->studyDS(); + _PTR(Study) studyDS = SalomeApp_Application::getStudy(); - std::string aName = name.toStdString(); - if( studyDS->IsVariable( aName ) ) + std::string aName = name.toStdString(); + if( studyDS->IsVariable( aName ) ) + { + if( studyDS->IsInteger( aName ) || studyDS->IsString( aName ) ) { - if( studyDS->IsInteger( aName ) || studyDS->IsString( aName ) ) + if( studyDS->IsString( aName ) ) { - if( studyDS->IsString( aName ) ) - { #ifndef DISABLE_PYCONSOLE - PyConsole_Interp* pyInterp = app->getPyInterp(); - PyLockWrapper aLock; // Acquire GIL - std::string command; - command = "import salome_notebook ; "; - command += "salome_notebook.notebook.setAsInteger(\""; - command += aName; - command += "\")"; - bool aResult; - aResult = pyInterp->run(command.c_str()); - if(aResult) - { - return IncorrectType; - } + PyConsole_Interp* pyInterp = app->getPyInterp(); + PyLockWrapper aLock; // Acquire GIL + std::string command; + command = "import salome_notebook ; "; + command += "salome_notebook.notebook.setAsInteger(\""; + command += aName; + command += "\")"; + bool aResult; + aResult = pyInterp->run(command.c_str()); + if(aResult) + { + return IncorrectType; + } #endif - } - value = studyDS->GetInteger( aName ); - return Found; } - return IncorrectType; + value = studyDS->GetInteger( aName ); + return Found; } + return IncorrectType; } } return NotFound; diff --git a/src/SalomeApp/SalomeApp_NoteBook.cxx b/src/SalomeApp/SalomeApp_NoteBook.cxx index 749ce3798..64d75941f 100644 --- a/src/SalomeApp/SalomeApp_NoteBook.cxx +++ b/src/SalomeApp/SalomeApp_NoteBook.cxx @@ -378,7 +378,7 @@ int NoteBook_Table::getUniqueIndex() const * Purpose : Add variables in the table from theStudy */ //============================================================================ -void NoteBook_Table::Init(_PTR(Study) theStudy) +void NoteBook_Table::Init() { isProcessItemChangedSignal = false; @@ -403,10 +403,10 @@ void NoteBook_Table::Init(_PTR(Study) theStudy) myVariableMap.clear(); //Add all variables into the table - std::vector aVariables = theStudy->GetVariableNames(); + std::vector aVariables = SalomeApp_Application::getStudy()->GetVariableNames(); for(int iVar = 0; iVar < aVariables.size(); iVar++ ) { AddRow(QString(aVariables[iVar].c_str()), - Variable2String(aVariables[iVar],theStudy)); + Variable2String(aVariables[iVar])); } //Add empty row @@ -414,8 +414,6 @@ void NoteBook_Table::Init(_PTR(Study) theStudy) isProcessItemChangedSignal = true; ResetMaps(); - - myStudy = theStudy; } //============================================================================ @@ -423,18 +421,18 @@ void NoteBook_Table::Init(_PTR(Study) theStudy) * Purpose : Convert variable values to QString */ //============================================================================ -QString NoteBook_Table::Variable2String(const std::string& theVarName, - _PTR(Study) theStudy) +QString NoteBook_Table::Variable2String(const std::string& theVarName) { + _PTR(Study) aStudy = SalomeApp_Application::getStudy(); QString aResult; - if( theStudy->IsReal(theVarName) ) - aResult = QString::number(theStudy->GetReal(theVarName)); - else if( theStudy->IsInteger(theVarName) ) - aResult = QString::number(theStudy->GetInteger(theVarName)); - else if( theStudy->IsBoolean(theVarName) ) - aResult = theStudy->GetBoolean(theVarName) ? QString("True") : QString("False"); - else if( theStudy->IsString(theVarName) ) - aResult = theStudy->GetString(theVarName).c_str(); + if( aStudy->IsReal(theVarName) ) + aResult = QString::number(aStudy->GetReal(theVarName)); + else if( aStudy->IsInteger(theVarName) ) + aResult = QString::number(aStudy->GetInteger(theVarName)); + else if( aStudy->IsBoolean(theVarName) ) + aResult = aStudy->GetBoolean(theVarName) ? QString("True") : QString("False"); + else if( aStudy->IsString(theVarName) ) + aResult = aStudy->GetString(theVarName).c_str(); return aResult; } @@ -566,7 +564,7 @@ void NoteBook_Table::onItemChanged(QTableWidgetItem* theItem) if( myVariableMap.contains( anIndex ) ) { const NoteBoox_Variable& aVariable = myVariableMap[ anIndex ]; - if( !aVariable.Name.isEmpty() && myStudy->IsVariableUsed( std::string( aVariable.Name.toLatin1().constData() ) ) ) + if( !aVariable.Name.isEmpty() && SalomeApp_Application::getStudy()->IsVariableUsed( std::string( aVariable.Name.toLatin1().constData() ) ) ) { if( QMessageBox::warning( parentWidget(), tr( "WARNING" ), tr( "RENAME_VARIABLE_IS_USED" ).arg( aVariable.Name ), @@ -661,6 +659,7 @@ bool NoteBook_Table::IsUniqueName(const NoteBook_TableRow* theRow) const //============================================================================ void NoteBook_Table::RemoveSelected() { + _PTR(Study) aStudy = SalomeApp_Application::getStudy(); isProcessItemChangedSignal = false; QList aSelectedItems = selectedItems(); if( !(aSelectedItems.size() > 0)) { @@ -678,7 +677,7 @@ void NoteBook_Table::RemoveSelected() else { int nRow = row(aSelectedItems[i]); - if( myStudy->IsVariableUsed( std::string( aRow->GetName().toLatin1().constData() ) ) ) + if( aStudy->IsVariableUsed( std::string( aRow->GetName().toLatin1().constData() ) ) ) { if( QMessageBox::warning( parentWidget(), tr( "WARNING" ), tr( "REMOVE_VARIABLE_IS_USED" ).arg( aRow->GetName() ), @@ -696,7 +695,7 @@ void NoteBook_Table::RemoveSelected() myVariableMap.remove( index ); removeRow(nRow); myRows.removeAt(nRow); - if(myStudy->IsVariable(aVarName.toLatin1().constData())) + if(aStudy->IsVariable(aVarName.toLatin1().constData())) removedFromStudy = true; } } @@ -757,9 +756,8 @@ void NoteBook_Table::ResetMaps() * Purpose : Constructor */ //============================================================================ -SalomeApp_NoteBook::SalomeApp_NoteBook(QWidget * parent, _PTR(Study) theStudy): - QWidget(parent), - myStudy(theStudy) +SalomeApp_NoteBook::SalomeApp_NoteBook(QWidget * parent): + QWidget(parent) { setObjectName("SalomeApp_NoteBook"); setWindowTitle(tr("NOTEBOOK_TITLE")); @@ -789,7 +787,7 @@ SalomeApp_NoteBook::SalomeApp_NoteBook(QWidget * parent, _PTR(Study) theStudy): connect( myUpdateStudyBtn, SIGNAL(clicked()), this, SLOT(onUpdateStudy()) ); connect( myRemoveButton, SIGNAL(clicked()), this, SLOT(onRemove())); - myTable->Init(myStudy); + myTable->Init(); myDumpedStudyScript = ""; myIsDumpedStudySaved = false; @@ -808,10 +806,8 @@ SalomeApp_NoteBook::~SalomeApp_NoteBook(){} * Purpose : init variable table */ //============================================================================ -void SalomeApp_NoteBook::Init(_PTR(Study) theStudy){ - if(myStudy!= theStudy) - myStudy = theStudy; - myTable->Init(myStudy); +void SalomeApp_NoteBook::Init(){ + myTable->Init(); } @@ -822,7 +818,7 @@ void SalomeApp_NoteBook::Init(_PTR(Study) theStudy){ //============================================================================ void SalomeApp_NoteBook::onVarUpdate(QString theVarName) { - myTable->Init(myStudy); + myTable->Init(); } //============================================================================ @@ -837,6 +833,7 @@ void SalomeApp_NoteBook::onApply() SUIT_MessageBox::warning( this, tr( "WARNING" ), tr( "INCORRECT_DATA" ) ); return; } + _PTR(Study) aStudy = SalomeApp_Application::getStudy(); double aDVal; int anIVal; @@ -852,7 +849,7 @@ void SalomeApp_NoteBook::onApply() if( aVariableMapRef.contains( anIndex ) ) { QString aRemovedVariable = aVariableMapRef[ anIndex ].Name; - myStudy->RemoveVariable( std::string( aRemovedVariable.toLatin1().constData() ) ); + aStudy->RemoveVariable( std::string( aRemovedVariable.toLatin1().constData() ) ); } } @@ -874,22 +871,22 @@ void SalomeApp_NoteBook::onApply() if( !aNameRef.isEmpty() && !aValueRef.isEmpty() && aNameRef != aName ) { - myStudy->RenameVariable( std::string( aNameRef.toLatin1().constData() ), - std::string( aName.toLatin1().constData() ) ); + aStudy->RenameVariable( std::string( aNameRef.toLatin1().constData() ), + std::string( aName.toLatin1().constData() ) ); } } if( NoteBook_TableRow::IsIntegerValue(aValue,&anIVal) ) - myStudy->SetInteger(std::string(aName.toLatin1().constData()),anIVal); + aStudy->SetInteger(std::string(aName.toLatin1().constData()),anIVal); else if( NoteBook_TableRow::IsRealValue(aValue,&aDVal) ) - myStudy->SetReal(std::string(aName.toLatin1().constData()),aDVal); + aStudy->SetReal(std::string(aName.toLatin1().constData()),aDVal); else if( NoteBook_TableRow::IsBooleanValue(aValue,&aBVal) ) - myStudy->SetBoolean(std::string(aName.toLatin1().constData()),aBVal); + aStudy->SetBoolean(std::string(aName.toLatin1().constData()),aBVal); else - myStudy->SetString(std::string(aName.toLatin1().constData()),aValue.toStdString()); + aStudy->SetString(std::string(aName.toLatin1().constData()),aValue.toStdString()); } } myTable->ResetMaps(); @@ -898,7 +895,7 @@ void SalomeApp_NoteBook::onApply() if(app) app->updateActions(); - myStudy->Modified(); + aStudy->Modified(); } //============================================================================ diff --git a/src/SalomeApp/SalomeApp_NoteBook.h b/src/SalomeApp/SalomeApp_NoteBook.h index ba4e96b25..4722ee7aa 100644 --- a/src/SalomeApp/SalomeApp_NoteBook.h +++ b/src/SalomeApp/SalomeApp_NoteBook.h @@ -95,9 +95,8 @@ class SALOMEAPP_EXPORT NoteBook_Table : public QTableWidget NoteBook_Table(QWidget * parent = 0); virtual ~NoteBook_Table(); - void Init(_PTR(Study) theStudy); - static QString Variable2String(const std::string& theVarName, - _PTR(Study) theStudy); + void Init(); + static QString Variable2String(const std::string& theVarName); bool IsValid() const; @@ -137,18 +136,16 @@ class SALOMEAPP_EXPORT NoteBook_Table : public QTableWidget QList myRemovedRows; VariableMap myVariableMapRef; VariableMap myVariableMap; - - _PTR(Study) myStudy; }; class SALOMEAPP_EXPORT SalomeApp_NoteBook : public QWidget { Q_OBJECT public: - SalomeApp_NoteBook(QWidget * parent , _PTR(Study) theStudy); + SalomeApp_NoteBook(QWidget * parent); virtual ~SalomeApp_NoteBook(); - void Init(_PTR(Study) theStudy); + void Init(); QString getDumpedStudyName() { return myDumpedStudyName; } void setDumpedStudyName(QString theName) { myDumpedStudyName = theName; } @@ -170,7 +167,6 @@ class SALOMEAPP_EXPORT SalomeApp_NoteBook : public QWidget QPushButton* myRemoveButton; QPushButton* myUpdateStudyBtn; - _PTR(Study) myStudy; QString myDumpedStudyScript; // path to script of dumped study QString myDumpedStudyName; bool myIsDumpedStudySaved; diff --git a/src/SalomeApp/SalomeApp_PyInterp.cxx b/src/SalomeApp/SalomeApp_PyInterp.cxx index 4db5aff1a..942aa6da4 100755 --- a/src/SalomeApp/SalomeApp_PyInterp.cxx +++ b/src/SalomeApp/SalomeApp_PyInterp.cxx @@ -72,7 +72,7 @@ int SalomeApp_PyInterp::beforeRun() int ret = simpleRun( "import salome", false ); if ( ret ) return ret; - ret = simpleRun( "salome.salome_init(0,1)", false ); + ret = simpleRun( "salome.salome_init(1)", false ); if ( ret ) return ret; } diff --git a/src/SalomeApp/SalomeApp_Study.cxx b/src/SalomeApp/SalomeApp_Study.cxx index e44ceb9ae..716445877 100644 --- a/src/SalomeApp/SalomeApp_Study.cxx +++ b/src/SalomeApp/SalomeApp_Study.cxx @@ -82,9 +82,8 @@ class SalomeApp_Study::Observer_i : public virtual POA_SALOMEDS::Observer, QObje public: - Observer_i(_PTR(Study) aStudyDS, SalomeApp_Study* aStudy):QObject(aStudy) + Observer_i( SalomeApp_Study* aStudy):QObject(aStudy) { - myStudyDS=aStudyDS; myStudy=aStudy; fillEntryMap(); } @@ -122,7 +121,7 @@ public: switch(event) { case 1: { //Add sobject - _PTR(SObject) aSObj = myStudyDS->FindObjectID(theID); + _PTR(SObject) aSObj = SalomeApp_Application::getStudy()->FindObjectID(theID); _PTR(SComponent) aSComp = aSObj->GetFatherComponent(); if (!aSComp || aSComp->IsNull()) { @@ -131,7 +130,7 @@ public: } // Mantis issue 0020136: Drag&Drop in OB - _PTR(UseCaseBuilder) aUseCaseBuilder = myStudyDS->GetUseCaseBuilder(); + _PTR(UseCaseBuilder) aUseCaseBuilder = SalomeApp_Application::getStudy()->GetUseCaseBuilder(); if (aUseCaseBuilder->IsUseCaseNode(aSComp)) { // BEGIN: work with tree nodes structure if (!aUseCaseBuilder->IsUseCaseNode(aSObj)) { // tree node is not yet set, it is a normal situation @@ -392,7 +391,6 @@ private: } private: - _PTR(Study) myStudyDS; SalomeApp_Study* myStudy; EntryMap entry2SuitObject; }; @@ -404,6 +402,7 @@ private: SalomeApp_Study::SalomeApp_Study( SUIT_Application* app ) : LightApp_Study( app ), myObserver( 0 ) { + myStudyDS = SalomeApp_Application::getStudy(); } /*! @@ -424,17 +423,6 @@ void SalomeApp_Study::onNoteBookVarUpdate( QString theVarName) } #endif -/*! - Gets study id. -*/ -int SalomeApp_Study::id() const -{ - int id = -1; - if ( studyDS() ) - id = studyDS()->StudyId(); - return id; -} - /*! Get study name. */ @@ -444,7 +432,7 @@ QString SalomeApp_Study::studyName() const // it can be changed outside of GUI // TEMPORARILY SOLUTION: better to be implemented with help of SALOMEDS observers if ( studyDS() ) { - QString newName = QString::fromUtf8(studyDS()->Name().c_str()); + QString newName = QString::fromUtf8(studyDS()->URL().c_str()); if ( LightApp_Study::studyName() != newName ) { SalomeApp_Study* that = const_cast( this ); that->setStudyName( newName ); @@ -469,35 +457,7 @@ bool SalomeApp_Study::createDocument( const QString& theStr ) { MESSAGE( "createDocument" ); - // initialize myStudyDS, read HDF file - QString aName = newStudyName(); - - _PTR(Study) study; - bool showError = !application()->property("open_study_from_command_line").isValid() || - !application()->property("open_study_from_command_line").toBool(); - try { - study = _PTR(Study)( SalomeApp_Application::studyMgr()->NewStudy( aName.toUtf8().data() ) ); - } - catch(const SALOME_Exception& ex) { - application()->putInfo(tr(ex.what())); - if ( showError ) - SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(), - tr("ERR_ERROR"), tr(ex.what())); - return false; - } - catch(...) { - application()->putInfo(tr("CREATE_DOCUMENT_PROBLEM")); - if ( showError ) - SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(), - tr("ERR_ERROR"), tr("CREATE_DOCUMENT_PROBLEM")); - return false; - } - - if ( !study ) - return false; - - setStudyDS( study ); - setStudyName( aName ); + setStudyName( QString::fromUtf8(myStudyDS->URL().c_str()) ); // create myRoot SalomeApp_RootObject* aRoot=new SalomeApp_RootObject( this ); @@ -509,7 +469,7 @@ bool SalomeApp_Study::createDocument( const QString& theStr ) bool aRet = CAM_Study::createDocument( theStr ); #ifdef WITH_SALOMEDS_OBSERVER - myObserver = new Observer_i(myStudyDS,this); + myObserver = new Observer_i(this); //attach an observer to the study with notification of modifications myStudyDS->attach(myObserver->_this(),true); #endif @@ -527,12 +487,12 @@ bool SalomeApp_Study::openDocument( const QString& theFileName ) { MESSAGE( "openDocument" ); - // initialize myStudyDS, read HDF file - _PTR(Study) study; - bool showError = !application()->property("open_study_from_command_line").isValid() || + // read HDF file + bool res = false; + bool showError = !application()->property("open_study_from_command_line").isValid() || !application()->property("open_study_from_command_line").toBool(); try { - study = _PTR(Study) ( SalomeApp_Application::studyMgr()->Open( theFileName.toUtf8().data() ) ); + res = myStudyDS->Open( theFileName.toUtf8().data() ); } catch(const SALOME_Exception& ex) { application()->putInfo(tr(ex.what())); @@ -540,7 +500,7 @@ bool SalomeApp_Study::openDocument( const QString& theFileName ) SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(), tr("ERR_ERROR"), tr(ex.what())); return false; - } + } catch(...) { application()->putInfo(tr("OPEN_DOCUMENT_PROBLEM")); if ( showError ) @@ -549,11 +509,9 @@ bool SalomeApp_Study::openDocument( const QString& theFileName ) return false; } - if ( !study ) + if ( !res) return false; - setStudyDS( study ); - setRoot( new SalomeApp_RootObject( this ) ); // create myRoot // update loaded data models: call open() and update() on them. @@ -570,15 +528,15 @@ bool SalomeApp_Study::openDocument( const QString& theFileName ) #ifdef WITH_SALOMEDS_OBSERVER dynamic_cast( root() )->setToSynchronize(false); - myObserver = new Observer_i(myStudyDS,this); + myObserver = new Observer_i(this); //attach an observer to the study with notification of modifications myStudyDS->attach(myObserver->_this(),true); #endif - bool res = CAM_Study::openDocument( theFileName ); + res = CAM_Study::openDocument( theFileName ); emit opened( this ); - study->IsSaved(true); + myStudyDS->IsSaved(true); bool restore = application()->resourceMgr()->booleanValue( "Study", "store_visual_state", true ); if ( restore ) { @@ -592,20 +550,13 @@ bool SalomeApp_Study::openDocument( const QString& theFileName ) } /*! - Connects GUI study to SALOMEDS one already loaded into StudyManager + Connects GUI study to SALOMEDS one \param theStudyName - name of study */ bool SalomeApp_Study::loadDocument( const QString& theStudyName ) { MESSAGE( "loadDocument" ); - // obtain myStudyDS from StudyManager - _PTR(Study) study ( SalomeApp_Application::studyMgr()->GetStudyByName( theStudyName.toUtf8().data() ) ); - if ( !study ) - return false; - - setStudyDS( study ); - setRoot( new SalomeApp_RootObject( this ) ); // create myRoot //SRN: BugID IPAL9021, put there the same code as in a method openDocument @@ -625,7 +576,7 @@ bool SalomeApp_Study::loadDocument( const QString& theStudyName ) #ifdef WITH_SALOMEDS_OBSERVER dynamic_cast( root() )->setToSynchronize(false); - myObserver = new Observer_i(myStudyDS,this); + myObserver = new Observer_i(this); //attach an observer to the study with notification of modifications myStudyDS->attach(myObserver->_this(),true); #endif @@ -681,9 +632,7 @@ bool SalomeApp_Study::saveDocumentAs( const QString& theFileName ) bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ); bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false ); - bool res = (isAscii ? - SalomeApp_Application::studyMgr()->SaveAsASCII( theFileName.toUtf8().data(), studyDS(), isMultiFile ) : - SalomeApp_Application::studyMgr()->SaveAs ( theFileName.toUtf8().data(), studyDS(), isMultiFile )) + bool res = studyDS()->SaveAs( theFileName.toUtf8().data(), isMultiFile, isAscii ) && CAM_Study::saveDocumentAs( theFileName ); res = res && saveStudyData(theFileName); @@ -726,9 +675,7 @@ bool SalomeApp_Study::saveDocument() bool isMultiFile = resMgr->booleanValue( "Study", "multi_file", false ); bool isAscii = resMgr->booleanValue( "Study", "ascii_file", false ); - bool res = (isAscii ? - SalomeApp_Application::studyMgr()->SaveASCII( studyDS(), isMultiFile ) : - SalomeApp_Application::studyMgr()->Save ( studyDS(), isMultiFile )) && CAM_Study::saveDocument(); + bool res = studyDS()->Save( isMultiFile, isAscii ) && CAM_Study::saveDocument(); res = res && saveStudyData(studyName()); if ( res ) @@ -745,24 +692,18 @@ void SalomeApp_Study::closeDocument(bool permanently) LightApp_Study::closeDocument(permanently); // close SALOMEDS document - _PTR(Study) studyPtr = studyDS(); - if ( studyPtr ) - { - if ( myObserver ) - myStudyDS->detach( myObserver->_this() ); - if ( permanently ) { - SUIT_Desktop* desk = SUIT_Session::session()->activeApplication()->desktop(); - bool isBlocked = desk->signalsBlocked(); - desk->blockSignals( true ); - SalomeApp_Application::studyMgr()->Close( studyPtr ); - desk->blockSignals( isBlocked ); + if ( myObserver ) + myStudyDS->detach( myObserver->_this() ); + if ( permanently ) { + SUIT_Desktop* desk = SUIT_Session::session()->activeApplication()->desktop(); + bool isBlocked = desk->signalsBlocked(); + desk->blockSignals( true ); + myStudyDS->Clear(); + desk->blockSignals( isBlocked ); #ifndef DISABLE_PYCONSOLE - SalomeApp_Application* app = dynamic_cast( application() ); - app->getPyInterp()->destroy(); + SalomeApp_Application* app = dynamic_cast( application() ); + app->getPyInterp()->destroy(); #endif - } - SALOMEDSClient_Study* aStudy = 0; - setStudyDS( _PTR(Study)(aStudy) ); } } @@ -789,13 +730,12 @@ bool SalomeApp_Study::dump( const QString& theFileName, int savePoint; _PTR(AttributeParameter) ap; _PTR(IParameters) ip = ClientFactory::getIParameters(ap); - _PTR(Study) aStudy = studyDS(); - if( ip->isDumpPython( aStudy ) ) - ip->setDumpPython( aStudy ); //Unset DumpPython flag. + if( ip->isDumpPython() ) + ip->setDumpPython(); //Unset DumpPython flag. if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method - ip->setDumpPython( aStudy ); + ip->setDumpPython(); //SRN: create a temporary save point savePoint = SalomeApp_VisualState( dynamic_cast( application() ) ).storeState(); @@ -825,10 +765,10 @@ bool SalomeApp_Study::dump( const QString& theFileName, // Now dump SALOMEDS part that also involves SalomeApp_Engine in case if // any light module is present in the current configuration QFileInfo aFileInfo( theFileName ); - bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toUtf8().data(), - aFileInfo.baseName().toUtf8().data(), - toPublish, - isMultiFile); + bool res = myStudyDS->DumpStudy( aFileInfo.absolutePath().toUtf8().data(), + aFileInfo.baseName().toUtf8().data(), + toPublish, + isMultiFile); if ( toSaveGUI ) removeSavePoint( savePoint ); //SRN: remove the created temporary save point. @@ -857,8 +797,7 @@ bool SalomeApp_Study::isModified() const */ void SalomeApp_Study::Modified() { - if(_PTR(Study) aStudy = studyDS()) - aStudy->Modified(); + myStudyDS->Modified(); LightApp_Study::Modified(); } @@ -944,14 +883,6 @@ bool SalomeApp_Study::openStudyData( const QString& theFileName ) return true; } -/*! - Set studyDS. -*/ -void SalomeApp_Study::setStudyDS( const _PTR(Study)& s ) -{ - myStudyDS = s; -} - /*! Virtual method re-implemented from LightApp_Study in order to create the module object connected to SALOMEDS - SalomeApp_ModuleObject. @@ -985,11 +916,7 @@ CAM_ModuleObject* SalomeApp_Study::createModuleObject( LightApp_DataModel* theDa } if ( !res ){ - _PTR(Study) aStudy = studyDS(); - if ( !aStudy ) - return res; - - _PTR(SComponent) aComp = aStudy->FindComponent( + _PTR(SComponent) aComp = myStudyDS->FindComponent( theDataModel->module()->name().toStdString() ); if ( !aComp ) return res; @@ -1021,16 +948,13 @@ void SalomeApp_Study::addComponent(const CAM_DataModel* dm) // 1. aModule == 0 means that this is a light module (no CORBA enigine) if (!aModule) { // Check SComponent existance - _PTR(Study) aStudy = studyDS(); - if (!aStudy) - return; std::string aCompDataType = dm->module()->name().toStdString(); - _PTR(SComponent) aComp = aStudy->FindComponent(aCompDataType); + _PTR(SComponent) aComp = myStudyDS->FindComponent(aCompDataType); if (!aComp) { // Create SComponent - _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder(); + _PTR(StudyBuilder) aBuilder = myStudyDS->NewBuilder(); aComp = aBuilder->NewComponent(aCompDataType); aBuilder->SetName(aComp, dm->module()->moduleName().toStdString()); QString anIconName = dm->module()->iconName(); @@ -1049,7 +973,7 @@ void SalomeApp_Study::addComponent(const CAM_DataModel* dm) SalomeApp_DataModel::synchronize( aComp, this ); } else { - _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder(); + _PTR(StudyBuilder) aBuilder = myStudyDS->NewBuilder(); aBuilder->SetName(aComp, dm->module()->moduleName().toStdString()); QString anIconName = dm->module()->iconName(); if (!anIconName.isEmpty()) { @@ -1072,7 +996,6 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm // SalomeApp_DataModel* aDM = (SalomeApp_DataModel*)(dm); SalomeApp_Module* aModule = dynamic_cast( dm->module() ); - _PTR(Study) aStudy = studyDS(); // shared_ptr cannot be used here _PTR(SComponent) aSComp; QString anEngine; // 1. aModule == 0 means that this is a light module (no CORBA enigine) @@ -1080,7 +1003,7 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm // Issue 21377 - using separate engine for each type of light module std::string aCompDataType = dm->module()->name().toStdString(); anEngine = SalomeApp_Engine_i::EngineIORForComponent( aCompDataType.c_str(), true ).c_str(); - aSComp = aStudy->FindComponent( aCompDataType ); + aSComp = myStudyDS->FindComponent( aCompDataType ); } else { SalomeApp_DataModel* aDM = dynamic_cast( dm ); @@ -1091,11 +1014,11 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm anEngine = aDM->getModule()->engineIOR(); if ( anEngine.isEmpty() ) return false; - aSComp = aStudy->FindComponentID( std::string( anId.toLatin1() ) ); + aSComp = myStudyDS->FindComponentID( std::string( anId.toLatin1() ) ); } } if ( aSComp ) { - _PTR(StudyBuilder) aBuilder( aStudy->NewBuilder() ); + _PTR(StudyBuilder) aBuilder( myStudyDS->NewBuilder() ); if ( aBuilder ) { try { aBuilder->LoadWith( aSComp, std::string( anEngine.toLatin1() ) ); @@ -1129,28 +1052,6 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm return false; } -/*! - Create new study name. -*/ -QString SalomeApp_Study::newStudyName() const -{ - std::vector studies = SalomeApp_Application::studyMgr()->GetOpenStudies(); - QString prefix( "Study%1" ), newName, curName; - int i = 1, j, n = studies.size(); - while ( newName.isEmpty() ){ - curName = prefix.arg( i ); - for ( j = 0 ; j < n; j++ ){ - if ( !strcmp( studies[j].c_str(), curName.toLatin1() ) ) - break; - } - if ( j == n ) - newName = curName; - else - i++; - } - return newName; -} - /*! Note that this method does not create or activate SalomeApp_Engine_i instance, therefore it can be called safely for any kind of module, but for full @@ -1163,7 +1064,7 @@ std::vector SalomeApp_Study::GetListOfFiles( const char* theModuleN // Issue 21377 - using separate engine for each type of light module SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false ); if (aDefaultEngine) - return aDefaultEngine->GetListOfFiles(id()); + return aDefaultEngine->GetListOfFiles(); std::vector aListOfFiles; return aListOfFiles; @@ -1183,7 +1084,7 @@ void SalomeApp_Study::SetListOfFiles ( const char* theModuleName, // Issue 21377 - using separate engine for each type of light module SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false ); if (aDefaultEngine) - aDefaultEngine->SetListOfFiles(theListOfFiles, id()); + aDefaultEngine->SetListOfFiles(theListOfFiles); } /*! @@ -1204,17 +1105,17 @@ void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bo if (isMultiFile) return; - std::vector aListOfFiles = GetListOfFiles( theModuleName ); + SALOMEDS_Tool::ListOfFiles aListOfFiles = GetListOfFiles( theModuleName ); if (aListOfFiles.size() > 0) { std::string aTmpDir = aListOfFiles[0]; const int n = aListOfFiles.size() - 1; - SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames; - aSeq->length(n); + std::vector aSeq; + aSeq.reserve(n); for (int i = 0; i < n; i++) - aSeq[i] = CORBA::string_dup(aListOfFiles[i + 1].c_str()); + aSeq.push_back(CORBA::string_dup(aListOfFiles[i + 1].c_str())); - SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true); + SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq, true); } } @@ -1226,7 +1127,7 @@ void SalomeApp_Study::RemoveTemporaryFiles ( const char* theModuleName, const bo void SalomeApp_Study::updateFromNotebook( const QString& theFileName, bool isSaved ) { setStudyName(theFileName); - studyDS()->Name(theFileName.toStdString()); + studyDS()->URL(theFileName.toStdString()); setIsSaved( isSaved ); } #endif diff --git a/src/SalomeApp/SalomeApp_Study.h b/src/SalomeApp/SalomeApp_Study.h index cf93e4056..2284df8db 100644 --- a/src/SalomeApp/SalomeApp_Study.h +++ b/src/SalomeApp/SalomeApp_Study.h @@ -43,7 +43,6 @@ public: SalomeApp_Study( SUIT_Application* ); virtual ~SalomeApp_Study(); - virtual int id() const; virtual QString studyName() const; virtual bool createDocument( const QString& ); @@ -103,7 +102,7 @@ protected: protected: virtual void dataModelInserted( const CAM_DataModel* ); virtual bool openDataModel( const QString&, CAM_DataModel* ); - void setStudyDS(const _PTR(Study)& s ); + virtual CAM_ModuleObject* createModuleObject( LightApp_DataModel* theDataModel, SUIT_DataObject* theParent ) const; protected slots: @@ -112,9 +111,6 @@ protected slots: void onNoteBookVarUpdate( QString theVarName ); #endif -private: - QString newStudyName() const; - private: _PTR(Study) myStudyDS; Observer_i* myObserver; diff --git a/src/SalomeApp/SalomeApp_StudyPropertiesDlg.cxx b/src/SalomeApp/SalomeApp_StudyPropertiesDlg.cxx index 043a2e30c..55a4765c7 100644 --- a/src/SalomeApp/SalomeApp_StudyPropertiesDlg.cxx +++ b/src/SalomeApp/SalomeApp_StudyPropertiesDlg.cxx @@ -25,6 +25,7 @@ // Author : Roman NIKOLAEV #include "SalomeApp_StudyPropertiesDlg.h" +#include "SalomeApp_Application.h" #include "SalomeApp_Study.h" #include "SUIT_Session.h" @@ -69,12 +70,6 @@ SalomeApp_StudyPropertiesDlg::SalomeApp_StudyPropertiesDlg(QWidget* parent) setWindowFlags( windowFlags() & ~Qt::WindowContextHelpButtonHint ); - // Display study properties - SalomeApp_Study* study = - dynamic_cast( SUIT_Session::session()->activeApplication()->activeStudy() ); - if (study) - myStudyDoc = study->studyDS(); - //Author QLabel* authorLbl = new QLabel(tr("PRP_AUTHOR"),this); myAuthor = new QLineEdit(this); @@ -173,10 +168,10 @@ SalomeApp_StudyPropertiesDlg::~SalomeApp_StudyPropertiesDlg() */ void SalomeApp_StudyPropertiesDlg::initData() { - bool hasData = (myStudyDoc != NULL); + bool hasData = (SalomeApp_Application::getStudy() != NULL); _PTR(AttributeStudyProperties) propAttr; if (hasData) - propAttr = myStudyDoc->GetProperties(); + propAttr = SalomeApp_Application::getStudy()->GetProperties(); hasData = hasData && propAttr; if (hasData) { @@ -268,7 +263,7 @@ void SalomeApp_StudyPropertiesDlg::initData() */ void SalomeApp_StudyPropertiesDlg::clickOnOk() { - _PTR(AttributeStudyProperties) propAttr = myStudyDoc->GetProperties(); + _PTR(AttributeStudyProperties) propAttr = SalomeApp_Application::getStudy()->GetProperties(); //Firstly, store locked flag if(propAttr) { bool bLocked = myLocked->isChecked(); diff --git a/src/SalomeApp/SalomeApp_StudyPropertiesDlg.h b/src/SalomeApp/SalomeApp_StudyPropertiesDlg.h index 7289eb800..a88d54edb 100644 --- a/src/SalomeApp/SalomeApp_StudyPropertiesDlg.h +++ b/src/SalomeApp/SalomeApp_StudyPropertiesDlg.h @@ -60,7 +60,6 @@ private: void initData(); private: - _PTR(Study) myStudyDoc; bool myIsChanged; QLineEdit* myAuthor; QLabel* myDate; diff --git a/src/SalomeApp/SalomeApp_TypeFilter.cxx b/src/SalomeApp/SalomeApp_TypeFilter.cxx index 8d296e815..d2652792b 100644 --- a/src/SalomeApp/SalomeApp_TypeFilter.cxx +++ b/src/SalomeApp/SalomeApp_TypeFilter.cxx @@ -24,6 +24,7 @@ #include "LightApp_DataOwner.h" #include "SalomeApp_Study.h" +#include "SalomeApp_Application.h" /*! Constructor. @@ -48,20 +49,18 @@ bool SalomeApp_TypeFilter::isOk( const SUIT_DataOwner* sOwner ) const { const LightApp_DataOwner* owner = dynamic_cast ( sOwner ); - SalomeApp_Study* aDoc = getStudy(); - if (owner && aDoc && aDoc->studyDS()) + if (owner) + { + QString entry = owner->entry(); + + _PTR(SObject) aSObj( SalomeApp_Application::getStudy()->FindObjectID( entry.toStdString() ) ); + if (aSObj) { - _PTR(Study) aStudy = aDoc->studyDS(); - QString entry = owner->entry(); - - _PTR(SObject) aSObj( aStudy->FindObjectID( entry.toStdString() ) ); - if (aSObj) - { - _PTR(SComponent) aComponent(aSObj->GetFatherComponent()); - if ( aComponent && (aComponent->ComponentDataType() == myKind.toStdString()) ) - return true; - } + _PTR(SComponent) aComponent(aSObj->GetFatherComponent()); + if ( aComponent && (aComponent->ComponentDataType() == myKind.toStdString()) ) + return true; } + } return false; } diff --git a/src/SalomeApp/pluginsdemo/minmax_plugin.py b/src/SalomeApp/pluginsdemo/minmax_plugin.py index 1b0719bb1..f1b30c06a 100644 --- a/src/SalomeApp/pluginsdemo/minmax_plugin.py +++ b/src/SalomeApp/pluginsdemo/minmax_plugin.py @@ -22,9 +22,8 @@ from qtsalome import * def minmax(context): - # get context study, studyId, salomeGui + # get context study, salomeGui study = context.study - studyId = context.studyId sg = context.sg from minmax_ui import Ui_Dialog @@ -32,7 +31,7 @@ def minmax(context): import salome import SMESH from salome.smesh import smeshBuilder - smesh = smeshBuilder.New(salome.myStudy) + smesh = smeshBuilder.New() controls_dict = { "Aspect Ratio 3D" : SMESH.FT_AspectRatio3D, diff --git a/src/SalomeApp/pluginsdemo/salome_plugins.py b/src/SalomeApp/pluginsdemo/salome_plugins.py index eaeb93cbb..451b944e4 100755 --- a/src/SalomeApp/pluginsdemo/salome_plugins.py +++ b/src/SalomeApp/pluginsdemo/salome_plugins.py @@ -28,11 +28,11 @@ if DEMO_IS_ACTIVATED: try: import GEOM from salome.geom import geomBuilder - geompy = geomBuilder.New(salome.myStudy) + geompy = geomBuilder.New() import SMESH, SALOMEDS from salome.smesh import smeshBuilder - smesh = smeshBuilder.New(salome.myStudy) + smesh = smeshBuilder.New() except: DEMO_IS_ACTIVATED = False @@ -48,8 +48,7 @@ if DEMO_IS_ACTIVATED: from salome.geom import geomBuilder # Intialize the geompy factory with the active study - activeStudy = context.study - geompy = geomBuilder.New(activeStudy) + geompy = geomBuilder.New() # Create the objects Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) @@ -76,8 +75,7 @@ if DEMO_IS_ACTIVATED: from salome.geom import geomBuilder # Intialize the geompy factory with the active study - activeStudy = context.study - geompy = geomBuilder.New(activeStudy) + geompy = geomBuilder.New() # Create the objects Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) @@ -122,7 +120,6 @@ if DEMO_IS_ACTIVATED: def tube_shapewithgui(context): global tubebuilder, xalome, dialog - activeStudy = context.study # Get the parameter values from a gui dialog box. If the dialog is # closed using the Ok button, then the data are requested from the @@ -130,8 +127,8 @@ if DEMO_IS_ACTIVATED: dialog.exec_() if dialog.wasOk(): radius, length, width = dialog.getData() - shape = tubebuilder.createGeometry(activeStudy, radius, length, width) - entry = xalome.addToStudy(activeStudy, shape, "Tube" ) + shape = tubebuilder.createGeometry(radius, length, width) + entry = xalome.addToStudy(shape, "Tube" ) xalome.displayShape(entry) @@ -147,7 +144,6 @@ if DEMO_IS_ACTIVATED: # def tube_meshwithgui(context): global tube, dialog - activeStudy = context.study # Get the parameter values from a gui dialog box. If the dialog is # closed using the Ok button, then the data are requested from the @@ -155,7 +151,7 @@ if DEMO_IS_ACTIVATED: dialog.exec_() if dialog.wasOk(): radius, length, width = dialog.getData() - mesh = tubebuilder.createModel(activeStudy, radius, length, width) + mesh = tubebuilder.createModel(radius, length, width) salome_pluginsmanager.AddFunction('DEMO/Tube mesh from parameters', @@ -179,7 +175,6 @@ if DEMO_IS_ACTIVATED: dialogWithApply.setData(tubebuilder.DEFAULT_RADIUS, tubebuilder.DEFAULT_LENGTH, tubebuilder.DEFAULT_WIDTH) - activeStudy = None previewShapeEntry = None DEFAULT_FOLDER_NAME="TubeList" @@ -189,7 +184,7 @@ if DEMO_IS_ACTIVATED: def acceptCallback(): """Action to be done when click on Ok""" global tubebuilder, xalome - global dialogWithApply, activeStudy + global dialogWithApply global previewShapeEntry, deletePreviewShape global DEFAULT_FOLDER_NAME,DEFAULT_SHAPE_NAME @@ -199,8 +194,8 @@ if DEMO_IS_ACTIVATED: deletePreviewShape() radius, length, width = dialogWithApply.getData() - shape = tubebuilder.createGeometry(activeStudy, radius, length, width) - entry = xalome.addToStudy(activeStudy, shape, DEFAULT_SHAPE_NAME, DEFAULT_FOLDER_NAME) + shape = tubebuilder.createGeometry(radius, length, width) + entry = xalome.addToStudy(shape, DEFAULT_SHAPE_NAME, DEFAULT_FOLDER_NAME) xalome.displayShape(entry) def rejectCallback(): @@ -218,7 +213,7 @@ if DEMO_IS_ACTIVATED: def applyCallback(): """Action to be done when click on Apply""" global tubebuilder, xalome - global dialogWithApply, activeStudy + global dialogWithApply global previewShapeEntry, deletePreviewShape global PREVIEW_COLOR, DEFAULT_SHAPE_NAME, DEFAULT_FOLDER_NAME, PREVIEW_SHAPE_NAME @@ -228,16 +223,16 @@ if DEMO_IS_ACTIVATED: # Then we can create the new shape with the new parameter values radius, length, width = dialogWithApply.getData() - shape = tubebuilder.createGeometry(activeStudy, radius, length, width) + shape = tubebuilder.createGeometry(radius, length, width) # We apply a specific color on the shape for the preview state shape.SetColor(PREVIEW_COLOR) - previewShapeEntry = xalome.addToStudy(activeStudy, shape, PREVIEW_SHAPE_NAME, DEFAULT_FOLDER_NAME ) + previewShapeEntry = xalome.addToStudy(shape, PREVIEW_SHAPE_NAME, DEFAULT_FOLDER_NAME ) xalome.displayShape(previewShapeEntry) def deletePreviewShape(): """This delete the shape currently being displayed as a preview""" - global activeStudy, previewShapeEntry, xsalome - xalome.deleteShape(activeStudy,previewShapeEntry) + global previewShapeEntry, xsalome + xalome.deleteShape(previewShapeEntry) previewShapeEntry = None # Connection of callback functions to the dialog butoon click signals @@ -251,8 +246,7 @@ if DEMO_IS_ACTIVATED: required callback functions to be associated to the button signals. """ - global dialogWithApply, activeStudy - activeStudy = context.study + global dialogWithApply dialogWithApply.open() diff --git a/src/SalomeApp/pluginsdemo/trihedron.py b/src/SalomeApp/pluginsdemo/trihedron.py index 3439d0830..95fd3d001 100644 --- a/src/SalomeApp/pluginsdemo/trihedron.py +++ b/src/SalomeApp/pluginsdemo/trihedron.py @@ -26,7 +26,7 @@ import salome import GEOM from salome.geom import geomBuilder -geompy = geomBuilder.New(salome.myStudy) +geompy = geomBuilder.New() # Create the objects Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) diff --git a/src/SalomeApp/pluginsdemo/tubebuilder.py b/src/SalomeApp/pluginsdemo/tubebuilder.py index cd231842e..44e7ec508 100644 --- a/src/SalomeApp/pluginsdemo/tubebuilder.py +++ b/src/SalomeApp/pluginsdemo/tubebuilder.py @@ -27,14 +27,13 @@ DEFAULT_WIDTH = 20 from salome.geom import geomtools -def createGeometry(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DEFAULT_WIDTH): +def createGeometry(radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DEFAULT_WIDTH): ''' This function creates the geometry on the specified study and with given parameters. ''' print("TUBE: creating the geometry ...") - studyId = study._get_StudyId() - geompy = geomtools.getGeompy(studyId) + geompy = geomtools.getGeompy() radius_ext = radius radius_int = radius_ext - width @@ -44,17 +43,16 @@ def createGeometry(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DE Tube = geompy.MakeCut(CylinderExt, CylinderInt) return Tube -def createGeometryWithPartition(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DEFAULT_WIDTH): +def createGeometryWithPartition(radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DEFAULT_WIDTH): ''' This function create the geometrical shape with a partition so that the hexaedric algorithm could be used for meshing. ''' - shape = createGeometry(study,radius,length,width) + shape = createGeometry(radius,length,width) # We have to create a partition so that we can use an hexaedric # meshing algorithm. - studyId = study._get_StudyId() - geompy = geomtools.getGeompy(studyId) + geompy = geomtools.getGeompy() print("TUBE: creating a partition ...") toolPlane = geompy.MakeFaceHW(2.1*length,2.1*radius,3) @@ -62,12 +60,12 @@ def createGeometryWithPartition(study, radius=DEFAULT_RADIUS, length=DEFAULT_LEN entry = geompy.addToStudy( partition, "TubeWithPartition" ) return partition -def createMesh(study, shape): - '''This function creates the mesh of the specified shape on the specified study''' +def createMesh(shape): + '''This function creates the mesh of the specified shape on the current study''' print("TUBE: creating the mesh ...") import SMESH from salome.smesh import smeshBuilder - smesh = smeshBuilder.New(study) + smesh = smeshBuilder.New() mesh = smesh.Mesh(shape) Regular_1D = mesh.Segment() @@ -84,21 +82,21 @@ def createMesh(study, shape): smesh.SetName(Nb_Segments, 'Nb. Segments_1') smesh.SetName(Quadrangle_2D.GetAlgorithm(), 'Quadrangle_2D') smesh.SetName(Hexa_3D.GetAlgorithm(), 'Hexa_3D') - salome.sg.updateObjBrowser(False) + salome.sg.updateObjBrowser() return mesh -def createModel(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH,width=DEFAULT_WIDTH): +def createModel(radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH,width=DEFAULT_WIDTH): ''' This function create the geomtrical shape AND the associated mesh. ''' # We first create a shape with a partition so that the hexaedric # algorithm could be used. - shape = createGeometryWithPartition(study,radius,length,width) + shape = createGeometryWithPartition(radius,length,width) # Then the mesh can be defined and computed - mesh = createMesh(study,shape) + mesh = createMesh(shape) def exportModel(mesh, filename): ''' @@ -116,25 +114,21 @@ def exportModel(mesh, filename): # def TEST_createGeometry(): salome.salome_init() - theStudy=salome.myStudy - createGeometry(theStudy) + createGeometry() def TEST_createMesh(): salome.salome_init() - theStudy=salome.myStudy - shape = createGeometryWithPartition(theStudy) - mesh = createMesh(theStudy, shape) + shape = createGeometryWithPartition() + mesh = createMesh(shape) def TEST_createModel(): salome.salome_init() - theStudy=salome.myStudy - createModel(theStudy) + createModel() def TEST_exportModel(): salome.salome_init() - theStudy=salome.myStudy - shape = createGeometryWithPartition(theStudy) - mesh = createMesh(theStudy, shape) + shape = createGeometryWithPartition() + mesh = createMesh(shape) exportModel(mesh,"tubemesh.med") if __name__ == "__main__": diff --git a/src/SalomeApp/pluginsdemo/xalome.py b/src/SalomeApp/pluginsdemo/xalome.py index a2f5343d7..c2d55be7d 100644 --- a/src/SalomeApp/pluginsdemo/xalome.py +++ b/src/SalomeApp/pluginsdemo/xalome.py @@ -36,7 +36,7 @@ from salome.geom import geomtools # Helper functions to add/remove a geometrical shape in/from the study # ====================================================================== -def addToStudy(study,shape,shapeName,folderName=None): +def addToStudy(shape,shapeName,folderName=None): """ Add a GEOM shape in the study. It returns the associated entry that corresponds to the identifier of the entry in the study. This @@ -45,8 +45,7 @@ def addToStudy(study,shape,shapeName,folderName=None): created in the Geometry part of the study, and the shape study object is stored in this folder of the study. """ - studyId = study._get_StudyId() - geompy = geomtools.getGeompy(studyId) + geompy = geomtools.getGeompy() if folderName is None: # Insert the shape in the study by the standard way @@ -55,7 +54,7 @@ def addToStudy(study,shape,shapeName,folderName=None): # A folder name has been specified to embed this shape. Find # or create a folder with this name in the Geometry study, and # then store the shape in this folder. - studyEditor = getStudyEditor(studyId) + studyEditor = getStudyEditor() geomStudyFolder = studyEditor.findOrCreateComponent("GEOM") shapeStudyFolder = studyEditor.findOrCreateItem(geomStudyFolder,folderName) @@ -71,17 +70,16 @@ def addToStudy(study,shape,shapeName,folderName=None): return entry -def removeFromStudy(study,shapeStudyEntry): +def removeFromStudy(shapeStudyEntry): """ This removes the specified entry from the study. Note that this operation does not destroy the underlying GEOM object, neither erase the drawing in the viewer. The underlying GEOM object is returned (so that it can be destroyed) """ - studyId = study._get_StudyId() shape = IDToObject(shapeStudyEntry) studyObject = IDToSObject(shapeStudyEntry) - studyEditor = getStudyEditor(studyId) + studyEditor = getStudyEditor() studyEditor.removeItem(studyObject,True) return shape @@ -126,7 +124,7 @@ def eraseShape_version65(shapeStudyEntry): # Helper functions for a complete suppression of a shape from the # SALOME session. # ====================================================================== -def deleteShape(study,shapeStudyEntry): +def deleteShape(shapeStudyEntry): """ This completly deletes a geom shape. @@ -138,7 +136,7 @@ def deleteShape(study,shapeStudyEntry): 3. destroy the underlying geom object """ eraseShape(shapeStudyEntry) - shape = removeFromStudy(study, shapeStudyEntry) + shape = removeFromStudy(shapeStudyEntry) if shape is not None: shape.Destroy() @@ -162,11 +160,10 @@ def TEST_createAndDeleteShape(): """ import salome salome.salome_init() - study = salome.myStudy - studyId = salome.myStudyId + study = salome.myStudy from salome.geom import geomtools - geompy = geomtools.getGeompy(studyId) + geompy = geomtools.getGeompy() # -------------------------------------------------- # Create a first shape (GEOM object) @@ -178,7 +175,7 @@ def TEST_createAndDeleteShape(): # folder. A name must be specified. The register operation # (addToStudy) returns an identifier of the entry in the study. cylinderName = "cyl.r%s.l%s"%(radius,length) - cylinderStudyEntry = addToStudy(study, cylinder, cylinderName) + cylinderStudyEntry = addToStudy(cylinder, cylinderName) # Display the registered shape in a viewer displayShape(cylinderStudyEntry) @@ -188,7 +185,7 @@ def TEST_createAndDeleteShape(): radius = 10 sphere = geompy.MakeSphereR(radius) sphereName = "sph.r%s"%radius - sphereStudyEntry = addToStudy(study, sphere, sphereName) + sphereStudyEntry = addToStudy(sphere, sphereName) displayShape(sphereStudyEntry) # -------------------------------------------------- @@ -199,7 +196,7 @@ def TEST_createAndDeleteShape(): box = geompy.MakeBoxDXDYDZ(length,length,length) boxName = "box.l%s"%length folderName = "boxset" - boxStudyEntry = addToStudy(study, box, boxName, folderName) + boxStudyEntry = addToStudy(box, boxName, folderName) displayShape(boxStudyEntry,PreviewColor) # -------------------------------------------------- @@ -214,7 +211,7 @@ def TEST_createAndDeleteShape(): # SALOME session (erase from viewer, remove from study and finnaly # destroy the object). This is done by a simple call to # deleteShape(). - deleteShape(study,cylinderStudyEntry) + deleteShape(cylinderStudyEntry) # -------------------------------------------------- # At the end of the executioon of this test, you should have in diff --git a/src/SalomeApp/resources/SalomeApp_msg_en.ts b/src/SalomeApp/resources/SalomeApp_msg_en.ts index 58fb8aced..d75e202a2 100644 --- a/src/SalomeApp/resources/SalomeApp_msg_en.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_en.ts @@ -7,10 +7,6 @@ WRN_FILE_NOT_EXIST The file %1 does not exist. - - ERR_ACTIVEDOC_LOAD - A study is already active in your session, but you are not connected to it. Use the Connect button to load it in the interface. - WRN_STUDY_LOCKED Study is locked. @@ -214,7 +210,7 @@ Launch a new session or close the study. QUE_DOC_ALREADYEXIST - The document %1 already exists in study manager. + The document %1 already exists. Do you want to reload it ? diff --git a/src/SalomeApp/resources/SalomeApp_msg_fr.ts b/src/SalomeApp/resources/SalomeApp_msg_fr.ts index 5709c9727..c50fe9355 100755 --- a/src/SalomeApp/resources/SalomeApp_msg_fr.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_fr.ts @@ -7,10 +7,6 @@ WRN_FILE_NOT_EXIST Le fichier %1 n'existe pas. - - ERR_ACTIVEDOC_LOAD - Une étude est déjà chargée dans votre session mais vous n'y êtes pas connectée. Utilisez le bouton "Connecter" pour charger l'étude dans l'interface. - WRN_STUDY_LOCKED L'étude est verrouillée @@ -214,7 +210,7 @@ Lancez une nouvelle session ou fermez l'étude en cours. QUE_DOC_ALREADYEXIST - Le document %1 existe déjà dans le gestionnaire d'études. + Le document %1 existe déjà. Voulez-vous le recharger ? diff --git a/src/SalomeApp/resources/SalomeApp_msg_ja.ts b/src/SalomeApp/resources/SalomeApp_msg_ja.ts index 1d9a98edb..7dab9b3a4 100644 --- a/src/SalomeApp/resources/SalomeApp_msg_ja.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_ja.ts @@ -7,11 +7,6 @@ WRN_FILE_NOT_EXIST ファイル %1 は存在しません。 - - ERR_ACTIVEDOC_LOAD - A study is already active in your session, but you are not connected to it. Use the Connect button to load it in the interface. -スタディはあなたのセッション内ですでにアクティブになっていますが、接続できません。インターフェイス内でそれをロードするための接続用ボタンを使用してください。 - WRN_STUDY_LOCKED スタディがロックされています @@ -215,7 +210,7 @@ QUE_DOC_ALREADYEXIST - ドキュメント %1 は研究のマネージャーに既に存在します。それを再読み込みしますか。 + ドキュメント %1 はの存在。それを再読み込みしますか。 MEN_RENAME_VS diff --git a/src/SalomeApp/salome_pluginsmanager.py b/src/SalomeApp/salome_pluginsmanager.py index 3b5f3d2fa..c6bc59f1e 100644 --- a/src/SalomeApp/salome_pluginsmanager.py +++ b/src/SalomeApp/salome_pluginsmanager.py @@ -77,7 +77,6 @@ In short to add a plugin: context attributes: - sg : the SALOME Swig interface - - studyId : the SALOME studyId that must be used to execute the plugin - study : the SALOME study object that must be used to execute the plugin """ @@ -118,8 +117,7 @@ def initialize(module,name,basemenuname,menuname): class Context: def __init__(self,sgpyqt): self.sg=sgpyqt - self.studyId=salome.sg.getActiveStudyId() - self.study= salome.myStudyManager.GetStudyByID(self.studyId) + self.study=salome.myStudy def find_menu(smenu): lmenus=smenu.split("|") @@ -242,12 +240,7 @@ class PluginsManager: def importPlugins(self): """Execute the salome_plugins file that contains plugins definition """ - studyId=sg.getActiveStudyId() - if studyId == 0: - self.menu.clear() - self.menu.menuAction().setVisible(False) - return - elif self.lasttime ==0 or salome.myStudy == None: + if self.lasttime ==0 or salome.myStudy == None: salome.salome_init(embedded=1) lasttime=0 diff --git a/src/Session/Session_ServerCheck.cxx b/src/Session/Session_ServerCheck.cxx index 1575acb72..3e3e062fe 100644 --- a/src/Session/Session_ServerCheck.cxx +++ b/src/Session/Session_ServerCheck.cxx @@ -354,12 +354,12 @@ void Session_ServerCheck::run() SALOME_NamingService &NS = *SINGLETON_::Instance(); ASSERT( SINGLETON_::IsAlreadyExisting() ); NS.init_orb( orb ); - CORBA::Object_var obj = NS.Resolve( "/myStudyManager" ); - SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow( obj ); - if ( !CORBA::is_nil( studyManager ) ) { - MESSAGE( "/myStudyManager is found" ); - studyManager->ping(); - MESSAGE( "StudyManager was activated" ); + CORBA::Object_var obj = NS.Resolve( "/Study" ); + SALOMEDS::Study_var study = SALOMEDS::Study::_narrow( obj ); + if ( !CORBA::is_nil( study ) ) { + MESSAGE( "/Study is found" ); + study->ping(); + MESSAGE( "Study was activated" ); setStep( ++current * myAttempts ); break; } diff --git a/src/Session/Session_ServerThread.cxx b/src/Session/Session_ServerThread.cxx index ee1c1f681..753cacaab 100755 --- a/src/Session/Session_ServerThread.cxx +++ b/src/Session/Session_ServerThread.cxx @@ -142,7 +142,7 @@ void Session_ServerThread::Init() } case 4: // Session { - NamingService_WaitForServerReadiness(_NS,"/myStudyManager"); + NamingService_WaitForServerReadiness(_NS,"/Study"); std::string containerName = "/Containers/"; containerName = containerName + Kernel_Utils::GetHostname(); containerName = containerName + "/FactoryServer"; @@ -215,7 +215,7 @@ void Session_ServerThread::ActivateSALOMEDS(int argc, // counted objects, they will be deleted by the POA when they are no // longer needed. - ClientFactory::createStudyManager(_orb,_root_poa); + ClientFactory::createStudy(_orb,_root_poa); } catch(CORBA::SystemException&) { INFOS( "Caught CORBA::SystemException." ); diff --git a/src/Session/Session_Session_i.cxx b/src/Session/Session_Session_i.cxx index 95103de9c..d82cefc87 100755 --- a/src/Session/Session_Session_i.cxx +++ b/src/Session/Session_Session_i.cxx @@ -65,7 +65,6 @@ SALOME_Session_i::SALOME_Session_i(int argc, _argc = argc ; _argv = argv ; _isGUI = false ; - _runningStudies= 0 ; _orb = CORBA::ORB::_duplicate(orb) ; _poa = PortableServer::POA::_duplicate(poa) ; _GUIMutex = GUIMutex; @@ -206,7 +205,7 @@ void SALOME_Session_i::Shutdown() /*! Send a SALOME::StatSession structure (see idl) to the client - (number of running studies and presence of GUI) + (presence of GUI) */ /*class QtLock { @@ -220,24 +219,23 @@ SALOME::StatSession SALOME_Session_i::GetStatSession() { // update Session state _GUIMutex->lock(); + int activeStudy = 0; - _runningStudies = 0; { //QtLock lock; _isGUI = SUIT_Session::session(); if ( _isGUI && SUIT_Session::session()->activeApplication() ) - _runningStudies = SUIT_Session::session()->activeApplication()->getNbStudies(); + activeStudy = SUIT_Session::session()->activeApplication()->getNbStudies(); } // getting stat info - SALOME::StatSession_var myStats = new SALOME::StatSession ; - if (_runningStudies) + SALOME::StatSession_var myStats = new SALOME::StatSession; + if (activeStudy) myStats->state = SALOME::running ; else if (_isShuttingDown) myStats->state = SALOME::shutdown ; else myStats->state = SALOME::asleep ; - myStats->runningStudies = _runningStudies ; myStats->activeGUI = _isGUI ; _GUIMutex->unlock(); @@ -245,16 +243,6 @@ SALOME::StatSession SALOME_Session_i::GetStatSession() return myStats._retn() ; } -CORBA::Long SALOME_Session_i::GetActiveStudyId() -{ - long aStudyId=-1; - if ( SUIT_Session::session() && SUIT_Session::session()->activeApplication() ) { - if ( SUIT_Session::session()->activeApplication()->activeStudy() ) // mkr : IPAL12128 - aStudyId = SUIT_Session::session()->activeApplication()->activeStudy()->id(); - } - return aStudyId; -} - CORBA::Long SALOME_Session_i::getPID() { return (CORBA::Long) #ifndef WIN32 diff --git a/src/Session/Session_Session_i.hxx b/src/Session/Session_Session_i.hxx index 5a83d5fdf..1fbcc4d42 100755 --- a/src/Session/Session_Session_i.hxx +++ b/src/Session/Session_Session_i.hxx @@ -68,8 +68,6 @@ public: //! Unregister the servant from Naming Service void NSunregister(); - CORBA::Long GetActiveStudyId(); - void ping(){}; CORBA::Long getPID(); char* getHostname(); @@ -94,7 +92,6 @@ protected: CORBA::Boolean _isGUI ; QMutex* _GUIMutex ; QWaitCondition* _GUILauncher; - int _runningStudies ; CORBA::ORB_var _orb; PortableServer::POA_var _poa; bool _isShuttingDown; diff --git a/src/TOOLSGUI/CMakeLists.txt b/src/TOOLSGUI/CMakeLists.txt index d391fc676..91bef71a8 100755 --- a/src/TOOLSGUI/CMakeLists.txt +++ b/src/TOOLSGUI/CMakeLists.txt @@ -44,8 +44,10 @@ SET(_link_LIBRARIES ${CAS_KERNEL} ${KERNEL_SalomeIDLKernel} ${KERNEL_SALOMELocalTrace} + ${KERNEL_SalomeDSClient} ${KERNEL_SalomeNS} ${KERNEL_OpUtil} + ${KERNEL_SalomeKernelHelpers} ${OMNIORB_LIBRARIES} qtx suit ) diff --git a/src/TOOLSGUI/ToolsGUI.cxx b/src/TOOLSGUI/ToolsGUI.cxx index aba358027..253389ad7 100755 --- a/src/TOOLSGUI/ToolsGUI.cxx +++ b/src/TOOLSGUI/ToolsGUI.cxx @@ -25,6 +25,8 @@ // Author : Nicolas REJNERI // #include "ToolsGUI.h" +#include +#include /*! \class ToolsGUI @@ -33,13 +35,11 @@ /*! \brief Get visibility value of the "AttributeGraphic" attribute. - \param theStudy study \param theObj object \param theId sub-object identifier \return \c true if an object (sub-object) is visible */ -bool ToolsGUI::GetVisibility( _PTR(Study) theStudy, - _PTR(SObject) theObj, +bool ToolsGUI::GetVisibility( _PTR(SObject) theObj, void* theId ) { _PTR(GenericAttribute) anAttr; @@ -54,17 +54,16 @@ bool ToolsGUI::GetVisibility( _PTR(Study) theStudy, /*! \brief Set visibility value of the "AttributeGraphic" attribute. - \param theStudy study \param theObj object \return theValue new visibility value \param theId sub-object identifier */ -bool ToolsGUI::SetVisibility( _PTR(Study) theStudy, - const char* theEntry, +bool ToolsGUI::SetVisibility( const char* theEntry, const bool theValue, void* theId ) { - _PTR(SObject) anObj ( theStudy->FindObjectID( theEntry ) ); + _PTR(Study) aStudy = ClientFactory::Study(KERNEL::getStudyServant()); + _PTR(SObject) anObj ( aStudy->FindObjectID( theEntry ) ); if ( anObj ) { @@ -76,7 +75,7 @@ bool ToolsGUI::SetVisibility( _PTR(Study) theStudy, } else if ( theValue ) { - _PTR(StudyBuilder) aBuilder (theStudy->NewBuilder()); + _PTR(StudyBuilder) aBuilder (aStudy->NewBuilder()); _PTR(AttributeGraphic) anAttr (aBuilder->FindOrCreateAttribute(anObj, "AttributeGraphic")); anAttr->SetVisibility( (unsigned long)theId, theValue ); } diff --git a/src/TOOLSGUI/ToolsGUI.h b/src/TOOLSGUI/ToolsGUI.h index 5a2190d7a..05ab64815 100755 --- a/src/TOOLSGUI/ToolsGUI.h +++ b/src/TOOLSGUI/ToolsGUI.h @@ -43,11 +43,9 @@ class TOOLSGUI_EXPORT ToolsGUI { public : - static bool GetVisibility( _PTR(Study) theStudy, - _PTR(SObject) theObj, + static bool GetVisibility( _PTR(SObject) theObj, void* theId ); - static bool SetVisibility( _PTR(Study) theStudy, - const char* theEntry, + static bool SetVisibility( const char* theEntry, const bool theValue, void* theId ); }; diff --git a/tools/PyEditor/src/CMakeLists.txt b/tools/PyEditor/src/CMakeLists.txt index 94f88dae6..53f50bbea 100644 --- a/tools/PyEditor/src/CMakeLists.txt +++ b/tools/PyEditor/src/CMakeLists.txt @@ -43,9 +43,13 @@ SET(_link_LIBRARIES ${PLATFORM_LIBS} ${QT_LIBRARIES}) # header files / to be processed by moc SET(_moc_HEADERS PyEditor_Editor.h + PyEditor_FindTool.h PyEditor_LineNumberArea.h + PyEditor_Keywords.h + PyEditor_Completer.h PyEditor_PyHighlighter.h PyEditor_SettingsDlg.h + PyEditor_Widget.h PyEditor_Window.h ) @@ -82,11 +86,15 @@ QT_ADD_RESOURCES(_rcc_SOURCES ${_rcc_RESOURCES}) # sources / static SET(_other_SOURCES PyEditor_Editor.cxx + PyEditor_FindTool.cxx PyEditor_LineNumberArea.cxx + PyEditor_Keywords.cxx + PyEditor_Completer.cxx PyEditor_PyHighlighter.cxx PyEditor_Settings.cxx PyEditor_SettingsDlg.cxx PyEditor_StdSettings.cxx + PyEditor_Widget.cxx PyEditor_Window.cxx ) diff --git a/tools/PyEditor/src/PyEditor.cxx b/tools/PyEditor/src/PyEditor.cxx index 03a29b8e9..5a213338d 100644 --- a/tools/PyEditor/src/PyEditor.cxx +++ b/tools/PyEditor/src/PyEditor.cxx @@ -24,6 +24,7 @@ #include "PyEditor_StdSettings.h" #include +#include #include #include #include @@ -67,11 +68,11 @@ int main( int argc, char *argv[] ) app.setOrganizationDomain( "www.salome-platform.org" ); app.setApplicationName( "pyeditor" ); + QLocale locale; + PyEditor_StdSettings* settings = new PyEditor_StdSettings(); PyEditor_Settings::setSettings( settings ); - QString language = settings->language(); - // Load Qt translations. QString qtDirTrSet = QLibraryInfo::location( QLibraryInfo::TranslationsPath ); QString qtDirTrEnv = qtTrDir(); @@ -85,7 +86,11 @@ int main( int argc, char *argv[] ) foreach( QString qtTrFile, qtTrFiles ) { foreach ( QString qtTrDir, qtTrDirs ) { QTranslator* translator = new QTranslator; - if ( translator->load( QString("%1_%2").arg( qtTrFile ).arg( language ), qtTrDir ) ) { + if ( translator->load( locale, QString("%1").arg( qtTrFile ), "_", qtTrDir ) ) { + app.installTranslator( translator ); + break; + } + else if ( translator->load( QString("%1_en").arg( qtTrFile ), qtTrDir ) ) { app.installTranslator( translator ); break; } @@ -97,13 +102,27 @@ int main( int argc, char *argv[] ) // Load application's translations. QTranslator translator; - if ( translator.load( QString( "PyEditor_msg_%1" ).arg( language ), resourceDir() ) ) + if ( translator.load( locale, QString( "PyEditor_msg" ), "_", resourceDir() ) ) app.installTranslator( &translator ); - + else if ( translator.load( QString( "PyEditor_msg_en" ), resourceDir() ) ) + app.installTranslator( &translator ); + + QCommandLineParser parser; + parser.setApplicationDescription( QApplication::translate( "PyEditor", "PROGRAM_DESCRIPTION" ) ); + parser.addHelpOption(); + parser.addPositionalArgument( QApplication::translate( "PyEditor", "FILE_PARAM_NAME" ), + QApplication::translate( "PyEditor", "FILE_PARAM_DESCRIPTION" ) ); + + parser.process( app ); + const QStringList args = parser.positionalArguments(); + PyEditor_Window window; window.setWindowIcon( QIcon( ":/images/py_editor.png" ) ); window.resize( 650, 700 ); window.show(); + + if ( args.count() > 0 ) + window.loadFile( args[0], false ); return app.exec(); } diff --git a/tools/PyEditor/src/PyEditor_Completer.cxx b/tools/PyEditor/src/PyEditor_Completer.cxx new file mode 100644 index 000000000..bee9d992e --- /dev/null +++ b/tools/PyEditor/src/PyEditor_Completer.cxx @@ -0,0 +1,264 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_Completer.cxx +// Author : Sergey TELKOV, Open CASCADE S.A.S. (sergey.telkov@opencascade.com) +// + +#include "PyEditor_Completer.h" + +#include "PyEditor_Editor.h" +#include "PyEditor_Keywords.h" + +#include +#include +#include +#include +#include +#include +#include + +/*! + \brief Constructor. +*/ +PyEditor_Completer::PyEditor_Completer( PyEditor_Editor* editor, + PyEditor_Keywords* std, PyEditor_Keywords* user ) + : QCompleter( editor ), + myEditor( editor ), + myTimer( 0 ), + myStdKeywords( std ), + myUserKeywords( user ) +{ + setWidget( editor ); + setCompletionMode(QCompleter::PopupCompletion); + + connect(this, SIGNAL( activated( const QString& ) ), + this, SLOT( onActivated( const QString& ) ) ); + connect(editor, SIGNAL( textChanged() ), this, SLOT( onTextChanged() ) ); + connect(myStdKeywords, SIGNAL( keywordsChanged() ), + this, SLOT( onKeywordsChanged() ) ); + connect(myUserKeywords, SIGNAL( keywordsChanged() ), + this, SLOT( onKeywordsChanged() ) ); + + updateKeywords(); +} + +/*! + \brief Destructor. +*/ +PyEditor_Completer::~PyEditor_Completer() +{ +} + +/*! + \brief Perform the completion if it possible. +*/ +void PyEditor_Completer::perform() +{ + QString prefix = completionText(); + setCompletionPrefix( prefix ); + + if ( !completionPrefix().isEmpty() && + ( completionCount() > 1 || ( completionCount() == 1 && + currentCompletion() != completionPrefix() ) ) ) + complete(completionRect()); + else + uncomplete(); +} + +/*! + \brief Hide the completer's popup menu. +*/ +void PyEditor_Completer::uncomplete() +{ + if ( popup() ) + popup()->hide(); +} + +/*! + \brief Handling 'Enter' key. +*/ +bool PyEditor_Completer::eventFilter(QObject* o, QEvent* e) +{ + bool res = false; + if ( e->type() == QEvent::KeyPress && popup()->isVisible() ) { + QKeyEvent* ke = (QKeyEvent*)e; + if ( ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return ) { + res = true; + setCurrentRow(popup()->currentIndex().row()); + onActivated(currentCompletion()); + } + } + + if ( !res ) + res = QCompleter::eventFilter(o, e); + + return res; +} + +/*! + \brief Perform delayed completion. +*/ +void PyEditor_Completer::onTimeout() +{ + perform(); +} + +/*! + \brief Invoked when text changed in editor. +*/ +void PyEditor_Completer::onTextChanged() +{ + uncomplete(); + if ( myEditor->completionPolicy() == PyEditor_Editor::Auto || + myEditor->completionPolicy() == PyEditor_Editor::Always ) + triggerComplete(); +} + +/*! + \brief Invoked when keywords changed in editor. +*/ +void PyEditor_Completer::onKeywordsChanged() +{ + updateKeywords(); +} + +/*! + \brief Insert selected completion into editor. +*/ +void PyEditor_Completer::onActivated( const QString& text) +{ + QPoint rng = completionRange(); + QTextCursor cursor = myEditor->textCursor(); + cursor.setPosition(cursor.position() - rng.y() + rng.x() - 1, + QTextCursor::KeepAnchor); + cursor.insertText(text); + uncomplete(); +} + +/*! + \brief Get the rectangle for completion popup. + \return completion popup rect +*/ +QRect PyEditor_Completer::completionRect() const +{ + QRect res = myEditor->cursorRect(myEditor->textCursor()); + res.setWidth(popup()->sizeHint().width()); + res.translate(myEditor->document()->documentMargin(), + myEditor->document()->documentMargin()); + return res; +} + +/*! + \brief Get the current completion prefix from editor. + \return completion prefix string +*/ +QString PyEditor_Completer::completionText() const +{ + QString prefix; + if ( myEditor ) { + QString txt = myEditor->textCursor().block().text(); + if ( !txt.isEmpty() ) { + QPoint range = completionRange(); + prefix = txt.mid( range.x(), range.y() - range.x() + 1 ); + } + } + return prefix; +} + +/*! + \brief Get position of completion prefix in editor. + \return begin and end of completion prefix +*/ +QPoint PyEditor_Completer::completionRange() const +{ + QPoint range; + + if ( myEditor ) { + QTextCursor cursor = myEditor->textCursor(); + QString txt = cursor.block().text(); + int beg = 0; + int end = cursor.positionInBlock() - 1; + + QRegExp rx("[A-Za-z]{1}\\w*$"); + int pos = rx.indexIn(txt.mid(beg, end - beg + 1)); + + if ( pos >= 0 ) + beg = pos; + + range = QPoint(beg, end); + } + + return range; +} + +/*! + \brief Schedule the delayed completion. +*/ +void PyEditor_Completer::triggerComplete() +{ + if ( !myTimer ) { + myTimer = new QTimer( this ); + myTimer->setSingleShot( true ); + myTimer->setInterval( 200 ); + + connect( myTimer, SIGNAL( timeout() ), this, SLOT( onTimeout() ) ); + } + + if ( myTimer->isActive() ) + myTimer->stop(); + myTimer->start(); +} + +/*! + \brief Updates the keywords list in completer. +*/ +void PyEditor_Completer::updateKeywords() +{ + QStandardItemModel* model = new QStandardItemModel( this ); + KeywordMap kwMap = keywords(); + for ( KeywordMap::const_iterator it = kwMap.begin(); it != kwMap.end(); ++it ) { + QStandardItem* item = new QStandardItem( it.key() ); + if ( it.value().isValid() ) + item->setForeground( it.value() ); + model->appendRow( item ); + } + setModel( model ); +} + +/*! + \brief Gets the keywords list. + \return keyword string list +*/ +PyEditor_Completer::KeywordMap PyEditor_Completer::keywords() const +{ + KeywordMap res; + QList kwDicts; + kwDicts << myStdKeywords << myUserKeywords; + + for ( QList::iterator itr = kwDicts.begin(); itr != kwDicts.end(); ++itr ) { + PyEditor_Keywords* dict = *itr; + QStringList kwList = dict->keywords(); + for ( QStringList::const_iterator it = kwList.begin(); it != kwList.end(); ++it ) { + if ( !res.contains( *it ) ) { + res.insert( *it, dict->color( *it ) ); + } + } + } + return res; +} diff --git a/tools/PyEditor/src/PyEditor_Completer.h b/tools/PyEditor/src/PyEditor_Completer.h new file mode 100644 index 000000000..01e0f4efc --- /dev/null +++ b/tools/PyEditor/src/PyEditor_Completer.h @@ -0,0 +1,73 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_Completer.h +// Author : Sergey TELKOV, Open CASCADE S.A.S. (sergey.telkov@opencascade.com) +// + +#ifndef PYEDITOR_COMPLETER_H +#define PYEDITOR_COMPLETER_H + +#include + +class QTimer; +class PyEditor_Editor; +class PyEditor_Keywords; + +class PyEditor_Completer : public QCompleter +{ + Q_OBJECT + +public: + PyEditor_Completer( PyEditor_Editor*, + PyEditor_Keywords*, PyEditor_Keywords* ); + virtual ~PyEditor_Completer(); + + void perform(); + + void uncomplete(); + + virtual bool eventFilter(QObject*, QEvent*); + +private Q_SLOTS: + void onTimeout(); + void onTextChanged(); + void onKeywordsChanged(); + void onActivated( const QString& ); + +protected: + QRect completionRect() const; + QString completionText() const; + QPoint completionRange() const; + +private: + typedef QMap KeywordMap; + +private: + KeywordMap keywords() const; + void updateKeywords(); + void triggerComplete(); + +private: + PyEditor_Editor* myEditor; + QTimer* myTimer; + PyEditor_Keywords* myStdKeywords; + PyEditor_Keywords* myUserKeywords; +}; + +#endif diff --git a/tools/PyEditor/src/PyEditor_Editor.cxx b/tools/PyEditor/src/PyEditor_Editor.cxx index fff2e0425..6fe34f196 100644 --- a/tools/PyEditor/src/PyEditor_Editor.cxx +++ b/tools/PyEditor/src/PyEditor_Editor.cxx @@ -23,11 +23,15 @@ #include "PyEditor_Editor.h" #include "PyEditor_LineNumberArea.h" #include "PyEditor_PyHighlighter.h" +#include "PyEditor_Completer.h" #include "PyEditor_Settings.h" +#include "PyEditor_Keywords.h" #include #include +#include + /*! \class PyEditor_Editor \brief Widget to show / edit Python scripts. @@ -38,20 +42,28 @@ \param parent parent widget */ PyEditor_Editor::PyEditor_Editor( QWidget* parent ) - : QPlainTextEdit( parent ) + : QPlainTextEdit( parent ), + myCompletionPolicy( Always ) { + myStdKeywords = new PyEditor_StandardKeywords( this ); + myUserKeywords = new PyEditor_Keywords( this ); + myUserKeywords->append( "print", 0, Qt::red ); + // Set up line number area myLineNumberArea = new PyEditor_LineNumberArea( this ); myLineNumberArea->setMouseTracking( true ); // Set up syntax highighter - mySyntaxHighlighter = new PyEditor_PyHighlighter( this->document() ); + mySyntaxHighlighter = new PyEditor_PyHighlighter( this->document(), + myStdKeywords, myUserKeywords ); // Set-up settings PyEditor_Settings* settings = PyEditor_Settings::settings(); if ( settings ) setSettings( *settings ); + myCompleter = new PyEditor_Completer( this, myStdKeywords, myUserKeywords ); + // Connect signals connect( this, SIGNAL( blockCountChanged( int ) ), this, SLOT( updateLineNumberAreaWidth( int ) ) ); connect( this, SIGNAL( updateRequest( QRect, int ) ), this, SLOT( updateLineNumberArea( QRect, int ) ) ); @@ -98,6 +110,9 @@ void PyEditor_Editor::setSettings( const PyEditor_Settings& settings ) // Set size white spaces setTabStopWidth( mySettings.tabSize() * 10 ); + // Set completion policy + setCompletionPolicy( (CompletionPolicy)mySettings.completionPolicy() ); + // Update current line highlight updateHighlightCurrentLine(); @@ -108,6 +123,54 @@ void PyEditor_Editor::setSettings( const PyEditor_Settings& settings ) viewport()->update(); } +/*! + \brief Gets the current completion policy + \return completion policy +*/ +PyEditor_Editor::CompletionPolicy PyEditor_Editor::completionPolicy() const +{ + return myCompletionPolicy; +} + +/*! + \brief Sets the current completion policy + \param policy completion policy +*/ +void PyEditor_Editor::setCompletionPolicy( const CompletionPolicy& policy ) +{ + myCompletionPolicy = policy; +} + +/*! + \brief Gets the all user keywords. + \param event key press event + \return keyword string list +*/ +QStringList PyEditor_Editor::keywords() const +{ + return myUserKeywords->keywords(); +} + +/*! + \brief Add the user keywords. + \param kws keywords string list + \param type keywords type + \param color keywords color +*/ +void PyEditor_Editor::appendKeywords( const QStringList& kws, int type, const QColor& color ) +{ + myUserKeywords->append( kws, type, color ); +} + +/*! + \brief Remove the user keywords. + \param kws keywords string list +*/ +void PyEditor_Editor::removeKeywords( const QStringList& kws ) +{ + myUserKeywords->remove( kws ); +} + /*! Delete current selection contents. */ @@ -151,6 +214,12 @@ void PyEditor_Editor::keyPressEvent( QKeyEvent* event ) aCursor.endEditBlock(); event->accept(); } + else if ( aKey == Qt::Key_Space && aCtrl && !aShift && + ( completionPolicy() == Manual || completionPolicy() == Always ) ) + { + myCompleter->perform(); + event->accept(); + } else if ( event == QKeySequence::MoveToStartOfLine || event == QKeySequence::SelectStartOfLine ) { QTextCursor aCursor = this->textCursor(); @@ -824,3 +893,21 @@ QString PyEditor_Editor::text() const { return toPlainText(); } + +/*! + \brief Get user keywords dictionary. + \return keywords dictionary +*/ +PyEditor_Keywords* PyEditor_Editor::userKeywords() const +{ + return myUserKeywords; +} + +/*! + \brief Get standard keywords dictionary. + \return keywords dictionary +*/ +PyEditor_Keywords* PyEditor_Editor::standardKeywords() const +{ + return myStdKeywords; +} diff --git a/tools/PyEditor/src/PyEditor_Editor.h b/tools/PyEditor/src/PyEditor_Editor.h index 026635673..d37c1a860 100644 --- a/tools/PyEditor/src/PyEditor_Editor.h +++ b/tools/PyEditor/src/PyEditor_Editor.h @@ -28,20 +28,32 @@ #include +class PyEditor_Keywords; +class PyEditor_Completer; class PyEditor_PyHighlighter; class PYEDITOR_EXPORT PyEditor_Editor : public QPlainTextEdit { Q_OBJECT +public: + typedef enum { None, Auto, Manual, Always } CompletionPolicy; + public: PyEditor_Editor( QWidget* = 0 ); virtual ~PyEditor_Editor(); - void setSettings( const PyEditor_Settings& ); + void setSettings( const PyEditor_Settings& ); const PyEditor_Settings& settings() const; QString text() const; + QStringList keywords() const; + void appendKeywords( const QStringList&, int, const QColor& = QColor() ); + void removeKeywords( const QStringList& ); + + CompletionPolicy completionPolicy() const; + void setCompletionPolicy( const CompletionPolicy& ); + public Q_SLOTS: void deleteSelected(); void append( const QString& ); @@ -51,7 +63,10 @@ protected: virtual void keyPressEvent( QKeyEvent* ); virtual void resizeEvent( QResizeEvent* ); virtual void paintEvent( QPaintEvent* ); - + + PyEditor_Keywords* userKeywords() const; + PyEditor_Keywords* standardKeywords() const; + private Q_SLOTS: void updateHighlightCurrentLine(); void matchParentheses(); @@ -72,13 +87,19 @@ private: int lineIndent(); void tabIndentation( bool ); void indentSelection( bool ); - + int findFirstNonSpace( const QString& ); - + QWidget* myLineNumberArea; PyEditor_PyHighlighter* mySyntaxHighlighter; + PyEditor_Completer* myCompleter; PyEditor_Settings mySettings; + PyEditor_Keywords* myStdKeywords; + PyEditor_Keywords* myUserKeywords; + + CompletionPolicy myCompletionPolicy; + friend class PyEditor_LineNumberArea; }; diff --git a/tools/PyEditor/src/PyEditor_FindTool.cxx b/tools/PyEditor/src/PyEditor_FindTool.cxx new file mode 100644 index 000000000..b91000ab1 --- /dev/null +++ b/tools/PyEditor/src/PyEditor_FindTool.cxx @@ -0,0 +1,612 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_FindTool.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +#include "PyEditor_FindTool.h" +#include "PyEditor_Editor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*! + \class PyEditor_FindTool + \brief Find / Replace widget for PyEditor +*/ + +/*! + \brief Constructor. + \param editor Python editor widget. + \param parent Parent widget. +*/ +PyEditor_FindTool::PyEditor_FindTool( PyEditor_Editor* editor, QWidget* parent ) + : QWidget( parent ), myEditor( editor ) +{ + QLabel* findLabel = new QLabel( tr( "FIND_LABEL" ), this ); + myFindEdit = new QLineEdit( this ); + myFindEdit->setClearButtonEnabled( true ); + myFindEdit->installEventFilter( this ); + connect( myFindEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( find( const QString& ) ) ); + connect( myFindEdit, SIGNAL( returnPressed() ), this, SLOT( findNext() ) ); + myFindEdit->setCompleter( new QCompleter( myFindEdit ) ); + myFindEdit->completer()->setModel( &myFindCompletion ); + + QLabel* replaceLabel = new QLabel( tr( "REPLACE_LABEL" ), this ); + myReplaceEdit = new QLineEdit( this ); + myReplaceEdit->setClearButtonEnabled( true ); + myReplaceEdit->installEventFilter( this ); + myReplaceEdit->setCompleter( new QCompleter( myReplaceEdit ) ); + myReplaceEdit->completer()->setModel( &myReplaceCompletion ); + + myInfoLabel = new QLabel( this ); + myInfoLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); + + QToolButton* prevBtn = new QToolButton( this ); + prevBtn->setIcon( QIcon( ":images/py_find_previous.png" ) ); + prevBtn->setAutoRaise( true ); + connect( prevBtn, SIGNAL( clicked() ), this, SLOT( findPrevious() ) ); + + QToolButton* nextBtn = new QToolButton( this ); + nextBtn->setIcon( QIcon( ":images/py_find_next.png" ) ); + nextBtn->setAutoRaise( true ); + connect( nextBtn, SIGNAL( clicked() ), this, SLOT( findNext() ) ); + + QToolButton* replaceBtn = new QToolButton(); + replaceBtn->setText( tr( "REPLACE_BTN" ) ); + replaceBtn->setAutoRaise( true ); + connect( replaceBtn, SIGNAL( clicked() ), this, SLOT( replace() ) ); + + QToolButton* replaceAllBtn = new QToolButton(); + replaceAllBtn->setText( tr( "REPLACE_ALL_BTN" ) ); + replaceAllBtn->setAutoRaise( true ); + connect( replaceAllBtn, SIGNAL( clicked() ), this, SLOT( replaceAll() ) ); + + QHBoxLayout* hl = new QHBoxLayout; + hl->setContentsMargins( 0, 0, 0, 0 ); + hl->setSpacing( 0 ); + hl->addWidget( prevBtn ); + hl->addWidget( nextBtn ); + + QGridLayout* l = new QGridLayout( this ); + l->setContentsMargins( 6, 2, 6, 2 ); + l->setSpacing( 2 ); + l->addWidget( findLabel, 0, 0 ); + l->addWidget( myFindEdit, 0, 1 ); + l->addLayout( hl, 0, 2 ); + l->addWidget( myInfoLabel, 0, 3 ); + l->addWidget( replaceLabel, 1, 0 ); + l->addWidget( myReplaceEdit, 1, 1 ); + l->addWidget( replaceBtn, 1, 2 ); + l->addWidget( replaceAllBtn, 1, 3 ); + + QAction* menuAction = myFindEdit->addAction( QIcon(":images/py_search.png"), QLineEdit::LeadingPosition ); + connect( menuAction, SIGNAL( triggered( bool ) ), this, SLOT( showMenu() ) ); + + addAction( new QAction( tr( "CASE_SENSITIVE_CHECK" ), this ) ); + addAction( new QAction( tr( "WHOLE_WORDS_CHECK" ), this ) ); + addAction( new QAction( tr( "REGEX_CHECK" ), this ) ); + addAction( new QAction( tr( "Find" ), this ) ); + addAction( new QAction( tr( "FindPrevious" ), this ) ); + addAction( new QAction( tr( "FindNext" ), this ) ); + addAction( new QAction( tr( "Replace" ), this ) ); + + foreach ( QAction* action, actions().mid( CaseSensitive, RegExp+1 ) ) + { + action->setCheckable( true ); + connect( action, SIGNAL( toggled( bool ) ), this, SLOT( update() ) ); + } + + QSignalMapper* mapper = new QSignalMapper( this ); + connect( mapper, SIGNAL( mapped( int ) ), this, SLOT( activate( int ) ) ); + + for ( int i = Find; i < actions().count(); i++ ) + { + QAction* action = actions()[i]; + action->setShortcuts( shortcuts( i ) ); + action->setShortcutContext( Qt::WidgetWithChildrenShortcut ); + connect( action, SIGNAL( triggered( bool ) ), mapper, SLOT( map() ) ); + mapper->setMapping( action, i ); + myEditor->addAction( action ); + } + + myEditor->installEventFilter( this ); + + hide(); +} + +/*! + \brief Process events for this widget, + \param e Event being processed. + \return true if event's processing should be stopped; false otherwise. +*/ +bool PyEditor_FindTool::event( QEvent* e ) +{ + if ( e->type() == QEvent::EnabledChange ) + { + updateShortcuts(); + } + else if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent* ke = (QKeyEvent*)e; + switch ( ke->key() ) + { + case Qt::Key_Escape: + hide(); + return true; + default: + break; + } + } + else if ( e->type() == QEvent::Hide ) + { + addCompletion( myFindEdit->text(), false ); + addCompletion( myReplaceEdit->text(), true ); + myEditor->setFocus(); + } + return QWidget::event( e ); +} + +/*! + \brief Filter events from watched objects. + \param o Object being watched. + \param e Event being processed. + \return true if event should be filtered out; false otherwise. +*/ +bool PyEditor_FindTool::eventFilter( QObject* o, QEvent* e ) +{ + if ( o == myFindEdit ) + { + if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent* keyEvent = (QKeyEvent*)e; + if ( keyEvent->key() == Qt::Key_Escape && !myFindEdit->text().isEmpty() ) + { + addCompletion( myFindEdit->text(), false ); + myFindEdit->clear(); + return true; + } + } + } + else if ( o == myReplaceEdit ) + { + if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent* keyEvent = (QKeyEvent*)e; + if ( keyEvent->key() == Qt::Key_Escape && !myReplaceEdit->text().isEmpty() ) + { + myReplaceEdit->clear(); + return true; + } + } + } + else if ( o == myEditor ) + { + if ( e->type() == QEvent::EnabledChange ) + { + setEnabled( myEditor->isEnabled() ); + } + else if ( e->type() == QEvent::Hide ) + { + hide(); + } + else if ( e->type() == QEvent::KeyPress ) + { + QKeyEvent* ke = (QKeyEvent*)e; + switch ( ke->key() ) + { + case Qt::Key_Escape: + if ( isVisible() ) + hide(); + break; + default: + break; + } + } + } + return QWidget::eventFilter( o, e ); +} + +/*! + \brief Slot: activate 'Find' dialog. +*/ +void PyEditor_FindTool::activateFind() +{ + activate( Find ); +} + +/*! + \brief Slot: activate 'Replace' dialog. +*/ +void PyEditor_FindTool::activateReplace() +{ + activate( Replace ); +} + +/*! + \brief Slot: show context menu with search options. + \internal +*/ +void PyEditor_FindTool::showMenu() +{ + QMenu::exec( actions().mid( CaseSensitive, RegExp+1 ), QCursor::pos() ); +} + +/*! + \brief Slot: find text being typed in the 'Find' control. + \param text Text entered by the user. + \internal +*/ +void PyEditor_FindTool::find( const QString& text ) +{ + find( text, 0 ); +} + +/*! + \brief Slot: find text entered in the 'Find' control. + \internal + \overload +*/ +void PyEditor_FindTool::find() +{ + find( myFindEdit->text(), 0 ); +} + +/*! + \brief Slot: find previous matched item; called when user presses 'Previous' button. + \internal +*/ +void PyEditor_FindTool::findPrevious() +{ + find( myFindEdit->text(), -1 ); +} + +/*! + \brief Slot: find next matched item; called when user presses 'Next' button. + \internal +*/ +void PyEditor_FindTool::findNext() +{ + find( myFindEdit->text(), 1 ); +} + +/*! + \brief Slot: replace currently selected match; called when user presses 'Replace' button. + \internal +*/ +void PyEditor_FindTool::replace() +{ + QString text = myFindEdit->text(); + QString replacement = myReplaceEdit->text(); + + QTextCursor editor = myEditor->textCursor(); + if ( editor.hasSelection() && editor.selectedText() == text ) + { + editor.beginEditBlock(); + editor.removeSelectedText(); + editor.insertText( replacement ); + editor.endEditBlock(); + find(); + } +} + +/*! + \brief Slot: replace all matches; called when user presses 'Replace All' button. + \internal +*/ +void PyEditor_FindTool::replaceAll() +{ + QString text = myFindEdit->text(); + QString replacement = myReplaceEdit->text(); + QList results = matches( text ); + if ( !results.isEmpty() ) + { + QTextCursor editor( myEditor->document() ); + editor.beginEditBlock(); + foreach ( QTextCursor cursor, results ) + { + editor.setPosition( cursor.anchor() ); + editor.setPosition( cursor.position(), QTextCursor::KeepAnchor ); + editor.removeSelectedText(); + editor.insertText( replacement ); + } + editor.endEditBlock(); + find(); + } +} + +/*! + \brief Slot: restart search; called when search options are changed. + \internal +*/ +void PyEditor_FindTool::update() +{ + find(); +} + +/*! + \brief Slot: activate action; called when user types corresponding shortcut. + \param action Action being activated. + \internal +*/ +void PyEditor_FindTool::activate( int action ) +{ + QTextCursor cursor = myEditor->textCursor(); + cursor.movePosition( QTextCursor::StartOfWord ); + cursor.movePosition( QTextCursor::EndOfWord, QTextCursor::KeepAnchor ); + QString word = cursor.selectedText(); + + switch ( action ) + { + case Find: + case Replace: + showReplaceControls( action == Replace ); + show(); + if ( !word.isEmpty() ) { + myFindEdit->setText( word ); + myEditor->setTextCursor( cursor ); + } + myFindEdit->setFocus(); + myFindEdit->selectAll(); + find( myFindEdit->text() ); + break; + case FindPrevious: + findPrevious(); + break; + case FindNext: + findNext(); + break; + default: + break; + } +} + +/*! + \brief Get shortcuts for given action. + \param action Editor's action. + \return List of shortcuts. + \internal +*/ +QList PyEditor_FindTool::shortcuts( int action ) const +{ + QList bindings; + switch ( action ) + { + case Find: + bindings << QKeySequence( QKeySequence::Find ); + break; + case FindPrevious: + bindings << QKeySequence( QKeySequence::FindPrevious ); + break; + case FindNext: + bindings << QKeySequence( QKeySequence::FindNext ); + break; + case Replace: + bindings << QKeySequence( QKeySequence::Replace ); + bindings << QKeySequence( "Ctrl+H" ); + break; + default: + break; + } + return bindings; +} + +/*! + \brief Update shortcuts when widget is enabled / disabled. + \internal +*/ +void PyEditor_FindTool::updateShortcuts() +{ + foreach ( QAction* action, actions().mid( Find ) ) + { + action->setEnabled( isEnabled() && myEditor->isEnabled() ); + } +} + +/*! + \brief Show / hide 'Replace' controls. + \param on Visibility flag. + \internal +*/ +void PyEditor_FindTool::showReplaceControls( bool on ) +{ + QGridLayout* l = qobject_cast( layout() ); + for ( int j = 0; j < l->columnCount(); j++ ) + { + if ( l->itemAtPosition( 1, j )->widget() ) + l->itemAtPosition( 1, j )->widget()->setVisible( on ); + } +} + +/*! + \brief Set palette for 'Find' tool depending on results of search. + \param found Search result: true in case of success; false otherwise. + \internal +*/ +void PyEditor_FindTool::setSearchResult( bool found ) +{ + QPalette pal = myFindEdit->palette(); + QPalette ref = myReplaceEdit->palette(); + pal.setColor( QPalette::Active, QPalette::Text, + found ? ref.color( QPalette::Active, QPalette::Text ) : QColor( 255, 0, 0 ) ); + myFindEdit->setPalette( pal ); +} + +/*! + \brief Get 'Use regular expression' search option. + \return true if option is switched on; false otherwise. + \internal +*/ +bool PyEditor_FindTool::isRegExp() const +{ + return actions()[RegExp]->isChecked(); +} + +/*! + \brief Get 'Case sensitive search' search option. + \return true if option is switched on; false otherwise. + \internal +*/ +bool PyEditor_FindTool::isCaseSensitive() const +{ + return actions()[CaseSensitive]->isChecked(); +} + +/*! + \brief Get 'Whole words only' search option. + \return true if option is switched on; false otherwise. + \internal +*/ +bool PyEditor_FindTool::isWholeWord() const +{ + return actions()[WholeWord]->isChecked(); +} + +/*! + \brief Get search options. + \param back Search direction: backward if false; forward otherwise. + \return List of options + \internal +*/ +QTextDocument::FindFlags PyEditor_FindTool::searchFlags( bool back ) const +{ + QTextDocument::FindFlags flags = 0; + if ( isCaseSensitive() ) + flags |= QTextDocument::FindCaseSensitively; + if ( isWholeWord() ) + flags |= QTextDocument::FindWholeWords; + if ( back ) + flags |= QTextDocument::FindBackward; + return flags; +} + +/*! + \brief Get all matches from Python editor. + \param text Text being searched. + \return List of all matches. + \internal +*/ +QList PyEditor_FindTool::matches( const QString& text ) const +{ + QList results; + + QTextDocument* document = myEditor->document(); + + QTextCursor cursor( document ); + while ( !cursor.isNull() ) + { + cursor = isRegExp() ? + document->find( QRegExp( text, isCaseSensitive() ? + Qt::CaseSensitive : Qt::CaseInsensitive ), + cursor, searchFlags() ) : + document->find( text, cursor, searchFlags() ); + if ( !cursor.isNull() ) + results.append( cursor ); + } + return results; +} + +/*! + \brief Find specified text. + \param text Text being searched. + \param delta Search direction. + \internal +*/ +void PyEditor_FindTool::find( const QString& text, int delta ) +{ + QTextCursor cursor = myEditor->textCursor(); + int position = qMin( cursor.position(), cursor.anchor() ) + delta; + cursor.setPosition( position ); + myEditor->setTextCursor( cursor ); + + QList results = matches( text ); + + int index = -1; + if ( !results.isEmpty() ) + { + if ( delta >= 0 ) + { + // search forward + if ( position > results.last().anchor() ) + position = 0; + for ( int i = 0; i < results.count() && index == -1; i++ ) + { + QTextCursor result = results[i]; + if ( result.hasSelection() && position <= result.anchor() ) + { + index = i; + } + } + } + else + { + // search backward + if ( position < results.first().position() ) + position = results.last().position(); + + for ( int i = results.count()-1; i >= 0 && index == -1; i-- ) + { + QTextCursor result = results[i]; + if ( result.hasSelection() && position >= result.position() ) + { + index = i; + } + } + } + } + if ( index != -1 ) + { + myInfoLabel->setText( tr( "NB_MATCHED_LABEL" ).arg( index+1 ).arg( results.count() ) ); + myEditor->setTextCursor( results[index] ); + } + else + { + myInfoLabel->clear(); + cursor.clearSelection(); + myEditor->setTextCursor( cursor ); + } + + setSearchResult( text.isEmpty() || !results.isEmpty() ); +} + +/*! + \brief Add completion. + \param text Completeion being added. + \param replace true to add 'Replace' completion; false to add 'Find' completion. + \internal +*/ +void PyEditor_FindTool::addCompletion( const QString& text, bool replace ) +{ + QStringListModel& model = replace ? myReplaceCompletion : myFindCompletion; + + QStringList completions = model.stringList(); + if ( !text.isEmpty() and !completions.contains( text ) ) + { + completions.prepend( text ); + model.setStringList( completions ); + } +} diff --git a/tools/PyEditor/src/PyEditor_FindTool.h b/tools/PyEditor/src/PyEditor_FindTool.h new file mode 100644 index 000000000..e6501700e --- /dev/null +++ b/tools/PyEditor/src/PyEditor_FindTool.h @@ -0,0 +1,89 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_FindTool.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +#ifndef PYEDITOR_FINDTOOL_H +#define PYEDITOR_FINDTOOL_H + +#include "PyEditor.h" + +#include +#include +#include + +class PyEditor_Editor; +class QAction; +class QLabel; +class QLineEdit; + +class PYEDITOR_EXPORT PyEditor_FindTool : public QWidget +{ +Q_OBJECT + + enum { CaseSensitive, WholeWord, RegExp, Find, FindPrevious, FindNext, Replace }; + +public: + PyEditor_FindTool( PyEditor_Editor*, QWidget* = 0 ); + + bool event( QEvent* ); + bool eventFilter( QObject*, QEvent* ); + +public slots: + void activateFind(); + void activateReplace(); + +private slots: + void showMenu(); + void find( const QString& ); + void find(); + void findPrevious(); + void findNext(); + void replace(); + void replaceAll(); + void update(); + void activate( int ); + +private: + QList shortcuts( int ) const; + void updateShortcuts(); + + void showReplaceControls( bool ); + void setSearchResult( bool ); + + bool isRegExp() const; + bool isCaseSensitive() const; + bool isWholeWord() const; + QTextDocument::FindFlags searchFlags( bool = false ) const; + + QList matches( const QString& ) const; + void find( const QString&, int ); + + void addCompletion( const QString&, bool ); + +private: + PyEditor_Editor* myEditor; + QLineEdit* myFindEdit; + QLineEdit* myReplaceEdit; + QLabel* myInfoLabel; + QStringListModel myFindCompletion, myReplaceCompletion; +}; + +#endif // PYEDITOR_FINDTOOL_H diff --git a/tools/PyEditor/src/PyEditor_Keywords.cxx b/tools/PyEditor/src/PyEditor_Keywords.cxx new file mode 100644 index 000000000..ecc9fe673 --- /dev/null +++ b/tools/PyEditor/src/PyEditor_Keywords.cxx @@ -0,0 +1,243 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_Keywords.cxx +// Author : Sergey TELKOV, Open CASCADE S.A.S. (sergey.telkov@opencascade.com) +// + +#include "PyEditor_Keywords.h" + +#include + +/*! + \brief PyEditor_Keywords +*/ + +/*! + \brief Constructor. +*/ +PyEditor_Keywords::PyEditor_Keywords( QObject* parent ) + : QObject( parent ) +{ +} + +/*! + \brief Destructor. +*/ +PyEditor_Keywords::~PyEditor_Keywords() +{ +} + + +QList PyEditor_Keywords::types() const +{ + QMap map; + for ( KeywordMap::const_iterator it = myKeywords.begin(); it != myKeywords.end(); ++it ) { + map.insert( it.value().type, false ); + } + return map.keys(); +} + +/*! + \brief Gets the colors list. + \return color list +*/ +QList PyEditor_Keywords::colors() const +{ + QList list; + QSet set; + for ( KeywordMap::const_iterator it = myKeywords.begin(); it != myKeywords.end(); ++it ) { + const QColor& color = it.value().color; + if ( !set.contains( color.rgba() ) ) { + list.append( color ); + set.insert( color.rgba() ); + } + } + return list; +} + +/*! + \brief Gets the keyword type. + \return type number +*/ +int PyEditor_Keywords::type( const QString& keyword ) const +{ + return myKeywords.contains(keyword) ? myKeywords[keyword].type : -1; +} + +/*! + \brief Gets the keyword color. + \return color +*/ +QColor PyEditor_Keywords::color( const QString& keyword ) const +{ + return myKeywords.contains(keyword) ? myKeywords[keyword].color : QColor(); +} + +/*! + \brief Gets all keywords. + \return keywords string list +*/ +QStringList PyEditor_Keywords::keywords() const +{ + return myKeywords.keys(); +} + +/*! + \brief Gets all keywords of specified type. + \return keywords string list +*/ +QStringList PyEditor_Keywords::keywords( int type ) const +{ + QStringList keywords; + for ( KeywordMap::const_iterator it = myKeywords.begin(); it != myKeywords.end(); ++it ) { + if ( it.value().type == type ) + keywords.append( it.key() ); + } + return keywords; +} + +/*! + \brief Gets all keywords with specified color. + \return keywords string list +*/ +QStringList PyEditor_Keywords::keywords( const QColor& color ) const +{ + QStringList keywords; + for ( KeywordMap::const_iterator it = myKeywords.begin(); it != myKeywords.end(); ++it ) { + if ( it.value().color == color ) + keywords.append( it.key() ); + } + return keywords; +} + +/*! + \brief Append keyword with type and color. +*/ +void PyEditor_Keywords::append( const QString& keyword, + int type, const QColor& color ) +{ + append( QStringList() << keyword, type, color ); +} + +/*! + \brief Append keyword list with type and color. +*/ +void PyEditor_Keywords::append( const QStringList& keywords, + int type, const QColor& color ) +{ + bool modif = false; + for ( QStringList::const_iterator it = keywords.begin(); it != keywords.end(); ++it ) { + const QString& kw = *it; + bool changed = false; + if ( !myKeywords.contains( kw ) ) { + myKeywords.insert( kw, KeywordInfo() ); + changed = true; + } + KeywordInfo& info = myKeywords[kw]; + changed = changed || info.type != type || info.color != color; + info.type = type; + info.color = color; + + modif = modif || changed; + } + + if ( modif ) + Q_EMIT keywordsChanged(); +} + +/*! + \brief Remove all keywords with specified type. +*/ +void PyEditor_Keywords::remove( int type ) +{ + remove( keywords( type ) ); +} + +/*! + \brief Remove keyword. +*/ +void PyEditor_Keywords::remove( const QString& keyword ) +{ + remove( QStringList() << keyword ); +} + +/*! + \brief Remove keywords. +*/ +void PyEditor_Keywords::remove( const QStringList& keywords ) +{ + bool changed = false; + for ( QStringList::const_iterator it = keywords.begin(); it != keywords.end(); ++it ) { + if ( myKeywords.contains( *it ) ) { + myKeywords.remove( *it ); + changed = true; + } + } + if ( changed ) + Q_EMIT keywordsChanged(); +} + +/*! + \brief Remove all keywords. +*/ +void PyEditor_Keywords::clear() +{ + if ( !myKeywords.isEmpty() ) { + myKeywords.clear(); + Q_EMIT keywordsChanged(); + } +} + +/*! + \brief PyEditor_StandardKeywords +*/ + +PyEditor_StandardKeywords::PyEditor_StandardKeywords( QObject* parent ) + : PyEditor_Keywords( parent ) +{ + QStringList aBase; + aBase << "and" << "as" << "assert" << "break" << "class" << "continue" + << "def" << "elif" << "else" << "except" << "exec" << "finally" + << "False" << "for" << "from" << "global" << "if" << "import" + << "in" << "is" << "lambda" << "None" << "not" << "or" << "pass" + << "print" << "raise" << "return" << "True" << "try" << "while" + << "with" << "yield"; + append( aBase, Base, Qt::blue ); + + QStringList anExcept; + anExcept << "ArithmeticError" << "AssertionError" << "AttributeError" + << "EnvironmentError" << "EOFError" << "Exception" + << "FloatingPointError" << "ImportError" << "IndentationError" + << "IndexError" << "IOError" << "KeyboardInterrupt" << "KeyError" + << "LookupError" << "MemoryError" << "NameError" << "OSError" + << "NotImplementedError" << "OverflowError" << "ReferenceError" + << "RuntimeError" << "StandardError" << "StopIteration" + << "SyntaxError" << "SystemError" << "SystemExit" << "TabError" + << "TypeError" << "UnboundLocalError" << "UnicodeDecodeError" + << "UnicodeEncodeError" << "UnicodeError" << "UnicodeTranslateError" + << "ValueError" << "WindowsError" << "ZeroDivisionError" + << "Warning" << "UserWarning" << "DeprecationWarning" + << "PendingDeprecationWarning" << "SyntaxWarning" + << "OverflowWarning" << "RuntimeWarning" << "FutureWarning"; + append( anExcept, Exceptions, Qt::magenta ); +} + +PyEditor_StandardKeywords::~PyEditor_StandardKeywords() +{ +} diff --git a/tools/PyEditor/src/PyEditor_Keywords.h b/tools/PyEditor/src/PyEditor_Keywords.h new file mode 100644 index 000000000..03f550681 --- /dev/null +++ b/tools/PyEditor/src/PyEditor_Keywords.h @@ -0,0 +1,81 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_Keywords.h +// Author : Sergey TELKOV, Open CASCADE S.A.S. (sergey.telkov@opencascade.com) +// + +#ifndef PYEDITOR_KEYWORDS_H +#define PYEDITOR_KEYWORDS_H + +#include +#include +#include +#include + +class PyEditor_Keywords : public QObject +{ + Q_OBJECT + +public: + PyEditor_Keywords( QObject* = 0 ); + virtual ~PyEditor_Keywords(); + + QList types() const; + QList colors() const; + + int type( const QString& ) const; + QColor color( const QString& ) const; + + QStringList keywords() const; + QStringList keywords( int ) const; + QStringList keywords( const QColor& ) const; + + void append( const QString&, int, const QColor& = QColor() ); + void append( const QStringList&, int, const QColor& = QColor() ); + + void remove( int ); + void remove( const QString& ); + void remove( const QStringList& ); + + void clear(); + +Q_SIGNALS: + void keywordsChanged(); + +private: + typedef struct { int type; QColor color; } KeywordInfo; + typedef QMap KeywordMap; + +private: + KeywordMap myKeywords; +}; + +class PyEditor_StandardKeywords : public PyEditor_Keywords +{ + Q_OBJECT + +public: + typedef enum { Base, Exceptions } KeywordType; + +public: + PyEditor_StandardKeywords( QObject* = 0 ); + virtual ~PyEditor_StandardKeywords(); +}; + +#endif diff --git a/tools/PyEditor/src/PyEditor_PyHighlighter.cxx b/tools/PyEditor/src/PyEditor_PyHighlighter.cxx index 70ff0186a..70a92748b 100644 --- a/tools/PyEditor/src/PyEditor_PyHighlighter.cxx +++ b/tools/PyEditor/src/PyEditor_PyHighlighter.cxx @@ -22,6 +22,10 @@ #include "PyEditor_PyHighlighter.h" +#include "PyEditor_Keywords.h" + +#include + #define NORMAL 0 #define TRIPLESINGLE 1 #define TRIPLEDOUBLE 2 @@ -53,192 +57,20 @@ void PyEditor_PyHighlighter::TextBlockData::insert( PyEditor_PyHighlighter::Pare \brief Constructor. \param theDocument container for structured rich text documents. */ -PyEditor_PyHighlighter::PyEditor_PyHighlighter( QTextDocument* theDocument ) - : QSyntaxHighlighter( theDocument ) -{ - initialize(); -} - -/*! - \brief Initialization rules. -*/ -void PyEditor_PyHighlighter::initialize() +PyEditor_PyHighlighter::PyEditor_PyHighlighter( QTextDocument* theDocument, + PyEditor_Keywords* std, + PyEditor_Keywords* user ) + : QSyntaxHighlighter( theDocument ), + myStdKeywords( std ), + myUserKeywords( user ) { - HighlightingRule aRule; - - // Keywords - keywordFormat.setForeground( Qt::blue ); - QStringList aKeywords = keywords(); - foreach ( const QString& keyword, aKeywords ) - { - aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) ); - aRule.format = keywordFormat; - aRule.capture = 0; - highlightingRules.append( aRule ); - } - - // Special keywords - specialFromat.setForeground( Qt::magenta ); - QStringList aSpecialKeywords = specialKeywords(); - foreach ( const QString& keyword, aSpecialKeywords ) - { - aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) ); - aRule.format = specialFromat; - aRule.capture = 0; - highlightingRules.append( aRule ); - } - - // Reference to the current instance of the class - referenceClassFormat.setForeground( QColor( 179, 143, 0 ) ); - referenceClassFormat.setFontItalic( true ); - aRule.pattern = QRegExp( "\\bself\\b" ); - aRule.format = referenceClassFormat; - aRule.capture = 0; - highlightingRules.append( aRule ); - - // Numbers - numberFormat.setForeground( Qt::darkMagenta ); - aRule.pattern = QRegExp( "\\b([-+])?(\\d+(\\.)?\\d*|\\d*(\\.)?\\d+)(([eE]([-+])?)?\\d+)?\\b" ); - aRule.format = numberFormat; - aRule.capture = 0; - highlightingRules.append( aRule ); - - // String qoutation - quotationFormat.setForeground( Qt::darkGreen ); - aRule.pattern = QRegExp( "(?:'[^']*'|\"[^\"]*\")" ); - aRule.pattern.setMinimal( true ); - aRule.format = quotationFormat; - aRule.capture = 0; - highlightingRules.append( aRule ); - // Function names - functionFormat.setFontWeight( QFont::Bold ); - aRule.pattern = QRegExp( "(?:def\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" ); - aRule.capture = 1; - aRule.format = functionFormat; - highlightingRules.append( aRule ); - - // Class names - classFormat.setForeground( Qt::darkBlue ); - classFormat.setFontWeight( QFont::Bold ); - aRule.pattern = QRegExp( "(?:class\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" ); - aRule.capture = 1; - aRule.format = classFormat; - highlightingRules.append( aRule ); - - // Multi line comments - multiLineCommentFormat.setForeground( Qt::darkRed ); - tripleQuotesExpression = QRegExp( "(:?\"[\"]\".*\"[\"]\"|'''.*''')" ); - aRule.pattern = tripleQuotesExpression; - aRule.pattern.setMinimal( true ); - aRule.format = multiLineCommentFormat; - aRule.capture = 0; - highlightingRules.append( aRule ); - - tripleSingleExpression = QRegExp( "'''(?!\")" ); - tripleDoubleExpression = QRegExp( "\"\"\"(?!')" ); - - // Single comments - singleLineCommentFormat.setForeground( Qt::darkGray ); - aRule.pattern = QRegExp( "#[^\n]*" ); - aRule.format = singleLineCommentFormat; - aRule.capture = 0; - highlightingRules.append( aRule ); -} - -/*! - \return string list of Python keywords. - */ -QStringList PyEditor_PyHighlighter::keywords() -{ - QStringList aKeywords; - aKeywords << "and" - << "as" - << "assert" - << "break" - << "class" - << "continue" - << "def" - << "elif" - << "else" - << "except" - << "exec" - << "finally" - << "False" - << "for" - << "from" - << "global" - << "if" - << "import" - << "in" - << "is" - << "lambda" - << "None" - << "not" - << "or" - << "pass" - << "print" - << "raise" - << "return" - << "True" - << "try" - << "while" - << "with" - << "yield"; - return aKeywords; -} + connect(myStdKeywords, SIGNAL( keywordsChanged() ), + this, SLOT( onKeywordsChanged() ) ); + connect(myUserKeywords, SIGNAL( keywordsChanged() ), + this, SLOT( onKeywordsChanged() ) ); -/*! - \return string list of special Python keywords. -*/ -QStringList PyEditor_PyHighlighter::specialKeywords() -{ - QStringList aSpecialKeywords; - aSpecialKeywords << "ArithmeticError" - << "AssertionError" - << "AttributeError" - << "EnvironmentError" - << "EOFError" - << "Exception" - << "FloatingPointError" - << "ImportError" - << "IndentationError" - << "IndexError" - << "IOError" - << "KeyboardInterrupt" - << "KeyError" - << "LookupError" - << "MemoryError" - << "NameError" - << "NotImplementedError" - << "OSError" - << "OverflowError" - << "ReferenceError" - << "RuntimeError" - << "StandardError" - << "StopIteration" - << "SyntaxError" - << "SystemError" - << "SystemExit" - << "TabError" - << "TypeError" - << "UnboundLocalError" - << "UnicodeDecodeError" - << "UnicodeEncodeError" - << "UnicodeError" - << "UnicodeTranslateError" - << "ValueError" - << "WindowsError" - << "ZeroDivisionError" - << "Warning" - << "UserWarning" - << "DeprecationWarning" - << "PendingDeprecationWarning" - << "SyntaxWarning" - << "OverflowWarning" - << "RuntimeWarning" - << "FutureWarning"; - return aSpecialKeywords; + updateHighlight(); } void PyEditor_PyHighlighter::highlightBlock( const QString& theText ) @@ -353,3 +185,100 @@ void PyEditor_PyHighlighter::insertBracketsData( Brackets theBrackets, insertBracketsData( leftChar, rightChar, theData, theText ); } + +void PyEditor_PyHighlighter::onKeywordsChanged() +{ + updateHighlight(); + rehighlight(); +} + +void PyEditor_PyHighlighter::updateHighlight() +{ + highlightingRules.clear(); + + HighlightingRule aRule; + + QList dictList; + dictList << myStdKeywords << myUserKeywords; + + // Keywords + QSet existing; + for ( QList::const_iterator it = dictList.begin(); + it != dictList.end(); ++it ) { + PyEditor_Keywords* kwDict = *it; + QList colors = kwDict->colors(); + for ( QList::const_iterator itr = colors.begin(); itr != colors.end(); ++itr ) { + QColor color = *itr; + QTextCharFormat format; + format.setForeground( color ); + QStringList keywords = kwDict->keywords( color ); + foreach ( const QString& keyword, keywords ) { + if ( existing.contains( keyword ) ) + continue; + + aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) ); + aRule.format = format; + aRule.capture = 0; + highlightingRules.append( aRule ); + existing.insert( keyword ); + } + } + } + + // Reference to the current instance of the class + referenceClassFormat.setForeground( QColor( 179, 143, 0 ) ); + referenceClassFormat.setFontItalic( true ); + aRule.pattern = QRegExp( "\\bself\\b" ); + aRule.format = referenceClassFormat; + aRule.capture = 0; + highlightingRules.append( aRule ); + + // Numbers + numberFormat.setForeground( Qt::darkMagenta ); + aRule.pattern = QRegExp( "\\b([-+])?(\\d+(\\.)?\\d*|\\d*(\\.)?\\d+)(([eE]([-+])?)?\\d+)?\\b" ); + aRule.format = numberFormat; + aRule.capture = 0; + highlightingRules.append( aRule ); + + // String qoutation + quotationFormat.setForeground( Qt::darkGreen ); + aRule.pattern = QRegExp( "(?:'[^']*'|\"[^\"]*\")" ); + aRule.pattern.setMinimal( true ); + aRule.format = quotationFormat; + aRule.capture = 0; + highlightingRules.append( aRule ); + + // Function names + functionFormat.setFontWeight( QFont::Bold ); + aRule.pattern = QRegExp( "(?:def\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" ); + aRule.capture = 1; + aRule.format = functionFormat; + highlightingRules.append( aRule ); + + // Class names + classFormat.setForeground( Qt::darkBlue ); + classFormat.setFontWeight( QFont::Bold ); + aRule.pattern = QRegExp( "(?:class\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" ); + aRule.capture = 1; + aRule.format = classFormat; + highlightingRules.append( aRule ); + + // Multi line comments + multiLineCommentFormat.setForeground( Qt::darkRed ); + tripleQuotesExpression = QRegExp( "(:?\"[\"]\".*\"[\"]\"|'''.*''')" ); + aRule.pattern = tripleQuotesExpression; + aRule.pattern.setMinimal( true ); + aRule.format = multiLineCommentFormat; + aRule.capture = 0; + highlightingRules.append( aRule ); + + tripleSingleExpression = QRegExp( "'''(?!\")" ); + tripleDoubleExpression = QRegExp( "\"\"\"(?!')" ); + + // Single comments + singleLineCommentFormat.setForeground( Qt::darkGray ); + aRule.pattern = QRegExp( "#[^\n]*" ); + aRule.format = singleLineCommentFormat; + aRule.capture = 0; + highlightingRules.append( aRule ); +} diff --git a/tools/PyEditor/src/PyEditor_PyHighlighter.h b/tools/PyEditor/src/PyEditor_PyHighlighter.h index 961616fa2..07ac00611 100644 --- a/tools/PyEditor/src/PyEditor_PyHighlighter.h +++ b/tools/PyEditor/src/PyEditor_PyHighlighter.h @@ -26,6 +26,7 @@ #include class QTextDocument; +class PyEditor_Keywords; class PyEditor_PyHighlighter : public QSyntaxHighlighter { @@ -52,11 +53,14 @@ public: }; public: - PyEditor_PyHighlighter( QTextDocument* = 0 ); + PyEditor_PyHighlighter( QTextDocument*, + PyEditor_Keywords*, PyEditor_Keywords* ); - void initialize(); - QStringList keywords(); - QStringList specialKeywords(); +private Q_SLOTS: + void onKeywordsChanged(); + +protected: + void updateHighlight(); protected: struct HighlightingRule @@ -76,8 +80,6 @@ protected: QTextCharFormat classFormat; QTextCharFormat referenceClassFormat; QTextCharFormat functionFormat; - QTextCharFormat keywordFormat; - QTextCharFormat specialFromat; QTextCharFormat numberFormat; QTextCharFormat singleLineCommentFormat; QTextCharFormat multiLineCommentFormat; @@ -86,6 +88,10 @@ protected: void highlightBlock( const QString& ); void insertBracketsData( char, char, TextBlockData*, const QString& ); void insertBracketsData( Brackets, TextBlockData*, const QString& ); + +private: + PyEditor_Keywords* myStdKeywords; + PyEditor_Keywords* myUserKeywords; }; #endif // PYEDITOR_PYHIGHLIGHTER_H diff --git a/tools/PyEditor/src/PyEditor_Settings.cxx b/tools/PyEditor/src/PyEditor_Settings.cxx index d9fd52fd1..64a43d700 100644 --- a/tools/PyEditor/src/PyEditor_Settings.cxx +++ b/tools/PyEditor/src/PyEditor_Settings.cxx @@ -22,6 +22,8 @@ #include "PyEditor_Settings.h" +#include "PyEditor_Editor.h" + /*! \class PyEditor_Settings \brief Manager of setting values. @@ -61,7 +63,8 @@ PyEditor_Settings::PyEditor_Settings() myNumberColumns( 80 ), myTabSpaceVisible( true ), myTabSize( 4 ), - myFont( "Courier", 10 ) + myFont( "Courier", 10 ), + myCompletionPolicy( PyEditor_Editor::Always ) { } @@ -227,6 +230,24 @@ QFont PyEditor_Settings::font() const return myFont; } +/*! + \brief Set "completionPolicy" option. + \param completion policy option value +*/ +void PyEditor_Settings::setCompletionPolicy( int value ) +{ + myCompletionPolicy = value; +} + +/*! + \brief Get "completionPolicy" option. + \return option value +*/ +int PyEditor_Settings::completionPolicy() const +{ + return myCompletionPolicy; +} + /*! \brief Read settings from the persistence storage. Base implementation does nothing; it should be reimplemented in successors. @@ -258,6 +279,8 @@ void PyEditor_Settings::copyFrom( const PyEditor_Settings& other ) setVerticalEdge( other.verticalEdge() ); setNumberColumns( other.numberColumns() ); setFont( other.font() ); + setCompletionPolicy( other.completionPolicy() ); + save(); } @@ -278,6 +301,7 @@ QString PyEditor_Settings::option( Option option ) "TabSpaceVisible", "TabSize", "Font", + "CompletionPolicy" }; - return option >= 0 && option <= snFont ? options[option] : "Unknown"; + return option >= 0 && option <= snCompletionPolicy ? options[option] : "Unknown"; } diff --git a/tools/PyEditor/src/PyEditor_Settings.h b/tools/PyEditor/src/PyEditor_Settings.h index aa6de0419..7b7e4b7c2 100644 --- a/tools/PyEditor/src/PyEditor_Settings.h +++ b/tools/PyEditor/src/PyEditor_Settings.h @@ -39,7 +39,8 @@ protected: snNumberColumns, snTabSpaceVisible, snTabSize, - snFont }; + snFont, + snCompletionPolicy }; public: static PyEditor_Settings* settings(); @@ -75,6 +76,9 @@ public: void setFont( const QFont& ); QFont font() const; + void setCompletionPolicy( int ); + int completionPolicy() const; + virtual void load(); virtual void save(); @@ -101,6 +105,9 @@ private: // Font settings QFont myFont; + // Completion settings + int myCompletionPolicy; + static PyEditor_Settings* myGlobalSettings; }; diff --git a/tools/PyEditor/src/PyEditor_SettingsDlg.cxx b/tools/PyEditor/src/PyEditor_SettingsDlg.cxx index fc2c94b64..4b021a070 100644 --- a/tools/PyEditor/src/PyEditor_SettingsDlg.cxx +++ b/tools/PyEditor/src/PyEditor_SettingsDlg.cxx @@ -85,6 +85,16 @@ PyEditor_SettingsDlg::PyEditor_SettingsDlg( PyEditor_Editor* theEditor, aMainLayout->addWidget( aDisplaySetBox ); // . Display settings + // . Editor settings + QGroupBox* aEditorSetBox = new QGroupBox( tr( "GR_EDIT_SET" ), this ); + QGridLayout* aEditorSetLayout = new QGridLayout( aEditorSetBox ); + aEditorSetLayout->addWidget( new QLabel( tr( "LBL_COMPLETION_MODE" ), aEditorSetBox ), 0, 0 ); + aEditorSetLayout->addWidget( myCompletionPolicy = new QComboBox( aEditorSetBox ), 0, 1 ); + myCompletionPolicy->addItems( QStringList() << tr( "LBL_NONE" ) << tr( "LBL_AUTO" ) + << tr( "LBL_MANUAL" ) << tr( "LBL_ALWAYS" ) ); + aMainLayout->addWidget( aEditorSetBox ); + // . Editor settings + // . Tab settings QGroupBox* aTabSetBox = new QGroupBox( tr( "GR_TAB_SET" ), this ); QVBoxLayout* aTabSetLayout = new QVBoxLayout( aTabSetBox ); @@ -237,6 +247,7 @@ void PyEditor_SettingsDlg::settingsFromGui() settings.setVerticalEdge( myVerticalEdge->isChecked() ); settings.setNumberColumns( myNumberColumns->value() ); settings.setFont( font ); + settings.setCompletionPolicy( myCompletionPolicy->currentIndex() ); myEditor->setSettings(settings); // updateContent() PyEditor_Settings* globals = PyEditor_Settings::settings(); @@ -261,6 +272,7 @@ void PyEditor_SettingsDlg::settingsToGui() myNumberColumns->setValue( settings.numberColumns() ); myFontFamily->setCurrentFont( settings.font() ); setFontSize( QString::number( settings.font().pointSize() ) ); + myCompletionPolicy->setCurrentIndex( settings.completionPolicy() ); onVerticalEdgeChecked(); onFontChanged(); diff --git a/tools/PyEditor/src/PyEditor_SettingsDlg.h b/tools/PyEditor/src/PyEditor_SettingsDlg.h index 9f3dfa986..24e4c6768 100644 --- a/tools/PyEditor/src/PyEditor_SettingsDlg.h +++ b/tools/PyEditor/src/PyEditor_SettingsDlg.h @@ -39,7 +39,7 @@ class PYEDITOR_EXPORT PyEditor_SettingsDlg : public QDialog public: PyEditor_SettingsDlg( PyEditor_Editor*, bool = false, QWidget* = 0 ); - ~PyEditor_SettingsDlg(); + virtual ~PyEditor_SettingsDlg(); private Q_SLOTS: void onVerticalEdgeChecked(); @@ -71,6 +71,8 @@ private: QFontComboBox* myFontFamily; QComboBox* myFontSize; + QComboBox* myCompletionPolicy; + QCheckBox* myDefaultCheck; PyEditor_Editor* myEditor; diff --git a/tools/PyEditor/src/PyEditor_StdSettings.cxx b/tools/PyEditor/src/PyEditor_StdSettings.cxx index 816db3653..06a2b68eb 100644 --- a/tools/PyEditor/src/PyEditor_StdSettings.cxx +++ b/tools/PyEditor/src/PyEditor_StdSettings.cxx @@ -59,15 +59,24 @@ void PyEditor_StdSettings::load() { mySettings.beginGroup( myGroup.isEmpty() ? option( snEditor ) : myGroup ); - setHighlightCurrentLine( mySettings.value( option( snHighlightCurrentLine ), highlightCurrentLine() ).toBool() ); - setTextWrapping( mySettings.value( option( snTextWrapping ), textWrapping() ).toBool() ); - setCenterCursorOnScroll( mySettings.value( option( snCenterCursorOnScroll ), centerCursorOnScroll() ).toBool() ); - setLineNumberArea( mySettings.value( option( snLineNumberArea ), lineNumberArea() ).toBool() ); - setVerticalEdge( mySettings.value( option( snVerticalEdge ), verticalEdge() ).toBool() ); - setNumberColumns( mySettings.value( option( snNumberColumns ), numberColumns() ).toInt() ); - setTabSpaceVisible( mySettings.value( option( snTabSpaceVisible ), tabSpaceVisible() ).toBool() ); + setHighlightCurrentLine( mySettings.value( option( snHighlightCurrentLine ), + highlightCurrentLine() ).toBool() ); + setTextWrapping( mySettings.value( option( snTextWrapping ), + textWrapping() ).toBool() ); + setCenterCursorOnScroll( mySettings.value( option( snCenterCursorOnScroll ), + centerCursorOnScroll() ).toBool() ); + setLineNumberArea( mySettings.value( option( snLineNumberArea ), + lineNumberArea() ).toBool() ); + setVerticalEdge( mySettings.value( option( snVerticalEdge ), + verticalEdge() ).toBool() ); + setNumberColumns( mySettings.value( option( snNumberColumns ), + numberColumns() ).toInt() ); + setTabSpaceVisible( mySettings.value( option( snTabSpaceVisible ), + tabSpaceVisible() ).toBool() ); setTabSize( mySettings.value( option( snTabSize ), tabSize() ).toInt() ); setFont( mySettings.value( option( snFont ), font() ).value() ); + setCompletionPolicy( mySettings.value( option( snCompletionPolicy ), + completionPolicy() ).toInt() ); setLanguage( mySettings.value( "language", language() ).toString() ); mySettings.endGroup(); @@ -86,6 +95,7 @@ void PyEditor_StdSettings::save() mySettings.setValue( option( snTabSpaceVisible ), tabSpaceVisible() ); mySettings.setValue( option( snTabSize ), tabSize() ); mySettings.setValue( option( snFont ), font() ); + mySettings.setValue( option( snCompletionPolicy ), completionPolicy() ); mySettings.setValue( "language", language() ); mySettings.endGroup(); diff --git a/tools/PyEditor/src/PyEditor_Widget.cxx b/tools/PyEditor/src/PyEditor_Widget.cxx new file mode 100644 index 000000000..badf97329 --- /dev/null +++ b/tools/PyEditor/src/PyEditor_Widget.cxx @@ -0,0 +1,251 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_Widget.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +#include "PyEditor_Editor.h" +#include "PyEditor_FindTool.h" +#include "PyEditor_Widget.h" + +#include + +/*! + \class PyEditor_Widget + \brief Wraps Python editor with the find/replace functionality to a single widget. +*/ + +/*! + \brief Constructor. + \param parent Parent widget. +*/ +PyEditor_Widget::PyEditor_Widget( QWidget* parent ) +{ + // Create editor. + myEditor = new PyEditor_Editor( this ); + + // Create find tool. + myFindTool = new PyEditor_FindTool( myEditor, this ); + + // Set-up layout + QVBoxLayout* layout = new QVBoxLayout( this ); + layout->setContentsMargins( 0, 0, 0, 0 ); + layout->setSpacing( 3 ); + layout->addWidget( myEditor ); + layout->addWidget( myFindTool ); + + connect( myEditor, SIGNAL( modificationChanged( bool ) ), + this, SIGNAL( modificationChanged( bool ) ) ); + connect( myEditor, SIGNAL( undoAvailable( bool ) ), + this, SIGNAL( undoAvailable( bool ) ) ); + connect( myEditor, SIGNAL( redoAvailable( bool ) ), + this, SIGNAL( redoAvailable( bool ) ) ); + connect( myEditor, SIGNAL( copyAvailable( bool ) ), + this, SIGNAL( copyAvailable( bool ) ) ); + + connect( myEditor, SIGNAL( selectionChanged() ), + this, SIGNAL( selectionChanged() ) ); + connect( myEditor, SIGNAL( textChanged() ), + this, SIGNAL( textChanged() ) ); + connect( myEditor, SIGNAL( cursorPositionChanged() ), + this, SIGNAL( cursorPositionChanged() ) ); + + setFocusProxy( myEditor ); +} + +/*! + \brief Get editor. + \return Pointer to editor. +*/ +PyEditor_Editor* PyEditor_Widget::editor() +{ + return myEditor; +} + +/*! + \brief Get find tool. + \return Pointer to find tool. +*/ +PyEditor_FindTool* PyEditor_Widget::findTool() +{ + return myFindTool; +} + +/*! + \brief Get all custom keywords from editor. + \return List of keywords. +*/ +QStringList PyEditor_Widget::keywords() const +{ + return myEditor->keywords(); +} + +/*! + \brief Set custom keywords to editor. + \param keywords List of keywords. + \param type Type of keywords (group id). + \param color Color of keywords. +*/ +void PyEditor_Widget::appendKeywords( const QStringList& keywords, int type, const QColor& color ) +{ + myEditor->appendKeywords( keywords, type, color ); +} + +/*! + \brief Remove given custom keywords from editor. + \param keywords List of keywords to remove. +*/ +void PyEditor_Widget::removeKeywords( const QStringList& keywords ) +{ + myEditor->removeKeywords( keywords ); +} + +/*! + \brief Get current editor's completion policy. + \return Completion policy (see PyEditor_Editor::CompletionPolicy). +*/ +int PyEditor_Widget::completionPolicy() const +{ + return (int) myEditor->completionPolicy(); +} + +/*! + \brief Set editor's completion policy. + \param policy Completion policy (see PyEditor_Editor::CompletionPolicy). +*/ +void PyEditor_Widget::setCompletionPolicy( int policy ) +{ + myEditor->setCompletionPolicy( (PyEditor_Editor::CompletionPolicy) policy ); +} + +/*! + \brief Activate Find dialog. +*/ +void PyEditor_Widget::find() +{ + myFindTool->activateFind(); +} + +/*! + \brief Activate Replace dialog. +*/ +void PyEditor_Widget::replace() +{ + myFindTool->activateReplace(); +} + +/*! + \brief Undo last editor's operation. +*/ +void PyEditor_Widget::undo() +{ + myEditor->undo(); +} + +/*! + \brief Redo last undone editor's operation. +*/ +void PyEditor_Widget::redo() +{ + myEditor->redo(); +} + +/*! + \brief Cut text selected in editor and put it into clipboard. +*/ +void PyEditor_Widget::cut() +{ + myEditor->cut(); +} + +/*! + \brief Copy text selected in editor into clipboard. +*/ +void PyEditor_Widget::copy() +{ + myEditor->copy(); +} + +/*! + \brief Paste text from clipboard into editor. +*/ +void PyEditor_Widget::paste() +{ + myEditor->paste(); +} + +/*! + \brief Delete text selected in editor. +*/ +void PyEditor_Widget::deleteSelected() +{ + myEditor->deleteSelected(); +} + +/*! + \brief Select all text in editor. +*/ +void PyEditor_Widget::selectAll() +{ + myEditor->selectAll(); +} + +/*! + \brief Clear content of editor. +*/ +void PyEditor_Widget::clear() +{ + myEditor->clear(); +} + +/*! + \brief Set/clear modified flag of editor. + \param on 'Modified' flag's value. +*/ +void PyEditor_Widget::setModified( bool on ) +{ + myEditor->document()->setModified( on ); +} + +/*! + \brief Get modified flag of editor. + \return 'Modified' flag's value. +*/ +bool PyEditor_Widget::isModified() +{ + return myEditor->document()->isModified(); +} + +/*! + \brief Set text to editor. + \param text Text to be put into editor. +*/ +void PyEditor_Widget::setText( const QString& text ) +{ + myEditor->setPlainText( text ); +} + +/*! + \brief Get text from editor. + \return Current editor contents. +*/ +QString PyEditor_Widget::text() const +{ + return myEditor->toPlainText(); +} diff --git a/tools/PyEditor/src/PyEditor_Widget.h b/tools/PyEditor/src/PyEditor_Widget.h new file mode 100644 index 000000000..0927a9fe8 --- /dev/null +++ b/tools/PyEditor/src/PyEditor_Widget.h @@ -0,0 +1,85 @@ +// Copyright (C) 2015-2016 OPEN CASCADE +// +// 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, or (at your option) any later version. +// +// 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 : PyEditor_Widget.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +#ifndef PYEDITOR_WIDGET_H +#define PYEDITOR_WIDGET_H + +#include "PyEditor.h" + +#include + +class PyEditor_Editor; +class PyEditor_FindTool; + +class PYEDITOR_EXPORT PyEditor_Widget : public QWidget +{ + Q_OBJECT + +public: + PyEditor_Widget( QWidget* = 0 ); + + PyEditor_Editor* editor(); + PyEditor_FindTool* findTool(); + + bool isModified(); + + QString text() const; + + QStringList keywords() const; + void appendKeywords( const QStringList&, int, const QColor& = QColor() ); + void removeKeywords( const QStringList& ); + + int completionPolicy() const; + void setCompletionPolicy( int ); + +public slots: + void find(); + void replace(); + + void undo(); + void redo(); + void cut(); + void copy(); + void paste(); + void deleteSelected(); + void selectAll(); + void clear(); + + void setModified( bool ); + + void setText( const QString& ); + +signals: + void modificationChanged( bool ); + void undoAvailable( bool ); + void redoAvailable( bool ); + void copyAvailable( bool ); + void selectionChanged(); + void textChanged(); + void cursorPositionChanged(); + +private: + PyEditor_Editor* myEditor; + PyEditor_FindTool* myFindTool; +}; + +#endif // PYEDITOR_WIDGET_H diff --git a/tools/PyEditor/src/PyEditor_Window.cxx b/tools/PyEditor/src/PyEditor_Window.cxx index 74c0be042..125a27b81 100644 --- a/tools/PyEditor/src/PyEditor_Window.cxx +++ b/tools/PyEditor/src/PyEditor_Window.cxx @@ -21,12 +21,13 @@ // #include "PyEditor_Window.h" -#include "PyEditor_Editor.h" +#include "PyEditor_Widget.h" #include "PyEditor_Settings.h" #include "PyEditor_SettingsDlg.h" #include #include +#include #include #include #include @@ -48,9 +49,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : { Q_INIT_RESOURCE( PyEditor ); - // Create editor and set it as a central widget. - myTextEditor = new PyEditor_Editor( this ); - setCentralWidget( myTextEditor ); + // Create central widget. + myEditor = new PyEditor_Widget( this ); + setCentralWidget( myEditor ); // Create actions. QAction* action; @@ -81,7 +82,7 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setShortcut( QKeySequence::Save ); connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) ); action->setEnabled( false ); - connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ), + connect( myEditor, SIGNAL( modificationChanged( bool ) ), action, SLOT( setEnabled( bool ) ) ); myActions[ SaveId ] = action; @@ -109,9 +110,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_UNDO" ) ); action->setStatusTip( tr( "DSC_UNDO" ) ); action->setShortcut( QKeySequence::Undo ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( undo() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( undo() ) ); action->setEnabled( false ); - connect( myTextEditor->document(), SIGNAL( undoAvailable( bool ) ), + connect( myEditor, SIGNAL( undoAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); myActions[ UndoId ] = action; @@ -121,9 +122,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_REDO" ) ); action->setStatusTip( tr( "DSC_REDO" ) ); action->setShortcut( QKeySequence::Redo ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( redo() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( redo() ) ); action->setEnabled( false ); - connect( myTextEditor->document(), SIGNAL( redoAvailable( bool ) ), + connect( myEditor, SIGNAL( redoAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); myActions[ RedoId ] = action; @@ -133,9 +134,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_CUT" ) ); action->setStatusTip( tr( "DSC_CUT" ) ); action->setShortcut( QKeySequence::Cut ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( cut() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( cut() ) ); action->setEnabled( false ); - connect( myTextEditor, SIGNAL( copyAvailable( bool ) ), + connect( myEditor, SIGNAL( copyAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); myActions[ CutId ] = action; @@ -145,9 +146,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_COPY" ) ); action->setStatusTip( tr( "DSC_COPY" ) ); action->setShortcut( QKeySequence::Copy ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( copy() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) ); action->setEnabled( false ); - connect( myTextEditor, SIGNAL( copyAvailable( bool ) ), + connect( myEditor, SIGNAL( copyAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); myActions[ CopyId ] = action; @@ -157,7 +158,7 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_PASTE" ) ); action->setStatusTip( tr( "DSC_PASTE" ) ); action->setShortcut( QKeySequence::Paste ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( paste() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) ); myActions[ PasteId ] = action; // . Delete @@ -166,9 +167,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_DELETE" ) ); action->setStatusTip( tr( "DSC_DELETE" ) ); action->setShortcut( QKeySequence::Delete ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( deleteSelected() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( deleteSelected() ) ); action->setEnabled( false ); - connect( myTextEditor, SIGNAL( copyAvailable( bool ) ), + connect( myEditor, SIGNAL( copyAvailable( bool ) ), action, SLOT( setEnabled( bool ) ) ); myActions[ DeleteId ] = action; @@ -178,9 +179,29 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : action->setToolTip( tr( "TTP_SELECT_ALL" ) ); action->setStatusTip( tr( "DSC_SELECT_ALL" ) ); action->setShortcut( QKeySequence::SelectAll ); - connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( selectAll() ) ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) ); myActions[ SelectAllId ] = action; + // . Find + action = new QAction( QIcon( ":/images/py_find.png" ), + tr( "ACT_FIND" ), this ); + action->setToolTip( tr( "TTP_FIND" ) ); + action->setStatusTip( tr( "DSC_FIND" ) ); + action->setShortcut( QKeySequence::Find ); + action->setShortcutContext( Qt::WidgetShortcut ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( find() ) ); + myActions[ FindId ] = action; + + // . Replace + action = new QAction( QIcon( ":/images/py_replace.png" ), + tr( "ACT_REPLACE" ), this ); + action->setToolTip( tr( "TTP_REPLACE" ) ); + action->setStatusTip( tr( "DSC_REPLACE" ) ); + action->setShortcut( QKeySequence::Replace ); + action->setShortcutContext( Qt::WidgetShortcut ); + connect( action, SIGNAL( triggered( bool ) ), myEditor, SLOT( replace() ) ); + myActions[ ReplaceId ] = action; + // . Preferences action = new QAction( QIcon( ":/images/py_preferences.png" ), tr( "ACT_PREFERENCES" ), this ); @@ -218,6 +239,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : menu->addSeparator(); menu->addAction( myActions[ SelectAllId ] ); menu->addSeparator(); + menu->addAction( myActions[ FindId ] ); + menu->addAction( myActions[ ReplaceId ] ); + menu->addSeparator(); menu->addAction( myActions[ PreferencesId ] ); menu = menuBar()->addMenu( tr( "MNU_HELP" ) ); @@ -242,6 +266,9 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : toolbar->addAction( myActions[ DeleteId ] ); toolbar->addAction( myActions[ SelectAllId ] ); toolbar->addSeparator(); + toolbar->addAction( myActions[ FindId ] ); + toolbar->addAction( myActions[ ReplaceId ] ); + toolbar->addSeparator(); toolbar->addAction( myActions[ PreferencesId ] ); toolbar->addSeparator(); toolbar->addAction( myActions[ HelpId ] ); @@ -250,7 +277,7 @@ PyEditor_Window::PyEditor_Window( QWidget* parent ) : setCurrentFile( QString() ); // Additional set-up for main window. - connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ), + connect( myEditor, SIGNAL( modificationChanged( bool ) ), this, SLOT( setWindowModified( bool ) ) ); // Initialize status bar. @@ -283,7 +310,7 @@ void PyEditor_Window::onNew() { if ( whetherSave() ) { - myTextEditor->clear(); + myEditor->clear(); setCurrentFile( QString() ); } } @@ -343,7 +370,7 @@ bool PyEditor_Window::onSaveAs() */ void PyEditor_Window::onPreferences() { - PyEditor_SettingsDlg dlg( myTextEditor, true, this ); + PyEditor_SettingsDlg dlg( myEditor->editor(), true, this ); connect( &dlg, SIGNAL( help() ), this, SLOT( onHelp() ) ); dlg.exec(); } @@ -355,7 +382,7 @@ void PyEditor_Window::onPreferences() void PyEditor_Window::setCurrentFile( const QString& filePath ) { myURL = filePath; - myTextEditor->document()->setModified( false ); + myEditor->setModified( false ); setWindowModified( false ); @@ -369,7 +396,7 @@ void PyEditor_Window::setCurrentFile( const QString& filePath ) */ bool PyEditor_Window::whetherSave() { - if ( myTextEditor->document()->isModified() ) + if ( myEditor->isModified() ) { QMessageBox::StandardButton answer = QMessageBox::warning( this, tr( "NAME_PYEDITOR" ), @@ -394,19 +421,20 @@ bool PyEditor_Window::whetherSave() \brief Open file. \param filePath file path */ -void PyEditor_Window::loadFile( const QString& filePath ) +void PyEditor_Window::loadFile( const QString& filePath, bool verbose ) { QFile aFile( filePath ); if ( !aFile.open(QFile::ReadOnly | QFile::Text) ) { - QMessageBox::warning( this, tr( "NAME_PYEDITOR" ), - tr( "WRN_READ_FILE" ).arg( filePath ).arg( aFile.errorString() ) ); + if ( verbose ) + QMessageBox::warning( this, tr( "NAME_PYEDITOR" ), + tr( "WRN_READ_FILE" ).arg( filePath ).arg( aFile.errorString() ) ); return; } QTextStream anInput( &aFile ); QApplication::setOverrideCursor( Qt::WaitCursor ); - myTextEditor->setPlainText( anInput.readAll() ); + myEditor->setText( anInput.readAll() ); QApplication::restoreOverrideCursor(); setCurrentFile( filePath ); @@ -419,19 +447,20 @@ void PyEditor_Window::loadFile( const QString& filePath ) \brief Save file. \param filePath file path */ -bool PyEditor_Window::saveFile( const QString& filePath ) +bool PyEditor_Window::saveFile( const QString& filePath, bool verbose ) { QFile aFile( filePath ); if ( !aFile.open( QFile::WriteOnly | QFile::Text ) ) { - QMessageBox::warning( this, tr( "NAME_PYEDITOR" ), - tr( "WRN_WRITE_FILE" ).arg( filePath ).arg( aFile.errorString() ) ); + if ( verbose ) + QMessageBox::warning( this, tr( "NAME_PYEDITOR" ), + tr( "WRN_WRITE_FILE" ).arg( filePath ).arg( aFile.errorString() ) ); return false; } QTextStream anOutput( &aFile ); QApplication::setOverrideCursor( Qt::WaitCursor ); - anOutput << myTextEditor->toPlainText(); + anOutput << myEditor->text(); QApplication::restoreOverrideCursor(); setCurrentFile( filePath ); diff --git a/tools/PyEditor/src/PyEditor_Window.h b/tools/PyEditor/src/PyEditor_Window.h index 209739e77..1369db1cd 100644 --- a/tools/PyEditor/src/PyEditor_Window.h +++ b/tools/PyEditor/src/PyEditor_Window.h @@ -29,7 +29,7 @@ #include class QAction; -class PyEditor_Editor; +class PyEditor_Widget; class PYEDITOR_EXPORT PyEditor_Window : public QMainWindow { @@ -38,11 +38,15 @@ class PYEDITOR_EXPORT PyEditor_Window : public QMainWindow public: enum { NewId, OpenId, SaveId, SaveAsId, ExitId, UndoId, RedoId, CutId, CopyId, PasteId, DeleteId, SelectAllId, + FindId, ReplaceId, PreferencesId, HelpId }; PyEditor_Window( QWidget* = 0 ); ~PyEditor_Window(); + void loadFile( const QString&, bool = true ); + bool saveFile( const QString&, bool = true ); + protected: virtual void closeEvent( QCloseEvent* ); @@ -54,16 +58,12 @@ private Q_SLOTS: void onPreferences(); void onHelp(); -private: - void loadFile( const QString& ); - bool saveFile( const QString& ); - void setCurrentFile( const QString& ); bool whetherSave(); QString defaultName() const; private: - PyEditor_Editor* myTextEditor; + PyEditor_Widget* myEditor; QString myURL; QMap myActions; }; diff --git a/tools/PyEditor/src/python/PyEditorPy.sip b/tools/PyEditor/src/python/PyEditorPy.sip index 372cc2898..d6b530be9 100644 --- a/tools/PyEditor/src/python/PyEditorPy.sip +++ b/tools/PyEditor/src/python/PyEditorPy.sip @@ -66,6 +66,9 @@ public: void setFont( const QFont& ); QFont font() const; + + void setCompletionPolicy( int ); + int completionPolicy() const; }; class PyEditor_Editor : QPlainTextEdit @@ -82,6 +85,10 @@ public: const PyEditor_Settings& settings() const; QString text() const; + QStringList keywords() const; + void appendKeywords( const QStringList&, int, const QColor& = QColor() ); + void removeKeywords( const QStringList& ); + public slots: void deleteSelected(); void append( const QString& ); @@ -96,3 +103,75 @@ private: PyEditor_Editor( const PyEditor_Editor& ); PyEditor_Editor& operator=( const PyEditor_Editor& ); }; + +class PyEditor_FindTool : public QWidget +{ +%TypeHeaderCode +#include +%End + +public: + explicit PyEditor_FindTool( PyEditor_Editor* /TransferThis/, QWidget* /TransferThis/ = 0 ); + +public slots: + void activateFind(); + void activateReplace(); + +private: + PyEditor_FindTool( const PyEditor_FindTool& ); + PyEditor_FindTool& operator=( const PyEditor_FindTool& ); +}; + +class PyEditor_Widget : public QWidget +{ +%TypeHeaderCode +#include +%End + +public: + explicit PyEditor_Widget( QWidget* /TransferThis/ = 0 ); + + PyEditor_Editor* editor(); + PyEditor_FindTool* findTool(); + + bool isModified(); + + QString text() const; + + QStringList keywords() const; + void appendKeywords( const QStringList&, int, const QColor& = QColor() ); + void removeKeywords( const QStringList& ); + + int completionPolicy() const; + void setCompletionPolicy( int ); + +public slots: + void find(); + void replace(); + + void undo(); + void redo(); + void cut(); + void copy(); + void paste(); + void deleteSelected(); + void selectAll(); + void clear(); + + void setModified( bool ); + + void setText( const QString& ); + +signals: + void modificationChanged( bool ); + void undoAvailable( bool ); + void redoAvailable( bool ); + void copyAvailable( bool ); + void selectionChanged(); + void textChanged(); + void cursorPositionChanged(); + +private: + PyEditor_Widget( const PyEditor_Widget& ); + PyEditor_Widget& operator=( const PyEditor_Widget& ); +}; diff --git a/tools/PyEditor/src/resources/PyEditor.qrc b/tools/PyEditor/src/resources/PyEditor.qrc index 7df3d3208..d2ab431f7 100644 --- a/tools/PyEditor/src/resources/PyEditor.qrc +++ b/tools/PyEditor/src/resources/PyEditor.qrc @@ -5,14 +5,19 @@ images/py_delete.png images/py_editor.png images/py_exit.png + images/py_find.png + images/py_find_next.png + images/py_find_previous.png images/py_help.png images/py_new.png images/py_open.png images/py_paste.png images/py_preferences.png images/py_redo.png + images/py_replace.png images/py_save.png images/py_save_as.png + images/py_search.png images/py_select_all.png images/py_undo.png about.txt diff --git a/tools/PyEditor/src/resources/about.txt b/tools/PyEditor/src/resources/about.txt index aeb24ff7c..9f914c70c 100644 --- a/tools/PyEditor/src/resources/about.txt +++ b/tools/PyEditor/src/resources/about.txt @@ -1,10 +1,16 @@ Python Editor
+

Python Editor is a simple program for writing Python scripts. +

+ +

Program provides standard editing operations like copy/cut/paste, undo/redo, select all, delete, etc. -Also it supports syntax highlighting and auto-indentation of Python code. +It supports syntax highlighting and auto-indentation of Python code. +

+

Most often used editing operations are available via the toolbar:

  • New: creates new document.
  • @@ -22,7 +28,13 @@ Most often used editing operations are available via the toolbar:
  • Preferences: opens Preferences dialog that allows specifying advanced parameters for the program.
  • Help: shows this help information.
+

+ +

+Also, editor supports standard Find and Replace operations. +

+

The behavior of the editor can be customized via the Preferences dialog. The following options can be customized:

  • Font settings: choose the font.
  • @@ -30,7 +42,9 @@ The behavior of the editor can be customized via the Preferences dialog.
  • Enable text wrapping: allows wrapping text at the border of the editor's window.
  • Center cursor on scroll: allows scrolling the script vertically to make the cursor visible at the center of the viewer.
  • Display line numbers area: shows line numbers at the left border of the editor.
  • +
  • Completion mode: select the completion mode for inputted keywords.
  • Vertical edge settings: draws vertical line at the specified column of the viewer.
  • Display tab delimiters: displays tab marks at a given number of white spaces.
  • Save settings as default: saves chosen options as a default ones. These settings will be restored after application restart.
+

diff --git a/tools/PyEditor/src/resources/images/py_find.png b/tools/PyEditor/src/resources/images/py_find.png new file mode 100644 index 000000000..be705fd83 Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_find.png differ diff --git a/tools/PyEditor/src/resources/images/py_find_next.png b/tools/PyEditor/src/resources/images/py_find_next.png new file mode 100644 index 000000000..66a1cfecf Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_find_next.png differ diff --git a/tools/PyEditor/src/resources/images/py_find_previous.png b/tools/PyEditor/src/resources/images/py_find_previous.png new file mode 100644 index 000000000..d236de927 Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_find_previous.png differ diff --git a/tools/PyEditor/src/resources/images/py_replace.png b/tools/PyEditor/src/resources/images/py_replace.png new file mode 100644 index 000000000..2e0c0ec9a Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_replace.png differ diff --git a/tools/PyEditor/src/resources/images/py_search.png b/tools/PyEditor/src/resources/images/py_search.png new file mode 100644 index 000000000..989d1afdb Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_search.png differ diff --git a/tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts b/tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts index c32adddb2..b692da78d 100644 --- a/tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts +++ b/tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts @@ -31,6 +31,30 @@ LBL_LINE_NUMBS_AREA Display line numbers area
+ + GR_EDIT_SET + Editor settings + + + LBL_COMPLETION_MODE + Completion mode + + + LBL_NONE + None + + + LBL_AUTO + Auto + + + LBL_MANUAL + Manual + + + LBL_ALWAYS + Always + GR_TAB_SET Tab settings @@ -226,6 +250,30 @@ DSC_SELECT_ALL Select all the contents + + ACT_FIND + Find + + + TTP_FIND + Find + + + DSC_FIND + Find text + + + ACT_REPLACE + Replace + + + TTP_REPLACE + Find & Replace + + + DSC_REPLACE + Find and replace text + ACT_PREFERENCES Pre&ferences @@ -284,11 +332,13 @@ WRN_READ_FILE - Cannot read file %1:\n%2. + Cannot read file %1: +%2. WRN_WRITE_FILE - Cannot write file %1:\n%2. + Cannot write file %1: +%2. STS_READY @@ -307,4 +357,54 @@ Noname.py + + PyEditor + + PROGRAM_DESCRIPTION + Simple Python editor + + + FILE_PARAM_NAME + file + + + FILE_PARAM_DESCRIPTION + File to edit. + + + + PyEditor_FindTool + + FIND_LABEL + Find: + + + REPLACE_LABEL + Replace with: + + + REPLACE_BTN + Replace + + + REPLACE_ALL_BTN + Replace All + + + CASE_SENSITIVE_CHECK + Case Sensitive + + + WHOLE_WORDS_CHECK + Whole Words Only + + + REGEX_CHECK + Use Regular Expressions + + + NB_MATCHED_LABEL + %1 of %2 matches + + diff --git a/tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts b/tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts index 96cd1e001..fc2decc6a 100644 --- a/tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts +++ b/tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts @@ -31,6 +31,30 @@ LBL_LINE_NUMBS_AREA Affiche les numéros de ligne + + GR_EDIT_SET + Editor settings + + + LBL_COMPLETION_MODE + Completion mode + + + LBL_NONE + None + + + LBL_AUTO + Auto + + + LBL_MANUAL + Manual + + + LBL_ALWAYS + Always + GR_TAB_SET Indentation @@ -226,6 +250,30 @@ DSC_SELECT_ALL Sélectionne tout le contenu + + ACT_FIND + Find + + + TTP_FIND + Find + + + DSC_FIND + Find text + + + ACT_REPLACE + Replace + + + TTP_REPLACE + Find & Replace + + + DSC_REPLACE + Find and replace text + ACT_PREFERENCES Préférences @@ -284,11 +332,13 @@ WRN_READ_FILE - Impossible de lire le fichier %1:\n%2. + Impossible de lire le fichier %1: +%2. WRN_WRITE_FILE - Impossible d'écrire le fichier %1:\n%2. + Impossible d'écrire le fichier %1: +%2. STS_READY @@ -307,4 +357,54 @@ Noname.py + + PyEditor + + PROGRAM_DESCRIPTION + Editeur python + + + FILE_PARAM_NAME + file + + + FILE_PARAM_DESCRIPTION + File to edit. + + + + PyEditor_FindTool + + FIND_LABEL + Find: + + + REPLACE_LABEL + Replace with: + + + REPLACE_BTN + Replace + + + REPLACE_ALL_BTN + Replace All + + + CASE_SENSITIVE_CHECK + Case Sensitive + + + WHOLE_WORDS_CHECK + Whole Words Only + + + REGEX_CHECK + Use Regular Expressions + + + NB_MATCHED_LABEL + %1 of %2 matches + + diff --git a/tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts b/tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts index e77eaa134..ec1846668 100644 --- a/tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts +++ b/tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts @@ -31,6 +31,30 @@ LBL_LINE_NUMBS_AREA ライン番号エリアの表示 + + GR_EDIT_SET + Editor settings + + + LBL_COMPLETION_MODE + Completion mode + + + LBL_NONE + None + + + LBL_AUTO + Auto + + + LBL_MANUAL + Manual + + + LBL_ALWAYS + Always + GR_TAB_SET タブ設定 @@ -226,6 +250,30 @@ DSC_SELECT_ALL 全選択 + + ACT_FIND + Find + + + TTP_FIND + Find + + + DSC_FIND + Find text + + + ACT_REPLACE + Replace + + + TTP_REPLACE + Find & Replace + + + DSC_REPLACE + Find and replace text + ACT_PREFERENCES 環境設定 (&f) @@ -284,11 +332,13 @@ WRN_READ_FILE - ファイルが読めません %1:\n%2. + ファイルが読めません %1: +%2. WRN_WRITE_FILE - ファイルが書き込めません %1:\n%2. + ファイルが書き込めません %1: +%2. STS_READY @@ -307,4 +357,54 @@ Noname. py + + PyEditor + + PROGRAM_DESCRIPTION + Pythonのエディタ + + + FILE_PARAM_NAME + file + + + FILE_PARAM_DESCRIPTION + File to edit. + + + + PyEditor_FindTool + + FIND_LABEL + Find: + + + REPLACE_LABEL + Replace with: + + + REPLACE_BTN + Replace + + + REPLACE_ALL_BTN + Replace All + + + CASE_SENSITIVE_CHECK + Case Sensitive + + + WHOLE_WORDS_CHECK + Whole Words Only + + + REGEX_CHECK + Use Regular Expressions + + + NB_MATCHED_LABEL + %1 of %2 matches + +