]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_DataModel.cpp
Salome HOME
97269a35176e3072b115e88e6f14c69847a10fbd
[modules/shaper.git] / src / XGUI / XGUI_DataModel.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        ModuleBase_IDocumentDataModel.cpp
4 // Created:     28 Apr 2015
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "XGUI_DataModel.h"
8
9 #include <ModuleBase_IconFactory.h>
10
11 #include <ModelAPI_Session.h>
12 #include <ModelAPI_Events.h>
13 #include <ModelAPI_ResultParameter.h>
14 #include <ModelAPI_AttributeDouble.h>
15 #include <ModelAPI_ResultPart.h>
16 #include <ModelAPI_Feature.h>
17 #include <ModelAPI_CompositeFeature.h>
18 #include <ModelAPI_ResultCompSolid.h>
19 #include <ModelAPI_Tools.h>
20
21 #include <Config_FeatureMessage.h>
22
23 #include <Events_Loop.h>
24 #include <Events_Error.h>
25
26 #include <QIcon>
27 #include <QBrush>
28
29 #define ACTIVE_COLOR QColor(0,72,140)
30 #define PASSIVE_COLOR Qt::black
31
32 /// Returns ResultPart object if the given object is a Part feature
33 /// Otherwise returns NULL
34 ResultPartPtr getPartResult(ModelAPI_Object* theObj)
35 {
36   ModelAPI_Feature* aFeature = dynamic_cast<ModelAPI_Feature*>(theObj);
37   if (aFeature) {
38     ResultPtr aRes = aFeature->firstResult();
39     if (aRes.get() && (aRes->groupName() == ModelAPI_ResultPart::group())) {
40       return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aRes);
41     }
42   }
43   return ResultPartPtr();
44 }
45
46 /// Returns pointer on document if the given object is document object
47 ModelAPI_Document* getSubDocument(void* theObj)
48 {
49   ModelAPI_Document* aDoc = dynamic_cast<ModelAPI_Document*>((ModelAPI_Entity*)theObj);
50   return aDoc;
51 }
52
53
54
55
56 // Constructor *************************************************
57 XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)
58 {
59   myXMLReader.readAll();
60
61   Events_Loop* aLoop = Events_Loop::loop();
62   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
63   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
64 }
65
66 //******************************************************
67 void XGUI_DataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
68 {
69   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
70   std::string aRootType = myXMLReader.rootType();
71   std::string aSubType = myXMLReader.subType();
72   int aNbFolders = foldersCount();
73
74   // Created object event *******************
75   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
76     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
77         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
78     std::set<ObjectPtr> aObjects = aUpdMsg->objects();
79
80     std::set<ObjectPtr>::const_iterator aIt;
81     std::string aObjType;
82     for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
83       ObjectPtr aObject = (*aIt);
84       aObjType = aObject->groupName();
85       DocumentPtr aDoc = aObject->document();
86       if (aDoc == aRootDoc) {
87         // Check that new folders could appear
88         QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
89         foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
90           if ((aNotEmptyFolder.toStdString() == aObjType) && (aRootDoc->size(aObjType) == 1))
91             // Appears first object in folder which can not be shown empty
92             insertRow(myXMLReader.rootFolderId(aObjType));
93         }
94         // Insert new object
95         int aRow = aRootDoc->size(aObjType) - 1;
96         if (aObjType == aRootType) {
97           insertRow(aRow + aNbFolders + 1);
98         } else {
99           int aFolderId = myXMLReader.rootFolderId(aObjType);
100           if (aFolderId != -1) {
101             insertRow(aRow, createIndex(aFolderId, 0, -1));
102           }
103         } 
104       } else {
105         // Object created in sub-document
106         QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get());
107         if (aDocRoot.isValid()) {
108           // Check that new folders could appear
109           QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
110           foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
111             if ((aNotEmptyFolder.toStdString() == aObjType) && (aDoc->size(aObjType) == 1))
112               // Appears first object in folder which can not be shown empty
113               insertRow(myXMLReader.subFolderId(aObjType), aDocRoot);
114           }
115           int aRow = aDoc->size(aObjType) - 1;
116           int aNbSubFolders = foldersCount(aDoc.get());
117           if (aObjType == aSubType) {
118             // List of objects under document root
119             insertRow(aRow + aNbSubFolders, aDocRoot);
120           } else {
121             // List of objects under a folder
122             if (aRow != -1) {
123               int aFolderId = myXMLReader.subFolderId(aObjType);
124               if (aFolderId != -1) {
125                 insertRow(aRow, createIndex(aFolderId, 0, aDoc.get()));
126               }
127             }
128           }
129         } 
130 #ifdef _DEBUG
131         else {
132           Events_Error::send("Problem with Data Model definition of sub-document");
133         }
134 #endif
135       }
136     }
137     // Deleted object event ***********************
138   } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
139     std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
140         std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
141     DocumentPtr aDoc = aUpdMsg->document();
142     std::set<std::string> aGroups = aUpdMsg->groups();
143     std::set<std::string>::const_iterator aIt;
144     for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
145       std::string aGroup = (*aIt);
146       if (aDoc == aRootDoc) {  // If root objects
147         int aRow = aRootDoc->size(aGroup);
148         if (aGroup == aRootType) {
149           removeRow(aRow + aNbFolders);
150         } else {
151           int aFolderId = myXMLReader.rootFolderId(aGroup);
152           if (aFolderId != -1) {
153             QModelIndex aFolderIndex = createIndex(aFolderId, 0, -1);
154             removeRow(aRow, aFolderIndex);
155           }
156         }
157         // Check that some folders could erased
158         QStringList aNotEmptyFolders = listOfShowNotEmptyFolders();
159         foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
160           if ((aNotEmptyFolder.toStdString() == aGroup) && (aRootDoc->size(aGroup) == 0))
161             // Appears first object in folder which can not be shown empty
162             removeRow(myXMLReader.rootFolderId(aGroup));
163         }
164       } else {
165         // Remove row for sub-document
166         QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get());
167         if (aDocRoot.isValid()) {
168           int aRow = aDoc->size(aGroup);
169           int aNbSubFolders = foldersCount(aDoc.get());
170           if (aGroup == aSubType) {
171             // List of objects under document root
172             removeRow(aRow + aNbSubFolders, aDocRoot);
173           } else {
174             // List of objects under a folder
175             int aFolderId = myXMLReader.subFolderId(aGroup);
176             if (aFolderId != -1) {
177               removeRow(aRow, createIndex(aFolderId, 0, aDoc.get()));
178             }
179           }
180           // Check that some folders could disappear
181           QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
182           foreach (QString aNotEmptyFolder, aNotEmptyFolders) {
183             if ((aNotEmptyFolder.toStdString() == aGroup) && (aDoc->size(aGroup) == 1))
184               // Appears first object in folder which can not be shown empty
185               removeRow(myXMLReader.subFolderId(aGroup), aDocRoot);
186           }
187         } 
188 #ifdef _DEBUG
189         else {
190           Events_Error::send("Problem with Data Model definition of sub-document");
191         }
192 #endif
193       }
194     }
195   } 
196 }
197
198 //******************************************************
199 void XGUI_DataModel::clear()
200 {
201
202 }
203
204 //******************************************************
205 void XGUI_DataModel::rebuildDataTree()
206 {
207
208 }
209
210 //******************************************************
211 ObjectPtr XGUI_DataModel::object(const QModelIndex& theIndex) const
212 {
213   if (theIndex.internalId() < 0) // this is a folder
214     return ObjectPtr();
215   ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer();
216   if (getSubDocument(aObj)) // the selected index is a folder of sub-document
217     return ObjectPtr();
218
219   // We can not create the ObjectPtr directly because the pointer will be deleted 
220   // with deletion of the ObjectPtr because its counter become to 0.
221   DocumentPtr aDoc = aObj->document();
222   std::string aType = aObj->groupName();
223
224   ObjectPtr aObjPtr;
225   for (int i = 0; i < aDoc->size(aType); i++) {
226     aObjPtr = aDoc->object(aType, i);
227     if (aObjPtr.get() == aObj)
228       return aObjPtr;
229   }
230   return ObjectPtr();
231 }
232
233 //******************************************************
234 QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const
235 {
236   std::string aType = theObject->groupName();
237   DocumentPtr aDoc = theObject->document();
238   int aRow = aDoc->index(theObject);
239   if (aRow == -1) {
240     // it could be a part of complex object
241     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
242     if (aFeature.get()) {
243       CompositeFeaturePtr aCompFea = ModelAPI_Tools::compositeOwner(aFeature);
244       if (aCompFea.get()) {
245         for (int i = 0; i < aCompFea->numberOfSubs(); i++) {
246           if (aCompFea->subFeature(i, true) == theObject) {
247             aRow = i;
248             break;
249           }
250         }
251       }
252     } else {
253       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
254       //if (aResult.get()) {
255       //  ResultCompSolidPtr aCompRes = ModelAPI_Tools::compositeOwner(aResult);
256       //  if (aCompRes.get()) {
257       //    for (int i = 0; i < aCompRes->numberOfSubs(); i++) {
258       //      if (aCompRes->subResult(i, true) == theObject) {
259       //        aRow = i;
260       //        break;
261       //      }
262       //    }
263       //  }
264       //}
265     }
266     if (aRow == -1)
267       return QModelIndex();
268     else 
269       return createIndex(aRow, 0, theObject.get());
270   }
271   SessionPtr aSession = ModelAPI_Session::get();
272   DocumentPtr aRootDoc = aSession->moduleDocument();
273   if (aDoc == aRootDoc && myXMLReader.rootType() == aType) { 
274     // The object from root document
275     aRow += foldersCount();
276   } else if (myXMLReader.subType() == aType) { 
277     // The object from sub document
278     aRow += foldersCount(aDoc.get());
279   }
280   return createIndex(aRow, 0, theObject.get());
281 }
282
283 //******************************************************
284 QVariant XGUI_DataModel::data(const QModelIndex& theIndex, int theRole) const
285 {
286   SessionPtr aSession = ModelAPI_Session::get();
287   DocumentPtr aRootDoc = aSession->moduleDocument();
288   int aNbFolders = foldersCount();
289   int theIndexRow = theIndex.row();
290
291   if ((theRole == Qt::DecorationRole) && (theIndex == lastHistoryIndex()))
292     return QIcon(":pictures/arrow.png");
293
294   if (theIndex.column() == 1)
295     return QVariant();
296
297   int aParentId = theIndex.internalId();
298   if (aParentId == -1) { // root folders
299     switch (theRole) {
300       case Qt::DisplayRole:
301         return QString(myXMLReader.rootFolderName(theIndexRow).c_str()) + 
302           QString(" (%1)").arg(rowCount(theIndex));
303       case Qt::DecorationRole:
304         return QIcon(myXMLReader.rootFolderIcon(theIndexRow).c_str());
305       case Qt::ForegroundRole:
306         if (aSession->activeDocument() == aRootDoc)
307           return QBrush(ACTIVE_COLOR);
308         else
309           return QBrush(PASSIVE_COLOR);
310     }
311   } else { // an object or sub-document
312     ModelAPI_Document* aSubDoc = getSubDocument(theIndex.internalPointer());
313
314     if (theRole == Qt::ForegroundRole) {
315       bool aIsActive = false;
316       if (aSubDoc)
317         aIsActive = (aSession->activeDocument().get() == aSubDoc);
318       else {
319         ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer();
320         if (aObj->isDisabled())
321           return QBrush(Qt::lightGray);
322         aIsActive = (aSession->activeDocument() == aObj->document());
323       }
324       if (aIsActive)
325         return QBrush(ACTIVE_COLOR);
326       else
327         return QBrush(PASSIVE_COLOR);
328     }
329
330     if (aSubDoc) { // this is a folder of sub document
331       switch (theRole) {
332         case Qt::DisplayRole:
333           return QString(myXMLReader.subFolderName(theIndexRow).c_str()) + 
334             QString(" (%1)").arg(rowCount(theIndex));
335         case Qt::DecorationRole:
336           return QIcon(myXMLReader.subFolderIcon(theIndexRow).c_str());
337       }
338     } else {
339       ModelAPI_Object* aObj = (ModelAPI_Object*)theIndex.internalPointer();
340       switch (theRole) {
341       case Qt::DisplayRole:
342         if (aObj->groupName() == ModelAPI_ResultParameter::group()) {
343           ModelAPI_ResultParameter* aParam = dynamic_cast<ModelAPI_ResultParameter*>(aObj);
344           AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
345           QString aVal = QString::number(aValueAttribute->value());
346           QString aTitle = QString(aObj->data()->name().c_str());
347           return aTitle + " = " + aVal;
348         }
349         return aObj->data()->name().c_str();
350       case Qt::DecorationRole:
351         return ModuleBase_IconFactory::get()->getIcon(object(theIndex));
352       }
353     }
354   }
355   return QVariant();
356 }
357
358 //******************************************************
359 QVariant XGUI_DataModel::headerData(int theSection, Qt::Orientation theOrient, int theRole) const
360 {
361   return QVariant();
362 }
363
364 //******************************************************
365 int XGUI_DataModel::rowCount(const QModelIndex& theParent) const
366 {
367   SessionPtr aSession = ModelAPI_Session::get();
368   if (!aSession->hasModuleDocument())
369     return 0;
370   DocumentPtr aRootDoc = aSession->moduleDocument();
371
372   if (!theParent.isValid()) {
373     // Return number of items in root
374     int aNbFolders = foldersCount();
375     int aNbItems = 0;
376     std::string aType = myXMLReader.rootType();
377     if (!aType.empty())
378       aNbItems = aRootDoc->size(aType);
379     return aNbFolders + aNbItems;
380   }
381
382   int aId = theParent.internalId();
383   if (aId == -1) { 
384     // this is a folder under root
385     int aParentPos = theParent.row();
386     std::string aType = myXMLReader.rootFolderType(aParentPos);
387     //qDebug("### %s = %i\n", aType.c_str(), aRootDoc->size(aType));
388     return aRootDoc->size(aType);
389   } else {
390     // It is an object which could have children
391     ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
392     if (aDoc) { 
393       // a folder of sub-document
394       std::string aType = myXMLReader.subFolderType(theParent.row());
395       return aDoc->size(aType);
396     } else {
397       ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer();
398       // Check for Part feature
399       ResultPartPtr aPartRes = getPartResult(aObj);
400       if (aPartRes.get()) {
401         DocumentPtr aSubDoc = aPartRes->partDoc();
402         int aNbSubFolders = foldersCount(aSubDoc.get());
403         int aNbSubItems = 0;
404         std::string aSubType = myXMLReader.subType();
405         if (!aSubType.empty())
406           aNbSubItems = aSubDoc->size(aSubType);
407         return aNbSubItems + aNbSubFolders;
408       } else {
409         // Check for composite object
410         ModelAPI_CompositeFeature* aCompFeature = dynamic_cast<ModelAPI_CompositeFeature*>(aObj);
411         if (aCompFeature) 
412           return aCompFeature->numberOfSubs(true);
413         ModelAPI_ResultCompSolid* aCompRes = dynamic_cast<ModelAPI_ResultCompSolid*>(aObj);
414         if (aCompRes) 
415           return aCompRes->numberOfSubs(true);
416       }
417     }
418   }
419   return 0;
420 }
421
422 //******************************************************
423 int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
424 {
425   return 2;
426 }
427
428 //******************************************************
429 QModelIndex XGUI_DataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
430 {
431   SessionPtr aSession = ModelAPI_Session::get();
432   DocumentPtr aRootDoc = aSession->moduleDocument();
433   int aNbFolders = foldersCount();
434
435   QModelIndex aIndex;
436
437   if (!theParent.isValid()) {
438     if (theRow < aNbFolders) // Return first level folder index
439       return createIndex(theRow, theColumn, -1);
440     else { // return object under root index
441       std::string aType = myXMLReader.rootType();
442       int aObjId = theRow - aNbFolders;
443       if (aObjId < aRootDoc->size(aType)) {
444         ObjectPtr aObj = aRootDoc->object(aType, aObjId);
445         aIndex = objectIndex(aObj);
446       }
447     }
448   } else {
449     int aId = theParent.internalId();
450     int aParentPos = theParent.row();
451     if (aId == -1) { // return object index inside of first level of folders
452       std::string aType = myXMLReader.rootFolderType(aParentPos);
453       if (theRow < aRootDoc->size(aType)) {
454         ObjectPtr aObj = aRootDoc->object(aType, theRow);
455         aIndex = objectIndex(aObj);
456       }
457     } else {
458       // It is an object which could have children
459       ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
460       if (aDoc) { 
461         // It is a folder of sub-document
462         std::string aType = myXMLReader.subFolderType(aParentPos);
463         if (theRow < aDoc->size(aType)) {
464           ObjectPtr aObj = aDoc->object(aType, theRow);
465           aIndex = objectIndex(aObj);
466         }
467       } else {
468         ModelAPI_Object* aParentObj = (ModelAPI_Object*)theParent.internalPointer();
469
470         // Check for Part feature
471         ResultPartPtr aPartRes = getPartResult(aParentObj);
472         if (aPartRes.get()) {
473           DocumentPtr aSubDoc = aPartRes->partDoc();
474           int aNbSubFolders = foldersCount(aSubDoc.get());
475           if (theRow < aNbSubFolders) { // Create a Folder of sub-document
476             aIndex = createIndex(theRow, theColumn, aSubDoc.get());
477           } else {
478             // this is an object under sub document root
479             std::string aType = myXMLReader.subType();
480             ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders);
481             aIndex = objectIndex(aObj);
482           }
483         } else {
484           // Check for composite object
485           ModelAPI_CompositeFeature* aCompFeature = dynamic_cast<ModelAPI_CompositeFeature*>(aParentObj);
486           if (aCompFeature) {
487             aIndex = objectIndex(aCompFeature->subFeature(theRow));
488           } else {
489             ModelAPI_ResultCompSolid* aCompRes = dynamic_cast<ModelAPI_ResultCompSolid*>(aParentObj);
490             if (aCompRes) 
491               aIndex = objectIndex(aCompRes->subResult(theRow));
492           }
493         }
494       }
495     }
496   }
497   if (theColumn != 0)
498     return createIndex(aIndex.row(), theColumn, aIndex.internalPointer());
499   return aIndex;
500 }
501
502 //******************************************************
503 QModelIndex XGUI_DataModel::parent(const QModelIndex& theIndex) const
504 {
505   int aId = theIndex.internalId();
506   if (aId != -1) { // The object is not a root folder
507     ModelAPI_Document* aDoc = getSubDocument(theIndex.internalPointer());
508     if (aDoc) { 
509       // It is a folder of sub-document
510       return findDocumentRootIndex(aDoc);
511     }
512     ModelAPI_Object* aObj = (ModelAPI_Object*) theIndex.internalPointer();
513     std::string aType = aObj->groupName();
514     SessionPtr aSession = ModelAPI_Session::get();
515     DocumentPtr aRootDoc = aSession->moduleDocument();
516     DocumentPtr aSubDoc = aObj->document();
517     if (aSubDoc == aRootDoc) {
518       if (aType == myXMLReader.rootType())
519         return QModelIndex();
520       else {
521         // return first level of folder index
522         int aFolderId = myXMLReader.rootFolderId(aType);
523         // Items in a one row must have the same parent
524         return createIndex(aFolderId, 0, -1);
525       }
526     } else {
527       if (aType == myXMLReader.subType())
528         return findDocumentRootIndex(aSubDoc.get());
529       else {
530         // return first level of folder index
531         int aFolderId = myXMLReader.subFolderId(aType);
532         // Items in a one row must have the same parent
533         return createIndex(aFolderId, 0, aSubDoc.get());
534       }
535     }
536   } 
537   return QModelIndex();
538 }
539
540 //******************************************************
541 bool XGUI_DataModel::hasChildren(const QModelIndex& theParent) const
542 {
543   if (!theParent.isValid()) {
544     int aNbFolders = foldersCount();
545     if (aNbFolders > 0)
546       return true;
547     SessionPtr aSession = ModelAPI_Session::get();
548     DocumentPtr aRootDoc = aSession->moduleDocument();
549     return aRootDoc->size(myXMLReader.rootType()) > 0;
550   }
551   if (theParent.internalId() == -1) {
552     std::string aType = myXMLReader.rootFolderType(theParent.row());
553     if (!aType.empty()) {
554       SessionPtr aSession = ModelAPI_Session::get();
555       DocumentPtr aRootDoc = aSession->moduleDocument();
556       return aRootDoc->size(aType) > 0;
557     }
558   } else {
559     ModelAPI_Document* aDoc = getSubDocument(theParent.internalPointer());
560     if (aDoc) { 
561       // a folder of sub-document
562       std::string aType = myXMLReader.subFolderType(theParent.row());
563       return aDoc->size(aType) > 0;
564     } else {
565       // Check that it could be an object with children
566       ModelAPI_Object* aObj = (ModelAPI_Object*)theParent.internalPointer();
567
568       // Check for Part feature
569       ResultPartPtr aPartRes = getPartResult(aObj);
570       if (aPartRes.get())
571         return true;
572       else {
573         // Check for composite object
574         ModelAPI_CompositeFeature* aCompFeature = dynamic_cast<ModelAPI_CompositeFeature*>(aObj);
575         if (aCompFeature) 
576           return aCompFeature->numberOfSubs(true) > 0;
577         ModelAPI_ResultCompSolid* aCompRes = dynamic_cast<ModelAPI_ResultCompSolid*>(aObj);
578         if (aCompRes) 
579           return aCompRes->numberOfSubs(true) > 0;
580       }
581     }
582   }
583   return false;
584 }
585
586 //******************************************************
587 bool XGUI_DataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
588 {
589   beginInsertRows(theParent, theRow, theRow + theCount - 1);
590   endInsertRows();
591
592   return true;
593 }
594
595 //******************************************************
596 bool XGUI_DataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
597 {
598   beginRemoveRows(theParent, theRow, theRow + theCount - 1);
599   endRemoveRows();
600   return true;
601 }
602
603 //******************************************************
604 Qt::ItemFlags XGUI_DataModel::flags(const QModelIndex& theIndex) const
605 {
606   Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
607
608   ModelAPI_Object* aObj = 0;
609   if (theIndex.internalId() != -1) {
610     if (!getSubDocument(theIndex.internalPointer()))
611       aObj = (ModelAPI_Object*) theIndex.internalPointer();
612   }
613   if (aObj) {
614     aFlags |= Qt::ItemIsEditable;
615   
616     if (!aObj->isDisabled())
617       aFlags |= Qt::ItemIsEnabled;
618   } else
619     aFlags |= Qt::ItemIsEnabled;
620   return aFlags;
621 }
622
623 //******************************************************
624 QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc) const
625 {
626   SessionPtr aSession = ModelAPI_Session::get();
627   DocumentPtr aRootDoc = aSession->moduleDocument();
628   if (myXMLReader.isAttachToResult()) { // If document is attached to result
629     int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
630     ObjectPtr aObj;
631     ResultPartPtr aPartRes;
632     for (int i = 0; i < aNb; i++) {
633       aObj = aRootDoc->object(ModelAPI_ResultPart::group(), i);
634       aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
635       if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
636         int aRow = i;
637         if (myXMLReader.rootType() == ModelAPI_Feature::group())
638           aRow += foldersCount();
639         return createIndex(aRow, 0, aObj.get());
640       }
641     }
642   } else { // If document is attached to feature
643     int aNb = aRootDoc->size(ModelAPI_Feature::group());
644     ObjectPtr aObj;
645     ResultPartPtr aPartRes;
646     for (int i = 0; i < aNb; i++) {
647       aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
648       aPartRes = getPartResult(aObj.get());
649       if (aPartRes.get() && (aPartRes->partDoc().get() == theDoc)) {
650         int aRow = i;
651         if (myXMLReader.rootType() == ModelAPI_Feature::group())
652           aRow += foldersCount();
653         return createIndex(aRow, 0, aObj.get());
654       }
655     }
656   }
657   return QModelIndex();
658 }
659
660 //******************************************************
661 QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc) const
662 {
663   SessionPtr aSession = ModelAPI_Session::get();
664   DocumentPtr aRootDoc = aSession->moduleDocument();
665   if (theDoc == aRootDoc)
666     return QModelIndex();
667   else 
668     return findDocumentRootIndex(theDoc.get());
669 }
670
671 //******************************************************
672 int XGUI_DataModel::foldersCount(ModelAPI_Document* theDoc) const
673 {
674   int aNb = 0;
675   SessionPtr aSession = ModelAPI_Session::get();
676   DocumentPtr aRootDoc = aSession->moduleDocument();
677   if ((theDoc == 0) || (theDoc == aRootDoc.get())) {
678     for (int i = 0; i < myXMLReader.rootFoldersNumber(); i++) {
679       if (myXMLReader.rootShowEmpty(i))
680         aNb++;
681       else {
682         if (aRootDoc->size(myXMLReader.rootFolderType(i)) > 0)
683           aNb++;
684       }
685     }
686   } else {
687     for (int i = 0; i < myXMLReader.subFoldersNumber(); i++) {
688       if (myXMLReader.subShowEmpty(i))
689         aNb++;
690       else {
691         if (theDoc->size(myXMLReader.subFolderType(i)) > 0)
692           aNb++;
693       }
694     }
695   }
696   return aNb;
697 }
698
699 //******************************************************
700 QStringList XGUI_DataModel::listOfShowNotEmptyFolders(bool fromRoot) const
701 {
702   QStringList aResult;
703   if (fromRoot) {
704     for (int i = 0; i < myXMLReader.rootFoldersNumber(); i++) {
705       if (!myXMLReader.rootShowEmpty(i))
706         aResult << myXMLReader.rootFolderType(i).c_str();
707     }
708   } else {
709     for (int i = 0; i < myXMLReader.subFoldersNumber(); i++) {
710       if (!myXMLReader.subShowEmpty(i))
711         aResult << myXMLReader.subFolderType(i).c_str();
712     }
713   }
714   return aResult;
715 }
716
717 //******************************************************
718 QModelIndex XGUI_DataModel::lastHistoryIndex() const
719 {
720   SessionPtr aSession = ModelAPI_Session::get();
721   DocumentPtr aCurDoc = aSession->activeDocument();
722   FeaturePtr aFeature = aCurDoc->currentFeature(true);
723   if (aFeature.get()) {
724     QModelIndex aInd = objectIndex(aFeature);
725     return createIndex(aInd.row(), 1, aInd.internalPointer());
726   } else {
727     if (aCurDoc == aSession->moduleDocument())
728       return createIndex(foldersCount() - 1, 1, -1);
729     else 
730       return createIndex(foldersCount(aCurDoc.get()) - 1, 1, aCurDoc.get());
731   }
732 }