X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_DataModel.cpp;h=746b33e03ec1f2b8a4530c33cb27996a186c01cf;hb=1e63ae393cf1ce1923329c90aa66fa33f957f268;hp=1d422355b6e4f9ac8844a9bd7f5c3707c715ac5d;hpb=816672e21b195db53d6f8a2e9914bfc400cd49de;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_DataModel.cpp b/src/XGUI/XGUI_DataModel.cpp index 1d422355b..746b33e03 100644 --- a/src/XGUI/XGUI_DataModel.cpp +++ b/src/XGUI/XGUI_DataModel.cpp @@ -1,10 +1,27 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: ModuleBase_IDocumentDataModel.cpp -// Created: 28 Apr 2015 -// Author: Vitaly SMETANNIKOV +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include "XGUI_DataModel.h" +#include "XGUI_Workshop.h" +#include "XGUI_ObjectsBrowser.h" +#include "XGUI_Displayer.h" #include @@ -16,28 +33,38 @@ #include #include #include +#include #include #include +#include #include -#include #include #include -#define ACTIVE_COLOR QColor(0,72,140) -#define PASSIVE_COLOR Qt::black +#define ACTIVE_COLOR QColor(Qt::black) +//#define ACTIVE_COLOR QColor(0,72,140) +//#define PASSIVE_COLOR Qt::black /// Returns ResultPart object if the given object is a Part feature /// Otherwise returns NULL + +#define SELECTABLE_COLOR QColor(80, 80, 80) +#define DISABLED_COLOR QColor(200, 200, 200) + + ResultPartPtr getPartResult(ModelAPI_Object* theObj) { ModelAPI_Feature* aFeature = dynamic_cast(theObj); if (aFeature) { ResultPtr aRes = aFeature->firstResult(); if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) { - return std::dynamic_pointer_cast(aRes); + ResultPartPtr aPartRes = std::dynamic_pointer_cast(aRes); + // Use only original parts, not a placement results + if (aPartRes == aPartRes->original()) + return aPartRes; } } return ResultPartPtr(); @@ -54,22 +81,33 @@ ModelAPI_Document* getSubDocument(void* theObj) // Constructor ************************************************* -XGUI_DataModel::XGUI_DataModel(QObject* theParent) : ModuleBase_IDocumentDataModel(theParent) +XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)//, + //myIsEventsProcessingBlocked(false) { - myXMLReader.readAll(); + XGUI_ObjectsBrowser* aOB = qobject_cast(theParent); + myWorkshop = aOB->workshop(); Events_Loop* aLoop = Events_Loop::loop(); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_ORDER_UPDATED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED)); } +XGUI_DataModel::~XGUI_DataModel() +{ + clear(); +} + //****************************************************** void XGUI_DataModel::processEvent(const std::shared_ptr& theMessage) { + //if (myIsEventsProcessingBlocked) + // return; DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); - std::string aRootType = myXMLReader.rootType(); - std::string aSubType = myXMLReader.subType(); + std::string aRootType = myXMLReader->rootType(); + std::string aSubType = myXMLReader->subType(); int aNbFolders = foldersCount(); // Created object event ******************* @@ -82,7 +120,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr& theMess std::string aObjType; for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { ObjectPtr aObject = (*aIt); - // We do not show objects which not has to be shown in object browser + // We do not show objects which does not need to be shown in object browser if (!aObject->isInHistory()) continue; @@ -92,50 +130,66 @@ void XGUI_DataModel::processEvent(const std::shared_ptr& theMess // Check that new folders could appear QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(); foreach (QString aNotEmptyFolder, aNotEmptyFolders) { - if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) == 1)) + if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) > 0)) { // Appears first object in folder which can not be shown empty - insertRow(myXMLReader.rootFolderId(aObjType)); + if (!hasShownFolder(aRootDoc, aNotEmptyFolder)) { + insertRow(myXMLReader->rootFolderId(aObjType)); + addShownFolder(aRootDoc, aNotEmptyFolder); + } + } } // Insert new object int aRow = aRootDoc->size(aObjType) - 1; - if (aObjType == aRootType) { - insertRow(aRow + aNbFolders + 1); - } else { - int aFolderId = myXMLReader.rootFolderId(aObjType); - if (aFolderId != -1) { - insertRow(aRow, createIndex(aFolderId, 0, -1)); + if (aRow != -1) { + if (aObjType == aRootType) { + insertRow(aRow + aNbFolders + 1); + } else { + int aFolderId = myXMLReader->rootFolderId(aObjType); + if (aFolderId != -1) { + insertRow(aRow, createIndex(aFolderId, 0, (void*)Q_NULLPTR)); + } } - } + } } else { // Object created in sub-document - QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get()); + QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0); if (aDocRoot.isValid()) { // Check that new folders could appear QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false); foreach (QString aNotEmptyFolder, aNotEmptyFolders) { - if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) == 1)) + if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) > 0)) { // Appears first object in folder which can not be shown empty - insertRow(myXMLReader.subFolderId(aObjType), aDocRoot); - } - int aRow = aDoc->size(aObjType) - 1; - int aNbSubFolders = foldersCount(aDoc.get()); - if (aObjType == aSubType) { - // List of objects under document root - insertRow(aRow + aNbSubFolders, aDocRoot); - } else { - // List of objects under a folder - if (aRow != -1) { - int aFolderId = myXMLReader.subFolderId(aObjType); - if (aFolderId != -1) { - insertRow(aRow, createIndex(aFolderId, 0, aDoc.get())); + if (!hasShownFolder(aDoc, aNotEmptyFolder)) { + insertRow(myXMLReader->subFolderId(aObjType), aDocRoot); + addShownFolder(aDoc, aNotEmptyFolder); + } + } + } + int aRow = aDoc->index(aObject); + if (aRow != -1) { + int aNbSubFolders = foldersCount(aDoc.get()); + if (aObjType == aSubType) { + // List of objects under document root + insertRow(aRow + aNbSubFolders, aDocRoot); + } else { + // List of objects under a folder + if (aRow != -1) { + int aFolderId = folderId(aObjType, aDoc.get()); + if (aFolderId != -1) { + QModelIndex aParentFolder = createIndex(aFolderId, 0, aDoc.get()); + insertRow(aRow, aParentFolder); + emit dataChanged(aParentFolder, aParentFolder); + } } } + } else { + rebuildDataTree(); + break; } - } -#ifdef _DEBUG - else - Events_Error::send("Problem with Data Model definition of sub-document"); -#endif + } else { + rebuildDataTree(); + break; + } } } // Deleted object event *********************** @@ -143,90 +197,181 @@ void XGUI_DataModel::processEvent(const std::shared_ptr& theMess std::shared_ptr aUpdMsg = std::dynamic_pointer_cast(theMessage); DocumentPtr aDoc = aUpdMsg->document(); - std::set aGroups = aUpdMsg->groups(); - std::set::const_iterator aIt; + std::set aMsgGroups = aUpdMsg->groups(); + + /// Sort groups because RootType deletion has to be done after others + std::string aType = (aDoc == aRootDoc)? aRootType : aSubType; + std::list aGroups; + std::set::const_iterator aSetIt; + for (aSetIt = aMsgGroups.begin(); aSetIt != aMsgGroups.end(); ++aSetIt) { + std::string aGroup = (*aSetIt); + if (aGroup == aType) + aGroups.push_back(aGroup); + else + aGroups.push_front(aGroup); + } + + std::list::const_iterator aIt; for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) { std::string aGroup = (*aIt); if (aDoc == aRootDoc) { // If root objects int aRow = aRootDoc->size(aGroup); if (aGroup == aRootType) { + // Process root folder removeRow(aRow + aNbFolders); + rebuildBranch(aNbFolders, aRow); } else { - int aFolderId = myXMLReader.rootFolderId(aGroup); + // Process root sub-folder + int aFolderId = myXMLReader->rootFolderId(aGroup); if (aFolderId != -1) { - QModelIndex aFolderIndex = createIndex(aFolderId, 0, -1); + QModelIndex aFolderIndex = createIndex(aFolderId, 0, (void*)Q_NULLPTR); removeRow(aRow, aFolderIndex); + //rebuildBranch(0, aRow); } } // Check that some folders could erased QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(); foreach (QString aNotEmptyFolder, aNotEmptyFolders) { - if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup) == 0)) + if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup) == 0)) { // Appears first object in folder which can not be shown empty - removeRow(myXMLReader.rootFolderId(aGroup)); + removeRow(myXMLReader->rootFolderId(aGroup)); + removeShownFolder(aRootDoc, aNotEmptyFolder); + //rebuildBranch(0, aNbFolders + aDoc->size(myXMLReader->rootType())); + break; + } } } else { // Remove row for sub-document - QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get()); + QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0); if (aDocRoot.isValid()) { int aRow = aDoc->size(aGroup); int aNbSubFolders = foldersCount(aDoc.get()); if (aGroup == aSubType) { // List of objects under document root removeRow(aRow + aNbSubFolders, aDocRoot); + rebuildBranch(aNbSubFolders, aRow, aDocRoot); } else { // List of objects under a folder - int aFolderId = myXMLReader.subFolderId(aGroup); + int aFolderId = folderId(aGroup, aDoc.get()); if (aFolderId != -1) { - removeRow(aRow, createIndex(aFolderId, 0, aDoc.get())); + QModelIndex aFolderRoot = createIndex(aFolderId, 0, aDoc.get()); + removeRow(aRow, aFolderRoot); + //rebuildBranch(0, aRow, aFolderRoot); } } // Check that some folders could disappear QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false); + int aSize = aDoc->size(aGroup); foreach (QString aNotEmptyFolder, aNotEmptyFolders) { - if ((aNotEmptyFolder.toStdString() == aGroup) && (aDoc->size(aGroup) == 1)) + if ((aNotEmptyFolder.toStdString() == aGroup) && (aSize == 0)) { // Appears first object in folder which can not be shown empty - removeRow(myXMLReader.subFolderId(aGroup), aDocRoot); + removeRow(myXMLReader->subFolderId(aGroup), aDocRoot); + removeShownFolder(aDoc, aNotEmptyFolder); + //rebuildBranch(0, aNbSubFolders + aDoc->size(myXMLReader->subType()), aDocRoot); + break; + } } - } -#ifdef _DEBUG - else - Events_Error::send("Problem with Data Model definition of sub-document"); -#endif + } else { + rebuildDataTree(); + break; + } + } + } + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) { + std::shared_ptr aUpdMsg = + std::dynamic_pointer_cast(theMessage); + std::set aObjects = aUpdMsg->objects(); + + std::set::const_iterator aIt; + std::string aObjType; + for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) { + ObjectPtr aObject = (*aIt); + if (aObject->data()->isValid()) { + FeaturePtr aFeature = std::dynamic_pointer_cast(aObject); + if (aFeature.get() && aFeature->firstResult().get() + && (aFeature->firstResult()->groupName() == ModelAPI_ResultField::group())) { + ResultFieldPtr aResult = + std::dynamic_pointer_cast(aFeature->firstResult()); + QModelIndex aIndex = objectIndex(aResult, 0); + removeRows(0, aResult->stepsSize(), aIndex); + } else { + QModelIndex aIndex = objectIndex(aObject, 0); + if (aIndex.isValid()) { + emit dataChanged(aIndex, aIndex); + } + } + } else { + rebuildDataTree(); + break; + } + } + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) { + std::shared_ptr aUpdMsg = + std::dynamic_pointer_cast(theMessage); + if (aUpdMsg->reordered().get()) { + DocumentPtr aDoc = aUpdMsg->reordered()->document(); + std::string aGroup = aUpdMsg->reordered()->group(); + + QModelIndex aParent; + int aStartId = 0; + if (aDoc == aRootDoc) { + // Update a group under root + if (aGroup == myXMLReader->rootType()) // Update objects under root + aStartId = foldersCount(); + else // Update objects in folder under root + aParent = createIndex(folderId(aGroup), 0, (void*)Q_NULLPTR); + } else { + // Update a sub-document + if (aGroup == myXMLReader->subType()) { + // Update sub-document root + aParent = findDocumentRootIndex(aDoc.get(), 0); + aStartId = foldersCount(aDoc.get()); + } else + // update folder in sub-document + aParent = createIndex(folderId(aGroup, aDoc.get()), 0, aDoc.get()); } + int aChildNb = rowCount(aParent); + rebuildBranch(aStartId, aChildNb - aStartId, aParent); + } else { + rebuildDataTree(); } } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) { DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument(); if (aDoc != aRootDoc) { - QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get()); + QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0); if (aDocRoot.isValid()) emit dataChanged(aDocRoot, aDocRoot); -#ifdef _DEBUG else - Events_Error::send("Problem with Data Model definition of sub-document"); -#endif + // We have got a new document + rebuildDataTree(); } - } + } } //****************************************************** void XGUI_DataModel::clear() { - + beginResetModel(); + endResetModel(); } //****************************************************** void XGUI_DataModel::rebuildDataTree() { - + beginResetModel(); + endResetModel(); + emit treeRebuilt(); } //****************************************************** ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const { - if (theIndex.internalId() < 0) // this is a folder + if (theIndex.internalId() == 0) // this is a folder + return ObjectPtr(); + ModelAPI_Object* aObj = + dynamic_cast((ModelAPI_Entity*)theIndex.internalPointer()); + if (!aObj) return ObjectPtr(); - ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer(); if (getSubDocument(aObj)) // the selected index is a folder of sub-document return ObjectPtr(); @@ -234,7 +379,7 @@ ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const } //****************************************************** -QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const +QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const { std::string aType = theObject->groupName(); DocumentPtr aDoc = theObject->document(); @@ -257,30 +402,25 @@ QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const if (aResult.get()) { ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult); if (aCompRes.get()) { - for (int i = 0; i < aCompRes->numberOfSubs(true); i++) { - if (aCompRes->subResult(i, true) == theObject) { - aRow = i; - break; - } - } + aRow = ModelAPI_Tools::compSolidIndex(aResult); } } } if (aRow == -1) return QModelIndex(); - else - return createIndex(aRow, 0, theObject.get()); + else + return createIndex(aRow, theColumn, theObject.get()); } SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); - if (aDoc == aRootDoc && myXMLReader.rootType() == aType) { + if (aDoc == aRootDoc && myXMLReader->rootType() == aType) { // The object from root document aRow += foldersCount(); - } else if (myXMLReader.subType() == aType) { + } else if (myXMLReader->subType() == aType) { // The object from sub document aRow += foldersCount(aDoc.get()); } - return createIndex(aRow, 0, theObject.get()); + return createIndex(aRow, theColumn, theObject.get()); } //****************************************************** @@ -291,67 +431,113 @@ QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const int aNbFolders = foldersCount(); int theIndexRow = theIndex.row(); - if ((theRole == Qt::DecorationRole) && (theIndex == lastHistoryIndex())) - return QIcon(":pictures/arrow.png"); + if (theRole == Qt::DecorationRole) { + if (theIndex == lastHistoryIndex()) + return QIcon(":pictures/arrow.png"); + else if (theIndex.column() == 0) { + VisibilityState aState = getVisibilityState(theIndex); + switch (aState) { + case NoneState: + return QIcon(); + case Visible: + return QIcon(":pictures/eyeopen.png"); + case SemiVisible: + return QIcon(":pictures/eyemiclosed.png"); + case Hidden: + return QIcon(":pictures/eyeclosed.png"); + } + } + } - if (theIndex.column() == 1) + //if (theIndex.column() == 1) + if (theIndex.column() != 1) return QVariant(); - int aParentId = theIndex.internalId(); - if (aParentId == -1) { // root folders + quintptr aParentId = theIndex.internalId(); + if (aParentId == 0) { // root folders switch (theRole) { case Qt::DisplayRole: - return QString(myXMLReader.rootFolderName(theIndexRow).c_str()) + + return QString(myXMLReader->rootFolderName(theIndexRow).c_str()) + QString(" (%1)").arg(rowCount(theIndex)); case Qt::DecorationRole: - return QIcon(myXMLReader.rootFolderIcon(theIndexRow).c_str()); + return QIcon(myXMLReader->rootFolderIcon(theIndexRow).c_str()); case Qt::ForegroundRole: - if (aSession->activeDocument() == aRootDoc) - return QBrush(ACTIVE_COLOR); - else - return QBrush(PASSIVE_COLOR); + { + Qt::ItemFlags aFlags = theIndex.flags(); + if (aFlags == Qt::ItemFlags()) + return QBrush(DISABLED_COLOR); + if (!aFlags.testFlag(Qt::ItemIsEditable)) + return QBrush(SELECTABLE_COLOR); + } + return ACTIVE_COLOR; } } else { // an object or sub-document - ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer()); - if (theRole == Qt::ForegroundRole) { - bool aIsActive = false; - if (aSubDoc) - aIsActive = (aSession->activeDocument().get() == aSubDoc); - else { - ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer(); - if (aObj->isDisabled()) - return QBrush(Qt::lightGray); - aIsActive = (aSession->activeDocument() == aObj->document()); - } - if (aIsActive) - return QBrush(ACTIVE_COLOR); - else - return QBrush(PASSIVE_COLOR); + Qt::ItemFlags aFlags = theIndex.flags(); + if (aFlags == Qt::ItemFlags()) + return QBrush(DISABLED_COLOR); + if (!aFlags.testFlag(Qt::ItemIsEditable)) + return QBrush(SELECTABLE_COLOR); + return ACTIVE_COLOR; } + ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer()); if (aSubDoc) { // this is a folder of sub document - switch (theRole) { - case Qt::DisplayRole: - return QString(myXMLReader.subFolderName(theIndexRow).c_str()) + - QString(" (%1)").arg(rowCount(theIndex)); - case Qt::DecorationRole: - return QIcon(myXMLReader.subFolderIcon(theIndexRow).c_str()); + QIntList aMissedIdx = missedFolderIndexes(aSubDoc); + int aRow = theIndexRow; + while (aMissedIdx.contains(aRow)) + aRow++; + if (aRow < myXMLReader->subFoldersNumber()) { + switch (theRole) { + case Qt::DisplayRole: + return QString(myXMLReader->subFolderName(aRow).c_str()) + + QString(" (%1)").arg(rowCount(theIndex)); + case Qt::DecorationRole: + return QIcon(myXMLReader->subFolderIcon(aRow).c_str()); + } } } else { - ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer(); - switch (theRole) { - case Qt::DisplayRole: - if (aObj->groupName() == ModelAPI_ResultParameter::group()) { - ModelAPI_ResultParameter* aParam = dynamic_cast(aObj); - AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE()); - QString aVal = QString::number(aValueAttribute->value()); - QString aTitle = QString(aObj->data()->name().c_str()); - return aTitle + " = " + aVal; + ModelAPI_Object* aObj = + dynamic_cast((ModelAPI_Entity*)theIndex.internalPointer()); + if (aObj) { + switch (theRole) { + case Qt::DisplayRole: + { + if (aObj->groupName() == ModelAPI_ResultParameter::group()) { + ModelAPI_ResultParameter* aParam = dynamic_cast(aObj); + AttributeDoublePtr aValueAttribute = + aParam->data()->real(ModelAPI_ResultParameter::VALUE()); + QString aVal = QString::number(aValueAttribute->value()); + QString aTitle = QString(aObj->data()->name().c_str()); + return aTitle + " = " + aVal; + } + QString aSuffix; + if (aObj->groupName() == myXMLReader->subType()) { + ResultPartPtr aPartRes = getPartResult(aObj); + if (aPartRes.get()) { + if (aPartRes->partDoc().get() == NULL) + aSuffix = " (Not loaded)"; + } + } + return aObj->data()->name().c_str() + aSuffix; + } + case Qt::DecorationRole: + return ModuleBase_IconFactory::get()->getIcon(object(theIndex)); + } + } else { + switch (theRole) { + case Qt::DisplayRole: + { + ModelAPI_ResultField::ModelAPI_FieldStep* aStep = + dynamic_cast + ((ModelAPI_Entity*)theIndex.internalPointer()); + if (aStep) { + return "Step " + QString::number(aStep->id() + 1) + " " + + aStep->field()->textLine(aStep->id()).c_str(); + } + } + break; } - return aObj->data()->name().c_str(); - case Qt::DecorationRole: - return ModuleBase_IconFactory::get()->getIcon(object(theIndex)); } } } @@ -376,46 +562,58 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const // Return number of items in root int aNbFolders = foldersCount(); int aNbItems = 0; - std::string aType = myXMLReader.rootType(); + std::string aType = myXMLReader->rootType(); if (!aType.empty()) aNbItems = aRootDoc->size(aType); return aNbFolders + aNbItems; } - int aId = theParent.internalId(); - if (aId == -1) { + quintptr aId = theParent.internalId(); + if (aId == 0) { // this is a folder under root int aParentPos = theParent.row(); - std::string aType = myXMLReader.rootFolderType(aParentPos); - //qDebug("### %s = %i\n", aType.c_str(), aRootDoc->size(aType)); + std::string aType = myXMLReader->rootFolderType(aParentPos); return aRootDoc->size(aType); } else { // It is an object which could have children ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer()); - if (aDoc) { + if (aDoc) { // a folder of sub-document - std::string aType = myXMLReader.subFolderType(theParent.row()); - return aDoc->size(aType); + QIntList aMissedIdx = missedFolderIndexes(aDoc); + int aRow = theParent.row(); + while (aMissedIdx.contains(aRow)) + aRow++; + if (aRow < myXMLReader->subFoldersNumber()) { + std::string aType = myXMLReader->subFolderType(aRow); + return aDoc->size(aType); + } } else { - ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer(); + ModelAPI_Object* aObj = + dynamic_cast((ModelAPI_Entity*)theParent.internalPointer()); // Check for Part feature ResultPartPtr aPartRes = getPartResult(aObj); if (aPartRes.get()) { DocumentPtr aSubDoc = aPartRes->partDoc(); + if (!aSubDoc.get()) + return 0; + int aNbSubFolders = foldersCount(aSubDoc.get()); int aNbSubItems = 0; - std::string aSubType = myXMLReader.subType(); + std::string aSubType = myXMLReader->subType(); if (!aSubType.empty()) aNbSubItems = aSubDoc->size(aSubType); return aNbSubItems + aNbSubFolders; } else { // Check for composite object ModelAPI_CompositeFeature* aCompFeature = dynamic_cast(aObj); - if (aCompFeature) + if (aCompFeature) return aCompFeature->numberOfSubs(true); ModelAPI_ResultCompSolid* aCompRes = dynamic_cast(aObj); - if (aCompRes) + if (aCompRes) return aCompRes->numberOfSubs(true); + ModelAPI_ResultField* aFieldRes = dynamic_cast(aObj); + if (aFieldRes) + return aFieldRes->stepsSize(); } } } @@ -425,7 +623,7 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const //****************************************************** int XGUI_DataModel::columnCount(const QModelIndex& theParent) const { - return 2; + return 3; } //****************************************************** @@ -439,36 +637,43 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex & if (!theParent.isValid()) { if (theRow < aNbFolders) // Return first level folder index - return createIndex(theRow, theColumn, -1); + return createIndex(theRow, theColumn, (void*)Q_NULLPTR); else { // return object under root index - std::string aType = myXMLReader.rootType(); + std::string aType = myXMLReader->rootType(); int aObjId = theRow - aNbFolders; if (aObjId < aRootDoc->size(aType)) { ObjectPtr aObj = aRootDoc->object(aType, aObjId); - aIndex = objectIndex(aObj); + aIndex = objectIndex(aObj, theColumn); } } } else { - int aId = theParent.internalId(); + quintptr aId = theParent.internalId(); int aParentPos = theParent.row(); - if (aId == -1) { // return object index inside of first level of folders - std::string aType = myXMLReader.rootFolderType(aParentPos); + if (aId == 0) { // return object index inside of first level of folders + std::string aType = myXMLReader->rootFolderType(aParentPos); if (theRow < aRootDoc->size(aType)) { ObjectPtr aObj = aRootDoc->object(aType, theRow); - aIndex = objectIndex(aObj); + aIndex = objectIndex(aObj, theColumn); } } else { // It is an object which could have children ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer()); - if (aDoc) { + if (aDoc) { // It is a folder of sub-document - std::string aType = myXMLReader.subFolderType(aParentPos); - if (theRow < aDoc->size(aType)) { - ObjectPtr aObj = aDoc->object(aType, theRow); - aIndex = objectIndex(aObj); + int aParentRow = aParentPos; + QIntList aMissedIdx = missedFolderIndexes(aDoc); + while (aMissedIdx.contains(aParentRow)) + aParentRow++; + if (aParentRow < myXMLReader->subFoldersNumber()) { + std::string aType = myXMLReader->subFolderType(aParentRow); + if (theRow < aDoc->size(aType)) { + ObjectPtr aObj = aDoc->object(aType, theRow); + aIndex = objectIndex(aObj, theColumn); + } } } else { - ModelAPI_Object* aParentObj = (ModelAPI_Object*)theParent.internalPointer(); + ModelAPI_Object* aParentObj = + dynamic_cast((ModelAPI_Entity*)theParent.internalPointer()); // Check for Part feature ResultPartPtr aPartRes = getPartResult(aParentObj); @@ -479,26 +684,33 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex & aIndex = createIndex(theRow, theColumn, aSubDoc.get()); } else { // this is an object under sub document root - std::string aType = myXMLReader.subType(); + std::string aType = myXMLReader->subType(); ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders); - aIndex = objectIndex(aObj); + aIndex = objectIndex(aObj, theColumn); } } else { // Check for composite object - ModelAPI_CompositeFeature* aCompFeature = dynamic_cast(aParentObj); + ModelAPI_CompositeFeature* aCompFeature = + dynamic_cast(aParentObj); if (aCompFeature) { - aIndex = objectIndex(aCompFeature->subFeature(theRow)); + aIndex = objectIndex(aCompFeature->subFeature(theRow), theColumn); } else { - ModelAPI_ResultCompSolid* aCompRes = dynamic_cast(aParentObj); - if (aCompRes) - aIndex = objectIndex(aCompRes->subResult(theRow)); + ModelAPI_ResultCompSolid* aCompRes = + dynamic_cast(aParentObj); + if (aCompRes) + aIndex = objectIndex(aCompRes->subResult(theRow), theColumn); + else { + ModelAPI_ResultField* aFieldRes = + dynamic_cast(aParentObj); + if (aFieldRes) { + aIndex = createIndex(theRow, theColumn, aFieldRes->step(theRow)); + } + } } } } } } - if (theColumn != 0) - return createIndex(aIndex.row(), theColumn, aIndex.internalPointer()); return aIndex; } @@ -506,19 +718,36 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex & static QModelIndex MYLastDeleted; QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const { + if (!theIndex.isValid()) + return QModelIndex(); // To avoid additional request about index which was already deleted if (theIndex == MYLastDeleted) return QModelIndex(); - int aId = theIndex.internalId(); - if (aId != -1) { // The object is not a root folder + SessionPtr aSession = ModelAPI_Session::get(); + quintptr aId = theIndex.internalId(); + if (aId != 0) { // The object is not a root folder ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer()); - if (aDoc) { + if (aDoc) { // It is a folder of sub-document return findDocumentRootIndex(aDoc); } ObjectPtr aObj = object(theIndex); if (!aObj.get()) { + // It can b e a step of a field + ModelAPI_ResultField::ModelAPI_FieldStep* aStep = + dynamic_cast + ((ModelAPI_Entity*)theIndex.internalPointer()); + if (aStep) { + ModelAPI_ResultField* aField = aStep->field(); + DocumentPtr aDoc = aSession->activeDocument(); + ObjectPtr aFld; + for(int i = 0; i < aDoc->size(ModelAPI_ResultField::group()); i++) { + aFld = aDoc->object(ModelAPI_ResultField::group(), i); + if (aFld.get() == aField) + return objectIndex(aFld); + } + } // To avoid additional request about index which was already deleted // If deleted it causes a crash on delete object from Part MYLastDeleted = theIndex; @@ -541,76 +770,35 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const } // Use as ordinary object std::string aType = aObj->groupName(); - SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); DocumentPtr aSubDoc = aObj->document(); if (aSubDoc == aRootDoc) { - if (aType == myXMLReader.rootType()) + if (aType == myXMLReader->rootType()) return QModelIndex(); else { // return first level of folder index - int aFolderId = myXMLReader.rootFolderId(aType); + int aFolderId = myXMLReader->rootFolderId(aType); // Items in a one row must have the same parent - return createIndex(aFolderId, 0, -1); + return createIndex(aFolderId, 1, (void*)Q_NULLPTR); } } else { - if (aType == myXMLReader.subType()) + if (aType == myXMLReader->subType()) return findDocumentRootIndex(aSubDoc.get()); else { // return first level of folder index - int aFolderId = myXMLReader.subFolderId(aType); + int aFolderId = folderId(aType, aSubDoc.get()); // Items in a one row must have the same parent - return createIndex(aFolderId, 0, aSubDoc.get()); + return createIndex(aFolderId, 1, aSubDoc.get()); } } - } + } return QModelIndex(); } //****************************************************** bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const { - if (!theParent.isValid()) { - int aNbFolders = foldersCount(); - if (aNbFolders > 0) - return true; - SessionPtr aSession = ModelAPI_Session::get(); - DocumentPtr aRootDoc = aSession->moduleDocument(); - return aRootDoc->size(myXMLReader.rootType()) > 0; - } - if (theParent.internalId() == -1) { - std::string aType = myXMLReader.rootFolderType(theParent.row()); - if (!aType.empty()) { - SessionPtr aSession = ModelAPI_Session::get(); - DocumentPtr aRootDoc = aSession->moduleDocument(); - return aRootDoc->size(aType) > 0; - } - } else { - ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer()); - if (aDoc) { - // a folder of sub-document - std::string aType = myXMLReader.subFolderType(theParent.row()); - return aDoc->size(aType) > 0; - } else { - // Check that it could be an object with children - ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer(); - - // Check for Part feature - ResultPartPtr aPartRes = getPartResult(aObj); - if (aPartRes.get()) - return aPartRes->partDoc().get() != NULL; - else { - // Check for composite object - ModelAPI_CompositeFeature* aCompFeature = dynamic_cast(aObj); - if (aCompFeature) - return aCompFeature->numberOfSubs(true) > 0; - ModelAPI_ResultCompSolid* aCompRes = dynamic_cast(aObj); - if (aCompRes) - return aCompRes->numberOfSubs(true) > 0; - } - } - } - return false; + return rowCount(theParent) > 0; } //****************************************************** @@ -633,29 +821,82 @@ bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& the //****************************************************** Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const { - Qt::ItemFlags aFlags = Qt::ItemIsSelectable; - + quintptr aIt = theIndex.internalId(); ModelAPI_Object* aObj = 0; - if (theIndex.internalId() != -1) { - if (!getSubDocument(theIndex.internalPointer())) - aObj = (ModelAPI_Object*) theIndex.internalPointer(); + ModelAPI_Document* aDoc = 0; + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aActiveDoc = aSession->activeDocument(); + + Qt::ItemFlags aNullFlag; + Qt::ItemFlags aDefaultFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + Qt::ItemFlags aEditingFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; + + + if (aIt == 0) { + // Folders under root + DocumentPtr aRootDoc = aSession->moduleDocument(); + if (aRootDoc != aActiveDoc) + return aDefaultFlag; + } else { + aDoc = getSubDocument(theIndex.internalPointer()); + if (!aDoc) + aObj = dynamic_cast((ModelAPI_Entity*)theIndex.internalPointer()); } + if (aObj) { - aFlags |= Qt::ItemIsEditable; - - if (!aObj->isDisabled()) - aFlags |= Qt::ItemIsEnabled; - } else - aFlags |= Qt::ItemIsEnabled; - return aFlags; + // An object + if (aObj->isDisabled()) + return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag; + + if (aSession->moduleDocument() != aObj->document()) + if (aActiveDoc != aObj->document()) + return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag; + + bool isCompositeSub = false; + // An object which is sub-object of a composite object can not be accessible in column 2 + if (theIndex.column() == 2) { + ObjectPtr aObjPtr = aObj->data()->owner(); + FeaturePtr aFeature = std::dynamic_pointer_cast(aObjPtr); + if (aFeature.get()) { + CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature); + if (aCompFea.get()) + isCompositeSub = true; + } else { + ResultPtr aResult = std::dynamic_pointer_cast(aObjPtr); + if (aResult.get()) { + ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult); + if (aCompRes.get()) + isCompositeSub = true; + } + } + } + if (isCompositeSub) + return Qt::ItemIsSelectable; + + if (aObj->document() != aActiveDoc) { + // The object could be a root of sub-tree + ResultPartPtr aPartRes = getPartResult(aObj); + if (aPartRes.get()) { + if (aPartRes->partDoc() == aActiveDoc) + return aEditingFlag; + } + return aDefaultFlag; + } + } else if (aDoc) { + // A folder under sub-document + if (aActiveDoc.get() != aDoc) + return aNullFlag; + } + return aEditingFlag; } //****************************************************** -QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc) const +QModelIndex + XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn) const { SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); - if (myXMLReader.isAttachToResult()) { // If document is attached to result + if (myXMLReader->isAttachToResult()) { // If document is attached to result int aNb = aRootDoc->size(ModelAPI_ResultPart::group()); ObjectPtr aObj; ResultPartPtr aPartRes; @@ -664,9 +905,10 @@ QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDo aPartRes = std::dynamic_pointer_cast(aObj); if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) { int aRow = i; - if (myXMLReader.rootType() == ModelAPI_Feature::group()) + if (myXMLReader->rootType() == ModelAPI_Feature::group()) { aRow += foldersCount(); - return createIndex(aRow, 0, aObj.get()); + } + return createIndex(aRow, aColumn, aObj.get()); } } } else { // If document is attached to feature @@ -678,9 +920,9 @@ QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDo aPartRes = getPartResult(aObj.get()); if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) { int aRow = i; - if (myXMLReader.rootType() == ModelAPI_Feature::group()) + if (myXMLReader->rootType() == ModelAPI_Feature::group()) aRow += foldersCount(); - return createIndex(aRow, 0, aObj.get()); + return createIndex(aRow, aColumn, aObj.get()); } } } @@ -688,14 +930,14 @@ QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDo } //****************************************************** -QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc) const +QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const { SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); if (theDoc == aRootDoc) return QModelIndex(); - else - return findDocumentRootIndex(theDoc.get()); + else + return findDocumentRootIndex(theDoc.get(), theColumn); } //****************************************************** @@ -705,20 +947,20 @@ int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); if ((theDoc == 0) || (theDoc == aRootDoc.get())) { - for (int i = 0; i < myXMLReader.rootFoldersNumber(); i++) { - if (myXMLReader.rootShowEmpty(i)) + for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) { + if (myXMLReader->rootShowEmpty(i)) aNb++; else { - if (aRootDoc->size(myXMLReader.rootFolderType(i)) > 0) + if (aRootDoc->size(myXMLReader->rootFolderType(i)) > 0) aNb++; } } } else { - for (int i = 0; i < myXMLReader.subFoldersNumber(); i++) { - if (myXMLReader.subShowEmpty(i)) + for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) { + if (myXMLReader->subShowEmpty(i)) aNb++; else { - if (theDoc->size(myXMLReader.subFolderType(i)) > 0) + if (theDoc->size(myXMLReader->subFolderType(i)) > 0) aNb++; } } @@ -726,19 +968,45 @@ int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const return aNb; } + +//****************************************************** +QIntList XGUI_DataModel::missedFolderIndexes(ModelAPI_Document* theDoc) const +{ + QIntList aList; + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aRootDoc = aSession->moduleDocument(); + if ((theDoc == 0) || (theDoc == aRootDoc.get())) { + for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) { + if (!myXMLReader->rootShowEmpty(i)) { + if (aRootDoc->size(myXMLReader->rootFolderType(i)) == 0) + aList.append(i); + } + } + } else { + for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) { + if (!myXMLReader->subShowEmpty(i)) { + if (theDoc->size(myXMLReader->subFolderType(i)) == 0) + aList.append(i); + } + } + } + return aList; +} + + //****************************************************** QStringList XGUI_DataModel::listOfShowNotEmptyFolders(bool fromRoot) const { QStringList aResult; if (fromRoot) { - for (int i = 0; i < myXMLReader.rootFoldersNumber(); i++) { - if (!myXMLReader.rootShowEmpty(i)) - aResult << myXMLReader.rootFolderType(i).c_str(); + for (int i = 0; i < myXMLReader->rootFoldersNumber(); i++) { + if (!myXMLReader->rootShowEmpty(i)) + aResult << myXMLReader->rootFolderType(i).c_str(); } } else { - for (int i = 0; i < myXMLReader.subFoldersNumber(); i++) { - if (!myXMLReader.subShowEmpty(i)) - aResult << myXMLReader.subFolderType(i).c_str(); + for (int i = 0; i < myXMLReader->subFoldersNumber(); i++) { + if (!myXMLReader->subShowEmpty(i)) + aResult << myXMLReader->subFolderType(i).c_str(); } } return aResult; @@ -752,11 +1020,100 @@ QModelIndex XGUI_DataModel::lastHistoryIndex() const FeaturePtr aFeature = aCurDoc->currentFeature(true); if (aFeature.get()) { QModelIndex aInd = objectIndex(aFeature); - return createIndex(aInd.row(), 1, aInd.internalPointer()); + return createIndex(aInd.row(), 2, aInd.internalPointer()); } else { if (aCurDoc == aSession->moduleDocument()) - return createIndex(foldersCount() - 1, 1, -1); - else - return createIndex(foldersCount(aCurDoc.get()) - 1, 1, aCurDoc.get()); + return createIndex(foldersCount() - 1, 2, -1); + else + return createIndex(foldersCount(aCurDoc.get()) - 1, 2, aCurDoc.get()); + } +} + +//****************************************************** +int XGUI_DataModel::folderId(std::string theType, ModelAPI_Document* theDoc) const +{ + SessionPtr aSession = ModelAPI_Session::get(); + ModelAPI_Document* aDoc = theDoc; + if (aDoc == 0) + aDoc = aSession->moduleDocument().get(); + + bool aUseSubDoc = (aDoc != aSession->moduleDocument().get()); + + int aRes = -1; + if (aUseSubDoc) { + int aId = myXMLReader->subFolderId(theType); + aRes = aId; + for (int i = 0; i < aId; i++) { + if (!myXMLReader->subShowEmpty(i)) { + if (aDoc->size(myXMLReader->subFolderType(i)) == 0) + aRes--; + } + } + } else { + int aId = myXMLReader->rootFolderId(theType); + aRes = aId; + for (int i = 0; i < aId; i++) { + if (!myXMLReader->rootShowEmpty(i)) { + if (aDoc->size(myXMLReader->rootFolderType(i)) == 0) + aRes--; + } + } + } + return aRes; +} + +//****************************************************** +void XGUI_DataModel::rebuildBranch(int theRow, int theCount, const QModelIndex& theParent) +{ + if (theCount > 0) { + removeRows(theRow, theCount, theParent); + insertRows(theRow, theCount, theParent); + } +} + +//****************************************************** +//bool XGUI_DataModel::blockEventsProcessing(const bool theState) +//{ +// bool aPreviousState = myIsEventsProcessingBlocked; +// myIsEventsProcessingBlocked = theState; +// return aPreviousState; +//} + +//****************************************************** +XGUI_DataModel::VisibilityState + XGUI_DataModel::getVisibilityState(const QModelIndex& theIndex) const +{ + Qt::ItemFlags aFlags = theIndex.flags(); + if (aFlags == Qt::ItemFlags()) + return NoneState; + + ObjectPtr aObj = object(theIndex); + if (aObj.get()) { + ResultPtr aResObj = std::dynamic_pointer_cast(aObj); + if (aResObj.get()) { + XGUI_Displayer* aDisplayer = myWorkshop->displayer(); + ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast(aResObj); + if (aCompRes.get()) { + VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ? + (aDisplayer->isVisible(aCompRes)? Visible : Hidden) : NoneState; + for (int i = 0; i < aCompRes->numberOfSubs(true); i++) { + ResultPtr aSubRes = aCompRes->subResult(i, true); + VisibilityState aS = aDisplayer->isVisible(aSubRes)? Visible : Hidden; + if (aState == NoneState) + aState = aS; + else if (aState != aS) { + aState = SemiVisible; + break; + } + } + return aState; + } else { + if (aDisplayer->isVisible(aResObj)) + return Visible; + else + return Hidden; + } + } } -} \ No newline at end of file + return NoneState; +}