#include "XGUI_DocumentDataModel.h"
#include "XGUI_PartDataModel.h"
+#include "XGUI_Workshop.h"
#include <ModelAPI_PluginManager.h>
-#include <ModelAPI_Iterator.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Data.h>
#include <Model_Events.h>
-#include <Event_Loop.h>
+#include <Events_Loop.h>
+#include <Config_FeatureMessage.h>
#include <QIcon>
#include <QString>
+#include <QBrush>
+#define ACTIVE_COLOR QColor(0,72,140)
+#define PASSIVE_COLOR Qt::black
+
XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
- : QAbstractItemModel(theParent)
+ : QAbstractItemModel(theParent), myActivePart(0)
{
// Find Document object
- std::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
+ boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
myDocument = aMgr->currentDocument();
// Register in event loop
- Event_Loop::loop()->registerListener(this, Event_Loop::eventByName(EVENT_FEATURE_CREATED));
- Event_Loop::loop()->registerListener(this, Event_Loop::eventByName(EVENT_FEATURE_UPDATED));
- Event_Loop::loop()->registerListener(this, Event_Loop::eventByName(EVENT_FEATURE_DELETED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
// Create a top part of data tree model
myModel = new XGUI_TopDataModel(myDocument, this);
+ myModel->setItemsColor(ACTIVE_COLOR);
}
}
-void XGUI_DocumentDataModel::processEvent(const Event_Message* theMessage)
+void XGUI_DocumentDataModel::processEvent(const Events_Message* theMessage)
{
// Created object event *******************
- if (QString(theMessage->eventID().eventText()) == EVENT_FEATURE_CREATED) {
- const ModelAPI_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const ModelAPI_FeatureUpdatedMessage*>(theMessage);
- std::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
- std::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
+ if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED)) {
+ const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+ boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
+ boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
if (aDoc == myDocument) { // If root objects
- if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
+ if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Update only Parts group
// Add a new part
- int aStart = myModel->rowCount(QModelIndex()) + myPartModels.size() + 1;
+ int aStart = myPartModels.size() + 1;
XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
aModel->setPartId(myPartModels.count());
myPartModels.append(aModel);
- insertRows(QModelIndex(), aStart, aStart);
+ insertRow(aStart, partFolderNode());
} else { // Update top groups (other except parts
QModelIndex aIndex = myModel->findParent(aFeature);
int aStart = myModel->rowCount(aIndex) - 1;
aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- insertRows(aIndex, aStart, aStart);
+ insertRow(aStart, aIndex);
}
} else { // if sub-objects of first level nodes
XGUI_PartModel* aPartModel = 0;
QModelIndex aIndex = aPartModel->findParent(aFeature);
int aStart = aPartModel->rowCount(aIndex) - 1;
aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- insertRows(aIndex, aStart, aStart);
+ insertRow(aStart, aIndex);
}
}
- // Deteted object event ***********************
- } else if (QString(theMessage->eventID().eventText()) == EVENT_FEATURE_DELETED) {
- const ModelAPI_FeatureDeletedMessage* aUpdMsg = dynamic_cast<const ModelAPI_FeatureDeletedMessage*>(theMessage);
- std::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
+ // Deleted object event ***********************
+ } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_DELETED)) {
+ const Model_FeatureDeletedMessage* aUpdMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
+ boost::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
if (aDoc == myDocument) { // If root objects
if (aUpdMsg->group().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
- int aStart = myModel->rowCount(QModelIndex()) + myPartModels.size() - 1;
- beginRemoveRows(QModelIndex(), aStart, aStart);
+ int aStart = myPartModels.size();
removeSubModel(myPartModels.size() - 1);
- endRemoveRows();
+ removeRow(aStart, partFolderNode());
} else { // Update top groups (other except parts
QModelIndex aIndex = myModel->findGroup(aUpdMsg->group());
int aStart = myModel->rowCount(aIndex);
aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- beginRemoveRows(aIndex, aStart, aStart);
- endRemoveRows();
+ removeRow(aStart, aIndex);
}
} else {
XGUI_PartModel* aPartModel = 0;
QModelIndex aIndex = aPartModel->findGroup(aUpdMsg->group());
int aStart = aPartModel->rowCount(aIndex);
aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
- beginRemoveRows(aIndex, aStart, aStart);
- endRemoveRows();
+ removeRow(aStart, aIndex);
}
}
+ // Deleted object event ***********************
+ } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED)) {
+ //const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+ //boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
+ //boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
+
+ // TODO: Identify the necessary index by the modified feature
+ QModelIndex aIndex;
+ emit dataChanged(aIndex, aIndex);
+
// Reset whole tree **************************
} else {
beginResetModel();
- int aNbParts = myDocument->featuresIterator(PARTS_GROUP)->numIterationsLeft();
+ int aNbParts = myDocument->size(PARTS_GROUP);
if (myPartModels.size() != aNbParts) { // resize internal models
while (myPartModels.size() > aNbParts) {
delete myPartModels.last();
{
if (!theIndex.isValid())
return QVariant();
- return toSourceModelIndex(theIndex).data(theRole);
+ switch (theIndex.internalId()) {
+ case PartsFolder:
+ switch (theRole) {
+ case Qt::DisplayRole:
+ return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
+ case Qt::DecorationRole:
+ return QIcon(":pictures/constr_folder.png");
+ case Qt::ToolTipRole:
+ return tr("Parts folder");
+ case Qt::ForegroundRole:
+ if (myActivePart)
+ return QBrush(PASSIVE_COLOR);
+ else
+ return QBrush(ACTIVE_COLOR);
+ default:
+ return QVariant();
+ }
+ break;
+ case HistoryNode:
+ {
+ int aOffset = historyOffset();
+ FeaturePtr aFeature = myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
+ if (!aFeature)
+ return QVariant();
+ switch (theRole) {
+ case Qt::DisplayRole:
+ if (aFeature)
+ return aFeature->data()->getName().c_str();
+ else
+ return QVariant();
+ case Qt::DecorationRole:
+ return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
+ case Qt::ToolTipRole:
+ return tr("Feature object");
+ case Qt::ForegroundRole:
+ if (myActivePart)
+ return QBrush(PASSIVE_COLOR);
+ else
+ return QBrush(ACTIVE_COLOR);
+ default:
+ return QVariant();
+ }
+ }
+ break;
+ }
+ QModelIndex aParent = theIndex.parent();
+ if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
+ return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
+ }
+ return toSourceModelIndex(theIndex)->data(theRole);
}
int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
{
if (!theParent.isValid()) {
- int aVal = myModel->rowCount(theParent) + myPartModels.size();
- return myModel->rowCount(theParent) + myPartModels.size();
+ // Size of external models
+ int aVal = historyOffset();
+ // Plus history size
+ aVal += myDocument->size(FEATURES_GROUP);
+ return aVal;
}
- QModelIndex aParent = toSourceModelIndex(theParent);
- if (!hasSubModel(aParent.model()))
+ if (theParent.internalId() == PartsFolder) {
+ return myPartModels.size();
+ }
+ if (theParent.internalId() == HistoryNode) {
+ return 0;
+ }
+ QModelIndex* aParent = toSourceModelIndex(theParent);
+ const QAbstractItemModel* aModel = aParent->model();
+ if (!isSubModel(aModel))
return 0;
- return aParent.model()->rowCount(aParent);
+ /*if (isPartSubModel(aModel)) {
+ if (aModel != myActivePart)
+ return 0;
+ }*/
+ return aModel->rowCount(*aParent);
}
int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
QModelIndex aIndex;
if (!theParent.isValid()) {
int aOffs = myModel->rowCount();
- if (theRow < aOffs)
+ if (theRow < aOffs) {
aIndex = myModel->index(theRow, theColumn, theParent);
- else {
- if (myPartModels.size() > 0) {
- int aPos = theRow - aOffs;
- if (aPos >= myPartModels.size())
- aPos = 0;
- aIndex = myPartModels.at(aPos)->index(aPos, theColumn, theParent);
- } else
- return aIndex;
+ aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
+ } else {
+ if (theRow == aOffs) // Create Parts node
+ aIndex = partFolderNode();
+ else // create history node
+ aIndex = createIndex(theRow, theColumn, HistoryNode);
}
- aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
} else {
- QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
- aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
-
+ if (theParent.internalId() == PartsFolder) {
+ aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
+ } else {
+ QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
+ aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
+ }
aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
}
return aIndex;
QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
{
- QModelIndex aParent = toSourceModelIndex(theIndex);
- if (!hasSubModel(aParent.model()))
+ if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+ return QModelIndex();
+
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ const QAbstractItemModel* aModel = aIndex->model();
+ if (!isSubModel(aModel))
return QModelIndex();
- aParent = aParent.model()->parent(aParent);
- if (aParent.isValid())
- return createIndex(aParent.row(), aParent.column(), (void*)getModelIndex(aParent));
- return aParent;
+ if (isPartSubModel(aModel)) {
+ if (!aModel->parent(*aIndex).isValid()) {
+ return partFolderNode();
+ }
+ }
+
+ QModelIndex aIndex1 = aModel->parent(*aIndex);
+ if (aIndex1.isValid())
+ return createIndex(aIndex1.row(), aIndex1.column(), (void*)getModelIndex(aIndex1));
+ return aIndex1;
}
}
-QModelIndex XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
+QModelIndex* XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
{
QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
- return (*aIndexPtr);
+ return aIndexPtr;
}
FeaturePtr XGUI_DocumentDataModel::feature(const QModelIndex& theIndex) const
{
- QModelIndex aIndex = toSourceModelIndex(theIndex);
- if (!hasSubModel(aIndex.model()))
- return 0;
+ if (theIndex.internalId() == PartsFolder)
+ return FeaturePtr();
+ if (theIndex.internalId() == HistoryNode) {
+ int aOffset = historyOffset();
+ return myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
+ }
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ if (!isSubModel(aIndex->model()))
+ return FeaturePtr();
- const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex.model());
- return aModel->feature(aIndex);
+ const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex->model());
+ return aModel->feature(*aIndex);
}
-void XGUI_DocumentDataModel::insertRows(const QModelIndex& theParent, int theStart, int theEnd)
+bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
{
- beginInsertRows(theParent, theStart, theEnd);
+ beginInsertRows(theParent, theRow, theRow + theCount - 1);
+ //endInsertRows();
+
+ // Update history
+ QModelIndex aRoot;
+ int aRow = rowCount(aRoot);
+ beginInsertRows(aRoot, aRow, aRow);
endInsertRows();
- if (theStart == 0) // Update parent if this is a first child in order to update node decoration
- emit dataChanged(theParent, theParent);
+
+ return true;
}
+bool XGUI_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
+{
+ beginRemoveRows(theParent, theRow, theRow + theCount - 1);
+ endRemoveRows();
+ return true;
+}
+
+
void XGUI_DocumentDataModel::removeSubModel(int theModelId)
{
XGUI_PartModel* aModel = myPartModels.at(theModelId);
myPartModels.removeAt(theModelId);
}
-bool XGUI_DocumentDataModel::hasSubModel(const QAbstractItemModel* theModel) const
+bool XGUI_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
{
if (theModel == myModel)
return true;
- QList<XGUI_PartModel*>::const_iterator aIt;
- for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt)
- if ((*aIt) == theModel)
- return true;
+ return isPartSubModel(theModel);
+}
+
+bool XGUI_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
+{
+ return myPartModels.contains((XGUI_PartModel*)theModel);
+}
+
+QModelIndex XGUI_DocumentDataModel::partFolderNode() const
+{
+ int aPos = myModel->rowCount(QModelIndex());
+ return createIndex(aPos, columnCount() - 1, PartsFolder);
+}
+
+int XGUI_DocumentDataModel::historyOffset() const
+{
+ // Nb of rows of top model + Parts folder
+ return myModel->rowCount(QModelIndex()) + 1;
+}
+
+bool XGUI_DocumentDataModel::activatedIndex(const QModelIndex& theIndex)
+{
+ if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+ return false;
+
+ QModelIndex* aIndex = toSourceModelIndex(theIndex);
+ if (!aIndex)
+ return false;
+
+ const QAbstractItemModel* aModel = aIndex->model();
+
+ if (isPartSubModel(aModel)) {
+ // if this is root node (Part item index)
+ if (!aIndex->parent().isValid()) {
+ if (myActivePart) myActivePart->setItemsColor(PASSIVE_COLOR);
+
+ if (myActivePart == aModel) {
+ myActivePart = 0;
+ myActivePartIndex = QModelIndex();
+ } else {
+ myActivePart = (XGUI_PartModel*)aModel;
+ myActivePartIndex = theIndex;
+ }
+
+ if (myActivePart) {
+ myActivePart->setItemsColor(ACTIVE_COLOR);
+ myModel->setItemsColor(PASSIVE_COLOR);
+ } else
+ myModel->setItemsColor(ACTIVE_COLOR);
+ return true;
+ }
+ }
return false;
-}
\ No newline at end of file
+}
+
+FeaturePtr XGUI_DocumentDataModel::activePart() const
+{
+ if (myActivePart)
+ return myActivePart->part();
+ return FeaturePtr();
+}
+
+void XGUI_DocumentDataModel::deactivatePart()
+{
+ if (myActivePart)
+ myActivePart->setItemsColor(PASSIVE_COLOR);
+ myActivePart = 0;
+ myModel->setItemsColor(ACTIVE_COLOR);
+}