1 #include "XGUI_DocumentDataModel.h"
2 #include "XGUI_PartDataModel.h"
3 #include "XGUI_Workshop.h"
5 #include <ModelAPI_PluginManager.h>
6 #include <ModelAPI_Document.h>
7 #include <ModelAPI_Feature.h>
8 #include <ModelAPI_Data.h>
9 #include <Model_Events.h>
11 #include <Events_Loop.h>
13 #include <Config_FeatureMessage.h>
20 #define ACTIVE_COLOR QColor(0,72,140)
21 #define PASSIVE_COLOR Qt::black
23 XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
24 : QAbstractItemModel(theParent), myActivePart(0)
26 // Find Document object
27 boost::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
28 myDocument = aMgr->currentDocument();
30 // Register in event loop
31 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_CREATED));
32 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
33 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_DELETED));
35 // Create a top part of data tree model
36 myModel = new XGUI_TopDataModel(myDocument, this);
37 myModel->setItemsColor(ACTIVE_COLOR);
41 XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
47 void XGUI_DocumentDataModel::processEvent(const Events_Message* theMessage)
49 // Created object event *******************
50 if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_CREATED)) {
51 const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
52 boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
53 boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
55 if (aDoc == myDocument) { // If root objects
56 if (aFeature->getGroup().compare(PARTS_GROUP) == 0) { // Update only Parts group
58 int aStart = myPartModels.size() + 1;
59 XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
60 aModel->setPartId(myPartModels.count());
61 myPartModels.append(aModel);
62 insertRow(aStart, partFolderNode());
63 } else { // Update top groups (other except parts
64 QModelIndex aIndex = myModel->findParent(aFeature);
65 int aStart = myModel->rowCount(aIndex) - 1;
66 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
67 insertRow(aStart, aIndex);
69 } else { // if sub-objects of first level nodes
70 XGUI_PartModel* aPartModel = 0;
71 QList<XGUI_PartModel*>::const_iterator aIt;
72 for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
73 if ((*aIt)->hasDocument(aDoc)) {
79 QModelIndex aIndex = aPartModel->findParent(aFeature);
80 int aStart = aPartModel->rowCount(aIndex) - 1;
81 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
82 insertRow(aStart, aIndex);
86 // Deleted object event ***********************
87 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_DELETED)) {
88 const Model_FeatureDeletedMessage* aUpdMsg = dynamic_cast<const Model_FeatureDeletedMessage*>(theMessage);
89 boost::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
91 if (aDoc == myDocument) { // If root objects
92 if (aUpdMsg->group().compare(PARTS_GROUP) == 0) { // Updsate only Parts group
93 int aStart = myPartModels.size();
94 removeSubModel(myPartModels.size() - 1);
95 removeRow(aStart, partFolderNode());
96 } else { // Update top groups (other except parts
97 QModelIndex aIndex = myModel->findGroup(aUpdMsg->group());
98 int aStart = myModel->rowCount(aIndex);
99 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
100 removeRow(aStart, aIndex);
103 XGUI_PartModel* aPartModel = 0;
104 QList<XGUI_PartModel*>::const_iterator aIt;
105 for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
106 if ((*aIt)->hasDocument(aDoc)) {
112 QModelIndex aIndex = aPartModel->findGroup(aUpdMsg->group());
113 int aStart = aPartModel->rowCount(aIndex);
114 aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
115 removeRow(aStart, aIndex);
119 // Deleted object event ***********************
120 } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_UPDATED)) {
121 //const Model_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
122 //boost::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
123 //boost::shared_ptr<ModelAPI_Document> aDoc = aFeature->document();
125 // TODO: Identify the necessary index by the modified feature
127 emit dataChanged(aIndex, aIndex);
129 // Reset whole tree **************************
132 int aNbParts = myDocument->size(PARTS_GROUP);
133 if (myPartModels.size() != aNbParts) { // resize internal models
134 while (myPartModels.size() > aNbParts) {
135 delete myPartModels.last();
136 myPartModels.removeLast();
138 while (myPartModels.size() < aNbParts) {
139 myPartModels.append(new XGUI_PartDataModel(myDocument, this));
141 for (int i = 0; i < myPartModels.size(); i++)
142 myPartModels.at(i)->setPartId(i);
149 QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
151 if (!theIndex.isValid())
153 switch (theIndex.internalId()) {
156 case Qt::DisplayRole:
157 return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
158 case Qt::DecorationRole:
159 return QIcon(":pictures/constr_folder.png");
160 case Qt::ToolTipRole:
161 return tr("Parts folder");
162 case Qt::ForegroundRole:
164 return QBrush(PASSIVE_COLOR);
166 return QBrush(ACTIVE_COLOR);
173 int aOffset = historyOffset();
174 FeaturePtr aFeature = myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
178 case Qt::DisplayRole:
180 return aFeature->data()->getName().c_str();
183 case Qt::DecorationRole:
184 return QIcon(XGUI_Workshop::featureIcon(aFeature->getKind()));
185 case Qt::ToolTipRole:
186 return tr("Feature object");
187 case Qt::ForegroundRole:
189 return QBrush(PASSIVE_COLOR);
191 return QBrush(ACTIVE_COLOR);
198 QModelIndex aParent = theIndex.parent();
199 if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
200 return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
202 return toSourceModelIndex(theIndex)->data(theRole);
206 QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
211 int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
213 if (!theParent.isValid()) {
214 // Size of external models
215 int aVal = historyOffset();
217 aVal += myDocument->size(FEATURES_GROUP);
220 if (theParent.internalId() == PartsFolder) {
221 return myPartModels.size();
223 if (theParent.internalId() == HistoryNode) {
226 QModelIndex* aParent = toSourceModelIndex(theParent);
227 const QAbstractItemModel* aModel = aParent->model();
228 if (!isSubModel(aModel))
231 /*if (isPartSubModel(aModel)) {
232 if (aModel != myActivePart)
235 return aModel->rowCount(*aParent);
238 int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
243 QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
246 if (!theParent.isValid()) {
247 int aOffs = myModel->rowCount();
248 if (theRow < aOffs) {
249 aIndex = myModel->index(theRow, theColumn, theParent);
250 aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
252 if (theRow == aOffs) // Create Parts node
253 aIndex = partFolderNode();
254 else // create history node
255 aIndex = createIndex(theRow, theColumn, HistoryNode);
258 if (theParent.internalId() == PartsFolder) {
259 aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
261 QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
262 aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
264 aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
270 QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
272 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
273 return QModelIndex();
275 QModelIndex* aIndex = toSourceModelIndex(theIndex);
276 const QAbstractItemModel* aModel = aIndex->model();
277 if (!isSubModel(aModel))
278 return QModelIndex();
280 if (isPartSubModel(aModel)) {
281 if (!aModel->parent(*aIndex).isValid()) {
282 return partFolderNode();
286 QModelIndex aIndex1 = aModel->parent(*aIndex);
287 if (aIndex1.isValid())
288 return createIndex(aIndex1.row(), aIndex1.column(), (void*)getModelIndex(aIndex1));
293 bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
295 if (!theParent.isValid())
297 return rowCount(theParent) > 0;
301 QModelIndex* XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
303 QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
308 QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
310 QList<QModelIndex*>::const_iterator aIt;
311 for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
312 QModelIndex* aIndex = (*aIt);
313 if ((*aIndex) == theIndex)
319 QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
321 QModelIndex* aIndexPtr = findModelIndex(theIndex);
323 aIndexPtr = new QModelIndex(theIndex);
324 XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
325 that->myIndexes.append(aIndexPtr);
330 void XGUI_DocumentDataModel::clearModelIndexes()
332 QList<QModelIndex*>::const_iterator aIt;
333 for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt)
338 FeaturePtr XGUI_DocumentDataModel::feature(const QModelIndex& theIndex) const
340 if (theIndex.internalId() == PartsFolder)
342 if (theIndex.internalId() == HistoryNode) {
343 int aOffset = historyOffset();
344 return myDocument->feature(FEATURES_GROUP, theIndex.row() - aOffset);
346 QModelIndex* aIndex = toSourceModelIndex(theIndex);
347 if (!isSubModel(aIndex->model()))
350 const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex->model());
351 return aModel->feature(*aIndex);
354 bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
356 beginInsertRows(theParent, theRow, theRow + theCount - 1);
361 int aRow = rowCount(aRoot);
362 beginInsertRows(aRoot, aRow, aRow);
368 bool XGUI_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
370 beginRemoveRows(theParent, theRow, theRow + theCount - 1);
376 void XGUI_DocumentDataModel::removeSubModel(int theModelId)
378 XGUI_PartModel* aModel = myPartModels.at(theModelId);
380 for (int i = 0; i < myIndexes.size(); i++) {
381 if (myIndexes.at(i)->model() == aModel)
385 while(aToRemove.size() > 0) {
386 aId = aToRemove.last();
387 delete myIndexes.at(aId);
388 myIndexes.removeAt(aId);
389 aToRemove.removeLast();
392 myPartModels.removeAt(theModelId);
395 bool XGUI_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
397 if (theModel == myModel)
399 return isPartSubModel(theModel);
402 bool XGUI_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
404 return myPartModels.contains((XGUI_PartModel*)theModel);
407 QModelIndex XGUI_DocumentDataModel::partFolderNode() const
409 int aPos = myModel->rowCount(QModelIndex());
410 return createIndex(aPos, columnCount() - 1, PartsFolder);
413 int XGUI_DocumentDataModel::historyOffset() const
415 // Nb of rows of top model + Parts folder
416 return myModel->rowCount(QModelIndex()) + 1;
419 bool XGUI_DocumentDataModel::activatedIndex(const QModelIndex& theIndex)
421 if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
424 QModelIndex* aIndex = toSourceModelIndex(theIndex);
428 const QAbstractItemModel* aModel = aIndex->model();
430 if (isPartSubModel(aModel)) {
431 // if this is root node (Part item index)
432 if (!aIndex->parent().isValid()) {
433 if (myActivePart) myActivePart->setItemsColor(PASSIVE_COLOR);
435 if (myActivePart == aModel) {
437 myActivePartIndex = QModelIndex();
439 myActivePart = (XGUI_PartModel*)aModel;
440 myActivePartIndex = theIndex;
444 myActivePart->setItemsColor(ACTIVE_COLOR);
445 myModel->setItemsColor(PASSIVE_COLOR);
447 myModel->setItemsColor(ACTIVE_COLOR);
454 FeaturePtr XGUI_DocumentDataModel::activePart() const
457 return myActivePart->part();
461 void XGUI_DocumentDataModel::deactivatePart()
464 myActivePart->setItemsColor(PASSIVE_COLOR);
466 myModel->setItemsColor(ACTIVE_COLOR);