Salome HOME
Merge branch 'origin/BR_PORTING_CENTOS_6_3'
[modules/shaper.git] / src / XGUI / XGUI_DocumentDataModel.cpp
1 #include "XGUI_DocumentDataModel.h"
2 #include "XGUI_PartDataModel.h"
3
4 #include <ModelAPI_PluginManager.h>
5 #include <ModelAPI_Iterator.h>
6 #include <ModelAPI_Document.h>
7 #include <ModelAPI_Feature.h>
8 #include <ModelAPI_Data.h>
9 #include <Model_Events.h>
10
11 #include <Event_Loop.h>
12
13
14 #include <QIcon>
15 #include <QString>
16
17
18 XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
19   : QAbstractItemModel(theParent)
20 {
21   // Find Document object
22   std::shared_ptr<ModelAPI_PluginManager> aMgr = ModelAPI_PluginManager::get();
23   myDocument = aMgr->currentDocument();
24
25   // Register in event loop
26   Event_Loop::loop()->registerListener(this, Event_Loop::eventByName(EVENT_FEATURE_CREATED));
27   Event_Loop::loop()->registerListener(this, Event_Loop::eventByName(EVENT_FEATURE_UPDATED));
28
29   // Create a top part of data tree model
30   myModel = new XGUI_TopDataModel(myDocument, this);
31 }
32
33
34 XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
35 {
36   clearModelIndexes();
37 }
38
39
40 void XGUI_DocumentDataModel::processEvent(const Event_Message* theMessage)
41 {
42   if (QString(theMessage->eventID().eventText()) == EVENT_FEATURE_CREATED) {
43     const ModelAPI_FeatureUpdatedMessage* aUpdMsg = dynamic_cast<const ModelAPI_FeatureUpdatedMessage*>(theMessage);
44     std::shared_ptr<ModelAPI_Document> aDoc = aUpdMsg->document();
45     std::shared_ptr<ModelAPI_Feature> aFeature = aUpdMsg->feature();
46
47     if (aDoc == myDocument) {
48       if (aFeature->getGroup().compare(PARTS_GROUP) == 0) {
49         // Add a new part
50         int aStart = myModel->rowCount(QModelIndex()) + myPartModels.size();
51         beginInsertRows(QModelIndex(), aStart, aStart + 1);
52         XGUI_PartDataModel* aModel = new XGUI_PartDataModel(myDocument, this);
53         aModel->setPartId(myPartModels.count());
54         myPartModels.append(aModel);
55         endInsertRows();
56       } else {
57         QModelIndex aIndex = myModel->findParent(aFeature);
58         int aStart = myModel->rowCount(aIndex);
59         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
60         beginInsertRows(aIndex, aStart-1, aStart);
61         endInsertRows();
62         if (aStart == 1) // Update parent if this is a first child in order to update node decoration
63           emit dataChanged(aIndex, aIndex);
64       }
65     } else {
66       XGUI_PartModel* aPartModel = 0;
67       QList<XGUI_PartModel*>::const_iterator aIt;
68       for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) {
69         if ((*aIt)->hasDocument(aDoc)) {
70           aPartModel = (*aIt);
71           break;
72         }
73       }
74       if (aPartModel) {
75         QModelIndex aIndex = aPartModel->findParent(aFeature);
76         int aStart = aPartModel->rowCount(aIndex);
77         aIndex = createIndex(aIndex.row(), aIndex.column(), (void*)getModelIndex(aIndex));
78         beginInsertRows(aIndex, aStart-1, aStart);
79         endInsertRows();
80         if (aStart == 1) // Update parent if this is a first child in order to update node decoration
81           emit dataChanged(aIndex, aIndex);
82       }
83     }
84   } else {
85     // Reset whole tree
86     beginResetModel();
87     int aNbParts = myDocument->featuresIterator(PARTS_GROUP)->numIterationsLeft();
88     if (myPartModels.size() != aNbParts) { // resize internal models
89       while (myPartModels.size() > aNbParts) {
90         delete myPartModels.last();
91         myPartModels.removeLast();
92       }
93       while (myPartModels.size() < aNbParts) {
94         myPartModels.append(new XGUI_PartDataModel(myDocument, this));
95       }
96       for (int i = 0; i < myPartModels.size(); i++)
97         myPartModels.at(i)->setPartId(i);
98     }
99     clearModelIndexes();
100     endResetModel();
101   }
102 }
103
104 QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
105 {
106   if (!theIndex.isValid())
107     return QVariant();
108   return toSourceModel(theIndex).data(theRole);
109 }
110
111
112 QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
113 {
114   return QVariant();
115 }
116
117 int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
118 {
119   if (!theParent.isValid()) 
120     return myModel->rowCount(theParent) + myPartModels.size();
121
122   QModelIndex aParent = toSourceModel(theParent);
123   return aParent.model()->rowCount(aParent);
124 }
125
126 int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
127 {
128   return 1;
129 }
130
131 QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
132 {
133   QModelIndex aIndex;
134   if (!theParent.isValid()) {
135     int aOffs = myModel->rowCount();
136     if (theRow < aOffs) 
137       aIndex = myModel->index(theRow, theColumn, theParent);
138     else
139       aIndex = myPartModels.at(theRow - aOffs)->index(theRow - aOffs, theColumn, theParent);
140
141     aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
142   } else {
143     QModelIndex* aParent = (QModelIndex*)theParent.internalPointer();
144     aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
145
146     aIndex = createIndex(theRow, theColumn, (void*)getModelIndex(aIndex));
147   }
148   return aIndex;
149 }
150
151
152 QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
153 {
154   QModelIndex aParent = toSourceModel(theIndex);
155   aParent = aParent.model()->parent(aParent);
156   if (aParent.isValid())
157     return createIndex(aParent.row(), aParent.column(), (void*)getModelIndex(aParent));
158   return aParent;
159 }
160
161
162 bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
163 {
164   if (!theParent.isValid())
165     return true;
166   return rowCount(theParent) > 0;
167 }
168
169
170 QModelIndex XGUI_DocumentDataModel::toSourceModel(const QModelIndex& theProxy) const
171 {
172   QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
173   return (*aIndexPtr);
174 }
175
176
177 QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
178 {
179   QList<QModelIndex*>::const_iterator aIt;
180   for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
181     QModelIndex* aIndex = (*aIt);
182     if ((*aIndex) == theIndex)
183       return aIndex;
184   }
185   return 0;
186 }
187
188 QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
189 {
190   QModelIndex* aIndexPtr = findModelIndex(theIndex);
191   if (!aIndexPtr) {
192     aIndexPtr = new QModelIndex(theIndex);
193     XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
194     that->myIndexes.append(aIndexPtr);
195   }
196   return aIndexPtr;
197 }
198
199 void XGUI_DocumentDataModel::clearModelIndexes()
200 {
201   QList<QModelIndex*>::const_iterator aIt;
202   for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) 
203     delete (*aIt);
204   myIndexes.clear();
205 }
206
207 FeaturePtr XGUI_DocumentDataModel::feature(const QModelIndex& theIndex) const
208 {
209   QModelIndex aIndex = toSourceModel(theIndex);
210   const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex.model());
211   return aModel->feature(aIndex);
212 }