X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_DataModel.cpp;h=fa38f0a1d4a129570bd723d9a2d22d54a2dee8fa;hb=45314f99ce0639af40401746aab4917f076102f2;hp=35cadb93c0fab97a8d1b51acd7794f83207f99cb;hpb=f3b6abdd8d0a128e2fdb93273190ff24f9bf0609;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_DataModel.cpp b/src/XGUI/XGUI_DataModel.cpp index 35cadb93c..fa38f0a1d 100644 --- a/src/XGUI/XGUI_DataModel.cpp +++ b/src/XGUI/XGUI_DataModel.cpp @@ -6,11 +6,17 @@ #include "XGUI_DataModel.h" +#include + #include #include #include #include #include +#include +#include +#include +#include #include @@ -18,6 +24,11 @@ #include #include +#include + +#define ACTIVE_COLOR 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 @@ -27,7 +38,10 @@ ResultPartPtr getPartResult(ModelAPI_Object* 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(); @@ -51,7 +65,9 @@ XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParen 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(Config_FeatureMessage::GUI_EVENT())); + 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)); } //****************************************************** @@ -60,8 +76,7 @@ void XGUI_DataModel::processEvent(const std::shared_ptr& theMess DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); std::string aRootType = myXMLReader.rootType(); std::string aSubType = myXMLReader.subType(); - int aNbFolders = myXMLReader.rootFoldersNumber(); - int aNbSubFolders = myXMLReader.subFoldersNumber(); + int aNbFolders = foldersCount(); // Created object event ******************* if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) { @@ -73,36 +88,65 @@ 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 does not need to be shown in object browser + if (!aObject->isInHistory()) + continue; + aObjType = aObject->groupName(); DocumentPtr aDoc = aObject->document(); if (aDoc == aRootDoc) { + // Check that new folders could appear + QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(); + foreach (QString aNotEmptyFolder, aNotEmptyFolders) { + if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) == 1)) + // Appears first object in folder which can not be shown empty + insertRow(myXMLReader.rootFolderId(aObjType)); + } + // Insert new object int aRow = aRootDoc->size(aObjType) - 1; - if (aObjType == aRootType) { - insertRow(aRow + aNbFolders); - } 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, -1)); + } + } + } } else { // Object created in sub-document QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get()); if (aDocRoot.isValid()) { - int aRow = aDoc->size(aObjType) - 1; - if (aObjType == aSubType) { - insertRow(aRow + aNbSubFolders, aDocRoot); - } else { - int aFolderId = myXMLReader.subFolderId(aObjType); - if (aFolderId != -1) { - insertRow(aRow, createIndex(aFolderId, 0, aDoc.get())); + // Check that new folders could appear + QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false); + foreach (QString aNotEmptyFolder, aNotEmptyFolders) { + if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) == 1)) + // Appears first object in folder which can not be shown empty + insertRow(myXMLReader.subFolderId(aObjType), aDocRoot); + } + 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); + } + } } } } #ifdef _DEBUG - else { + else Events_Error::send("Problem with Data Model definition of sub-document"); - } #endif } } @@ -118,16 +162,114 @@ void XGUI_DataModel::processEvent(const std::shared_ptr& theMess if (aDoc == aRootDoc) { // If root objects int aRow = aRootDoc->size(aGroup); if (aGroup == aRootType) { + // Process root folder removeRow(aRow + aNbFolders); + rebuildBranch(aNbFolders, aRow); } else { + // Process root sub-folder int aFolderId = myXMLReader.rootFolderId(aGroup); if (aFolderId != -1) { QModelIndex aFolderIndex = createIndex(aFolderId, 0, -1); 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)) { + // Appears first object in folder which can not be shown empty + removeRow(myXMLReader.rootFolderId(aGroup)); + //rebuildBranch(0, aNbFolders + aDoc->size(myXMLReader.rootType())); + break; + } + } + } else { + // Remove row for sub-document + QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get()); + 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 = folderId(aGroup, aDoc.get()); + if (aFolderId != -1) { + 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) && (aSize == 0)) { + // Appears first object in folder which can not be shown empty + removeRow(myXMLReader.subFolderId(aGroup), aDocRoot); + //rebuildBranch(0, aNbSubFolders + aDoc->size(myXMLReader.subType()), aDocRoot); + 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); + QModelIndex aIndex = objectIndex(aObject); + if (aIndex.isValid()) + emit dataChanged(aIndex, aIndex); + } + } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_ORDER_UPDATED)) { + std::shared_ptr aUpdMsg = + std::dynamic_pointer_cast(theMessage); + DocumentPtr aDoc = aUpdMsg->document(); + std::string aGroup = aUpdMsg->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, -1); + } else { + // Update a sub-document + if (aGroup == myXMLReader.subType()) { + // Update sub-document root + aParent = findDocumentRootIndex(aDoc.get()); + 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 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) { + DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument(); + if (aDoc != aRootDoc) { + QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get()); + if (aDocRoot.isValid()) + emit dataChanged(aDocRoot, aDocRoot); + else + // We have got a new document + rebuildDataTree(); +//#ifdef _DEBUG +// else +// Events_Error::send("Problem with Data Model definition of sub-document"); +//#endif + } } } @@ -140,7 +282,8 @@ void XGUI_DataModel::clear() //****************************************************** void XGUI_DataModel::rebuildDataTree() { - + beginResetModel(); + endResetModel(); } //****************************************************** @@ -152,18 +295,7 @@ ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const if (getSubDocument(aObj)) // the selected index is a folder of sub-document return ObjectPtr(); - // We can not create the ObjectPtr directly because the pointer will be deleted - // with deletion of the ObjectPtr because its counter become to 0. - DocumentPtr aDoc = aObj->document(); - std::string aType = aObj->groupName(); - - ObjectPtr aObjPtr; - for (int i = 0; i < aDoc->size(aType); i++) { - aObjPtr = aDoc->object(aType, i); - if (aObjPtr.get() == aObj) - return aObjPtr; - } - return ObjectPtr(); + return aObj->data()->owner(); } //****************************************************** @@ -172,17 +304,46 @@ QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const std::string aType = theObject->groupName(); DocumentPtr aDoc = theObject->document(); int aRow = aDoc->index(theObject); - if (aRow == -1) - return QModelIndex(); - + if (aRow == -1) { + // it could be a part of complex object + FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); + if (aFeature.get()) { + CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature); + if (aCompFea.get()) { + for (int i = 0; i < aCompFea->numberOfSubs(true); i++) { + if (aCompFea->subFeature(i, true) == theObject) { + aRow = i; + break; + } + } + } + } else { + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + 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; + } + } + } + } + } + if (aRow == -1) + return QModelIndex(); + else + return createIndex(aRow, 0, theObject.get()); + } SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); if (aDoc == aRootDoc && myXMLReader.rootType() == aType) { // The object from root document - aRow += myXMLReader.rootFoldersNumber(); + aRow += foldersCount(); } else if (myXMLReader.subType() == aType) { // The object from sub document - aRow += myXMLReader.subFoldersNumber(); + aRow += foldersCount(aDoc.get()); } return createIndex(aRow, 0, theObject.get()); } @@ -192,17 +353,14 @@ QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const { SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); - int aNbFolders = myXMLReader.rootFoldersNumber(); + int aNbFolders = foldersCount(); int theIndexRow = theIndex.row(); - if ((theIndex.column() == 1) ) { - //if (theIndexRow >= aNbFolders) { - // if (theRole == Qt::DecorationRole) { - // return QIcon(":pictures/arrow.png"); - // } - //} + if ((theRole == Qt::DecorationRole) && (theIndex == lastHistoryIndex())) + return QIcon(":pictures/arrow.png"); + + if (theIndex.column() == 1) return QVariant(); - } int aParentId = theIndex.internalId(); if (aParentId == -1) { // root folders @@ -212,29 +370,56 @@ QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const QString(" (%1)").arg(rowCount(theIndex)); case Qt::DecorationRole: return QIcon(myXMLReader.rootFolderIcon(theIndexRow).c_str()); + case Qt::ForegroundRole: + if ((theIndex.flags() & Qt::ItemIsEditable) == 0) + return QBrush(Qt::lightGray); + return ACTIVE_COLOR; } - } else { + } else { // an object or sub-document + if (theRole == Qt::ForegroundRole) { + if ((theIndex.flags() & Qt::ItemIsEditable) == 0) + return QBrush(Qt::lightGray); + return ACTIVE_COLOR; + } + ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer()); if (aSubDoc) { // this is a folder of sub document + QIntList aMissedIdx = missedFolderIndexes(aSubDoc); + int aRow = theIndexRow; + while (aMissedIdx.contains(aRow)) + aRow++; + switch (theRole) { case Qt::DisplayRole: - return QString(myXMLReader.subFolderName(theIndexRow).c_str()) + + return QString(myXMLReader.subFolderName(aRow).c_str()) + QString(" (%1)").arg(rowCount(theIndex)); case Qt::DecorationRole: - return QIcon(myXMLReader.subFolderIcon(theIndexRow).c_str()); + 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; + { + 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; } - return aObj->data()->name().c_str(); + case Qt::DecorationRole: + return ModuleBase_IconFactory::get()->getIcon(object(theIndex)); } } } @@ -257,7 +442,7 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const if (!theParent.isValid()) { // Return number of items in root - int aNbFolders = myXMLReader.rootFoldersNumber(); + int aNbFolders = foldersCount(); int aNbItems = 0; std::string aType = myXMLReader.rootType(); if (!aType.empty()) @@ -269,29 +454,42 @@ int XGUI_DataModel::rowCount(const QModelIndex& theParent) const if (aId == -1) { // this is a folder under root int aParentPos = theParent.row(); - if (aId == -1) { // first level of folders - std::string aType = myXMLReader.rootFolderType(aParentPos); - return 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) { // a folder of sub-document - std::string aType = myXMLReader.subFolderType(theParent.row()); + QIntList aMissedIdx = missedFolderIndexes(aDoc); + int aRow = theParent.row(); + while (aMissedIdx.contains(aRow)) + aRow++; + std::string aType = myXMLReader.subFolderType(aRow); return aDoc->size(aType); } else { - // Check for Part feature ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer(); + // Check for Part feature ResultPartPtr aPartRes = getPartResult(aObj); if (aPartRes.get()) { DocumentPtr aSubDoc = aPartRes->partDoc(); - int aNbSubFolders = myXMLReader.subFoldersNumber(); + if (!aSubDoc.get()) + return 0; + + int aNbSubFolders = foldersCount(aSubDoc.get()); int aNbSubItems = 0; 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) + return aCompFeature->numberOfSubs(true); + ModelAPI_ResultCompSolid* aCompRes = dynamic_cast(aObj); + if (aCompRes) + return aCompRes->numberOfSubs(true); } } } @@ -309,7 +507,9 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex & { SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); - int aNbFolders = myXMLReader.rootFoldersNumber(); + int aNbFolders = foldersCount(); + + QModelIndex aIndex; if (!theParent.isValid()) { if (theRow < aNbFolders) // Return first level folder index @@ -319,66 +519,75 @@ QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex & int aObjId = theRow - aNbFolders; if (aObjId < aRootDoc->size(aType)) { ObjectPtr aObj = aRootDoc->object(aType, aObjId); - QModelIndex aIndex = objectIndex(aObj); - if (theColumn != 0) - return createIndex(aIndex.row(), theColumn, aIndex.internalPointer()); - return aIndex; + aIndex = objectIndex(aObj); } - return QModelIndex(); - } - } - int 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 (theRow < aRootDoc->size(aType)) { - ObjectPtr aObj = aRootDoc->object(aType, theRow); - QModelIndex aIndex = objectIndex(aObj); - if (theColumn != 0) - return createIndex(aIndex.row(), theColumn, aIndex.internalPointer()); - return aIndex; } } else { - // It is an object which could have children - ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer()); - 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); - QModelIndex aIndex = objectIndex(aObj); - if (theColumn != 0) - return createIndex(aIndex.row(), theColumn, aIndex.internalPointer()); - return aIndex; + int 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 (theRow < aRootDoc->size(aType)) { + ObjectPtr aObj = aRootDoc->object(aType, theRow); + aIndex = objectIndex(aObj); } } else { - ModelAPI_Object* aParentObj = (ModelAPI_Object*)theParent.internalPointer(); - - // Check for Part feature - ResultPartPtr aPartRes = getPartResult(aParentObj); - if (aPartRes.get()) { - DocumentPtr aSubDoc = aPartRes->partDoc(); - int aNbSubFolders = myXMLReader.subFoldersNumber(); - if (theRow < aNbSubFolders) { // Create a Folder of sub-document - return createIndex(theRow, theColumn, aSubDoc.get()); + // It is an object which could have children + ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer()); + if (aDoc) { + // It is a folder of sub-document + int aParentRow = aParentPos; + QIntList aMissedIdx = missedFolderIndexes(aDoc); + while (aMissedIdx.contains(aParentRow)) + aParentRow++; + std::string aType = myXMLReader.subFolderType(aParentRow); + if (theRow < aDoc->size(aType)) { + ObjectPtr aObj = aDoc->object(aType, theRow); + aIndex = objectIndex(aObj); + } + } else { + ModelAPI_Object* aParentObj = (ModelAPI_Object*)theParent.internalPointer(); + + // Check for Part feature + ResultPartPtr aPartRes = getPartResult(aParentObj); + if (aPartRes.get()) { + DocumentPtr aSubDoc = aPartRes->partDoc(); + int aNbSubFolders = foldersCount(aSubDoc.get()); + if (theRow < aNbSubFolders) { // Create a Folder of sub-document + aIndex = createIndex(theRow, theColumn, aSubDoc.get()); + } else { + // this is an object under sub document root + std::string aType = myXMLReader.subType(); + ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders); + aIndex = objectIndex(aObj); + } } else { - // this is an object under sub document root - std::string aType = myXMLReader.subType(); - ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders); - QModelIndex aIndex = objectIndex(aObj); - if (theColumn != 0) - return createIndex(aIndex.row(), theColumn, aIndex.internalPointer()); - return aIndex; + // Check for composite object + ModelAPI_CompositeFeature* aCompFeature = dynamic_cast(aParentObj); + if (aCompFeature) { + aIndex = objectIndex(aCompFeature->subFeature(theRow)); + } else { + ModelAPI_ResultCompSolid* aCompRes = dynamic_cast(aParentObj); + if (aCompRes) + aIndex = objectIndex(aCompRes->subResult(theRow)); + } } } } } - return QModelIndex(); + if (theColumn != 0) + return createIndex(aIndex.row(), theColumn, aIndex.internalPointer()); + return aIndex; } //****************************************************** +static QModelIndex MYLastDeleted; QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const { + // 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 ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer()); @@ -386,7 +595,29 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const // It is a folder of sub-document return findDocumentRootIndex(aDoc); } - ModelAPI_Object* aObj = (ModelAPI_Object*) theIndex.internalPointer(); + ObjectPtr aObj = object(theIndex); + if (!aObj.get()) { + // To avoid additional request about index which was already deleted + // If deleted it causes a crash on delete object from Part + MYLastDeleted = theIndex; + return QModelIndex(); + } + // Check is it object a sub-object of a complex object + FeaturePtr aFeature = std::dynamic_pointer_cast(aObj); + if (aFeature.get()) { + CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature); + if (aCompFea.get()) { + return objectIndex(aCompFea); + } + } + ResultPtr aResult = std::dynamic_pointer_cast(aObj); + if (aResult.get()) { + ResultCompSolidPtr aCompRes = ModelAPI_Tools::compSolidOwner(aResult); + if (aCompRes.get()) { + return objectIndex(aCompRes); + } + } + // Use as ordinary object std::string aType = aObj->groupName(); SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); @@ -417,33 +648,7 @@ QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const //****************************************************** bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const { - int aNbFolders = myXMLReader.rootFoldersNumber(); - if (!theParent.isValid() && aNbFolders) - return true; - 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 true; - } - } - return false; + return rowCount(theParent) > 0; } //****************************************************** @@ -466,15 +671,73 @@ 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 | Qt::ItemIsEnabled; - if (theIndex.internalId() > -1) { - aFlags |= Qt::ItemIsEditable; + qint64 aIt = theIndex.internalId(); + ModelAPI_Object* aObj = 0; + 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 == -1) { + // Folders under root + DocumentPtr aRootDoc = aSession->moduleDocument(); + if (aRootDoc != aActiveDoc) + return aDefaultFlag; + } else { + aDoc = getSubDocument(theIndex.internalPointer()); + if (!aDoc) + aObj = (ModelAPI_Object*) theIndex.internalPointer(); } - return aFlags; + + if (aObj) { + // An object + if (aObj->isDisabled()) + return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag; + + bool isCompositeSub = false; + // An object which is sub-object of a composite object can not be accessible in column 1 + if (theIndex.column() == 1) { + 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(ModelAPI_Document* theDoc) const +QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc) const { SessionPtr aSession = ModelAPI_Session::get(); DocumentPtr aRootDoc = aSession->moduleDocument(); @@ -487,8 +750,9 @@ QModelIndex XGUI_DataModel::findDocumentRootIndex(ModelAPI_Document* theDoc) con aPartRes = std::dynamic_pointer_cast(aObj); if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) { int aRow = i; - if (myXMLReader.rootType() == ModelAPI_Feature::group()) - aRow += myXMLReader.rootFoldersNumber(); + if (myXMLReader.rootType() == ModelAPI_Feature::group()) { + aRow += foldersCount(); + } return createIndex(aRow, 0, aObj.get()); } } @@ -502,10 +766,152 @@ QModelIndex XGUI_DataModel::findDocumentRootIndex(ModelAPI_Document* theDoc) con if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) { int aRow = i; if (myXMLReader.rootType() == ModelAPI_Feature::group()) - aRow += myXMLReader.rootFoldersNumber(); + aRow += foldersCount(); return createIndex(aRow, 0, aObj.get()); } } } return QModelIndex(); } + +//****************************************************** +QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc) const +{ + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aRootDoc = aSession->moduleDocument(); + if (theDoc == aRootDoc) + return QModelIndex(); + else + return findDocumentRootIndex(theDoc.get()); +} + +//****************************************************** +int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const +{ + int aNb = 0; + 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)) + aNb++; + else { + if (aRootDoc->size(myXMLReader.rootFolderType(i)) > 0) + aNb++; + } + } + } else { + for (int i = 0; i < myXMLReader.subFoldersNumber(); i++) { + if (myXMLReader.subShowEmpty(i)) + aNb++; + else { + if (theDoc->size(myXMLReader.subFolderType(i)) > 0) + aNb++; + } + } + } + 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(); + } + } else { + for (int i = 0; i < myXMLReader.subFoldersNumber(); i++) { + if (!myXMLReader.subShowEmpty(i)) + aResult << myXMLReader.subFolderType(i).c_str(); + } + } + return aResult; +} + +//****************************************************** +QModelIndex XGUI_DataModel::lastHistoryIndex() const +{ + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aCurDoc = aSession->activeDocument(); + FeaturePtr aFeature = aCurDoc->currentFeature(true); + if (aFeature.get()) { + QModelIndex aInd = objectIndex(aFeature); + return createIndex(aInd.row(), 1, aInd.internalPointer()); + } else { + if (aCurDoc == aSession->moduleDocument()) + return createIndex(foldersCount() - 1, 1, -1); + else + return createIndex(foldersCount(aCurDoc.get()) - 1, 1, aCurDoc.get()); + } +} + +//****************************************************** +int XGUI_DataModel::folderId(std::string theType, ModelAPI_Document* theDoc) +{ + 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); + } +}