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