Salome HOME
d124d80fc5272b0b2955a1074a38da7999387e5f
[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
21 #include <QIcon>
22 #include <QBrush>
23
24
25 PartSet_TopDataModel::PartSet_TopDataModel(QObject* theParent)
26     : PartSet_FeaturesModel(theParent)
27 {
28 }
29
30 PartSet_TopDataModel::~PartSet_TopDataModel()
31 {
32 }
33
34 QVariant PartSet_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
35 {
36   if (theIndex.column() == 1)
37     return QVariant();
38
39   switch (theRole) {
40     case Qt::DisplayRole:
41       // return a name
42       switch (theIndex.internalId()) {
43         case ParamsFolder:
44           return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
45         case ParamObject: {
46           DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
47           ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
48           if (aObject) {
49             ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
50             AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
51             QString aVal = QString::number(aValueAttribute->value());
52             QString aTitle = QString(aObject->data()->name().c_str());
53             return aTitle + " = " + aVal;
54           }
55         }
56           break;
57         case ConstructFolder:
58           return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
59         case ConstructObject: {
60           DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
61           ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultConstruction::group(),
62                                                theIndex.row());
63           if (aObject)
64             return aObject->data()->name().c_str();
65         }
66           break;
67         //case GroupsFolder:
68         //  return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
69         //case GroupObject: {
70         //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
71         //  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultGroup::group(),
72         //                                       theIndex.row());
73         //  if (aObject)
74         //    return aObject->data()->name().c_str();
75         //}
76         //  break;
77       }
78       break;
79
80     case Qt::DecorationRole:
81       {
82       // return an Icon
83       switch (theIndex.internalId()) {
84         case ParamsFolder:
85           return QIcon(":pictures/params_folder.png");
86         case ConstructFolder:
87           return QIcon(":pictures/constr_folder.png");
88         case ConstructObject:
89           return QIcon(":pictures/constr_object.png");
90         //case GroupsFolder:
91         //  return QIcon(":pictures/constr_folder.png");
92         }
93       }
94       break;
95
96     case Qt::ToolTipRole:
97       // return Tooltip
98       break;
99     case Qt::ForegroundRole:
100       return QBrush(myItemsColor);
101       break;
102   }
103   return QVariant();
104 }
105
106 QVariant PartSet_TopDataModel::headerData(int section, Qt::Orientation orientation, int role) const
107 {
108   return QVariant();
109 }
110
111 int PartSet_TopDataModel::rowCount(const QModelIndex& theParent) const
112 {
113   if (!theParent.isValid())
114     return 2;  // In case of groups using it has to be +1
115
116   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
117   if (theParent.internalId() == ParamsFolder)
118     return aRootDoc->size(ModelAPI_ResultParameter::group());
119
120   if (theParent.internalId() == ConstructFolder)
121     return aRootDoc->size(ModelAPI_ResultConstruction::group());
122
123   //if (theParent.internalId() == GroupsFolder)
124   //  return aRootDoc->size(ModelAPI_ResultGroup::group());
125
126   return 0;
127 }
128
129 int PartSet_TopDataModel::columnCount(const QModelIndex &parent) const
130 {
131   return 1;
132 }
133
134 QModelIndex PartSet_TopDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
135 {
136   if (!theParent.isValid()) {
137     switch (theRow) {
138       case 0:
139         return createIndex(theRow, theColumn, (qint32) ParamsFolder);
140       case 1:
141         return createIndex(theRow, theColumn, (qint32) ConstructFolder);
142       //case 2:
143       //  return createIndex(theRow, theColumn, (qint32) GroupsFolder);
144     }
145   } else {
146     if (theParent.internalId() == ParamsFolder)
147       return createIndex(theRow, theColumn, (qint32) ParamObject);
148
149     if (theParent.internalId() == ConstructFolder)
150       return createIndex(theRow, theColumn, (qint32) ConstructObject);
151
152     //if (theParent.internalId() == GroupsFolder)
153     //  return createIndex(theRow, theColumn, (qint32) GroupObject);
154   }
155   return QModelIndex();
156 }
157
158 QModelIndex PartSet_TopDataModel::parent(const QModelIndex& theIndex) const
159 {
160   int aId = (int) theIndex.internalId();
161   switch (aId) {
162     case ParamsFolder:
163     case ConstructFolder:
164     //case GroupsFolder:
165       return QModelIndex();
166     case ParamObject:
167       return createIndex(0, 0, (qint32) ParamsFolder);
168     case ConstructObject:
169       return createIndex(1, 0, (qint32) ConstructFolder);
170     //case GroupObject:
171     //  return createIndex(2, 0, (qint32) GroupsFolder);
172   }
173   return QModelIndex();
174 }
175
176 bool PartSet_TopDataModel::hasChildren(const QModelIndex& theParent) const
177 {
178   return rowCount(theParent) > 0;
179 }
180
181 ObjectPtr PartSet_TopDataModel::object(const QModelIndex& theIndex) const
182 {
183   switch (theIndex.internalId()) {
184     case ParamsFolder:
185     case ConstructFolder:
186       return ObjectPtr();
187     case ParamObject: {
188       DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
189       return aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
190     }
191     case ConstructObject: {
192       DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
193       return aRootDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
194     }
195     //case GroupObject: {
196     //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
197     //  return aRootDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
198     //}
199   }
200   return ObjectPtr();
201 }
202
203 QModelIndex PartSet_TopDataModel::findParent(const ObjectPtr& theObject) const
204 {
205   return findGroup(theObject->groupName().c_str());
206 }
207
208 QModelIndex PartSet_TopDataModel::findGroup(const std::string& theGroup) const
209 {
210   if (theGroup == ModelAPI_ResultParameter::group())
211     return createIndex(0, 0, (qint32) ParamsFolder);
212   if (theGroup == ModelAPI_ResultConstruction::group())
213     return createIndex(1, 0, (qint32) ConstructFolder);
214   //if (theGroup == ModelAPI_ResultGroup::group())
215   //  return createIndex(2, 0, (qint32) ConstructFolder);
216   return QModelIndex();
217 }
218
219 QModelIndex PartSet_TopDataModel::objectIndex(const ObjectPtr& theObject) const
220 {
221   QModelIndex aIndex;
222   if (theObject) {
223     DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
224     std::string aGroup = theObject->groupName();
225     int aNb = aRootDoc->size(aGroup);
226     int aRow = -1;
227     for (int i = 0; i < aNb; i++) {
228       if (aRootDoc->object(aGroup, i) == theObject) {
229         aRow = i;
230         break;
231       }
232     }
233     if (aRow != -1) {
234       if (aGroup == ModelAPI_ResultParameter::group())
235         return createIndex(aRow, 0, (qint32) ParamObject);
236       if (aGroup == ModelAPI_ResultConstruction::group())
237         return createIndex(aRow, 0, (qint32) ConstructObject);
238       //if (aGroup == ModelAPI_ResultGroup::group())
239       //  return createIndex(aRow, 0, (qint32) GroupObject);
240     }
241   }
242   return aIndex;
243 }
244
245 //******************************************************************
246 //******************************************************************
247 //******************************************************************
248 PartSet_PartDataModel::PartSet_PartDataModel(QObject* theParent)
249     : PartSet_PartModel(theParent)
250 {
251 }
252
253 PartSet_PartDataModel::~PartSet_PartDataModel()
254 {
255 }
256
257 QVariant PartSet_PartDataModel::data(const QModelIndex& theIndex, int theRole) const
258 {
259   DocumentPtr aPartDoc = partDocument();
260   if (theIndex.column() == 1) {
261     DocumentPtr aActiveDoc = ModelAPI_Session::get()->activeDocument();
262     QModelIndex aParent = theIndex.parent();
263     if (aActiveDoc == aPartDoc) {
264       if (!aParent.isValid()) {
265         switch (theRole) {
266         case Qt::DecorationRole:
267           if (theIndex.row() == lastHistoryRow())
268             return QIcon(":pictures/arrow.png");
269         }
270       }
271     }
272     return QVariant();
273   }
274
275   switch (theRole) {
276     case Qt::DisplayRole:
277       // return a name
278       switch (theIndex.internalId()) {
279         //case MyRoot: {
280         //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
281         //  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
282         //  if (aObject)
283         //    return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
284         //}
285         case ParamsFolder:
286           return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
287         case ConstructFolder:
288           return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
289         case BodiesFolder:
290           return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
291         case GroupsFolder:
292           return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
293         case ParamObject: {
294           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
295           if (aObject) {
296             ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
297             AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
298             QString aVal = QString::number(aValueAttribute->value());
299             QString aTitle = QString(aObject->data()->name().c_str());
300             return aTitle + " = " + aVal;
301           }
302         }
303           break;
304         case ConstructObject: {
305           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
306           if (aObject)
307             return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
308         }
309           break;
310         case BodiesObject: {
311           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), theIndex.row());
312           if (aObject)
313             return aObject->data()->name().c_str();
314         }
315           break;
316         case GroupObject: {
317           ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
318           if (aObject)
319             return aObject->data()->name().c_str();
320         }
321         case HistoryObject: {
322           ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
323           if (aObject)
324             return aObject->data()->name().c_str();
325         }
326       }
327       break;
328     case Qt::DecorationRole:
329       // return an Icon
330       switch (theIndex.internalId()) {
331         //case MyRoot:
332         //  return QIcon(":pictures/part_ico.png");
333         case ParamsFolder:
334           return QIcon(":pictures/params_folder.png");
335         case ConstructFolder:
336         case BodiesFolder:
337           return QIcon(":pictures/constr_folder.png");
338         case GroupsFolder:
339           return QIcon(":pictures/constr_folder.png");
340         case ConstructObject:
341         case GroupObject:
342         case BodiesObject: {
343           std::string aGroup = theIndex.internalId() == ConstructObject ?
344             ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group();
345           ObjectPtr anObject = aPartDoc->object(aGroup, theIndex.row());
346           if (anObject && anObject->data() && 
347               anObject->data()->execState() == ModelAPI_StateMustBeUpdated) {
348             return QIcon(":pictures/constr_object_modified.png");
349           }
350           return QIcon(":pictures/constr_object.png");
351         }
352         case HistoryObject: {
353           ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
354           FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
355           if (aFeature)
356             return PartSet_DocumentDataModel::featureIcon(aFeature);
357         }
358       }
359       break;
360     case Qt::ToolTipRole:
361       // return Tooltip
362       break;
363     case Qt::ForegroundRole:
364       if (theIndex.internalId() == HistoryObject) {
365         if (theIndex.row() > lastHistoryRow())
366           return QBrush(Qt::lightGray);
367       }
368       return QBrush(myItemsColor);
369   }
370   return QVariant();
371 }
372
373 QVariant PartSet_PartDataModel::headerData(int section, Qt::Orientation orientation, int role) const
374 {
375   return QVariant();
376 }
377
378 int PartSet_PartDataModel::rowCount(const QModelIndex& parent) const
379 {
380   if (!parent.isValid()) {
381     DocumentPtr aDoc = partDocument();
382     if (aDoc.get()) {
383       return getRowsNumber() + aDoc->size(ModelAPI_Feature::group());
384     } else 
385       return 0;
386   }
387   switch (parent.internalId()) {
388     case ParamsFolder:
389       return partDocument()->size(ModelAPI_ResultParameter::group());
390     case ConstructFolder:
391       return partDocument()->size(ModelAPI_ResultConstruction::group());
392     case BodiesFolder:
393       return partDocument()->size(ModelAPI_ResultBody::group());
394     case GroupsFolder:
395       return partDocument()->size(ModelAPI_ResultGroup::group());
396   }
397   return 0;
398 }
399
400 int PartSet_PartDataModel::columnCount(const QModelIndex &parent) const
401 {
402   return 2;
403 }
404
405 QModelIndex PartSet_PartDataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
406 {
407   if (!theParent.isValid()) {
408     switch (theRow) {
409       case 0:
410         return createIndex(theRow, theColumn, (qint32) ParamsFolder);
411       case 1:
412         return createIndex(theRow, theColumn, (qint32) ConstructFolder);
413       case 2:
414         return createIndex(theRow, theColumn, (qint32) BodiesFolder);
415       case 3:
416         {
417         int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
418         if (aSize > 0)
419           return createIndex(theRow, theColumn, (qint32) GroupsFolder);
420         else
421           return createIndex(theRow, theColumn, (qint32) HistoryObject);
422         }
423       default:
424         return createIndex(theRow, theColumn, (qint32) HistoryObject);
425     }
426   } else {
427     int aId = (int) theParent.internalId();
428     switch (aId) {
429       case ParamsFolder:
430         return createIndex(theRow, theColumn, (qint32) ParamObject);
431       case ConstructFolder:
432         return createIndex(theRow, theColumn, (qint32) ConstructObject);
433       case BodiesFolder:
434         return createIndex(theRow, theColumn, (qint32) BodiesObject);
435       case GroupsFolder:
436         return createIndex(theRow, theColumn, (qint32) GroupObject);
437     }
438   }
439   return QModelIndex();
440 }
441
442 QModelIndex PartSet_PartDataModel::parent(const QModelIndex& theIndex) const
443 {
444   switch (theIndex.internalId()) {
445     case ParamsFolder:
446     case ConstructFolder:
447     case BodiesFolder:
448     case GroupsFolder:
449     case HistoryObject:
450       return QModelIndex();
451
452     case ParamObject:
453       return createIndex(0, 0, (qint32) ParamsFolder);
454     case ConstructObject:
455       return createIndex(1, 0, (qint32) ConstructFolder);
456     case BodiesObject:
457       return createIndex(2, 0, (qint32) BodiesFolder);
458     case GroupObject:
459       return createIndex(3, 0, (qint32) GroupsFolder);
460   }
461   return QModelIndex();
462 }
463
464 bool PartSet_PartDataModel::hasChildren(const QModelIndex& theParent) const
465 {
466   return rowCount(theParent) > 0;
467 }
468
469 DocumentPtr PartSet_PartDataModel::partDocument() const
470 {
471   ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(myPart->firstResult()); 
472   if (aPart.get()) // this may be null is Part feature is disabled
473     return aPart->partDoc();
474   return DocumentPtr();
475 }
476
477 ObjectPtr PartSet_PartDataModel::object(const QModelIndex& theIndex) const
478 {
479   switch (theIndex.internalId()) {
480     case ParamsFolder:
481     case ConstructFolder:
482     case BodiesFolder:
483     case GroupsFolder:
484       return ObjectPtr();
485
486     case ParamObject:
487       return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
488     case ConstructObject:
489       return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
490     case BodiesObject:
491       return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
492     case GroupObject:
493       return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
494     case HistoryObject:
495       return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
496   }
497   return ObjectPtr();
498 }
499
500 bool PartSet_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
501 {
502   return (partDocument() == theDoc);
503 }
504
505 QModelIndex PartSet_PartDataModel::findParent(const ObjectPtr& theObject) const
506 {
507   return findGroup(theObject->groupName().c_str());
508 }
509
510 QModelIndex PartSet_PartDataModel::findGroup(const std::string& theGroup) const
511 {
512   if (theGroup == ModelAPI_ResultParameter::group())
513     return createIndex(0, 0, (qint32) ParamsFolder);
514   if (theGroup == ModelAPI_ResultConstruction::group())
515     return createIndex(1, 0, (qint32) ConstructFolder);
516   if (theGroup == ModelAPI_ResultBody::group())
517     return createIndex(2, 0, (qint32) BodiesFolder);
518   if (theGroup == ModelAPI_ResultGroup::group())
519     return createIndex(3, 0, (qint32) GroupsFolder);
520   return QModelIndex();
521 }
522
523 QModelIndex PartSet_PartDataModel::objectIndex(const ObjectPtr& theObject) const
524 {
525   QModelIndex aIndex;
526   if (theObject) {
527     if (part() == theObject)
528       return aIndex;
529
530     std::string aGroup = theObject->groupName();
531     DocumentPtr aDoc = theObject->document();
532     int aNb = aDoc->size(aGroup);
533     int aRow = -1;
534     for (int i = 0; i < aNb; i++) {
535       if (aDoc->object(aGroup, i) == theObject) {
536         aRow = i;
537         break;
538       }
539     }
540     if (aRow == -1)
541       return aIndex;
542     if (aGroup == ModelAPI_ResultParameter::group())
543       return createIndex(aRow, 0, (qint32) ParamObject);
544     else if (aGroup == ModelAPI_ResultConstruction::group())
545       return createIndex(aRow, 0, (qint32) ConstructObject);
546     else if (aGroup == ModelAPI_ResultBody::group())
547       return createIndex(aRow, 0, (qint32) BodiesObject);
548     else if (aGroup == ModelAPI_ResultGroup::group())
549       return createIndex(aRow, 0, (qint32) GroupObject);
550     else
551       return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject);
552   }
553   return aIndex;
554 }
555
556
557 int PartSet_PartDataModel::getRowsNumber() const
558 {
559   int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
560   if (aSize == 0) // If there are no groups then do not show group folder
561     return 3;
562   return 4;
563 }
564
565 int PartSet_PartDataModel::lastHistoryRow() const
566 {
567   DocumentPtr aDoc = partDocument();
568   FeaturePtr aFeature = aDoc->currentFeature(true);
569   if (aFeature.get())
570     return getRowsNumber() + aDoc->index(aFeature);
571   else
572     return getRowsNumber() - 1;
573 }
574
575 void PartSet_PartDataModel::setLastHistoryItem(const QModelIndex& theIndex)
576 {
577   SessionPtr aMgr = ModelAPI_Session::get();
578   DocumentPtr aDoc = partDocument();
579   std::string aOpName = tr("History change").toStdString();
580   if (theIndex.internalId() == HistoryObject) {
581     ObjectPtr aObject = object(theIndex);
582     aMgr->startOperation(aOpName);
583     aDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
584     aMgr->finishOperation();
585   } else {
586     aMgr->startOperation(aOpName);
587     aDoc->setCurrentFeature(FeaturePtr(), true);
588     aMgr->finishOperation();
589   }
590 }
591
592 QModelIndex PartSet_PartDataModel::lastHistoryItem() const
593 {
594   return index(lastHistoryRow(), 1);
595 }
596
597 Qt::ItemFlags PartSet_PartDataModel::flags(const QModelIndex& theIndex) const
598 {
599   Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
600   if (object(theIndex)) {
601     aFlags |= Qt::ItemIsEditable;
602   }
603   if (theIndex.internalId() == HistoryObject) {
604     if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
605       aFlags |= Qt::ItemIsEnabled;
606   } else
607     aFlags |= Qt::ItemIsEnabled;
608   return aFlags;
609 }