Salome HOME
Minor changes
[modules/shaper.git] / src / PartSet / PartSet_PartDataModel.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 #include "PartSet_PartDataModel.h"
4 #include "PartSet_Module.h"
5 #include "PartSet_DocumentDataModel.h"
6
7 #include <ModelAPI_Session.h>
8 #include <ModelAPI_Document.h>
9 #include <ModelAPI_Feature.h>
10 #include <ModelAPI_Result.h>
11 #include <ModelAPI_Data.h>
12 #include <ModelAPI_AttributeDocRef.h>
13 #include <ModelAPI_Object.h>
14 #include <ModelAPI_ResultPart.h>
15 #include <ModelAPI_ResultConstruction.h>
16 #include <ModelAPI_ResultParameter.h>
17 #include <ModelAPI_ResultBody.h>
18 #include <ModelAPI_ResultGroup.h>
19 #include <ModelAPI_AttributeDouble.h>
20 #include <ModelAPI_Events.h>
21 #include <ModelAPI_Tools.h>
22
23 #include <Events_Loop.h>
24
25 #include <QIcon>
26 #include <QBrush>
27
28
29 PartSet_PartDataModel::PartSet_PartDataModel(QObject* theParent)
30     : PartSet_PartModel(theParent)
31 {
32 }
33
34 PartSet_PartDataModel::~PartSet_PartDataModel()
35 {
36 }
37
38 QVariant PartSet_PartDataModel::data(const QModelIndex& theIndex, int theRole) const
39 {
40   DocumentPtr aPartDoc = partDocument();
41   if (theIndex.column() == 1) {
42     DocumentPtr aActiveDoc = ModelAPI_Session::get()->activeDocument();
43     QModelIndex aParent = theIndex.parent();
44     if (aActiveDoc == aPartDoc) {
45       if (!aParent.isValid()) {
46         switch (theRole) {
47         case Qt::DecorationRole:
48           if (theIndex.row() == lastHistoryRow())
49             return QIcon(":pictures/arrow.png");
50         }
51       }
52     }
53     return QVariant();
54   }
55
56   if (theIndex.internalId() >= 0) {
57     ObjectPtr aObj = object(theIndex);
58     switch (theRole) {
59       case Qt::DisplayRole:
60         return aObj->data()->name().c_str();
61       case Qt::DecorationRole: 
62         {
63           FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
64           if (aFeature)
65             return PartSet_DocumentDataModel::featureIcon(aFeature);
66         }
67         break;
68       case Qt::ForegroundRole:
69         if (theIndex.internalId() > lastHistoryRow())
70           return QBrush(Qt::lightGray);
71         return QBrush(myItemsColor);
72     }
73   }
74
75   switch (theRole) {
76     case Qt::DisplayRole:
77       // return a name
78       switch (theIndex.internalId()) {
79         //case MyRoot: {
80         //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
81         //  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
82         //  if (aObject)
83         //    return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
84         //}
85         case ParamsFolder:
86           return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
87         case ConstructFolder:
88           return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
89         case BodiesFolder:
90           return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
91         case GroupsFolder:
92           return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
93         case ParamObject: {
94           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
95           if (aObject) {
96             ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
97             AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
98             QString aVal = QString::number(aValueAttribute->value());
99             QString aTitle = QString(aObject->data()->name().c_str());
100             return aTitle + " = " + aVal;
101           }
102         }
103           break;
104         case ConstructObject: {
105           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
106           if (aObject)
107             return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
108         }
109           break;
110         case BodiesObject: {
111           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), theIndex.row());
112           if (aObject)
113             return aObject->data()->name().c_str();
114         }
115           break;
116         case GroupObject: {
117           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
118           if (aObject)
119             return aObject->data()->name().c_str();
120         }
121         case HistoryObject: {
122           ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
123           if (aObject)
124             return aObject->data()->name().c_str();
125         }
126       }
127       break;
128     case Qt::DecorationRole:
129       // return an Icon
130       switch (theIndex.internalId()) {
131         //case MyRoot:
132         //  return QIcon(":pictures/part_ico.png");
133         case ParamsFolder:
134           return QIcon(":pictures/params_folder.png");
135         case ConstructFolder:
136         case BodiesFolder:
137           return QIcon(":pictures/constr_folder.png");
138         case GroupsFolder:
139           return QIcon(":pictures/constr_folder.png");
140         case ConstructObject:
141         case GroupObject:
142         case BodiesObject: {
143           std::string aGroup;
144           if (theIndex.internalId() == ConstructObject)
145             aGroup = ModelAPI_ResultConstruction::group();
146           else if (theIndex.internalId() == BodiesObject)
147             aGroup = ModelAPI_ResultBody::group();
148           else if (theIndex.internalId() == GroupObject)
149             aGroup = ModelAPI_ResultGroup::group();
150           if (aGroup.length() > 0) {
151             ObjectPtr anObject = aPartDoc->object(aGroup, theIndex.row());
152             if (anObject && anObject->data() && 
153                 anObject->data()->execState() == ModelAPI_StateMustBeUpdated) {
154               return QIcon(":pictures/constr_object_modified.png");
155             }
156           }
157           return QIcon(":pictures/constr_object.png");
158         }
159         case HistoryObject: {
160           ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
161           FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
162           if (aFeature)
163             return PartSet_DocumentDataModel::featureIcon(aFeature);
164         }
165       }
166       break;
167     case Qt::ToolTipRole:
168       // return Tooltip
169       break;
170     case Qt::ForegroundRole:
171       if (theIndex.internalId() == HistoryObject) {
172         if (theIndex.row() > lastHistoryRow())
173           return QBrush(Qt::lightGray);
174       }
175       return QBrush(myItemsColor);
176   }
177   return QVariant();
178 }
179
180 QVariant PartSet_PartDataModel::headerData(int section, Qt::Orientation orientation, int role) const
181 {
182   return QVariant();
183 }
184
185 int PartSet_PartDataModel::rowCount(const QModelIndex& parent) const
186 {
187   if (!parent.isValid()) {
188     DocumentPtr aDoc = partDocument();
189     if (aDoc.get()) {
190       return getRowsNumber() + aDoc->size(ModelAPI_Feature::group());
191     } else 
192       return 0;
193   }
194   switch (parent.internalId()) {
195     case ParamsFolder:
196       return partDocument()->size(ModelAPI_ResultParameter::group());
197     case ConstructFolder:
198       return partDocument()->size(ModelAPI_ResultConstruction::group());
199     case BodiesFolder:
200       return partDocument()->size(ModelAPI_ResultBody::group());
201     case GroupsFolder:
202       return partDocument()->size(ModelAPI_ResultGroup::group());
203     case HistoryObject:
204       {
205         ObjectPtr aObj = object(parent);
206         CompositeFeaturePtr aCompFeature = 
207           std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aObj);
208         if (aCompFeature.get()) {
209           return aCompFeature->numberOfSubs(true);
210         }
211       }
212   }
213   return 0;
214 }
215
216 int PartSet_PartDataModel::columnCount(const QModelIndex &parent) const
217 {
218   return 2;
219 }
220
221 QModelIndex PartSet_PartDataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
222 {
223   if (!theParent.isValid()) {
224     switch (theRow) {
225       case 0:
226         return createIndex(theRow, theColumn, (qint32) ParamsFolder);
227       case 1:
228         return createIndex(theRow, theColumn, (qint32) ConstructFolder);
229       case 2:
230         return createIndex(theRow, theColumn, (qint32) BodiesFolder);
231       case 3:
232         {
233         int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
234         if (aSize > 0)
235           return createIndex(theRow, theColumn, (qint32) GroupsFolder);
236         else
237           return createIndex(theRow, theColumn, (qint32) HistoryObject);
238         }
239       default:
240         return createIndex(theRow, theColumn, (qint32) HistoryObject);
241     }
242   } else {
243     int aId = (int) theParent.internalId();
244     switch (aId) {
245       case ParamsFolder:
246         return createIndex(theRow, theColumn, (qint32) ParamObject);
247       case ConstructFolder:
248         return createIndex(theRow, theColumn, (qint32) ConstructObject);
249       case BodiesFolder:
250         return createIndex(theRow, theColumn, (qint32) BodiesObject);
251       case GroupsFolder:
252         return createIndex(theRow, theColumn, (qint32) GroupObject);
253       case HistoryObject:
254         {
255           return createIndex(theRow, theColumn, (qint32) theParent.row());
256         }
257     }
258   }
259   return QModelIndex();
260 }
261
262 QModelIndex PartSet_PartDataModel::parent(const QModelIndex& theIndex) const
263 {
264   if (theIndex.internalId() >= 0) {
265     int aPRow = theIndex.internalId();
266     return createIndex(aPRow, 0, (qint32) HistoryObject);
267   }
268   switch (theIndex.internalId()) {
269     case ParamsFolder:
270     case ConstructFolder:
271     case BodiesFolder:
272     case GroupsFolder:
273     case HistoryObject:
274       return QModelIndex();
275
276     case ParamObject:
277       return createIndex(0, 0, (qint32) ParamsFolder);
278     case ConstructObject:
279       return createIndex(1, 0, (qint32) ConstructFolder);
280     case BodiesObject:
281       return createIndex(2, 0, (qint32) BodiesFolder);
282     case GroupObject:
283       return createIndex(3, 0, (qint32) GroupsFolder);
284   }
285   return QModelIndex();
286 }
287
288 bool PartSet_PartDataModel::hasChildren(const QModelIndex& theParent) const
289 {
290   return rowCount(theParent) > 0;
291 }
292
293 DocumentPtr PartSet_PartDataModel::partDocument() const
294 {
295   ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(myPart->firstResult()); 
296   if (aPart.get()) // this may be null is Part feature is disabled
297     return aPart->partDoc();
298   return DocumentPtr();
299 }
300
301 ObjectPtr PartSet_PartDataModel::object(const QModelIndex& theIndex) const
302 {
303   if (theIndex.internalId() >= 0) {
304     int aPRow = theIndex.internalId();
305     ObjectPtr aObj = 
306       partDocument()->object(ModelAPI_Feature::group(), aPRow - getRowsNumber());
307     CompositeFeaturePtr aCompFeature = 
308       std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aObj);
309     if (aCompFeature.get()) {
310       return aCompFeature->subFeature(theIndex.row(), true);
311     }
312     return ObjectPtr();
313   }
314   switch (theIndex.internalId()) {
315     case ParamsFolder:
316     case ConstructFolder:
317     case BodiesFolder:
318     case GroupsFolder:
319       return ObjectPtr();
320
321     case ParamObject:
322       return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
323     case ConstructObject:
324       return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
325     case BodiesObject:
326       return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
327     case GroupObject:
328       return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
329     case HistoryObject:
330       return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
331   }
332   return ObjectPtr();
333 }
334
335 bool PartSet_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
336 {
337   return (partDocument() == theDoc);
338 }
339
340 QModelIndex PartSet_PartDataModel::findParent(const ObjectPtr& theObject) const
341 {
342   return findGroup(theObject->groupName().c_str());
343 }
344
345 QModelIndex PartSet_PartDataModel::findGroup(const std::string& theGroup) const
346 {
347   if (theGroup == ModelAPI_ResultParameter::group())
348     return createIndex(0, 0, (qint32) ParamsFolder);
349   if (theGroup == ModelAPI_ResultConstruction::group())
350     return createIndex(1, 0, (qint32) ConstructFolder);
351   if (theGroup == ModelAPI_ResultBody::group())
352     return createIndex(2, 0, (qint32) BodiesFolder);
353   if (theGroup == ModelAPI_ResultGroup::group())
354     return createIndex(3, 0, (qint32) GroupsFolder);
355   return QModelIndex();
356 }
357
358 QModelIndex PartSet_PartDataModel::objectIndex(const ObjectPtr& theObject) const
359 {
360   QModelIndex aIndex;
361   if (theObject) {
362     if (part() == theObject)
363       return aIndex;
364
365     std::string aGroup = theObject->groupName();
366     DocumentPtr aDoc = theObject->document();
367     int aNb = aDoc->size(aGroup);
368     int aRow = -1;
369     for (int i = 0; i < aNb; i++) {
370       if (aDoc->object(aGroup, i) == theObject) {
371         aRow = i;
372         break;
373       }
374     }
375     if (aRow == -1)
376       return aIndex;
377     if (aGroup == ModelAPI_ResultParameter::group())
378       return createIndex(aRow, 0, (qint32) ParamObject);
379     else if (aGroup == ModelAPI_ResultConstruction::group())
380       return createIndex(aRow, 0, (qint32) ConstructObject);
381     else if (aGroup == ModelAPI_ResultBody::group())
382       return createIndex(aRow, 0, (qint32) BodiesObject);
383     else if (aGroup == ModelAPI_ResultGroup::group())
384       return createIndex(aRow, 0, (qint32) GroupObject);
385     else
386       return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject);
387   }
388   return aIndex;
389 }
390
391
392 int PartSet_PartDataModel::getRowsNumber() const
393 {
394   int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
395   if (aSize == 0) // If there are no groups then do not show group folder
396     return 3;
397   return 4;
398 }
399
400 int PartSet_PartDataModel::lastHistoryRow() const
401 {
402   DocumentPtr aDoc = partDocument();
403   FeaturePtr aFeature = aDoc->currentFeature(true);
404   if (aFeature.get())
405     return getRowsNumber() + aDoc->index(aFeature);
406   else
407     return getRowsNumber() - 1;
408 }
409
410 void PartSet_PartDataModel::setLastHistoryItem(const QModelIndex& theIndex)
411 {
412   SessionPtr aMgr = ModelAPI_Session::get();
413   DocumentPtr aDoc = partDocument();
414   std::string aOpName = tr("History change").toStdString();
415   if (theIndex.internalId() == HistoryObject) {
416     ObjectPtr aObject = object(theIndex);
417     aMgr->startOperation(aOpName);
418     aDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
419     aMgr->finishOperation();
420   } else {
421     aMgr->startOperation(aOpName);
422     aDoc->setCurrentFeature(FeaturePtr(), true);
423     aMgr->finishOperation();
424   }
425 }
426
427 QModelIndex PartSet_PartDataModel::lastHistoryItem() const
428 {
429   return index(lastHistoryRow(), 1);
430 }
431
432 Qt::ItemFlags PartSet_PartDataModel::flags(const QModelIndex& theIndex) const
433 {
434   // Disable sub-features at column 1
435   if ((theIndex.column() == 1)  && (theIndex.internalId() >= 0))
436     return 0;
437
438   Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
439   if (object(theIndex)) {
440     aFlags |= Qt::ItemIsEditable;
441   }
442
443   if (theIndex.internalId() == HistoryObject) {
444     if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
445       aFlags |= Qt::ItemIsEnabled;
446   } else
447     aFlags |= Qt::ItemIsEnabled;
448   return aFlags;
449 }