Salome HOME
Merge branch 'Dev_1.2.0' of newgeom:newgeom into Dev_1.2.0
[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   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
472   ObjectPtr aObject = aRootDoc->object(ModelAPI_Feature::group(), myId);
473   FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
474   ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFeature->firstResult()); 
475   if (aPart.get()) // this may be null is Part feature is disabled
476     return aPart->partDoc();
477   return DocumentPtr();
478 }
479
480 ObjectPtr PartSet_PartDataModel::object(const QModelIndex& theIndex) const
481 {
482   switch (theIndex.internalId()) {
483     case ParamsFolder:
484     case ConstructFolder:
485     case BodiesFolder:
486     case GroupsFolder:
487       return ObjectPtr();
488
489     case ParamObject:
490       return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
491     case ConstructObject:
492       return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
493     case BodiesObject:
494       return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
495     case GroupObject:
496       return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
497     case HistoryObject:
498       return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
499   }
500   return ObjectPtr();
501 }
502
503 bool PartSet_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
504 {
505   return (partDocument() == theDoc);
506 }
507
508 QModelIndex PartSet_PartDataModel::findParent(const ObjectPtr& theObject) const
509 {
510   return findGroup(theObject->groupName().c_str());
511 }
512
513 QModelIndex PartSet_PartDataModel::findGroup(const std::string& theGroup) const
514 {
515   if (theGroup == ModelAPI_ResultParameter::group())
516     return createIndex(0, 0, (qint32) ParamsFolder);
517   if (theGroup == ModelAPI_ResultConstruction::group())
518     return createIndex(1, 0, (qint32) ConstructFolder);
519   if (theGroup == ModelAPI_ResultBody::group())
520     return createIndex(2, 0, (qint32) BodiesFolder);
521   if (theGroup == ModelAPI_ResultGroup::group())
522     return createIndex(3, 0, (qint32) GroupsFolder);
523   return QModelIndex();
524 }
525
526 ResultPartPtr PartSet_PartDataModel::part() const
527 {
528   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
529   ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
530   return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
531 }
532
533 QModelIndex PartSet_PartDataModel::objectIndex(const ObjectPtr& theObject) const
534 {
535   QModelIndex aIndex;
536   if (theObject) {
537     if (part() == theObject)
538       return aIndex;
539
540     std::string aGroup = theObject->groupName();
541     DocumentPtr aDoc = theObject->document();
542     int aNb = aDoc->size(aGroup);
543     int aRow = -1;
544     for (int i = 0; i < aNb; i++) {
545       if (aDoc->object(aGroup, i) == theObject) {
546         aRow = i;
547         break;
548       }
549     }
550     if (aRow == -1)
551       return aIndex;
552     if (aGroup == ModelAPI_ResultParameter::group())
553       return createIndex(aRow, 0, (qint32) ParamObject);
554     else if (aGroup == ModelAPI_ResultConstruction::group())
555       return createIndex(aRow, 0, (qint32) ConstructObject);
556     else if (aGroup == ModelAPI_ResultBody::group())
557       return createIndex(aRow, 0, (qint32) BodiesObject);
558     else if (aGroup == ModelAPI_ResultGroup::group())
559       return createIndex(aRow, 0, (qint32) GroupObject);
560     else
561       return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject);
562   }
563   return aIndex;
564 }
565
566
567 int PartSet_PartDataModel::getRowsNumber() const
568 {
569   int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
570   if (aSize == 0) // If there are no groups then do not show group folder
571     return 3;
572   return 4;
573 }
574
575 int PartSet_PartDataModel::lastHistoryRow() const
576 {
577   DocumentPtr aDoc = partDocument();
578   FeaturePtr aFeature = aDoc->currentFeature(true);
579   if (aFeature.get())
580     return getRowsNumber() + aDoc->index(aFeature);
581   else
582     return getRowsNumber() - 1;
583 }
584
585 void PartSet_PartDataModel::setLastHistoryItem(const QModelIndex& theIndex)
586 {
587   SessionPtr aMgr = ModelAPI_Session::get();
588   DocumentPtr aDoc = partDocument();
589   std::string aOpName = tr("History change").toStdString();
590   if (theIndex.internalId() == HistoryObject) {
591     ObjectPtr aObject = object(theIndex);
592     aMgr->startOperation(aOpName);
593     aDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
594     aMgr->finishOperation();
595   } else {
596     aMgr->startOperation(aOpName);
597     aDoc->setCurrentFeature(FeaturePtr(), true);
598     aMgr->finishOperation();
599   }
600 }
601
602 QModelIndex PartSet_PartDataModel::lastHistoryItem() const
603 {
604   return index(lastHistoryRow(), 1);
605 }
606
607 Qt::ItemFlags PartSet_PartDataModel::flags(const QModelIndex& theIndex) const
608 {
609   Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
610   if (object(theIndex)) {
611     aFlags |= Qt::ItemIsEditable;
612   }
613   if (theIndex.internalId() == HistoryObject) {
614     if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
615       aFlags |= Qt::ItemIsEnabled;
616   } else
617     aFlags |= Qt::ItemIsEnabled;
618   return aFlags;
619 }