1 #include "XGUI_DocumentDataModel.h"
2 #include "XGUI_PartDataModel.h"
3 #include "XGUI_Workshop.h"
4 #include "XGUI_Tools.h"
6 #include <ModelAPI_PluginManager.h>
7 #include <ModelAPI_Document.h>
8 #include <ModelAPI_Feature.h>
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_ResultPart.h>
11 #include <Model_Events.h>
12 #include <ModelAPI_Object.h>
14 #include <Events_Loop.h>
16 #include <Config_FeatureMessage.h>
23 #define ACTIVE_COLOR QColor(0,72,140)
24 #define PASSIVE_COLOR Qt::black
26 XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
27 : QAbstractItemModel(theParent), myActivePart(0)
29 // Register in event loop
30 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
31 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
32 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
34 // Create a top part of data tree model
35 myModel = new XGUI_TopDataModel(this);
36 myModel->setItemsColor(ACTIVE_COLOR);
40 XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
46 void XGUI_DocumentDataModel::processEvent(const Events_Message* theMessage)
48 DocumentPtr aRootDoc = ModelAPI_PluginManager::get()->rootDocument();
50 // Created object event *******************
51 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
52 const Model_ObjectUpdatedMessage* aUpdMsg = dynamic_cast<const Model_ObjectUpdatedMessage*>(theMessage);
53 std::set<ObjectPtr> aObjects = aUpdMsg->objects();
55 std::set<ObjectPtr>::const_iterator aIt;
56 for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
57 ObjectPtr aObject = (*aIt);
58 FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
59 if (aFeature && (!aFeature->isInHistory()))
62 DocumentPtr aDoc = aObject->document();
63 if (aDoc == aRootDoc) { // If root objects
64 if (aObject->groupName() == ModelAPI_ResultPart::group()) { // Update only Parts group
66 int aStart = myPartModels.size();
67 XGUI_PartDataModel* aModel = new XGUI_PartDataModel(this);
68 aModel->setPartId(myPartModels.count());
69 myPartModels.append(aModel);
70 insertRow(aStart, partFolderNode());
71 } else { // Update top groups (other except parts
72 QModelIndex aIndex = myModel->findParent(aObject);
73 int aStart = myModel->rowCount(aIndex) - 1;
74 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
75 insertRow(aStart, aIndex);
77 } else { // if sub-objects of first level nodes
78 XGUI_PartModel* aPartModel = 0;
79 QList<XGUI_PartModel*>::const_iterator aIt;
80 for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
81 if ((*aIt)->hasDocument(aDoc)) {
87 QModelIndex aIndex = aPartModel->findParent(aObject);
88 int aStart = aPartModel->rowCount(aIndex) - 1;
89 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
90 insertRow(aStart, aIndex);
94 // Deleted object event ***********************
95 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
96 const Model_ObjectDeletedMessage* aUpdMsg = dynamic_cast<const Model_ObjectDeletedMessage*>(theMessage);
97 DocumentPtr aDoc = aUpdMsg->document();
98 std::set<std::string> aGroups = aUpdMsg->groups();
100 std::set<std::string>::const_iterator aIt;
101 for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
102 std::string aGroup = (*aIt);
103 if (aDoc == aRootDoc) { // If root objects
104 if (aGroup.compare(ModelAPI_ResultPart::group()) == 0) { // Updsate only Parts group
105 int aStart = myPartModels.size() - 1;
106 removeSubModel(aStart);
107 removeRow(aStart, partFolderNode());
108 if (myActivePart && (!isPartSubModel(myActivePart))) {
110 myActivePartIndex = QModelIndex();
111 myModel->setItemsColor(ACTIVE_COLOR);
113 } else { // Update top groups (other except parts
114 QModelIndex aIndex = myModel->findGroup(aGroup);
115 int aStart = myModel->rowCount(aIndex);
116 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
117 removeRow(aStart, aIndex);
120 XGUI_PartModel* aPartModel = 0;
121 QList<XGUI_PartModel*>::const_iterator aIt;
122 for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
123 if ((*aIt)->hasDocument(aDoc)) {
129 QModelIndex aIndex = aPartModel->findGroup(aGroup);
130 int aStart = aPartModel->rowCount(aIndex);
131 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
132 removeRow(aStart, aIndex);
136 // Deleted object event ***********************
137 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
138 //const Model_ObjectUpdatedMessage* aUpdMsg = dynamic_cast<const Model_ObjectUpdatedMessage*>(theMessage);
139 //ObjectPtr aFeature = aUpdMsg->feature();
140 //DocumentPtr aDoc = aFeature->document();
142 // TODO: Identify the necessary index by the modified feature
144 emit dataChanged(aIndex, aIndex);
146 // Reset whole tree **************************
152 void XGUI_DocumentDataModel::rebuildDataTree()
154 DocumentPtr aRootDoc = ModelAPI_PluginManager::get()->rootDocument();
159 int aNbParts = aRootDoc->size(ModelAPI_ResultPart::group());
160 if (myPartModels.size() != aNbParts) { // resize internal models
161 while (myPartModels.size() > aNbParts) {
162 delete myPartModels.last();
163 myPartModels.removeLast();
165 while (myPartModels.size() < aNbParts) {
166 myPartModels.append(new XGUI_PartDataModel(this));
168 for (int i = 0; i < myPartModels.size(); i++)
169 myPartModels.at(i)->setPartId(i);
174 QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
176 if (!theIndex.isValid())
178 switch (theIndex.internalId()) {
181 case Qt::DisplayRole:
182 return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
183 case Qt::DecorationRole:
184 return QIcon(":pictures/constr_folder.png");
185 case Qt::ToolTipRole:
186 return tr("Parts folder");
187 case Qt::ForegroundRole:
189 return QBrush(PASSIVE_COLOR);
191 return QBrush(ACTIVE_COLOR);
198 int aOffset = historyOffset();
199 DocumentPtr aRootDoc = ModelAPI_PluginManager::get()->rootDocument();
200 ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
201 FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
205 case Qt::DisplayRole:
207 return aFeature->data()->name().c_str();
210 case Qt::DecorationRole:
211 return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
212 case Qt::ToolTipRole:
213 return tr("Feature object");
214 case Qt::ForegroundRole:
216 return QBrush(PASSIVE_COLOR);
218 return QBrush(ACTIVE_COLOR);
225 QModelIndex aParent = theIndex.parent();
226 if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
227 return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
229 return toSourceModelIndex(theIndex)->data(theRole);
233 QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
238 int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
240 if (!theParent.isValid()) {
241 DocumentPtr aRootDoc = ModelAPI_PluginManager::get()->rootDocument();
242 // Size of external models
243 int aVal = historyOffset();
245 aVal += aRootDoc->size(ModelAPI_Feature::group());
248 if (theParent.internalId() == PartsFolder) {
249 return myPartModels.size();
251 if (theParent.internalId() == HistoryNode) {
254 QModelIndex* aParent = toSourceModelIndex(theParent);
255 const QAbstractItemModel* aModel = aParent->model();
256 if (!isSubModel(aModel))
259 /*if (isPartSubModel(aModel)) {
260 if (aModel != myActivePart)
263 return aModel->rowCount(*aParent);
266 int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
271 QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
274 if (!theParent.isValid()) {
275 int aOffs = myModel->rowCount();
276 if (theRow < aOffs) {
277 aIndex = myModel->index(theRow, theColumn, theParent);
278 aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
280 if (theRow == aOffs) // Create Parts node
281 aIndex = partFolderNode();
282 else // create history node
283 aIndex = createIndex(theRow, theColumn, HistoryNode);
286 if (theParent.internalId() == PartsFolder) {
287 aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
289 QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
290 aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
292 aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
298 QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
300 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
301 return QModelIndex();
303 QModelIndex* aIndex = toSourceModelIndex(theIndex);
304 const QAbstractItemModel* aModel = aIndex->model();
305 if (!isSubModel(aModel))
306 return QModelIndex();
308 if (isPartSubModel(aModel)) {
309 if (!aModel->parent(*aIndex).isValid()) {
310 return partFolderNode();
314 QModelIndex aIndex1 = aModel->parent(*aIndex);
315 if (aIndex1.isValid())
316 return createIndex(aIndex1.row(), aIndex1.column(), (void*)getModelIndex(aIndex1));
321 bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
323 if (!theParent.isValid())
325 return rowCount(theParent) > 0;
329 QModelIndex* XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
331 QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
336 QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
338 QList<QModelIndex*>::const_iterator aIt;
339 for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
340 QModelIndex* aIndex = (*aIt);
341 if ((*aIndex) == theIndex)
347 QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
349 QModelIndex* aIndexPtr = findModelIndex(theIndex);
351 aIndexPtr = new QModelIndex(theIndex);
352 XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
353 that->myIndexes.append(aIndexPtr);
358 void XGUI_DocumentDataModel::clearModelIndexes()
360 QList<QModelIndex*>::const_iterator aIt;
361 for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt)
366 ObjectPtr XGUI_DocumentDataModel::object(const QModelIndex& theIndex) const
368 if (theIndex.internalId() == PartsFolder)
370 if (theIndex.internalId() == HistoryNode) {
371 DocumentPtr aRootDoc = ModelAPI_PluginManager::get()->rootDocument();
372 int aOffset = historyOffset();
373 return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
375 QModelIndex* aIndex = toSourceModelIndex(theIndex);
376 if (!isSubModel(aIndex->model()))
379 const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex->model());
380 return aModel->object(*aIndex);
383 bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
385 beginInsertRows(theParent, theRow, theRow + theCount - 1);
390 int aRow = rowCount(aRoot);
391 beginInsertRows(aRoot, aRow, aRow);
397 bool XGUI_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
399 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
405 void XGUI_DocumentDataModel::removeSubModel(int theModelId)
407 XGUI_PartModel* aModel = myPartModels.at(theModelId);
409 for (int i = 0; i < myIndexes.size(); i++) {
410 if (myIndexes.at(i)->model() == aModel)
414 while(aToRemove.size() > 0) {
415 aId = aToRemove.last();
416 delete myIndexes.at(aId);
417 myIndexes.removeAt(aId);
418 aToRemove.removeLast();
421 myPartModels.removeAt(theModelId);
424 bool XGUI_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
426 if (theModel == myModel)
428 return isPartSubModel(theModel);
431 bool XGUI_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
433 return myPartModels.contains((XGUI_PartModel*)theModel);
436 QModelIndex XGUI_DocumentDataModel::partFolderNode() const
438 int aPos = myModel->rowCount(QModelIndex());
439 return createIndex(aPos, columnCount() - 1, PartsFolder);
442 int XGUI_DocumentDataModel::historyOffset() const
444 // Nb of rows of top model + Parts folder
445 return myModel->rowCount(QModelIndex()) + 1;
448 bool XGUI_DocumentDataModel::activatedIndex(const QModelIndex& theIndex)
450 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
453 QModelIndex* aIndex = toSourceModelIndex(theIndex);
457 const QAbstractItemModel* aModel = aIndex->model();
459 if (isPartSubModel(aModel)) {
460 // if this is root node (Part item index)
461 if (!aIndex->parent().isValid()) {
462 if (myActivePart) myActivePart->setItemsColor(PASSIVE_COLOR);
464 if (myActivePart == aModel) {
466 myActivePartIndex = QModelIndex();
468 myActivePart = (XGUI_PartModel*)aModel;
469 myActivePartIndex = theIndex;
473 myActivePart->setItemsColor(ACTIVE_COLOR);
474 myModel->setItemsColor(PASSIVE_COLOR);
476 myModel->setItemsColor(ACTIVE_COLOR);
483 ResultPartPtr XGUI_DocumentDataModel::activePart() const
486 return myActivePart->part();
487 return ResultPartPtr();
490 void XGUI_DocumentDataModel::deactivatePart()
493 myActivePart->setItemsColor(PASSIVE_COLOR);
495 myActivePartIndex = QModelIndex();
496 myModel->setItemsColor(ACTIVE_COLOR);
499 Qt::ItemFlags XGUI_DocumentDataModel::flags(const QModelIndex& theIndex) const
501 Qt::ItemFlags aFlags = QAbstractItemModel::flags(theIndex);
502 if (object(theIndex)) {
503 aFlags |= Qt::ItemIsEditable;
508 QModelIndex XGUI_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
511 XGUI_PartModel* aModel = 0;
512 foreach (XGUI_PartModel* aPartModel, myPartModels) {
514 if (aPartModel->part() == theObject) {
520 return createIndex(aRow, 0, (void*)getModelIndex(aModel->index(0, 0, QModelIndex())));
522 return QModelIndex();
525 QModelIndex XGUI_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
527 // Check that this feature belongs to root document
528 DocumentPtr aRootDoc = ModelAPI_PluginManager::get()->rootDocument();
529 DocumentPtr aDoc = theObject->document();
530 if (aDoc == aRootDoc) {
531 // This feature belongs to histrory or top model
532 if (theObject->isInHistory()) {
534 for (aId = 0; aId < aRootDoc->size(ModelAPI_Feature::group()); aId++) {
535 if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
538 return index(aId + historyOffset(), 0, QModelIndex());
540 QModelIndex aIndex = myModel->objectIndex(theObject);
541 return aIndex.isValid()?
542 createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex)) :
546 XGUI_PartModel* aPartModel = 0;
547 foreach(XGUI_PartModel* aModel, myPartModels) {
548 if (aModel->hasDocument(aDoc)) {
554 QModelIndex aIndex = aPartModel->objectIndex(theObject);
555 return aIndex.isValid()?
556 createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex)) :
560 return QModelIndex();