From: boulant Date: Wed, 2 Nov 2011 12:31:14 +0000 (+0000) Subject: ADD: packages GuiHelpers (general gui services for "end developpers") and TreeData... X-Git-Tag: V6_4_0b1~7 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a4babf35518c37bc837213d5b0dc76997697b16d;p=modules%2Fgui.git ADD: packages GuiHelpers (general gui services for "end developpers") and TreeData (tree classification of data characterized by properties. It comes with a graphic basic representation) --- diff --git a/configure.ac b/configure.ac index af9bf5351..c2ad5d5e1 100644 --- a/configure.ac +++ b/configure.ac @@ -660,6 +660,8 @@ AC_OUTPUT([ \ src/Session/Makefile \ src/SalomeApp/Makefile \ src/SalomeApp/Test/Makefile \ + src/GuiHelpers/Makefile \ + src/TreeData/Makefile \ src/SALOME_SWIG/Makefile \ src/SALOME_SWIG/supervisionexample.py \ src/SALOME_SWIG/supervisiongeomexample.py \ diff --git a/src/GuiHelpers/Makefile.am b/src/GuiHelpers/Makefile.am new file mode 100644 index 000000000..931d1a4d8 --- /dev/null +++ b/src/GuiHelpers/Makefile.am @@ -0,0 +1,81 @@ +# Copyright (C) 2011 CEA/DEN, EDF R&D, 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. +# +# 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 +# +# -* Makefile *- +# +# Author : Guillaume Boulant (EDF/R&D) +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# header files +salomeinclude_HEADERS = \ + QtHelper.hxx \ + SALOME_GuiServices.hxx \ + SALOME_AppStudyEditor.hxx \ + StandardApp_Module.hxx + +# Libraries targets +lib_LTLIBRARIES = libSalomeGuiHelpers.la + +dist_libSalomeGuiHelpers_la_SOURCES = \ + SALOME_GuiServices.cxx \ + SALOME_AppStudyEditor.cxx \ + StandardApp_Module.cxx + + +QT_CXXFLAGS=@QT_INCLUDES@ @QT_MT_INCLUDES@ +CAS_CXXFLAGS=@CAS_CPPFLAGS@ @CAS_CXXFLAGS@ +BOOST_CPPFLAGS=@BOOST_CPPFLAGS@ +BOOST_LIBS=@BOOST_LIBS@ +CORBA_CXXFLAGS=@OMNIORB_CXXFLAGS@ @OMNIORB_INCLUDES@ + +libSalomeGuiHelpers_la_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + $(CAS_CXXFLAGS) \ + $(BOOST_CPPFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(KERNEL_CXXFLAGS) \ + -I$(srcdir)/../SalomeApp \ + -I$(srcdir)/../LightApp \ + -I$(srcdir)/../SUIT \ + -I$(srcdir)/../Qtx \ + -I$(srcdir)/../CAM \ + -I$(srcdir)/../STD \ + -I$(srcdir)/../OBJECT + +libSalomeGuiHelpers_la_LDFLAGS = \ + $(KERNEL_LDFLAGS) -lSalomeKernelHelpers + $(builddir)/../SalomeApp/libSalomeApp.la + +# +# ======================================================= +# Specific definitions for Qt MOC files +# + +# moc-files generation +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +# MOC pre-processing +MOC_FILES = \ + StandardApp_Module_moc.cxx + +nodist_libSalomeGuiHelpers_la_SOURCES = $(MOC_FILES) + +EXTRA_DIST=$(MOC_FILES:%_moc.cxx=%.hxx) diff --git a/src/GuiHelpers/QtHelper.hxx b/src/GuiHelpers/QtHelper.hxx new file mode 100644 index 000000000..748c38b18 --- /dev/null +++ b/src/GuiHelpers/QtHelper.hxx @@ -0,0 +1,46 @@ +#ifndef _QT_HELPER_HXX_ +#define _QT_HELPER_HXX_ + +// +// ============================================================= +// Macro and template functions for type conversions. +// ============================================================= +// +#include "Basics_Utils.hxx" // To get ToString macro +#include + +// This can be used to convert QString into char *. +#define QCHARSTAR(qstring) qstring.toLatin1().data() +// This converts a string into a QString +#define S2QS(string) QString(string.c_str()) +// This converts a QString into a string +#define QS2S(qstring) ToString(QCHARSTAR(qstring)) +#define QSTRING(any) S2QS(ToString(any)) + +// +// ============================================================= +// General helper macros for manipulating widgets values +// ============================================================= +// +#define GETTEXT(widget) ToString(QCHARSTAR(widget->text().trimmed())) +#define SETTEXT(widget,str) widget->setText(str.c_str()) + +// +// ============================================================= +// Qt Logger macros +// ============================================================= +// + +// We can use the macros defined by SALOMELocalTrace/utilities.h +// as proposed in the file KERNEL_helper.hxx. But we can use instead +// the Qt debug function: +#include +#define QDEBUG qWarning() +//#define QDEBUG qDebug() +#define QLOG(data) QDEBUG << "[XSALOME] " << data +#ifdef LOG +#undef LOG +#endif +#define LOG QLOG + +#endif // __QT_HELPER_H_ diff --git a/src/GuiHelpers/SALOME_AppStudyEditor.cxx b/src/GuiHelpers/SALOME_AppStudyEditor.cxx new file mode 100644 index 000000000..0dbcc2a07 --- /dev/null +++ b/src/GuiHelpers/SALOME_AppStudyEditor.cxx @@ -0,0 +1,106 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "SALOME_AppStudyEditor.hxx" + +#include +#include +#include +#include + +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()); + return sobject._retn(); + } + } + return SALOMEDS::SObject::_nil(); +} + +/** + * This function creates a list of all the "study objects" (SObject) + * that map with the selection in the object browser (the "interactive + * objects", IObjects). Please note that the objects belongs to the + * active study. + */ +SALOME_StudyEditor::SObjectList * SALOME_AppStudyEditor::getSelectedObjects() { + + // _GBO_: please note that the use of this function can be + // underoptimal in the case where the number of selected objects is + // high, because we create a vector list of SObjects while the list + // of IObject can be processed directly. In the case where a high + // number of objects is selected (~1000), it's certainly better to + // use directly the SALOME_ListIO and iterators on it. + + LightApp_SelectionMgr* aSelectionMgr = _salomeApp->selectionMgr(); + SALOME_ListIO selectedIObjects; + aSelectionMgr->selectedObjects(selectedIObjects); + /* + * This returns a list containing the selected objects of the objects + * browser. Please note that the objects of the browser ARE NOT the + * objects of the study. What is returned by this function is a list + * of "interactive objects" (IObject) which are objects of the + * graphical context. Each of this IObject is characterized by an + * entry string that corresponds to the entry string of an associated + * "study object" (SObject) in the active study. The mapping can be + * done using the function IObjectToSObject. + */ + + SObjectList * listOfSObject = new SObjectList(); + SALOME_ListIteratorOfListIO It (selectedIObjects); + for (; It.More(); It.Next()) { + SALOMEDS::SObject_ptr sobject = this->IObjectToSObject(It.Value()); + if (!sobject->_is_nil()) { + listOfSObject->push_back(sobject); + } + } + + return listOfSObject; +} diff --git a/src/GuiHelpers/SALOME_AppStudyEditor.hxx b/src/GuiHelpers/SALOME_AppStudyEditor.hxx new file mode 100644 index 000000000..bc1225508 --- /dev/null +++ b/src/GuiHelpers/SALOME_AppStudyEditor.hxx @@ -0,0 +1,47 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef __APP_STUDY_EDITOR_HXX__ +#define __APP_STUDY_EDITOR_HXX__ + +#include +#include CORBA_CLIENT_HEADER(SALOMEDS) +#include +#include + +#include "SALOME_StudyEditor.hxx" + +class 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; + +}; + +#endif // __APP_STUDY_EDITOR_HXX__ diff --git a/src/GuiHelpers/SALOME_GuiServices.cxx b/src/GuiHelpers/SALOME_GuiServices.cxx new file mode 100644 index 000000000..0f314631c --- /dev/null +++ b/src/GuiHelpers/SALOME_GuiServices.cxx @@ -0,0 +1,134 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "SALOME_GuiServices.hxx" +#include + +namespace GUI { + /*! + * Get the SALOME application, i.e. the main GUI framework of + * SALOME. This function returns a pointer to the singleton instance + * of the SalomeApp_Application. + * + * The SALOME application can be used to get reference to + * the SALOME KERNEL services such that the naming service, the + * lifeCycleCORBA, ... Theses services can be retrieved using static + * functions (not required to get the singleton instance): + * + * SALOME_NamingService *aNamingService = SalomeApp_Application::namingService(); + * + * Please note that this usage can be done only from within the + * SALOME session server process, i.e. the process that embed the + * SALOME application. + */ + SalomeApp_Application * getSalomeApplication() { + static SalomeApp_Application * app; + if ( app == NULL ) { + app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() ); + } + return app; + } + + /*! + * Get the selection manager of the SALOME application. The + * selection manager can be used to get the selected items in the + * objects browser that is a GUI display of the active study. + * The function returns a pointer to the selectionMgr attribute of + * the SalomeApp_Application singleton instance. + */ + LightApp_SelectionMgr * getSelectionManager() { + SalomeApp_Application* anApp = GUI::getSalomeApplication(); + if ( anApp == NULL ) return NULL; + return dynamic_cast( anApp->selectionMgr() ); + } + + + SUIT_ResourceMgr * getResourcesManager() { + return SUIT_Session::session()->resourceMgr(); + } + // Note that the resource manager can be also retrieved from the + // 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()); + } + + + // __GBO__ Question: what is the difference between a + // SALOMEDS::Study and a SalomeApp_Study? + SalomeApp_Study* getSalomeAppActiveStudy() { + SUIT_Application* app = getSalomeApplication(); + if( app ) + return dynamic_cast( app->activeStudy() ); + else + return NULL; + } + + + SALOMEDS::SObject_ptr IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject) { + if (!iobject.IsNull()) { + if (iobject->hasEntry()) { + SalomeApp_Study* appStudy = getSalomeAppActiveStudy(); + if ( appStudy != NULL ) { + // + // IMPORTANT NOTE: + // + // Note that the SalomeApp_Study give acces to shared + // pointer (i.e. _PTR()) that points to proxy + // objects (i.e. SALOMEDSClien_) that embeds + // the CORBA servants (i.e. SALOMEDS::_ptr). + // Then to retrieve the corba servant, a method is to + // 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()); + return sobject; + } + } + } + return SALOMEDS::SObject::_nil(); + } + +} + diff --git a/src/GuiHelpers/SALOME_GuiServices.hxx b/src/GuiHelpers/SALOME_GuiServices.hxx new file mode 100644 index 000000000..6188ad0d8 --- /dev/null +++ b/src/GuiHelpers/SALOME_GuiServices.hxx @@ -0,0 +1,84 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef __GUI_SERVICES_H__ +#define __GUI_SERVICES_H__ + +#include +#include +#include +#include + +#include "SALOMEconfig.h" +#include CORBA_SERVER_HEADER(SALOMEDS) +#include +#include + +namespace GUI { + + // SALOME GUI main services + SalomeApp_Application * getSalomeApplication(); + LightApp_SelectionMgr * getSelectionManager(); + SUIT_ResourceMgr * getResourcesManager(); + + // Helper functions to deal with the study in a GUI context. + // + // First of all, in a GUI context, there is one of the opened + // studies that is considered as active. Please note that the active + // study is a GUI concept and it can be obtained only in the + // SALOME_SessionServer process, i.e. the process that embeds the + // SalomeApp_Application. The concept of active study doesn't make + // sense outside of the GUI context. + // + // The active study is associated with an GUI Objects Browser that + // displays a graphical representation of the study. The items that + // can be selected in the Objects Browser are name Interactive + // Objects (instance of class SALOME_InteractiveObject). To work + // with data, we have to retrieve from this Interactive Object (IO) + // the underlying Study Object (instance of class SALOMEDS::SObject) + // and from this last the data object that can be anything (that + // 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 + SALOMEDS::Study_ptr getActiveStudy(); + int getActiveStudyId(); + + // Another way to get the active study (to be converted in + // SALOMEDS::Study): + SalomeApp_Study * getSalomeAppActiveStudy(); + + SALOMEDS::SObject_ptr IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject); + + template typename TInterface::_var_type + IObjectToInterface(const Handle(SALOME_InteractiveObject)& iobject) { + SALOMEDS::SObject_ptr sobject = IObjectToSObject(iobject); + return KERNEL::SObjectToInterface(sobject); + } + // _MEM_: note that template functions have to be declared AND + // implemented in the header because they are not compiled in this + // library but in every client library that includes this header + // file. The effective compilation depends on the particular class + // used for TInterface. + + +} + +#endif // GUI_SERVICES diff --git a/src/GuiHelpers/StandardApp_Module.cxx b/src/GuiHelpers/StandardApp_Module.cxx new file mode 100644 index 000000000..1bc997fff --- /dev/null +++ b/src/GuiHelpers/StandardApp_Module.cxx @@ -0,0 +1,338 @@ +// Copyright (C) 2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// +// Author : Guillaume Boulant (EDF) + +#include "StandardApp_Module.hxx" + +#include +#include +#include +#include +#include "QtxPopupMgr.h" + +#include CORBA_CLIENT_HEADER(SALOMEDS) +#include CORBA_CLIENT_HEADER(SALOMEDS_Attributes) + +// QT Includes +#include +#include + +#include +#include "QtHelper.hxx" + +// Constructor +StandardApp_Module::StandardApp_Module() : + SalomeApp_Module( "" ), + LightApp_Module( "" ) +{ + // Note that it's no use to specify here the moduleName because it's + // automatically determined by the name of the GUI library + // (lib.so) just before initialize step. If you want + // nevertheless to setup the module name you should specified this + // name in the initialize function below using the CAM_module + // function setModuleName(QString&). You are warn then that the + // loading of resource files may be incorect and should be manually + // managed. In conclusion, if you don't need a special + // configuration, please conform to the standard convention: if + // is the name of the module as declared in the GUI + // configuration file (SalomeApp.xml), then you just have to provide + // a library whose name is lib.so and which contains a + // factory "extern C" function 'CAM_Module* createModule()' +} + +int StandardApp_Module::ACTIONID_DEFAULT_INIT_VALUE = 910; +int StandardApp_Module::ACTIONID_UNDEFINED = -1; + +// Module's initialization +void StandardApp_Module::initialize( CAM_Application* app ) +{ + // + // ---------------------------------------------------------------- + // Standard initialization + // ---------------------------------------------------------------- + // + SalomeApp_Module::initialize( app ); + _resourceMgr = app->resourceMgr(); + // Please note that the moduleName() function is inherited from + // CAM_module classe, and that its value is determined automatically + // from the name specified in the SalomeApp.xml associated to this + // module and which corresponds to the name of the GUI library + // (lib.so). For XSALOME, see + // share/salome/resources/xsalome/SalomeApp.xml in the install + // directory. + _defaultMenuId = this->createMenu( QCHARSTAR(moduleName()), -1, -1, 30 ); + _defaultToolbarId = this->createTool ( QCHARSTAR(moduleName()) ); + _actionId_internalCount = StandardApp_Module::ACTIONID_DEFAULT_INIT_VALUE; + + // + // ---------------------------------------------------------------- + // The following initializes the GUI widget and associated actions + // ---------------------------------------------------------------- + // These functions may be redefined in specialized version of this class + this->createModuleWidgets(); + this->createModuleActions(); +} + +QIcon StandardApp_Module::createIcon(const QString& iconName) { + // The icon file is supposed to be available througth the resource + // manager, i.e. in the folder containing the XSALOME resources (see + // specification in the module file SalomeApp.xml). + QPixmap aPixmap = _resourceMgr->loadPixmap( QCHARSTAR(moduleName()), iconName ); + return QIcon( aPixmap ); +} + +int StandardApp_Module::newActionId() { + _actionId_internalCount++; + return _actionId_internalCount; +} + +/*! + * This function creates an action and connects it to a button in the + * toolbar and to an item in the menu associated to this module. This + * function applies a common and standard procedure with a maximum of + * default values. If no identifier is specified, then a static + * internal counter is used to associate an identifier to the created + * action. In any case, the action identifier is returned. + * + * Note that the action (object of type QAction) can be retrieved + * using the method "QAction * action(int identifier)" of the super + * class. + */ +int StandardApp_Module::createStandardAction(const QString& label, + QObject * slotobject, + const char* slotmember, + const QString& iconName, + const QString& tooltip, + const int identifier) +{ + + // If the tooltip is not defined, we choose instead the label text. + QString effToolTip(tooltip); + if ( effToolTip.isEmpty() ) + effToolTip = label; + + QIcon actionIcon = this->createIcon(iconName); + + // If the identifier is not specified, then we use an internal + // counter. + int effIdentifier = identifier; + if ( effIdentifier == StandardApp_Module::ACTIONID_UNDEFINED ) { + effIdentifier=newActionId(); + } + + // Creating the action + QAction * action= this->createAction( effIdentifier, label, actionIcon, + label, effToolTip, 0, getApp()->desktop(), + false, slotobject, slotmember); + + return effIdentifier; +} + +/** + * Integrate the action in the default toolbar + */ +void StandardApp_Module::addActionInToolbar(int actionId) { + this->createTool( actionId, _defaultToolbarId ); +} + +/** + * Integrate the action in the default menu + */ +void StandardApp_Module::addActionInMenubar(int actionId) { + this->createMenu( actionId, _defaultMenuId, 10 ); +} + +/** + * Add the specified action as an item in the popup menu, with the + * specified visible rule. The default is "visible for object browser". + */ +void StandardApp_Module::addActionInPopupMenu(int actionId,const QString& rule) { + // _GBO_ for a fine customization of the rule (for example with a + // test on the type of the selected object), see the LIGTH module: + // implement "LightApp_Selection* createSelection() const;" + int parentId = -1; + QtxPopupMgr* mgr = this->popupMgr(); + mgr->insert ( this->action( actionId ), parentId, 0 ); + mgr->setRule( this->action( actionId ), rule, QtxPopupMgr::VisibleRule ); +} + +/*! + * This function can be used to create additionnal widget for this + * module GUI (e.g. docked widget). It can be redefined in a + * specialized version of this class. + */ +void StandardApp_Module::createModuleWidgets() { + // Nothing to do in this default gui +} + +/*! + * This function can be used to defined the list of actions for this + * module GUI. It can be redefined in a specialized version of this + * class. + * Depending on wether you use the method "createStandardAction" or + * not, the actions will be automatically plugged in the toolbar and + * the menu associated to the module. + */ +void StandardApp_Module::createModuleActions() { + int actionId = this->createStandardAction("Test", this, SLOT(OnTest()), + "f1.png", "Run the default test function"); + this->addActionInToolbar(actionId); +} + +// Get compatible dockable windows. +void StandardApp_Module::windows( QMap& theMap ) const +{ + theMap.clear(); + theMap.insert( SalomeApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea ); + theMap.insert( SalomeApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea ); +} + +// Module's engine IOR +QString StandardApp_Module::engineIOR() const +{ + CORBA::String_var anIOR = getApp()->orb()->object_to_string(getEngine()); + return QString( anIOR.in() ); +} + +/*! + * This specifies the filename for the icon to be used for the study + * component associated to the module. Note that this icon could be + * different than the module icon which is defined by the + * SalomeApp.xml file dedicated to this module (see the shared + * resources folder dedicated to the module) and which is used for the + * toolbar of the SALOME application. + */ +QString StandardApp_Module::studyIconName() +{ + // By default, we return the module icone name + return iconName(); // inherited from CAM_Module +} + +/*! + * This can be used to switch the layout of main application + * dockwidgets to one of the predefined configuration (see enum + * DockLayoutType). When a layout is set, the previous layout is + * memorized and can be restored using the unsetDockLayout function (1 + * step undo). It is typically to be used in the functions + * activateModule to setup the layout and deactivateModule to unset + * the layout, i.e. restore to the previous state. + */ +void StandardApp_Module::setDockLayout(DockLayoutType layoutType) { + SUIT_Desktop* desk = getApp()->desktop(); + _areaAtBottomLeftCorner = desk->corner(Qt::BottomLeftCorner); + _areaAtBottomRightCorner = desk->corner(Qt::BottomRightCorner); + + if ( layoutType == DOCKLAYOUT_LEFT_VLARGE ) { + desk->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); + desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + } else { + desk->setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea); + desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + } +} + +/*! + * This function restores the layout state that was previously in + * place before the last setDockLayout call. + */ +void StandardApp_Module::unsetDockLayout() { + SUIT_Desktop* desk = getApp()->desktop(); + desk->setCorner(Qt::BottomLeftCorner, _areaAtBottomLeftCorner); + desk->setCorner(Qt::BottomRightCorner, _areaAtBottomRightCorner); +} + +// Module's activation +bool StandardApp_Module::activateModule( SUIT_Study* theStudy ) +{ + bool bOk = SalomeApp_Module::activateModule( theStudy ); + + setMenuShown( true ); + setToolShown( true ); + + if ( this->createStudyComponentAtActivation() ) { + this->createStudyComponent(theStudy); + } + + return bOk; +} + +/*! + * This function should be implemented in a specialized class and must + * return true if you want to automatically create a study component + * for this module at activation step (when you first load the module + * for a given study). The default function return true. + */ +bool StandardApp_Module::createStudyComponentAtActivation() { + return true; +} + +/*! + * This creates a root entry in the active study for this module, i.e + * a SComponent with the name of the module and the icon specified for + * 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) { + + 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::SComponent_var aFather = aDSStudy->FindComponent(QCHARSTAR(moduleName())); + if (aFather->_is_nil()) + { + SALOMEDS::StudyBuilder_var aStudyBuilder = aDSStudy->NewBuilder(); + aFather = aStudyBuilder->NewComponent(QCHARSTAR(moduleName())); + SALOMEDS::GenericAttribute_var anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributeName"); + SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr); + aName->SetValue(QCHARSTAR(moduleName())); + aName->Destroy(); + anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributePixMap"); + SALOMEDS::AttributePixMap_var aPixMap = SALOMEDS::AttributePixMap::_narrow(anAttr); + aPixMap->SetPixMap(QCHARSTAR(studyIconName())); + + // WARN: The engine should be associated to the SComponent IF + // AND ONLY IF it is a SALOMEDS::Driver. Otherwise, there is no + // need to do that, and it could even lead to exception + // raising (eh, you work on SALOME isn't it?) + SALOMEDS::Driver_var driver = SALOMEDS::Driver::_narrow(this->getEngine()); + if ( ! driver->_is_nil() ) { + STDLOG("Associate the SComponent to the engine"); + aStudyBuilder->DefineComponentInstance(aFather, this->getEngine()); + } + } + +} + +// Module's deactivation +bool StandardApp_Module::deactivateModule( SUIT_Study* theStudy ) +{ + setMenuShown( false ); + setToolShown( false ); + + return SalomeApp_Module::deactivateModule( theStudy ); +} + +void StandardApp_Module::OnTest() +{ + // Just for test + STDLOG("OnTest: engine IOR = "< +#include + +#include +#include CORBA_SERVER_HEADER(SALOME_Component) + +#include + +/*! + * This class is provided as the base class for the standard gui part + * of a SALOME module. To define a gui part, you just have to + * implement the virtual functions: + * - getEngine() to specify the engine component associated to this module + * - createModuleActions(...) to specify the action functions + * - createModuleWidgets(...) to specify special additionnal widgets + * + * The gui part of a SALOME module is an extension of the SALOME + * client Application for this module. Technically speaking, it + * consists in a plugin that provides a derived class of CAM_Module + * (provided by the GUI module). + * + * A standard gui is the standard design for most of SALOME module + * (object browser on the left, viewer on the rigth, python console on + * the bottom, and toolbox in the toolbar with standard definition of + * the tool function). This standard design suggests also to specify + * the engine associated to the module by implementing the virtual + * pure function getEngine(). The engine of a module is the SALOME + * component that is associated to the study component for this + * module, and generally which is responsible for the persistency + * functions or data management for the module. + * + * See a use case example in the test module Xsalome provided by the + * test package (tst/module/gui/Xsalome.hxx and + * tst/module/gui/factory.cxx in the XSALOME library). + */ +class StandardApp_Module: public SalomeApp_Module +{ + Q_OBJECT + +public: + + // ================================================================ + // This part defines the standard interface of the SalomeApp_Module + // ================================================================ + + StandardApp_Module(); + void initialize( CAM_Application* ); + QString engineIOR() const; + virtual void windows( QMap& theMap ) const; + +public slots: + bool deactivateModule( SUIT_Study* ); + bool activateModule( SUIT_Study* ); + + // ================================================================ + // This part defines the specific interface of this class + // ================================================================ + +public: + /* Creates an action with standard default values */ + int createStandardAction(const QString& label, + QObject * slotobject, + const char* slotmember, + const QString& iconName=QString(), + const QString& tooltip=QString(), + const int identifier=ACTIONID_UNDEFINED); + + void addActionInToolbar(int actionId); + void addActionInMenubar(int actionId); + void addActionInPopupMenu(int actionId,const QString& rule="client='ObjectBrowser'"); + +protected: + /* Implement this to create additionnal widget (e.g. docked widget) */ + virtual void createModuleWidgets(); + /* Implement this to define the actions for this gui */ + virtual void createModuleActions(); + + /* Use this to create a root entry in the study for this module */ + void createStudyComponent(SUIT_Study*); + /* Implement this to say if study component entry should be created + at activation step */ + virtual bool createStudyComponentAtActivation(); + + /* The engine is the SALOME component associated to the study */ + virtual Engines::EngineComponent_ptr getEngine() const = 0; + // Note that the function getEngine() is virtual pure and must be + // implemented in the specific inherited classes. Note also that the + // const flag is required because getEngine is used by functions + // with const flags (see for ex: engineIOR()). + virtual QString studyIconName(); + + QIcon createIcon(const QString& iconName); + int newActionId(); + + enum DockLayoutType { + DOCKLAYOUT_BOTTOM_HLARGE, // Bottom is Horizontal Large + DOCKLAYOUT_LEFT_VLARGE, // Left is Vertical Large + }; + virtual void setDockLayout(DockLayoutType layoutType); + virtual void unsetDockLayout(); + + SUIT_ResourceMgr* _resourceMgr; + int _defaultMenuId; + int _defaultToolbarId; + + static int ACTIONID_DEFAULT_INIT_VALUE; + static int ACTIONID_UNDEFINED; + +private: + int _actionId_internalCount; + Qt::DockWidgetArea _areaAtBottomLeftCorner; + Qt::DockWidgetArea _areaAtBottomRightCorner; + + // ========================================================= + // This part defines slots for test purposes + // ========================================================= + +protected slots: + void OnTest(); +}; + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index d68377865..de80e714f 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,7 +106,7 @@ SUBDIRS_LIGHT = LightApp ResExporter # Full (CORBA) SALOME packages ## if GUI_ENABLE_CORBA - SUBDIRS_CORBA = TOOLSGUI Session SalomeApp + SUBDIRS_CORBA = TOOLSGUI Session SalomeApp GuiHelpers TreeData endif ## diff --git a/src/TreeData/DataModel.cxx b/src/TreeData/DataModel.cxx new file mode 100644 index 000000000..615cd865d --- /dev/null +++ b/src/TreeData/DataModel.cxx @@ -0,0 +1,57 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "DataModel.hxx" + +DataModel::DataModel() { + +} + +DataModel::~DataModel() { + _mapDataObjects.clear(); +} + +bool DataModel::addDataObject(DataObject * dataObject) { + _mapDataObjects[dataObject->getNameId()] = dataObject; + return true; +} +bool DataModel::removeDataObject(string nameId) { + _mapDataObjects.erase(nameId); + return true; +} +bool DataModel::removeDataObject(DataObject * dataObject) { + if ( dataObject == NULL ) return false; + return removeDataObject(dataObject->getNameId()); +} + +DataObject * DataModel::getDataObject(string id) { + return _mapDataObjects[id]; +} + + + +map::iterator DataModel::begin() { + return _mapDataObjects.begin(); +} + +map::iterator DataModel::end() { + return _mapDataObjects.end(); +} diff --git a/src/TreeData/DataModel.hxx b/src/TreeData/DataModel.hxx new file mode 100644 index 000000000..432145137 --- /dev/null +++ b/src/TreeData/DataModel.hxx @@ -0,0 +1,62 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + + +#ifndef DATAMODEL_H +#define DATAMODEL_H + +#include +#include "DataObject.hxx" + +class DataModel { + +public: + DataModel(); + ~DataModel(); + + /*! + * This function can be used to create a specific instance of + * DataObject. Note that this function is a pure virtual method and + * then no default behavior is done. In particular, the newly + * created object is not automatically added to the data model. This + * behavior should be implemented in a dedicated version of this + * class. + */ + virtual DataObject * newDataObject() = 0; + + /*! Function to add data object to the model */ + bool addDataObject(DataObject * dataObject); + /*! Functions to remove data object from the model */ + bool removeDataObject(string nameId); + bool removeDataObject(DataObject * dataObject); + /*! Function to retrieve a data object in the model */ + DataObject * getDataObject(string nameId); + + map::iterator begin(); + map::iterator end(); + +private: + map _mapDataObjects; + + +}; + +#endif // DATAMODEL_H diff --git a/src/TreeData/DataObject.cxx b/src/TreeData/DataObject.cxx new file mode 100644 index 000000000..ac651472e --- /dev/null +++ b/src/TreeData/DataObject.cxx @@ -0,0 +1,73 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "DataObject.hxx" +#include + +// Static assignement +int DataObject::_lastId=0; +const string DataObject::_BASENAME = string("object_"); +const string DataObject::pathsep = string("/"); + +DataObject::DataObject() { + _nameId = _BASENAME+ToString(_lastId); + _lastId++; + // The default label is set to the nameId, but it can be modified + // using setLabel whereas the nameId can't be modified. + _label = _nameId; +} + +DataObject::~DataObject() { + _properties.clear(); +} + +void DataObject::setLabel(string label) { + _label = label; +} +string DataObject::getLabel() { + return _label; +} + +string DataObject::getPathName() { + string pathName; + pathName = this->getPath() + pathsep + this->getLabel(); + return pathName; +} + + +string DataObject::getNameId() { + return _nameId; +} + +void DataObject::setProperty(string key, string value) { + _properties[key] = value; +} +string DataObject::getProperty(string key) { + return _properties[key]; +} + +string DataObject::toString() { + string serialize="\n"; + serialize+="nameId = "+getNameId()+"\n"; + serialize+="label = "+getLabel()+"\n"; + serialize+="path = "+getPath(); + return serialize; +} diff --git a/src/TreeData/DataObject.hxx b/src/TreeData/DataObject.hxx new file mode 100644 index 000000000..f67d67606 --- /dev/null +++ b/src/TreeData/DataObject.hxx @@ -0,0 +1,66 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef DATAOBJECT_H +#define DATAOBJECT_H + +#include +#include +using namespace std; + +class DataObject { + +public: + DataObject(); + ~DataObject(); + + void setLabel(string label); + string getLabel(); + void setProperty(string key, string value); + string getProperty(string key); + + /*! + * This function specifies the localization of the object in the + * hierarchical organization that can be defined by the DataModel it + * belongs to. + */ + virtual string getPath() = 0; + string getPathName(); + string getNameId(); + + static const string pathsep; + + /*! This function can be used for debug */ + string toString(); + +private: + /*! The name this object can be displayed with */ + string _label; + /*! The identifier of this object. An identifier is invariant all the session long */ + string _nameId; + /*! The dictionnary of properties that characterize this object */ + map _properties; + + static int _lastId; + static const string _BASENAME; +}; + +#endif // DATAOBJECT_H diff --git a/src/TreeData/DataProcessor.cxx b/src/TreeData/DataProcessor.cxx new file mode 100644 index 000000000..f35676527 --- /dev/null +++ b/src/TreeData/DataProcessor.cxx @@ -0,0 +1,86 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + + +#include "DataProcessor.hxx" +#include +#include "QtHelper.hxx" + +DataProcessor::DataProcessor(DataModel * dataModel) { + _dataModel = dataModel; +} + +/*! + * This function retrieves in the data model all the DataObject + * associated to the item nameIds contained in the specified list. The + * input list is what the TreeView sends via the notification signal. + */ +DataObjectVector * DataProcessor::extract(QStringList itemNameIdList) { + if ( _dataModel == NULL ) { + STDLOG("No data model associated to this processor"); + return NULL; + } + + DataObjectVector * dataObjectList = new DataObjectVector(); + + // We can request the dataModel to obtain the dataObject associated + // to each of the item (iteNameId is a TreeView id, Qt stuff only). + QStringList::const_iterator it; + for (it = itemNameIdList.constBegin(); it != itemNameIdList.constEnd(); ++it) { + QString itemNameId = *it; + DataObject * dataObject = _dataModel->getDataObject(QS2S(itemNameId)); + + if ( dataObject != NULL ) { + dataObjectList->push_back(dataObject); + } else { + LOG("No data object associated to the item "<preprocess(itemNameIdList); + + // We can request the dataModel to obtain the dataObject associated + // to each of the item (iteNameId is a TreeView id, Qt stuff only). + QStringList::const_iterator it; + for (it = itemNameIdList.constBegin(); it != itemNameIdList.constEnd(); ++it) { + QString itemNameId = *it; + DataObject * dataObject = _dataModel->getDataObject(QS2S(itemNameId)); + + if ( dataObject != NULL ) { + this->processDataObject(dataObject); + } else { + STDLOG("No data object associated to the item "<postprocess(itemNameIdList); +} + + diff --git a/src/TreeData/DataProcessor.hxx b/src/TreeData/DataProcessor.hxx new file mode 100644 index 000000000..76b0d111b --- /dev/null +++ b/src/TreeData/DataProcessor.hxx @@ -0,0 +1,66 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef _DATAPROCESSOR_H_ +#define _DATAPROCESSOR_H_ + +#include "DataModel.hxx" +#include "DataObject.hxx" +#include +#include + +#include +typedef std::vector DataObjectVector; + +// +// ================================================================= +// This class can be used to automize processing on data objects. +// The inputs of public functions are list of selected items in the +// tree view. The function automize the extraction of associated +// DataObject and can automize the processing of these object if the +// virtual function processDataObject is implemented. +// ================================================================= +// + +class DataProcessor { + +public: + DataProcessor(DataModel * dataModel); + + DataObjectVector * extract(QStringList itemNameIdList); + void process(QStringList itemNameIdList); + + +protected: + virtual void preprocess(QStringList itemNameIdList) { + // Implement something to be executed at the begining of the process function + }; + virtual void postprocess(QStringList itemNameIdList) { + // Implement something to be executed at the end of the process function + }; + // Implement what must be done with each DataObject during the process function + virtual void processDataObject(DataObject * dataObject) = 0; + +private: + DataModel * _dataModel; +}; + +#endif diff --git a/src/TreeData/DockWidgets.cxx b/src/TreeData/DockWidgets.cxx new file mode 100644 index 000000000..ead3b5ce7 --- /dev/null +++ b/src/TreeData/DockWidgets.cxx @@ -0,0 +1,106 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "DockWidgets.hxx" + +// Qt includes +#include + +// SALOME includes +#include +#include +#include + +/*! + * This create a gui container to hold widgets dedicated to the XCAD + * data model. By default, the dock widgets are not visible. Use the + * show() method to control the visibility (usefull when activating + * and desactivating the module to show/hide the dock widgets). + * + * This class does not make any hypothesis on what will be embedded in + * the dock widgets (only that it is QTreeView). The QTreeView is + * defined elsewhere and is generaly rendering a tree model containing + * tree items. + */ +DockWidgets::DockWidgets(SalomeApp_Application* salomeApp, + bool tabify, + const char * title) { + _salomeApp = salomeApp; + + QMainWindow *parent = _salomeApp->desktop(); + _dwDataPanel = new QDockWidget(parent); + _dwDataPanel->setVisible(false); + _dwDataPanel->setWindowTitle(title); + parent->addDockWidget(Qt::LeftDockWidgetArea, _dwDataPanel); + // + // At this step, the _dwDataPanel is located side by side with the object + // browser (or one over the other). + // + // It is possible to tabify the different dock widgets in one single + // tabbed widget. See the above example: + this->tabify(tabify); +} + +void DockWidgets::tabify(bool tabify) { + if ( tabify ) { + // We first get the object browser tree view, and then the + // associated DockWidget. Note that the tree view is a SALOME + // specific extention of the originate QTreeView and called + // QtxTreeView. + SUIT_DataBrowser* objectBrowser = _salomeApp->objectBrowser(); + QtxTreeView* treeView = objectBrowser->treeView(); + QWidget* pw = treeView->parentWidget(); + QDockWidget* dwObjectBrowser = 0; + while ( pw && !dwObjectBrowser ) { + dwObjectBrowser = ::qobject_cast( pw ); + pw = pw->parentWidget(); + }; + QMainWindow *parent = _salomeApp->desktop(); + parent->tabifyDockWidget(_dwDataPanel, dwObjectBrowser); + parent->setTabOrder(_dwDataPanel, dwObjectBrowser); + parent->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + } + else { + // TO BE IMPLEMENTED + } +} + +/*! + * This function controls the visibility of the dock widgets. + */ +void DockWidgets::show(bool isVisible) { + _dwDataPanel->setVisible(isVisible); +} + +/*! + * This function initializes the central part of the dock widget with + * a tree view that can hold a hierarchical data model. + */ +void DockWidgets::setDataView(QTreeView * dataView) { + _tvDataView = dataView; + _tvDataView->setParent(_dwDataPanel); + _tvDataView->setMinimumHeight(200); + _dwDataPanel->setWidget(_tvDataView); +} + +void DockWidgets::setPropertiesView(QTreeView * propertiesView) { + // Not implemented yet +} diff --git a/src/TreeData/DockWidgets.hxx b/src/TreeData/DockWidgets.hxx new file mode 100644 index 000000000..26487c4f6 --- /dev/null +++ b/src/TreeData/DockWidgets.hxx @@ -0,0 +1,49 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef _DOCKWIDGETS_H_ +#define _DOCKWIDGETS_H_ + +// Qt includes +#include +#include + +// SALOME includes +#include + +class DockWidgets { + public: + DockWidgets(SalomeApp_Application* salomeApp, + bool tabify=false, + const char * title="Data Model"); + + void tabify(bool tabify); + void show(bool isVisible); + void setDataView(QTreeView * dataView); + void setPropertiesView(QTreeView * propertyView); + + private: + SalomeApp_Application* _salomeApp; + QDockWidget * _dwDataPanel; + QTreeView * _tvDataView; +}; + +#endif // _DOCKWIDGETS_H_ diff --git a/src/TreeData/Makefile.am b/src/TreeData/Makefile.am new file mode 100644 index 000000000..025b2c8ba --- /dev/null +++ b/src/TreeData/Makefile.am @@ -0,0 +1,106 @@ +# Copyright (C) 2010 CEA/DEN, EDF R&D, 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. +# +# 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 +# +# -* Makefile *- +# +# Author : Guillaume Boulant (EDF) +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# moc-files generation +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +mostlyclean-local: + rm -f @builddir@/*_moc.cxx + rm -f @builddir@/*.qm + +# Libraries targets +lib_LTLIBRARIES = libSalomeTreeData.la + +# +# Generic source files +# +salomeinclude_HEADERS = \ + DockWidgets.hxx \ + TreeModel.hxx \ + TreeItem.hxx \ + TreeView.hxx \ + TreeObserver.hxx \ + DataModel.hxx \ + DataObject.hxx \ + DataProcessor.hxx \ + TreeGuiManager.hxx + +dist_libSalomeTreeData_la_SOURCES = \ + DockWidgets.cxx \ + TreeModel.cxx \ + TreeItem.cxx \ + TreeView.cxx \ + TreeObserver.cxx \ + DataModel.cxx \ + DataObject.cxx \ + DataProcessor.cxx \ + TreeGuiManager.cxx + +# MOC pre-processing +MOC_FILES = \ + TreeModel_moc.cxx \ + TreeView_moc.cxx \ + TreeObserver_moc.cxx + +nodist_libSalomeTreeData_la_SOURCES = $(MOC_FILES) + +CORBA_CXXFLAGS=@OMNIORB_CXXFLAGS@ @OMNIORB_INCLUDES@ +CORBA_LIBS=@OMNIORB_LIBS@ + +QT_CXXFLAGS=@QT_INCLUDES@ @QT_MT_INCLUDES@ +CAS_CXXFLAGS=@CAS_CPPFLAGS@ @CAS_CXXFLAGS@ + +BOOST_CPPFLAGS=@BOOST_CPPFLAGS@ +BOOST_LIBS=@BOOST_LIBS@ + +libSalomeTreeData_la_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + $(CAS_CXXFLAGS) \ + $(BOOST_CPPFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(KERNEL_CXXFLAGS) \ + -I$(srcdir)/../SalomeApp \ + -I$(srcdir)/../LightApp \ + -I$(srcdir)/../CAM \ + -I$(srcdir)/../STD \ + -I$(srcdir)/../ObjBrowser \ + -I$(srcdir)/../SUIT \ + -I$(srcdir)/../Qtx \ + -I$(srcdir)/../GuiHelpers + + + + +libSalomeTreeData_la_LDFLAGS = \ + $(CORBA_LIBS) $(QT_LIBS)\ + $(KERNEL_LDFLAGS) -lSalomeLifeCycleCORBA -lSalomeKernelHelpers \ + $(top_builddir)/src/SalomeApp/libSalomeApp.la \ + $(top_builddir)/src/LightApp/libLightApp.la \ + $(top_builddir)/src/SUIT/libsuit.la \ + $(top_builddir)/src/Qtx/libqtx.la \ + $(top_builddir)/src/CAM/libCAM.la \ + $(top_builddir)/src/STD/libstd.la \ + $(top_builddir)/src/ObjBrowser/libObjBrowser.la diff --git a/src/TreeData/TreeGuiManager.cxx b/src/TreeData/TreeGuiManager.cxx new file mode 100644 index 000000000..297692b3b --- /dev/null +++ b/src/TreeData/TreeGuiManager.cxx @@ -0,0 +1,153 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "TreeGuiManager.hxx" + +// SALOME includes +#include + +// XCAD includes +#include "TreeView.hxx" +#include "QtHelper.hxx" + +// TODO: +// IMP: The constructor should have a dockwidget as argument. +// The creation of the void dockwidget (without the data tree +// embedded) should be done previously by the StandardApp_Module. +// The constructor would fill the dockwidget with a data tree view + +/*! + * The construction of the gui manager setups a graphic framework that + * consists in a set of dock widgets implanted in the SALOME GUI and + * embedding a tree view rendering a data model (collection of data + * objects) in a hierarchic graphical organisation. + * + * The data model is a straith list of data objects while the view is + * a tree representation of this collection where folders corresponds + * to specific properties of the objects. + * + * This represention is for the needs of navigation in a huge amount + * of data and to ease the selection and processing of items. + */ +TreeGuiManager::TreeGuiManager(SalomeApp_Application * salomeApp, const char * title) + : TreeObserver() +{ + _salomeApp = salomeApp; + + bool tabify = false; + _dockWidgets = new DockWidgets(_salomeApp, tabify, title); + + // Create a TreeView to be associated to a TreeModel dedicated to + // the Xcad data: + _dataTreeView = new TreeView(); + QStringList headers; + headers << tr("Name") << tr("Value"); + _dataTreeModel = new TreeModel(headers); + _dataTreeView->setModel(_dataTreeModel); + + // Then plug the TreeView in the dock widget: + _dockWidgets->setDataView(_dataTreeView); + + // We specify here the dataview to be observed + this->observe(_dataTreeView); +} + +/*! + * This returns the SALOME application (SalomeApp_Application + * instance) associated to this TreeGuiManager. + */ +SalomeApp_Application * TreeGuiManager::getSalomeApplication() { + return _salomeApp; +} + + +/*! + * This function set a layout of the different dock widgets in one + * single tabbed widget. + */ +void TreeGuiManager::tabifyDockWidgets(bool tabify) { + _dockWidgets->tabify(tabify); +} + +/*! + * This function switch on/off the dock widgets managed by this + * gui manager. + */ +void TreeGuiManager::showDockWidgets(bool isVisible) { + _dockWidgets->show(isVisible); +} + +/*! + * This returns the data tree model defined in this + * TreeGuiManager. The data tree model is a tree representation of the + * data model associated to this TreeGuiManager. + */ +TreeModel * TreeGuiManager::getDataTreeModel() { + return _dataTreeModel; +} + +/*! + * This returns the data tree view defined in this + * TreeGuiManager. The data tree view can be request to customize the + * popup menu associated to the tree representation. + */ +TreeView * TreeGuiManager::getDataTreeView() { + return _dataTreeView; +} + + +/*! + * This function specifies the data model to be used by the + * TreeGuiManager. + */ +void TreeGuiManager::setDataModel(DataModel * dataModel) { + _dataModel = dataModel; +} + +DataModel * TreeGuiManager::getDataModel() { + return _dataModel; +} + +/*! + * This function processes the edit signals received from the + * TreeView. This is a default implementation that only prints the + * reception of the signal and some information about the dataObject + * associated to the item whose id is specified. In practice, the data + * model could be requested here to retrieve the data object to be + * edited from the nameId. + * TO BE IMPLEMENTED IN A DOMAIN SPECIFIC VERSION OF THIS CLASS + */ + +void TreeGuiManager::processItemList(QStringList itemNameIdList, + int actionId) +{ + // WARN: THIS IS A DEFAULT IMPLEMENTATION GIVEN FOR DEMONSTRATION + // OF WHAT TO DO WITH THE PARAMETERS + + QString itemNameId = itemNameIdList[0]; + LOG("TreeGuiManager: signal received : process item "<getDataObject(QS2S(itemNameId)); + if ( dataObject != NULL ) { + LOG("TreeGuiManager: dataObject = "<toString().c_str()); + } else { + LOG("TreeGuiManager: no data object associated to this item"); + } +} diff --git a/src/TreeData/TreeGuiManager.hxx b/src/TreeData/TreeGuiManager.hxx new file mode 100644 index 000000000..c27e75011 --- /dev/null +++ b/src/TreeData/TreeGuiManager.hxx @@ -0,0 +1,62 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef _TREEGUIMANAGER_H_ +#define _TREEGUIMANAGER_H_ + +// SALOME includes +#include + +// TREEDATA includes +#include "DockWidgets.hxx" +#include "TreeModel.hxx" +#include "DataModel.hxx" +#include "TreeView.hxx" +#include "TreeObserver.hxx" + +class TreeGuiManager : public TreeObserver { + +public: + TreeGuiManager(SalomeApp_Application * salomeApp, const char * title="Data Model"); + void tabifyDockWidgets(bool tabify); + void showDockWidgets(bool isVisible); + SalomeApp_Application * getSalomeApplication(); + + TreeModel * getDataTreeModel(); + TreeView * getDataTreeView(); + + void setDataModel(DataModel * dataModel); + DataModel * getDataModel(); + +private: + SalomeApp_Application * _salomeApp; + + DockWidgets * _dockWidgets; + TreeView * _dataTreeView; + + TreeModel * _dataTreeModel; + DataModel * _dataModel; + +public slots: + virtual void processItemList(QStringList itemNameIdList, int actionId); +}; + +#endif /* _TREEGUIMANAGER_H_ */ diff --git a/src/TreeData/TreeItem.cxx b/src/TreeData/TreeItem.cxx new file mode 100644 index 000000000..9af3dca18 --- /dev/null +++ b/src/TreeData/TreeItem.cxx @@ -0,0 +1,242 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + + +#include +#include "TreeItem.hxx" + +TreeItem::TreeItem(const QString &nameId, + const QVector &columnValues, + TreeItem *parent) +{ + this->initialize(nameId, columnValues, parent); +} + +/*! + * This initializes the tree item. Called by the constructors. + */ +void TreeItem::initialize(const QString &nameId, + const QVector &columnValues, + TreeItem *parent) { + _itemNameId = nameId; + _itemData = columnValues; + _parentItem = parent; + + // An item is associated to the model of its parent. It can't be + //done automatically in the case where the item has no parent. Then + //the function associatedToModel has to be called explicitely from + //within the user code (for exemple at construction of the model, + //when creating the root item). + if ( parent != NULL ) { + this->associateToModel(parent->associatedModel()); + } +} + +TreeItem::~TreeItem() +{ + qDeleteAll(_childItems); + qDeleteAll(_childItemsMapById); + qDeleteAll(_childItemsMapByLabel); +} + +/*! + * This must be used to specified which model this item belongs to. It + * is required because the item sometimes requests its model for + * global informations about the data tree. In standard usage, this + * function is automatically set when the item is instantiated by + * requested the parent item. Then only the root item needs a manual + * setting. + */ +void TreeItem::associateToModel(TreeModel * model) { + _associatedModel = model; +} + +TreeModel * TreeItem::associatedModel() { + return _associatedModel; +} + +/*! + * This provide an identifier for this item + */ +QString TreeItem::nameId() { + return _itemNameId; +} + +/*! + * This creates an item from the specified dataObject and put it in + * the decendency of this item at the specified relativePath. The + * created item could not be a direct child of this item in the case + * where the relative path is not null. Note that no reference on the + * dataObject is kept in this instance. Only the identifier is used to + * set the item identifier, and the properties may be used to set the + * values of the item (stored in columns). + */ +void TreeItem::appendChild(DataObject * dataObject, + const QStringList &relativePath) { + // Definition of the nameId + QString nameId = QString(dataObject->getNameId().c_str()); + + // Definition of columns data values + QVector columnValues; + columnValues << QString(dataObject->getLabel().c_str()); + columnValues << "No value"; // We could use the dataObject properties + + // Append the item at the specified location with the specified values: + this->appendChild(nameId, columnValues, relativePath); +} + +void TreeItem::appendChild(const QString &nameId, + const QVector &columnValues, + const QStringList &relativePath) { + + if ( relativePath.isEmpty() ) { + // It is a direct child => just create and append to this. + TreeItem * child = new TreeItem(nameId, columnValues, this); + this->appendChild(child); + return; + } + + // The child is embedded in a sub-folder (to be created if doesn't + // exist). + // We first check if the sub-folder already exist: + TreeItem * folder = this->childByLabel(relativePath[0]); + if ( folder == NULL ) { + // The folder does not exist. It must be created before going any + // further. By convention we choose the folder name as + // identifier. + QString folderNameId = relativePath[0]; + QVector folderColumnValues; + folderColumnValues << relativePath[0] << "No value"; + folder = new TreeItem(folderNameId, folderColumnValues, this); + this->appendChild(folder); + } + + // We create the relative path of the next iteration (delete the + // first folder path). + QStringList nextRelativePath; + for (int i = 1; i < relativePath.size(); ++i) + nextRelativePath << relativePath[i]; + + folder->appendChild(nameId, columnValues, nextRelativePath); +} + +/*! + * This appends the specified child to this item. This item is the + * direct parent of the specified child. + */ +void TreeItem::appendChild(TreeItem *item) +{ + TreeModel * model = this->associatedModel(); + + int position = this->childCount(); + model->beginInsertRows(this->modelIndex(), position, position); + _childItems.append(item); + _childItemsMapById[item->nameId()] = item; + _childItemsMapByLabel[item->data(0).toString()] = item; + model->endInsertRows(); +} + +/*! + * The child() function returns the child that corresponds to the + * specified row number in the item's list of child items. + */ +TreeItem *TreeItem::child(int row) +{ + return _childItems.value(row); +} + +TreeItem *TreeItem::childById(const QString &nameId) +{ + QMap ::iterator it; + it = _childItemsMapById.find ( nameId ); + + if ( it != _childItemsMapById.end() ) { + return it.value(); + } + return NULL; +} + +TreeItem *TreeItem::childByLabel(const QString &label) +{ + QMap ::iterator it; + it = _childItemsMapByLabel.find ( label ); + + if ( it != _childItemsMapByLabel.end() ) { + return it.value(); + } + return NULL; +} + + + +int TreeItem::childCount() const +{ + return _childItems.count(); +} + +/*! + * The rowIndex() function reports the item's location within its + * parent's list of items. + */ +int TreeItem::rowIndex() const +{ + if (_parentItem) + return _parentItem->_childItems.indexOf(const_cast(this)); + + return 0; +} + +int TreeItem::columnCount() const +{ + return _itemData.count(); +} + +QVariant TreeItem::data(int column) const +{ + return _itemData.value(column); +} + +TreeItem *TreeItem::parent() +{ + return _parentItem; +} + +bool TreeItem::setData(int column, const QVariant &value) +{ + if (column < 0 || column >= _itemData.size()) + return false; + + _itemData[column] = value; + return true; +} + +QModelIndex TreeItem::modelIndex(int column) +{ + TreeModel * model = this->associatedModel(); + if (_parentItem && (_parentItem != model->getRootItem())) + return model->index(rowIndex(), + column, + _parentItem->modelIndex()); + else + return model->index(rowIndex(), + column, + QModelIndex()); +} diff --git a/src/TreeData/TreeItem.hxx b/src/TreeData/TreeItem.hxx new file mode 100644 index 000000000..fd3418859 --- /dev/null +++ b/src/TreeData/TreeItem.hxx @@ -0,0 +1,80 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#ifndef TREEITEM_H +#define TREEITEM_H + +#include +#include +#include +#include + +#include "DataObject.hxx" +#include "TreeModel.hxx" + +class TreeItem +{ + public: + TreeItem(const QString &nameId, const QVector &columnValues, TreeItem *parent = 0); + ~TreeItem(); + + QString nameId(); + void associateToModel(TreeModel * model); + TreeModel * associatedModel(); + QModelIndex modelIndex(int column=0); + TreeItem *parent(); + + void appendChild(TreeItem * child); + void appendChild(DataObject * dataObject, + const QStringList &relativePath=QStringList()); + void appendChild(const QString &nameId, + const QVector &columnValues, + const QStringList &relativePath=QStringList()); + + + + TreeItem *child(int row); + TreeItem *childById(const QString &nameId); + TreeItem *childByLabel(const QString &label); + int childCount() const; + int columnCount() const; + int rowIndex() const; + QVariant data(int column) const; + bool setData(int column, const QVariant &value); + + + private: + void initialize(const QString &nameId, + const QVector &columnValues, + TreeItem *parent); + + QList _childItems; + QMap _childItemsMapById; + QMap _childItemsMapByLabel; + + QString _itemNameId; + QVector _itemData; + TreeItem * _parentItem; + TreeModel * _associatedModel; + +}; + +#endif diff --git a/src/TreeData/TreeModel.cxx b/src/TreeData/TreeModel.cxx new file mode 100644 index 000000000..3e8f451f9 --- /dev/null +++ b/src/TreeData/TreeModel.cxx @@ -0,0 +1,210 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + + +#include + +#include "TreeItem.hxx" +#include "TreeModel.hxx" + +TreeModel::TreeModel(const QStringList &headers, QObject *parent) + : QAbstractItemModel(parent) +{ + QVector rootData; + foreach (QString header, headers) + rootData << header; + + // _MEM_ We have to specify a string identifier for each item so + // that it could be easily retrieved by its parent. In the case of + // the root item, the value of the identifier doesn't matter => we + // choose an arbitrary value + //QString rootNameId = "rootItem"; + _rootItem = new TreeItem("rootItem", rootData); + _rootItem->associateToModel(this); +} + +TreeModel::~TreeModel() +{ + delete _rootItem; +} + +TreeItem * TreeModel::getRootItem() { + return _rootItem; +} + +// +// ================================================================= +// This part of the implementation is the standard interface required +// for providing an operational TreeModel. These methods are used by +// the TreeView for display purpose. We just have to implement how we +// want the items to be displayed in the view. +// ================================================================= +// +int TreeModel::columnCount(const QModelIndex & /* parent */) const +{ + return _rootItem->columnCount(); +} + +/*! + * This function is used by the tree model to inform the tree view of + * what data used for rendering of the item in the different possible + * role (edition, ...). + */ +QVariant TreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role != Qt::DisplayRole && role != Qt::EditRole) + return QVariant(); + + TreeItem *item = getItem(index); + + return item->data(index.column()); +} + +Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +/*! + * This retrieves the item asociated to the specified index. + */ +TreeItem *TreeModel::getItem(const QModelIndex &index) const +{ + // The item associated to an index can be retrieved using the + // internalPointer() function on the index object. + if (index.isValid()) { + TreeItem *item = static_cast(index.internalPointer()); + if (item) return item; + } + return _rootItem; +} + +QVariant TreeModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return _rootItem->data(section); + + return QVariant(); +} + +/*! + * This retrieves the index of the item located at (row,column) place + * relative to the parent specified by its index. + */ +QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid() && parent.column() != 0) + return QModelIndex(); + + TreeItem *parentItem = getItem(parent); + + TreeItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} + +QModelIndex TreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + TreeItem *childItem = getItem(index); + TreeItem *parentItem = childItem->parent(); + + if (parentItem == _rootItem) + return QModelIndex(); + + return createIndex(parentItem->rowIndex(), 0, parentItem); +} + +int TreeModel::rowCount(const QModelIndex &parent) const +{ + TreeItem *parentItem = getItem(parent); + + return parentItem->childCount(); +} + +bool TreeModel::setData(const QModelIndex &index, const QVariant &value, + int role) +{ + if (role != Qt::EditRole) + return false; + + TreeItem *item = getItem(index); + bool result = item->setData(index.column(), value); + + if (result) + emit dataChanged(index, index); + + return result; +} + +bool TreeModel::setHeaderData(int section, Qt::Orientation orientation, + const QVariant &value, int role) +{ + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + bool result = _rootItem->setData(section, value); + + if (result) + emit headerDataChanged(orientation, section, section); + + return result; +} + + +// +// ================================================================= +// This part is a specific behavior to get a TreeModel that can +// organize itself the tree hierarchy using data provided in a +// filesystem-like format: +// +// data="a/b/c" ==> creation/filling of the hierarchy a->b->c +// The "folder" categories are unique whereas the leaves may exists +// in multiple instances. +// ================================================================= +// + +/* + * The addData functions run a recurcive filling of the tree model, starting + * form the rootItem and descending in the tree using the recurcive + * function TreeItem::addData. + */ + +bool TreeModel::addData(DataObject * dataObject) { + QStringList path = QString(dataObject->getPath().c_str()).split(DataObject::pathsep.c_str()); + return addData(dataObject, path); +} +bool TreeModel::addData(DataObject * dataObject, const QStringList &path) { + TreeItem * rootItem = this->getItem(); + rootItem->appendChild(dataObject, path); + return true; +} diff --git a/src/TreeData/TreeModel.hxx b/src/TreeData/TreeModel.hxx new file mode 100644 index 000000000..c58823512 --- /dev/null +++ b/src/TreeData/TreeModel.hxx @@ -0,0 +1,103 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + + +#ifndef TREEMODEL_H +#define TREEMODEL_H + +#include +#include +#include +#include + +#include "DataObject.hxx" + +class TreeItem; +class TreeView; + +class TreeModel : public QAbstractItemModel +{ + Q_OBJECT + + // IMPORTANT NOTE: + // In this implementation of QAbstractItemModel, a tree item is + // associated to the tree model it belongs to (it can request its + // model throw a pointer to this model). Then we declare the + // TreeItem as a friend class so that it can request the protected + // methods (for example beginInsertRows and endInsertRows, required + // to manage correctly the addition of an item in the model. An + // item can append a child to itself, so it needs to inform the + // model when it begins and when it ends). + friend class TreeItem; + friend class TreeView; + +public: + TreeModel(const QStringList &headers, QObject *parent = 0); + ~TreeModel(); + + // + // ================================================================= + // This part of the specification is the standard interface required + // for providing an operational TreeModel. These methods are used by + // the TreeView for display purpose. We just have to implement how + // we want the items to be displayed in the view. + // ================================================================= + // + // MEM: note that these methods are not intended to be used + // directly. That's the job of the viewer to know how to use + // them. We just have to give the implementation for customizing the + // appearance of the tree. The implementation generally requests the + // items'data to set the appearance features. + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + Qt::ItemFlags flags(const QModelIndex &index) const; + + // + // ================================================================= + // This part is a specific behavior to get a TreeModel that can + // organize itself the tree hierarchy using data provided in a + // filesystem-like format: + // + // data="a/b/c" ==> creation/filling of the hierarchy a->b->c + // The "folder" categories are unique whereas the leaves may exists + // in multiple instances. + // ================================================================= + // + bool addData(DataObject * dataObject); + bool addData(DataObject * dataObject, const QStringList &path); + + // TODO: We should implement the delete and the update fucntions + + // This part contains helper functions for general purposes + TreeItem * getRootItem(); + +private: + TreeItem *getItem(const QModelIndex &index = QModelIndex()) const; + TreeItem * _rootItem; +}; + +#endif // TREEMODEL_H diff --git a/src/TreeData/TreeObserver.cxx b/src/TreeData/TreeObserver.cxx new file mode 100644 index 000000000..310ea13ed --- /dev/null +++ b/src/TreeData/TreeObserver.cxx @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + +#include "TreeObserver.hxx" +#include "QtHelper.hxx" + +TreeObserver::TreeObserver() : QObject() { +} + +/*! + * This declares the TreeView to be observed by this tree events + * listener. + */ +void TreeObserver::observe(TreeView * treeView) { + // We just connect the signals emitted from the treeview to + // corresponding slots of this observer. + connect(treeView, SIGNAL(itemListToProcess(QStringList,int)), + this, SLOT(processItemList(QStringList,int))); +} + +/*! + * This slot should be implemented in a specialized version of + * TreeObserver to process the signal emitted from the TreeView. The + * parameters are: + * - itemNameIdList: the list of name identifiers of model objects + * associated to the selected qt items in the TreeView (ids for + * requesting directly the data model). + * - actionId: the identifier of the action selected in the popup menu + * that triggered this signal. + */ +void TreeObserver::processItemList(QStringList itemNameIdList, int actionId) { + LOG("TreeObserver::processItemList: signal received:\n"<< + "item list: "< +#include "TreeView.hxx" + +class TreeObserver : public QObject { + + Q_OBJECT + +public: + TreeObserver(); + void observe(TreeView * treeView); + +public slots: + /* These slots should be implemented in a specialized version of + the TreeObserver to process signals emitted from the TreeView */ + virtual void processItemList(QStringList itemNameIdList, int actionId); +}; + +#endif // _TREEOBSERVER_ diff --git a/src/TreeData/TreeView.cxx b/src/TreeData/TreeView.cxx new file mode 100644 index 000000000..462fad8c8 --- /dev/null +++ b/src/TreeData/TreeView.cxx @@ -0,0 +1,144 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, 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. +// +// 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 +// + +// Author: Guillaume Boulant (EDF/R&D) + + +// include Qt +#include +#include +#include +#include + +// include Xcad +#include "TreeView.hxx" +#include "TreeModel.hxx" +#include "TreeItem.hxx" +#include "QtHelper.hxx" + +TreeView::TreeView(QWidget * parent) + : QTreeView(parent) +{ + // We authorize the multiple selection of items + this->setSelectionMode(QAbstractItemView::ExtendedSelection); + + _lastActionId = 0; + + // Default actions for tests + int displayActionId = addAction(QObject::tr("Afficher")); + int editActionId = addAction(QObject::tr("Editer")); +} + +TreeView::~TreeView() { +} + +/*! + * This function defines a menu item to add in the popup menu + * associated to this TreeView, and return an integer that corresponds + * to the unique identifier of this action (identifier used in the + * signal emitted to notify observers that an action has been + * selected). Then the caller of this function has to take care of + * this return id (i.e. has to store it in its internal tables) to be + * able to process the notifications from this TreeView. + */ +int TreeView::addAction(QString label) { + QAction * action = new QAction(this); + int actionId = _lastActionId; + action->setObjectName(_idToName(actionId)); + action->setText(label); + _listActions << action; + _lastActionId++; + + return actionId; +} + +/*! + * This function removes all actions previously defined for the popup + * menu of this TreeView. + */ +void TreeView::clearActions() { + _listActions.clear(); +} + +/*! + * You must use this function to create the name of an action object + * from its id. + */ +QString TreeView::_idToName(int actionId) { + return QString::number(actionId); +} +/*! + * You must use this function to create the id of an action object + * from its name (stored in objectName() attribute of the QAction). + */ +int TreeView::_nameToId(QString actionName) { + return actionName.toInt(); +} + +void TreeView::contextMenuEvent(QContextMenuEvent *event) { + if ( _listActions.size() == 0 ) { + // Just return there is no actions defined for this popup menu + return; + } + + // _TODO_ display the QMenu only if the selected item is acceptable + QMenu menu(this); + for (int i = 0; i < _listActions.size(); ++i) { + menu.addAction(_listActions.at(i)); + } + connect(&menu, SIGNAL(triggered(QAction*)), + this, SLOT(processMenuAction(QAction*))); + + menu.exec(event->globalPos()); +} + +/*! + * This SLOT is connected on the signal emited by the menu when an + * action is selected. + */ +void TreeView::processMenuAction(QAction * actionSelected) { + LOG("processMenuAction: START"); + + // We first check than at least on item is selected + QModelIndexList indexList = this->selectionModel()->selectedRows(0); + if ( indexList.isEmpty() ) { + LOG("No item selected"); + return; + } + + // Then we can gather the list of model item ids associated the + // selection. + TreeModel *model = (TreeModel *)this->model(); + QListIterator it(indexList); + QStringList nameIdList; + while (it.hasNext()) { + TreeItem * item = model->getItem(it.next()); + nameIdList << item->nameId(); + } + + // Finally, one can emit a signal to observers specifying the list of + // id and the type of action (i.e. the action identifier) + int actionId = _nameToId(actionSelected->objectName()); + LOG("TreeView::processMenuAction: signal emitted:\n"<< + "item list: "< +#include +#include +#include + +class TreeView : public QTreeView +{ + Q_OBJECT + +public: + TreeView(QWidget * parent = 0 ); + ~TreeView(); + int addAction(QString label); + void clearActions(); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + +private: + int _lastActionId; + QList _listActions; + QString _idToName(int actionId); + int _nameToId(QString actionName); + + // --- + +private slots: + void processMenuAction(QAction * actionSelected); + +signals: + void itemListToProcess(QStringList itemNameIdList, int actionId); +}; + +#endif // TREEVIEW_H +