From 3e3fc52de000b4d8e51fdcffe7f72f82237833ad Mon Sep 17 00:00:00 2001 From: vsv Date: Wed, 22 Jul 2015 12:59:36 +0300 Subject: [PATCH] Initial pre-design of XML based Tree Model --- src/Config/CMakeLists.txt | 3 + src/Config/Config_DataModelReader.cpp | 40 +++++++ src/Config/Config_DataModelReader.h | 66 ++++++++++ src/Config/Config_Keywords.h | 10 +- src/Config/dataModel.xml | 8 ++ src/XGUI/CMakeLists.txt | 2 + src/XGUI/XGUI_DataModel.cpp | 166 ++++++++++++++++++++++++++ src/XGUI/XGUI_DataModel.h | 80 +++++++++++++ src/XGUI/XGUI_ObjectsBrowser.cpp | 9 ++ src/XGUI/XGUI_ObjectsBrowser.h | 15 ++- 10 files changed, 397 insertions(+), 2 deletions(-) create mode 100644 src/Config/Config_DataModelReader.cpp create mode 100644 src/Config/Config_DataModelReader.h create mode 100644 src/Config/dataModel.xml create mode 100644 src/XGUI/XGUI_DataModel.cpp create mode 100644 src/XGUI/XGUI_DataModel.h diff --git a/src/Config/CMakeLists.txt b/src/Config/CMakeLists.txt index 0837555e7..1dfbae0b1 100644 --- a/src/Config/CMakeLists.txt +++ b/src/Config/CMakeLists.txt @@ -23,6 +23,7 @@ SET(PROJECT_HEADERS Config_AttributeMessage.h Config_SelectionFilterMessage.h Config_ValidatorReader.h + Config_DataModelReader.h ) SET(PROJECT_SOURCES @@ -40,10 +41,12 @@ SET(PROJECT_SOURCES Config_AttributeMessage.cpp Config_SelectionFilterMessage.cpp Config_ValidatorReader.cpp + Config_DataModelReader.cpp ) SET(XML_RESOURCES plugins.xml + dataModel.xml ) SET(PROJECT_LIBRARIES diff --git a/src/Config/Config_DataModelReader.cpp b/src/Config/Config_DataModelReader.cpp new file mode 100644 index 000000000..5479a98e1 --- /dev/null +++ b/src/Config/Config_DataModelReader.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * Config_DataModelReader.cpp + * + * Created on: Jul 21, 2015 + * Author: vsv + */ + +#include "Config_DataModelReader.h" +#include +#include "Config_Common.h" + +#include + + +Config_DataModelReader::Config_DataModelReader() + : Config_XMLReader(DATAMODEL_FILE) +{ +} + +Config_DataModelReader::~Config_DataModelReader() +{ +} + +void Config_DataModelReader::processNode(xmlNodePtr theNode) +{ + if (isNode(theNode, NODE_FOLDER, NULL)) { + std::string aName = getProperty(theNode, FOLDER_NAME); + std::string aGroupType = getProperty(theNode, GROUP_TYPE); + if (aName.empty() || aGroupType.empty()) + Events_Error::send("Reading dataModel.xml: wrong folder definition"); + + myRootFolderNames.push_back(aName); + myRootFolderTypes.push_back(aGroupType); + myRootFolderIcons.push_back(getProperty(theNode, NODE_ICON)); + } else if (isNode(theNode, ROOT_NODE, NULL)) { + myRootTypes = getProperty(theNode, GROUP_TYPE); + } +} diff --git a/src/Config/Config_DataModelReader.h b/src/Config/Config_DataModelReader.h new file mode 100644 index 000000000..caba2b6b8 --- /dev/null +++ b/src/Config/Config_DataModelReader.h @@ -0,0 +1,66 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * Config_DataModelReader.h + * + * Created on: Jul 21, 2015 + * Author: vsv + */ + +#ifndef CONFIG_DATAMODELREADER_H_ +#define CONFIG_DATAMODELREADER_H_ + +#include +#include + +#include +#include + +/*! + * \class Config_DataModelReader + * \ingroup Config + * \brief Class that reads data model definition XML for + * further processing in the XGUI_DataModel + */ +class Config_DataModelReader : public Config_XMLReader +{ + public: + /*! + * Constructor + * \param theXmlFile - full path to the xml file which will be processed by the reader + */ + CONFIG_EXPORT Config_DataModelReader(); + CONFIG_EXPORT virtual ~Config_DataModelReader(); + + /// Returns name of type of tree items in root + CONFIG_EXPORT std::string rootType() const { return myRootTypes; } + + /// Returns number of folders under root + CONFIG_EXPORT int rootFoldersNumber() const { return myRootFolderNames.size(); } + + /// Returns name of the folder by its Id + /// \param theId id of the folder + CONFIG_EXPORT std::string rootFolderName(int theId) const { return myRootFolderNames[theId]; } + + /// Returns data type in the folder by its Id + /// \param theId id of the folder + CONFIG_EXPORT std::string rootFolderType(int theId) const { return myRootFolderTypes[theId]; } + + /// Returns icon of a folder by its Id + /// \param theId id of the folder + CONFIG_EXPORT std::string rootFolderIcon(int theId) const { return myRootFolderIcons[theId]; } + + protected: + /// Overloaded method. Defines how to process each node + virtual void processNode(xmlNodePtr theNode); + +private: + std::vector myRootFolderNames; + std::vector myRootFolderTypes; + std::vector myRootFolderIcons; + + std::string myRootTypes; +}; + + +#endif \ No newline at end of file diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index 96adf95b2..46a7f0137 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -95,6 +95,14 @@ const static char* PLUGIN_DEPENDENCY = "dependency"; const static char* PLUGIN_PLATFORM_SALOME = "salome"; const static char* PLUGIN_PLATFORM_NEWGEOM = "openparts"; - +/* + * Hardcoded xml entities of dataModel.xml + */ +const static char* DATAMODEL_FILE = "dataModel.xml"; +const static char* NODE_FOLDER = "folder"; +const static char* FOLDER_NAME = "name"; +const static char* GROUP_TYPE = "group_type"; +const static char* ROOT_NODE = "tree_root"; +const static char* NODE_ICON = "icon"; #endif /* CONFIG_KEYWORDS_H_ */ diff --git a/src/Config/dataModel.xml b/src/Config/dataModel.xml new file mode 100644 index 000000000..fae0ff016 --- /dev/null +++ b/src/Config/dataModel.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/XGUI/CMakeLists.txt b/src/XGUI/CMakeLists.txt index 494759b76..a5b6b0c2e 100644 --- a/src/XGUI/CMakeLists.txt +++ b/src/XGUI/CMakeLists.txt @@ -24,6 +24,7 @@ SET(PROJECT_HEADERS XGUI_Workshop.h XGUI_WorkshopListener.h XGUI_HistoryMenu.h + XGUI_DataModel.h ) SET(PROJECT_AUTOMOC @@ -50,6 +51,7 @@ SET(PROJECT_SOURCES XGUI_Workshop.cpp XGUI_WorkshopListener.cpp XGUI_HistoryMenu.cpp + XGUI_DataModel.cpp ) SET(PROJECT_RESOURCES diff --git a/src/XGUI/XGUI_DataModel.cpp b/src/XGUI/XGUI_DataModel.cpp new file mode 100644 index 000000000..5efbb827f --- /dev/null +++ b/src/XGUI/XGUI_DataModel.cpp @@ -0,0 +1,166 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: ModuleBase_IDocumentDataModel.cpp +// Created: 28 Apr 2015 +// Author: Vitaly SMETANNIKOV + +#include "XGUI_DataModel.h" + +#include +#include + +#include + +XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent) +{ + myXMLReader.readAll(); +} + +//****************************************************** +void XGUI_DataModel::clear() +{ + +} + +//****************************************************** +void XGUI_DataModel::rebuildDataTree() +{ + +} + +//****************************************************** +ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const +{ + return ObjectPtr(); +} + +//****************************************************** +QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const +{ + return QModelIndex(); +} + +//****************************************************** +QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const +{ + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aRootDoc = aSession->moduleDocument(); + int aNbFolders = myXMLReader.rootFoldersNumber(); + int theIndexRow = theIndex.row(); + + if ((theIndex.column() == 1) ) { + if (theIndexRow >= aNbFolders) { + if (theRole == Qt::DecorationRole) { + return QIcon(":pictures/arrow.png"); + } + } + return QVariant(); + } + + int aParentRow = theIndex.internalId(); + if (aParentRow == -1) { // First level of items + if (theIndexRow < aNbFolders) { // A folder + switch (theRole) { + case Qt::DisplayRole: + return QString(myXMLReader.rootFolderName(theIndexRow).c_str()) + + QString(" (%1)").arg(rowCount(theIndex)); + case Qt::DecorationRole: + return QIcon(myXMLReader.rootFolderIcon(theIndexRow).c_str()); + } + } else { + ObjectPtr aObj = aRootDoc->object(myXMLReader.rootType(), theIndexRow - aNbFolders); + switch (theRole) { + case Qt::DisplayRole: + return aObj->data()->name().c_str(); + //case Qt::DecorationRole: + // return featureIcon(aFeature); + } + } + } else { // Content of folders + if (aParentRow < aNbFolders) { + std::string aType = myXMLReader.rootFolderType(aParentRow); + ObjectPtr aObj = aRootDoc->object(aType, theIndexRow); + switch (theRole) { + case Qt::DisplayRole: + return aObj->data()->name().c_str(); + } + } + } + return QVariant(); +} + +//****************************************************** +QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const +{ + return QVariant(); +} + +//****************************************************** +int XGUI_DataModel::rowCount(const QModelIndex& theParent) const +{ + SessionPtr aSession = ModelAPI_Session::get(); + if (!aSession->hasModuleDocument()) + return 0; + DocumentPtr aRootDoc = aSession->moduleDocument(); + int aNbFolders = myXMLReader.rootFoldersNumber(); + + int aNbItems = 0; + std::string aType = myXMLReader.rootType(); + if (!aType.empty()) + aNbItems = aRootDoc->size(aType); + + if (!theParent.isValid()) + return aNbFolders + aNbItems; + + int aParentPos = theParent.row(); + if (aParentPos < aNbFolders) { + // This is number of items under folder + aType = myXMLReader.rootFolderType(aParentPos); + return aRootDoc->size(aType); + } + return 0; +} + +//****************************************************** +int XGUI_DataModel::columnCount(const QModelIndex& theParent) const +{ + return 2; +} + +//****************************************************** +QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const +{ + if (!theParent.isValid()) + return createIndex(theRow, theColumn, -1); + + return createIndex(theRow, theColumn, theParent.row()); +} + +//****************************************************** +QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const +{ + if (theIndex.isValid() && (theIndex.internalId() != -1)) { + return createIndex(theIndex.internalId(), theIndex.column(), -1); + } + return QModelIndex(); +} + +//****************************************************** +bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const +{ + int aNbFolders = myXMLReader.rootFoldersNumber(); + if (!theParent.isValid() && aNbFolders) + return true; + if (theParent.internalId() == -1) { + if (theParent.row() < aNbFolders) { + std::string aType = myXMLReader.rootFolderType(theParent.row()); + if (!aType.empty()) { + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aRootDoc = aSession->moduleDocument(); + return aRootDoc->size(aType) > 0; + } + } + } + return false; +} + diff --git a/src/XGUI/XGUI_DataModel.h b/src/XGUI/XGUI_DataModel.h new file mode 100644 index 000000000..e1157ccb7 --- /dev/null +++ b/src/XGUI/XGUI_DataModel.h @@ -0,0 +1,80 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: XGUI_DataModel.h +// Created: 21 Jul 2015 +// Author: Vitaly SMETANNIKOV + + +#ifndef XGUI_DataModel_H +#define XGUI_DataModel_H + +#include "XGUI.h" +#include +#include +#include + +class XGUI_EXPORT XGUI_DataModel : public QAbstractItemModel +{ +Q_OBJECT +public: + XGUI_DataModel(QObject* theParent); + + //! Returns an object by the given Model index. + //! Returns 0 if the given index is not index of an object + virtual ObjectPtr object(const QModelIndex& theIndex) const; + + //! Returns index of the object + //! \param theObject object to find + virtual QModelIndex objectIndex(const ObjectPtr theObject) const; + + //! Clear internal data + virtual void clear(); + + //! Rebuild data tree + virtual void rebuildDataTree(); + + + /// Returns the data stored under the given role for the item referred to by the index. + /// \param theIndex a model index + /// \param theRole a data role (see Qt::ItemDataRole) + virtual QVariant data(const QModelIndex& theIndex, int theRole) const; + + /// Returns the data for the given role and section in the header with the specified orientation. + /// \param theSection a section + /// \param theOrient an orientation + /// \param theRole a data role (see Qt::ItemDataRole) + virtual QVariant headerData(int theSection, Qt::Orientation theOrient, int theRole = + Qt::DisplayRole) const; + + /// Returns the number of rows under the given parent. When the parent is valid it means that + /// rowCount is returning the number of children of parent. + /// \param theParent a parent model index + virtual int rowCount(const QModelIndex& theParent = QModelIndex()) const; + + /// Returns the number of columns for the children of the given parent. + /// It has a one column + /// \param theParent a parent model index + virtual int columnCount(const QModelIndex& theParent = QModelIndex()) const; + + /// Returns the index of the item in the model specified by the given row, column and parent index. + /// \param theRow a row + /// \param theColumn a column + /// \param theParent a parent model index + virtual QModelIndex index(int theRow, int theColumn, const QModelIndex &theParent = + QModelIndex()) const; + + /// Returns the parent of the model item with the given index. + /// If the item has no parent, an invalid QModelIndex is returned. + /// \param theIndex a model index + virtual QModelIndex parent(const QModelIndex& theIndex) const; + + /// Returns true if parent has any children; otherwise returns false. + /// \param theParent a parent model index + virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const; + + +private: + Config_DataModelReader myXMLReader; +}; + +#endif \ No newline at end of file diff --git a/src/XGUI/XGUI_ObjectsBrowser.cpp b/src/XGUI/XGUI_ObjectsBrowser.cpp index 417a95ec6..658a1d1e2 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.cpp +++ b/src/XGUI/XGUI_ObjectsBrowser.cpp @@ -2,6 +2,7 @@ #include "XGUI_ObjectsBrowser.h" #include "XGUI_Tools.h" +#include "XGUI_DataModel.h" #include #include @@ -349,7 +350,11 @@ void XGUI_ObjectsBrowser::clearContent() void XGUI_ObjectsBrowser::setDataModel(ModuleBase_IDocumentDataModel* theModel) { +#ifdef ModuleDataModel myDocModel = theModel; +#else + myDocModel = new XGUI_DataModel(this); +#endif myTreeView->setModel(myDocModel); QItemSelectionModel* aSelMod = myTreeView->selectionModel(); connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), @@ -366,7 +371,11 @@ QObjectPtrList XGUI_ObjectsBrowser::selectedObjects(QModelIndexList* theIndexes) { QObjectPtrList aList; QModelIndexList aIndexes = selectedIndexes(); +#ifdef ModuleDataModel ModuleBase_IDocumentDataModel* aModel = dataModel(); +#else + XGUI_DataModel* aModel = dataModel(); +#endif QModelIndexList::const_iterator aIt; for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) { if ((*aIt).column() == 0) { diff --git a/src/XGUI/XGUI_ObjectsBrowser.h b/src/XGUI/XGUI_ObjectsBrowser.h index 09f9dc220..a59ec8bd3 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.h +++ b/src/XGUI/XGUI_ObjectsBrowser.h @@ -14,6 +14,9 @@ class ModuleBase_IDocumentDataModel; class QLineEdit; +class XGUI_DataModel; + +#define ModuleDataModel /** * \ingroup GUI @@ -70,10 +73,17 @@ Q_OBJECT virtual ~XGUI_ObjectsBrowser(); //! Returns Model which provides access to data objects +#ifdef ModuleDataModel ModuleBase_IDocumentDataModel* dataModel() const { return myDocModel; } +#else + XGUI_DataModel* dataModel() const + { + return myDocModel; + } +#endif //! Returns list of currently selected objects //! \param theIndexes - output list of corresponded indexes (can be NULL) @@ -140,8 +150,11 @@ signals: void closeDocNameEditing(bool toSave); //! Internal model +#ifdef ModuleDataModel ModuleBase_IDocumentDataModel* myDocModel; - +#else + XGUI_DataModel* myDocModel; +#endif QLineEdit* myActiveDocLbl; XGUI_DataTree* myTreeView; }; -- 2.39.2