]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_ObjectsBrowser.cpp
Salome HOME
Initial implementation of support of any level of hierarchy in Result Bodies.
[modules/shaper.git] / src / XGUI / XGUI_ObjectsBrowser.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "XGUI_ObjectsBrowser.h"
22 #include "XGUI_Tools.h"
23 #include "XGUI_DataModel.h"
24
25 #include <ModelAPI_Data.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_Document.h>
28 #include <ModelAPI_Tools.h>
29
30 #include <ModuleBase_Tools.h>
31
32 #include <XGUI_Workshop.h>
33
34 #include <QLayout>
35 #include <QLineEdit>
36 #include <QPixmap>
37 #include <QEvent>
38 #include <QMouseEvent>
39 #include <QAction>
40 #include <QStyledItemDelegate>
41 #include <QMessageBox>
42
43 #ifdef DEBUG_INDXES
44 #include <QToolTip>
45 #endif
46
47 /// Width of second column (minimum acceptable = 27)
48 #define FIRST_COL_WIDTH 20
49 #define SECOND_COL_WIDTH 30
50
51
52 /**
53 * \ingroup GUI
54 * Tree item delegate for definition of data in column items editor
55 */
56 class XGUI_TreeViewItemDelegate: public QStyledItemDelegate
57 {
58 public:
59   /// Constructor
60   /// \param theParent a parent of the delegate
61   XGUI_TreeViewItemDelegate(XGUI_DataTree* theParent):QStyledItemDelegate(theParent),
62     myTreedView(theParent) {}
63
64   /// Set data for item editor (name of the item)
65   /// \param editor a widget of editor
66   /// \param index the tree item index
67   virtual void  setEditorData ( QWidget* editor, const QModelIndex& index ) const
68   {
69     QLineEdit* aEditor = dynamic_cast<QLineEdit*>(editor);
70     if (aEditor) {
71       XGUI_DataModel* aModel = myTreedView->dataModel();
72       ObjectPtr aObj = aModel->object(index);
73       if (aObj.get() != NULL) {
74         aEditor->setText(aObj->data()->name().c_str());
75         return;
76       }
77     }
78     QStyledItemDelegate::setEditorData(editor, index);
79   }
80
81 private:
82   XGUI_DataTree* myTreedView;
83 };
84
85
86 XGUI_DataTree::XGUI_DataTree(QWidget* theParent)
87     : QTreeView(theParent)
88 {
89   setHeaderHidden(true);
90   setTreePosition(1);
91   setEditTriggers(QAbstractItemView::NoEditTriggers);
92   setSelectionBehavior(QAbstractItemView::SelectRows);
93   setSelectionMode(QAbstractItemView::ExtendedSelection);
94
95   setItemDelegateForColumn(1, new XGUI_TreeViewItemDelegate(this));
96
97   connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
98     SLOT(onDoubleClick(const QModelIndex&)));
99 }
100
101 XGUI_DataTree::~XGUI_DataTree()
102 {
103 }
104
105 XGUI_DataModel* XGUI_DataTree::dataModel() const
106 {
107   return static_cast<XGUI_DataModel*>(model());
108 }
109
110 void XGUI_DataTree::contextMenuEvent(QContextMenuEvent* theEvent)
111 {
112   emit contextMenuRequested(theEvent);
113 }
114
115 void XGUI_DataTree::commitData(QWidget* theEditor)
116 {
117   static int aEntrance = 0;
118   if (aEntrance == 0) {
119     // We have to check number of enter and exit of this function because it can be called
120     // recursively by Qt in order to avoid double modifying of a data
121     aEntrance = 1;
122     QLineEdit* aEditor = dynamic_cast<QLineEdit*>(theEditor);
123     if (aEditor) {
124       QString aName = aEditor->text();
125       QModelIndexList aIndexList = selectionModel()->selectedIndexes();
126       XGUI_DataModel* aModel = dataModel();
127       ObjectPtr aObj = aModel->object(aIndexList.first());
128
129       if (XGUI_Tools::canRename(aObj, aName)) {
130         SessionPtr aMgr = ModelAPI_Session::get();
131         aMgr->startOperation("Rename");
132         aObj->data()->setName(qPrintable(aName));
133         aMgr->finishOperation();
134       }
135     }
136   }
137   aEntrance = 0;
138 }
139
140 void XGUI_DataTree::clear()
141 {
142   dataModel()->clear();
143   reset();
144 }
145
146 void XGUI_DataTree::resizeEvent(QResizeEvent* theEvent)
147 {
148   QTreeView::resizeEvent(theEvent);
149   QSize aSize = theEvent->size();
150   if (aSize.isValid()) {
151     setColumnWidth(0, FIRST_COL_WIDTH);
152     setColumnWidth(1, aSize.width() - SECOND_COL_WIDTH - FIRST_COL_WIDTH - 10);
153     setColumnWidth(2, SECOND_COL_WIDTH);
154   }
155 }
156
157 #ifdef DEBUG_INDXES
158 void XGUI_DataTree::mousePressEvent(QMouseEvent* theEvent)
159 {
160   QTreeView::mousePressEvent(theEvent);
161   if (theEvent->button() != Qt::MidButton)
162     return;
163   QModelIndex aInd = indexAt(theEvent->pos());
164   QString aTxt =
165     QString("r=%1 c=%2 p=%3").arg(aInd.row()).arg(aInd.column()).arg((long)aInd.internalPointer());
166
167   QModelIndex aPar = aInd.parent();
168   QString aTxt1 =
169     QString("r=%1 c=%2 p=%3").arg(aPar.row()).arg(aPar.column()).arg((long)aPar.internalPointer());
170   QToolTip::showText(theEvent->globalPos(), aTxt + '\n' + aTxt1);
171 }
172 #endif
173
174 void XGUI_DataTree::mouseReleaseEvent(QMouseEvent* theEvent)
175 {
176   QTreeView::mouseReleaseEvent(theEvent);
177 #ifdef DEBUG_INDXES
178   if (theEvent->button() != Qt::MidButton)
179     return;
180   QToolTip::hideText();
181 #endif
182   if (theEvent->button() == Qt::LeftButton) {
183     QModelIndex aInd = indexAt(theEvent->pos());
184     if (aInd.column() == 0)
185       processEyeClick(aInd);
186   }
187 }
188
189 void XGUI_DataTree::processHistoryChange(const QModelIndex& theIndex)
190 {
191   SessionPtr aMgr = ModelAPI_Session::get();
192   // When operation is opened then we can not change history
193   if (aMgr->isOperation())
194     return;
195   XGUI_DataModel* aModel = dataModel();
196   if (aModel->flags(theIndex) == 0)
197     return;
198   ObjectPtr aObj = aModel->object(theIndex);
199
200   DocumentPtr aDoc = aMgr->activeDocument();
201
202   std::string aOpName = tr("History change").toStdString();
203   if (aObj.get()) {
204     if (aObj->document() != aDoc)
205       return;
206     aMgr->startOperation(aOpName);
207     aDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObj), true);
208     aMgr->finishOperation();
209   } else {
210     // Ignore clicks on folders outside current document
211     if ((theIndex.internalId() == 0) && (aDoc != aMgr->moduleDocument()))
212       // Clicked folder under root but active document is another
213       return;
214     if ((theIndex.internalId() != 0) && (aDoc.get() != theIndex.internalPointer()))
215       // Cliced not on active document folder
216       return;
217
218     aMgr->startOperation(aOpName);
219     aDoc->setCurrentFeature(FeaturePtr(), true);
220     aMgr->finishOperation();
221   }
222   QModelIndex aParent = theIndex.parent();
223   int aSize = aModel->rowCount(aParent);
224   for (int i = 0; i < aSize; i++) {
225     update(aModel->index(i, 0, aParent));
226     update(aModel->index(i, 1, aParent));
227     update(aModel->index(i, 2, aParent));
228   }
229 }
230
231 void XGUI_DataTree::processEyeClick(const QModelIndex& theIndex)
232 {
233   XGUI_DataModel* aModel = dataModel();
234   ObjectPtr aObj = aModel->object(theIndex);
235   if (aObj.get()) {
236     ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
237     XGUI_ObjectsBrowser* aObjBrowser = qobject_cast<XGUI_ObjectsBrowser*>(parent());
238     if (aResObj.get()) {
239       std::set<ObjectPtr> anObjects;
240       anObjects.insert(aResObj);
241
242       bool hasHiddenState = aModel->hasHiddenState(theIndex);
243       if (aObjBrowser && hasHiddenState && !aObjBrowser->workshop()->prepareForDisplay(anObjects))
244         return;
245       if (hasHiddenState) // #issue 2335(hide all faces then show solid problem)
246         aResObj->setDisplayed(true);
247       else
248         aResObj->setDisplayed(!aResObj->isDisplayed());
249       Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
250       update(theIndex);
251     }
252     // Update list of selected objects because this event happens after
253     // selection event in object browser
254     if (aObjBrowser) {
255       aObjBrowser->onSelectionChanged();
256     }
257   }
258 }
259
260 void XGUI_DataTree::onDoubleClick(const QModelIndex& theIndex)
261 {
262   switch (theIndex.column()) {
263   case 2:
264     processHistoryChange(theIndex);
265     break;
266   }
267 }
268
269
270 //********************************************************************
271 //********************************************************************
272 //********************************************************************
273 XGUI_ActiveDocLbl::XGUI_ActiveDocLbl(const QString& theText, QWidget* theParent )
274   : QLabel(theText, theParent),
275   myPreSelectionStyle(""),
276   myNeutralStyle(""),
277   mySelectionStyle(""),
278   myIsSelected(false)
279 {
280 }
281
282 void XGUI_ActiveDocLbl::setTreeView(QTreeView* theView)
283 {
284   myTreeView = theView;
285   setFont(myTreeView->font());
286
287   QPalette aPalet = myTreeView->palette();
288   QColor aHighlight = aPalet.highlight().color();
289   QColor aHighlightText = aPalet.highlightedText().color();
290
291   myPreSelectionStyle = "QLabel {background-color: ";
292   myPreSelectionStyle += aHighlight.lighter(170).name() + "}";
293   //myPreSelectionStyle += "qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:1 " +
294   //  aHighlight.lighter(170).name() + ");";
295   //myPreSelectionStyle += "border: 1px solid lightblue; border-radius: 2px }";
296
297   QString aName = aPalet.color(QPalette::Base).name();
298   myNeutralStyle = "QLabel { border: 1px solid " + aName + " }";
299
300
301 #if (!defined HAVE_SALOME) && (defined WIN32)
302   mySelectionStyle = "QLabel {background-color: ";
303   mySelectionStyle += "rgb(205, 232, 255); ";
304   //mySelectionStyle += "qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(236, 245, 255)";
305   //mySelectionStyle += ", stop:1 rgb(208, 229, 255));";
306   //mySelectionStyle += "border: 1px solid rgb(132, 172, 221); border-radius: 2px }";
307   mySelectionStyle += "border: 1px solid rgb(153, 209, 255) }";
308 #else
309   mySelectionStyle = "QLabel {background-color: " + aHighlight.name();
310   mySelectionStyle += "; color : " + aHighlightText.name() + "}";
311 #endif
312
313   myTreeView->viewport()->installEventFilter(this);
314 }
315
316
317 #if (!defined HAVE_SALOME) && (defined WIN32)
318 bool XGUI_ActiveDocLbl::event(QEvent* theEvent)
319 {
320   switch (theEvent->type()) {
321     case QEvent::Enter:
322       if (!myIsSelected)
323         setStyleSheet(myPreSelectionStyle);
324       break;
325     case QEvent::Leave:
326       if (!myIsSelected)
327         setStyleSheet(myNeutralStyle);
328       break;
329   }
330   return QLabel::event(theEvent);
331 }
332 #endif
333
334 bool XGUI_ActiveDocLbl::eventFilter(QObject* theObj, QEvent* theEvent)
335 {
336   if (theObj == myTreeView->viewport()) {
337     if (theEvent->type() == QEvent::MouseButtonRelease)
338       unselect();
339   }
340   return QLabel::eventFilter(theObj, theEvent);
341 }
342
343 static bool MYClearing = false;
344 void XGUI_ActiveDocLbl::mouseReleaseEvent( QMouseEvent* e)
345 {
346   MYClearing = true;
347   myIsSelected = true;
348   setStyleSheet(mySelectionStyle);
349   // We can not block signals because on
350   // clear selection the View state will not be updated
351   myTreeView->clearSelection();
352   QLabel::mouseReleaseEvent(e);
353   MYClearing = false;
354 }
355
356 void XGUI_ActiveDocLbl::unselect()
357 {
358   if (!MYClearing) {
359     myIsSelected = false;
360     setStyleSheet(myNeutralStyle);
361   }
362 }
363
364
365 //********************************************************************
366 //********************************************************************
367 //********************************************************************
368 XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent, XGUI_Workshop* theWorkshop)
369     : QWidget(theParent), myDocModel(0), myWorkshop(theWorkshop)
370 {
371   QVBoxLayout* aLayout = new QVBoxLayout(this);
372   ModuleBase_Tools::zeroMargins(aLayout);
373   aLayout->setSpacing(0);
374
375   QWidget* aLabelWgt = new QWidget(this);
376   aLabelWgt->setAutoFillBackground(true);
377
378   aLayout->addWidget(aLabelWgt);
379   QHBoxLayout* aLabelLay = new QHBoxLayout(aLabelWgt);
380   ModuleBase_Tools::zeroMargins(aLabelLay);
381   aLabelLay->setSpacing(0);
382
383   QLabel* aLbl = new QLabel(aLabelWgt);
384   aLbl->setPixmap(QPixmap(":pictures/assembly.png"));
385   aLbl->setMargin(2);
386   // Do not paint background of the label (in order to show icon)
387   aLbl->setAutoFillBackground(false);
388
389   aLabelLay->addWidget(aLbl);
390
391   SessionPtr aMgr = ModelAPI_Session::get();
392   DocumentPtr aDoc = aMgr->moduleDocument();
393
394   myActiveDocLbl = new XGUI_ActiveDocLbl(tr("Part set"), aLabelWgt);
395 //  myActiveDocLbl->setReadOnly(true);
396 //  myActiveDocLbl->setFrame(false);
397   myActiveDocLbl->setContextMenuPolicy(Qt::CustomContextMenu);
398
399   aLabelLay->addWidget(myActiveDocLbl);
400   aLabelLay->setStretch(1, 1);
401
402   myTreeView = new XGUI_DataTree(this);
403   myTreeView->setFrameShape(QFrame::NoFrame);
404   aLayout->addWidget(myTreeView);
405
406   QPalette aTreePalet = myTreeView->palette();
407   QColor aTreeBack = aTreePalet.color(QPalette::Base);
408
409   QPalette aPalet;
410   aPalet.setColor(QPalette::Base, aTreeBack);
411   aPalet.setColor(QPalette::Window, aTreeBack);
412   aLabelWgt->setPalette(aPalet);
413
414   myDocModel = new XGUI_DataModel(this);
415   connect(myDocModel, SIGNAL(modelAboutToBeReset()), SLOT(onBeforeReset()));
416   connect(myDocModel, SIGNAL(treeRebuilt()), SLOT(onAfterModelReset()));
417
418   connect(myTreeView, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
419           SLOT(onContextMenuRequested(QContextMenuEvent*)));
420 }
421
422 //***************************************************
423 XGUI_ObjectsBrowser::~XGUI_ObjectsBrowser()
424 {
425 }
426
427 void XGUI_ObjectsBrowser::initialize(ModuleBase_ITreeNode* theRoot)
428 {
429   //myDocModel->setXMLReader(theReader);
430   myDocModel->setRoot(theRoot);
431   myTreeView->setModel(myDocModel);
432
433   // It has to be done after setting of model
434   myActiveDocLbl->setTreeView(myTreeView);
435
436   QItemSelectionModel* aSelMod = myTreeView->selectionModel();
437   connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
438           this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
439 }
440
441 //***************************************************
442 void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent)
443 {
444   QModelIndexList aIndexes;
445   QObjectPtrList aSelectedData = selectedObjects(&aIndexes);
446   bool toEnable = false;
447
448   if (aSelectedData.size() == 1) {
449     QModelIndex aSelected = myTreeView->indexAt(theEvent->pos());
450     if (!aIndexes.contains(aSelected))
451       return; // menu is called on non selected item
452
453     Qt::ItemFlags aFlags = dataModel()->flags(aIndexes.first());
454     toEnable = ((aFlags & Qt::ItemIsEditable) != 0);
455   }
456   foreach(QAction* aCmd, actions()) {
457     aCmd->setEnabled(toEnable);
458   }
459   emit contextMenuRequested(theEvent);
460 }
461
462 //***************************************************
463 void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt)
464 {
465   myTreeView->selectionModel()->clearSelection();
466   //Empty feature pointer means that selected root document
467   foreach(QAction* aCmd, actions()) {
468     aCmd->setEnabled(true);
469   }
470   QContextMenuEvent aEvent(QContextMenuEvent::Mouse, thePnt, myActiveDocLbl->mapToGlobal(thePnt));
471   emit contextMenuRequested(&aEvent);
472 }
473
474 //***************************************************
475 void XGUI_ObjectsBrowser::onEditItem()
476 {
477   QObjectPtrList aSelectedData = selectedObjects();
478   if (aSelectedData.size() > 0) {
479     ObjectPtr anObject = aSelectedData.first();
480     if (anObject.get()) {  // Selection happens in TreeView
481       // check whether the object can be renamed. There should not be parts which are not loaded
482       std::set<FeaturePtr> aFeatures;
483       aFeatures.insert(ModelAPI_Feature::feature(anObject));
484       if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aFeatures))
485         return;
486
487       // Find index which corresponds the feature
488       QModelIndex aIndex;
489       foreach(QModelIndex aIdx, selectedIndexes()) {
490         ObjectPtr aFea = dataModel()->object(aIdx);
491         if (dataModel()->object(aIdx)->isSame(anObject)) {
492           aIndex = aIdx;
493           break;
494         }
495       }
496       if (aIndex.isValid()) {
497         myTreeView->setCurrentIndex(aIndex);
498         myTreeView->edit(aIndex);
499       }
500       return;
501     }
502   }
503 }
504
505 //***************************************************
506 QModelIndexList XGUI_ObjectsBrowser::expandedItems(const QModelIndex& theParent) const
507 {
508   QModelIndexList aIndexes;
509   QModelIndex aIndex;
510   for (int i = 0; i < myDocModel->rowCount(theParent); i++) {
511     aIndex = myDocModel->index(i, 0, theParent);
512     if (myDocModel->hasChildren(aIndex)) {
513       if (myTreeView->isExpanded(aIndex)) {
514         aIndexes.append(aIndex);
515         QModelIndexList aSubIndexes = expandedItems(aIndex);
516         if (!aSubIndexes.isEmpty())
517           aIndexes.append(aSubIndexes);
518       }
519     }
520   }
521   return aIndexes;
522 }
523
524 //***************************************************
525 void XGUI_ObjectsBrowser::rebuildDataTree()
526 {
527   myDocModel->rebuildDataTree();
528   update();
529 }
530
531 //***************************************************
532 void XGUI_ObjectsBrowser::setObjectsSelected(const QObjectPtrList& theObjects)
533 {
534   QList<QModelIndex> theIndexes;
535   QItemSelectionModel* aSelectModel = myTreeView->selectionModel();
536   aSelectModel->clear();
537
538   foreach(ObjectPtr aFeature, theObjects)
539   {
540     QModelIndex aIndex = myDocModel->objectIndex(aFeature);
541     if (aIndex.isValid()) {
542       aSelectModel->select(aIndex, QItemSelectionModel::Select);
543     }
544   }
545 }
546
547 //***************************************************
548 void XGUI_ObjectsBrowser::ensureVisible(const ObjectPtr theObject)
549 {
550   QModelIndex aIndex = myDocModel->objectIndex(theObject);
551   if (aIndex.isValid())  {
552     QModelIndex aParent = aIndex.parent();
553     while (aParent.isValid()) {
554       myTreeView->expand(aParent);
555       aParent = aParent.parent();
556     }
557     myTreeView->scrollTo(aIndex);
558   }
559 }
560
561 //***************************************************
562 void XGUI_ObjectsBrowser::clearContent()
563 {
564   myTreeView->clear();
565 }
566
567 //***************************************************
568 void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected,
569                                        const QItemSelection& theDeselected)
570 {
571   onSelectionChanged();
572 }
573
574 //***************************************************
575 void XGUI_ObjectsBrowser::onSelectionChanged()
576 {
577   emit selectionChanged();
578 }
579
580 //***************************************************
581 QObjectPtrList XGUI_ObjectsBrowser::selectedObjects(QModelIndexList* theIndexes) const
582 {
583   QObjectPtrList aList;
584   QModelIndexList aIndexes = selectedIndexes();
585   XGUI_DataModel* aModel = dataModel();
586   QModelIndexList::const_iterator aIt;
587   for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
588     if ((*aIt).column() == 1) {
589       ObjectPtr aObject = aModel->object(*aIt);
590       if (aObject) {
591         aList.append(aObject);
592         if (theIndexes)
593           theIndexes->append(*aIt);
594       }
595     }
596   }
597   return aList;
598 }
599
600 void XGUI_ObjectsBrowser::onBeforeReset()
601 {
602   myExpandedItems = expandedItems();
603 }
604
605 void XGUI_ObjectsBrowser::onAfterModelReset()
606 {
607   foreach(QModelIndex aIndex, myExpandedItems) {
608     if (myTreeView->dataModel()->hasIndex(aIndex))
609       myTreeView->setExpanded(aIndex, true);
610   }
611 }
612
613 std::list<bool> XGUI_ObjectsBrowser::getStateForDoc(DocumentPtr theDoc) const
614 {
615   std::list<bool> aStates;
616   XGUI_DataModel* aModel = dataModel();
617   QModelIndex aRootIdx = aModel->documentRootIndex(theDoc);
618   int aNbChild = aModel->rowCount(aRootIdx);
619   for (int i = 0; i < aNbChild; i++) {
620     QModelIndex aIdx = aModel->index(i, 0, aRootIdx);
621     aStates.push_back(myTreeView->isExpanded(aIdx));
622   }
623   return aStates;
624 }
625
626 void XGUI_ObjectsBrowser::setStateForDoc(DocumentPtr theDoc, const std::list<bool>& theStates)
627 {
628   if (theStates.size() == 0)
629     return;
630   XGUI_DataModel* aModel = dataModel();
631   QModelIndex aRootIdx = aModel->documentRootIndex(theDoc);
632   int aNbChild = aModel->rowCount(aRootIdx);
633
634   std::list<bool>::const_iterator aIt;
635   int i = 0;
636   for (aIt = theStates.cbegin(); aIt != theStates.cend(); aIt++, i++) {
637     if (i >= aNbChild )
638       break;
639     QModelIndex aIdx = aModel->index(i, 0, aRootIdx);
640     myTreeView->setExpanded(aIdx, (*aIt));
641   }
642 }
643
644 void XGUI_ObjectsBrowser::updateAllIndexes(int theColumn, const QModelIndex& theParent)
645 {
646   int aNb = myDocModel->rowCount(theParent);
647   for (int i = 0; i < aNb; i++) {
648     QModelIndex aIdx = myDocModel->index(i, theColumn, theParent);
649     if (aIdx.isValid() && myDocModel->hasIndex(aIdx)) {
650       myTreeView->update(aIdx);
651       if (myTreeView->isExpanded(aIdx))
652         updateAllIndexes(theColumn, aIdx);
653     }
654   }
655 }
656
657 QMap<ObjectPtr, bool> XGUI_ObjectsBrowser::getFoldersState(DocumentPtr theDoc) const
658 {
659   QMap<ObjectPtr, bool> aMap;
660
661   int aNb = theDoc->size(ModelAPI_Folder::group());
662   ObjectPtr aObj;
663   for (int i = 0; i < aNb; i++) {
664     aObj = theDoc->object(ModelAPI_Folder::group(), i);
665     QModelIndex aIdx = myDocModel->objectIndex(aObj, 0);
666     aMap[aObj] = myTreeView->isExpanded(aIdx);
667   }
668   return aMap;
669 }
670
671 void XGUI_ObjectsBrowser::setFoldersState(const QMap<ObjectPtr, bool>& theStates)
672 {
673   QMap<ObjectPtr, bool>::const_iterator aIt;
674   for (aIt = theStates.constBegin(); aIt != theStates.constEnd(); aIt++) {
675     QModelIndex aIdx = myDocModel->objectIndex(aIt.key(), 0);
676     myTreeView->setExpanded(aIdx, aIt.value());
677   }
678 }