1 // Created on: 2017-06-16
2 // Created by: Natalia ERMOLAEVA
3 // Copyright (c) 2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <inspector/TreeModel_ModelBase.hxx>
17
18 #include <inspector/TreeModel_ItemBase.hxx>
19 #include <inspector/TreeModel_ItemProperties.hxx>
20 #include <inspector/TreeModel_Tools.hxx>
21 #include <inspector/TreeModel_VisibilityState.hxx>
22
23 #include <Standard_Transient.hxx>
24
25 #include <Standard_WarningsDisable.hxx>
26 #include <QIcon>
27 #include <Standard_WarningsRestore.hxx>
28
29 const int COLUMN_NAME_WIDTH = 260;
30 const int COLUMN_SIZE_WIDTH = 30;
31
32 // =======================================================================
33 // function : Constructor
34 // purpose :
35 // =======================================================================
TreeModel_ModelBase(QObject * theParent)36 TreeModel_ModelBase::TreeModel_ModelBase (QObject* theParent)
37 : QAbstractItemModel (theParent), m_pUseVisibilityColumn (false),
38 myVisibilityState (0)
39 {
40 myVisibleIcon = QIcon (":/icons/item_visible.png");
41 myInvisibleIcon = QIcon (":/icons/item_invisible.png");
42 }
43
44 // =======================================================================
45 // function : InitColumns
46 // purpose :
47 // =======================================================================
InitColumns()48 void TreeModel_ModelBase::InitColumns()
49 {
50 setHeaderItem (TreeModel_ColumnType_Name, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH));
51 setHeaderItem (TreeModel_ColumnType_Visibility, TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth()));
52 setHeaderItem (TreeModel_ColumnType_Row, TreeModel_HeaderSection ("Row", COLUMN_SIZE_WIDTH));
53 }
54
55 // =======================================================================
56 // function : GetItemByIndex
57 // purpose :
58 // =======================================================================
GetItemByIndex(const QModelIndex & theIndex)59 TreeModel_ItemBasePtr TreeModel_ModelBase::GetItemByIndex (const QModelIndex& theIndex)
60 {
61 TreeModel_ItemBase* anItem = (TreeModel_ItemBase*)theIndex.internalPointer();
62 return TreeModel_ItemBasePtr (anItem);
63 }
64
65 // =======================================================================
66 // function : reset
67 // purpose :
68 // =======================================================================
Reset()69 void TreeModel_ModelBase::Reset()
70 {
71 for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++)
72 {
73 TreeModel_ItemBasePtr aRootItem = RootItem (aColId);
74 if (aRootItem)
75 aRootItem->Reset();
76 }
77 }
78
79 // =======================================================================
80 // function : index
81 // purpose :
82 // =======================================================================
index(int theRow,int theColumn,const QModelIndex & theParent) const83 QModelIndex TreeModel_ModelBase::index (int theRow, int theColumn, const QModelIndex& theParent) const
84 {
85 if (!hasIndex (theRow, theColumn, theParent))
86 return QModelIndex();
87
88 // to create index on the root item
89 if (!theParent.isValid())
90 return createIndex (theRow, theColumn, getIndexValue (RootItem (theColumn)));
91
92 TreeModel_ItemBasePtr aParentItem;
93 if (!theParent.isValid())
94 aParentItem = RootItem (theColumn);
95 else
96 aParentItem = GetItemByIndex (theParent);
97
98 TreeModel_ItemBasePtr aChildItem = aParentItem->Child (theRow, theColumn);
99 return aChildItem ? createIndex (theRow, theColumn, getIndexValue (aChildItem)) : QModelIndex();
100 }
101
102 // =======================================================================
103 // function : data
104 // purpose :
105 // =======================================================================
data(const QModelIndex & theIndex,int theRole) const106 QVariant TreeModel_ModelBase::data (const QModelIndex& theIndex, int theRole) const
107 {
108 if (!theIndex.isValid())
109 return QVariant ("undefined");
110
111 if (IsUseVisibilityColumn() && theIndex.column() == TreeModel_ColumnType_Visibility)
112 {
113 if (theRole != Qt::DecorationRole)
114 return QVariant();
115
116 TreeModel_ItemBasePtr anItem = GetItemByIndex (theIndex);
117 if (!anItem->data (theIndex, theRole).isNull()) // value is already in cache
118 return anItem->data (theIndex, theRole);
119
120 if (!anItem->IsInitialized())
121 anItem->Init();
122
123 if (!myVisibilityState || !myVisibilityState->CanBeVisible (theIndex))
124 return QVariant();
125
126 QVariant aValue = myVisibilityState->IsVisible (theIndex) ? myVisibleIcon : myInvisibleIcon;
127 anItem->SetCustomData (aValue, theRole);
128 return aValue;
129 }
130
131 TreeModel_ItemBasePtr anItem = GetItemByIndex (theIndex);
132 QVariant anItemData = anItem->data (theIndex, theRole);
133
134 if (anItemData.isNull() && theRole == Qt::BackgroundRole && myHighlightedIndices.contains (theIndex))
135 anItemData = TreeModel_Tools::LightHighlightColor();
136
137 return anItemData;
138 }
139
140 // =======================================================================
141 // function : parent
142 // purpose :
143 // =======================================================================
parent(const QModelIndex & theIndex) const144 QModelIndex TreeModel_ModelBase::parent (const QModelIndex& theIndex) const
145 {
146 if (!theIndex.isValid())
147 return QModelIndex();
148
149 TreeModel_ItemBasePtr aChildItem = GetItemByIndex (theIndex);
150 TreeModel_ItemBasePtr aParentItem = aChildItem ? aChildItem->Parent() : TreeModel_ItemBasePtr();
151
152 if (!aParentItem)
153 return QModelIndex();
154
155 return createIndex (aParentItem->Row(), aParentItem->Column(), getIndexValue (aParentItem));
156 }
157
158 // =======================================================================
159 // function : flags
160 // purpose :
161 // =======================================================================
flags(const QModelIndex & theIndex) const162 Qt::ItemFlags TreeModel_ModelBase::flags (const QModelIndex& theIndex) const
163 {
164 if (!theIndex.isValid())
165 {
166 return Qt::ItemFlags();
167 }
168 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
169 }
170
171 // =======================================================================
172 // function : headerData
173 // purpose :
174 // =======================================================================
headerData(int theSection,Qt::Orientation theOrientation,int theRole) const175 QVariant TreeModel_ModelBase::headerData (int theSection, Qt::Orientation theOrientation, int theRole) const
176 {
177 if (theOrientation != Qt::Horizontal || theRole != Qt::DisplayRole)
178 return QVariant();
179
180 if (IsUseVisibilityColumn() && theSection == TreeModel_ColumnType_Visibility)
181 return QVariant();
182
183 return myHeaderValues[theSection].GetName();
184 }
185
186 // =======================================================================
187 // function : rowCount
188 // purpose :
189 // =======================================================================
rowCount(const QModelIndex & theParent) const190 int TreeModel_ModelBase::rowCount (const QModelIndex& theParent) const
191 {
192 // to create index on the root item
193 if (!theParent.isValid())
194 return 1;
195
196 TreeModel_ItemBasePtr aParentItem;
197 if (!theParent.isValid())
198 aParentItem = RootItem (0);
199 else
200 aParentItem = GetItemByIndex (theParent);
201
202 if (!aParentItem)
203 return 0;
204
205 return aParentItem ? aParentItem->rowCount() : 0;
206 }
207
208 // =======================================================================
209 // function : EmitLayoutChanged
210 // purpose :
211 // =======================================================================
EmitLayoutChanged()212 void TreeModel_ModelBase::EmitLayoutChanged()
213 {
214 emit layoutChanged();
215 }
216
217 // =======================================================================
218 // function : EmitLayoutChanged
219 // purpose :
220 // =======================================================================
EmitDataChanged(const QModelIndex & theTopLeft,const QModelIndex & theBottomRight,const QVector<int> & theRoles,const bool isResetItem)221 void TreeModel_ModelBase::EmitDataChanged (const QModelIndex& theTopLeft, const QModelIndex& theBottomRight,
222 const QVector<int>& theRoles,
223 const bool isResetItem)
224 {
225 TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (theTopLeft);
226 if (anItemBase && isResetItem)
227 anItemBase->Reset();
228
229 #if QT_VERSION < 0x050000
230 (void)theRoles;
231 emit dataChanged (theTopLeft, theBottomRight);
232 #else
233 emit dataChanged (theTopLeft, theBottomRight, theRoles);
234 #endif
235 }
236
237 // =======================================================================
238 // function : Selected
239 // purpose :
240 // =======================================================================
Selected(const QModelIndexList & theIndices,const int theCellId,const Qt::Orientation theOrientation)241 QModelIndexList TreeModel_ModelBase::Selected (const QModelIndexList& theIndices, const int theCellId,
242 const Qt::Orientation theOrientation)
243 {
244 QModelIndexList aSelected;
245 for (QModelIndexList::const_iterator anIndicesIt = theIndices.begin(); anIndicesIt != theIndices.end(); anIndicesIt++)
246 {
247 QModelIndex anIndex = *anIndicesIt;
248 if ((theOrientation == Qt::Horizontal && anIndex.column() == theCellId) ||
249 (theOrientation == Qt::Vertical && anIndex.row() == theCellId))
250 aSelected.append (anIndex);
251 }
252 return aSelected;
253 }
254
255 // =======================================================================
256 // function : SingleSelected
257 // purpose :
258 // =======================================================================
SingleSelected(const QModelIndexList & theIndices,const int theCellId,const Qt::Orientation theOrientation)259 QModelIndex TreeModel_ModelBase::SingleSelected (const QModelIndexList& theIndices, const int theCellId,
260 const Qt::Orientation theOrientation)
261 {
262 QModelIndexList aSelected = Selected (theIndices, theCellId, theOrientation);
263 return aSelected.size() == 1 ? aSelected.first() : QModelIndex();
264 }
265
266 // =======================================================================
267 // function : SelectedItems
268 // purpose :
269 // =======================================================================
SelectedItems(const QModelIndexList & theIndices)270 QList<TreeModel_ItemBasePtr> TreeModel_ModelBase::SelectedItems (const QModelIndexList& theIndices)
271 {
272 QList<TreeModel_ItemBasePtr> anItems;
273
274 for (QModelIndexList::const_iterator anIndicesIt = theIndices.begin(); anIndicesIt != theIndices.end(); anIndicesIt++)
275 {
276 TreeModel_ItemBasePtr anItem = TreeModel_ModelBase::GetItemByIndex (*anIndicesIt);
277 if (!anItem || anItems.contains (anItem))
278 continue;
279 anItems.append (anItem);
280 }
281 return anItems;
282 }
283
284 // =======================================================================
285 // function : SubItemsPresentations
286 // purpose :
287 // =======================================================================
SubItemsPresentations(const QModelIndexList & theIndices,NCollection_List<Handle (Standard_Transient)> & thePresentations)288 void TreeModel_ModelBase::SubItemsPresentations (const QModelIndexList& theIndices,
289 NCollection_List<Handle(Standard_Transient)>& thePresentations)
290 {
291 QList<TreeModel_ItemBasePtr> anItems;
292
293 for (QModelIndexList::const_iterator anIndicesIt = theIndices.begin(); anIndicesIt != theIndices.end(); anIndicesIt++)
294 {
295 TreeModel_ItemBasePtr anItem = TreeModel_ModelBase::GetItemByIndex (*anIndicesIt);
296 if (!anItem || anItems.contains (anItem))
297 continue;
298 subItemsPresentations (anItem, thePresentations);
299 }
300 }
301
302 // =======================================================================
303 // function : subItemPresentations
304 // purpose :
305 // =======================================================================
subItemsPresentations(const TreeModel_ItemBasePtr & theItem,NCollection_List<Handle (Standard_Transient)> & thePresentations)306 void TreeModel_ModelBase::subItemsPresentations (const TreeModel_ItemBasePtr& theItem,
307 NCollection_List<Handle(Standard_Transient)>& thePresentations)
308 {
309 theItem->Presentations (thePresentations);
310
311 QList<TreeModel_ItemBasePtr> anItems;
312 for (int aRowId = 0; aRowId < theItem->rowCount(); aRowId++)
313 {
314 subItemsPresentations (theItem->Child (aRowId, theItem->Column()), thePresentations);
315 }
316 }
317
318 // =======================================================================
319 // function : createRoot
320 // purpose :
321 // =======================================================================
createRoot(const int theColumnId)322 void TreeModel_ModelBase::createRoot (const int theColumnId)
323 {
324 myRootItems.insert (theColumnId, createRootItem (theColumnId));
325 }
326
327 // =======================================================================
328 // function : setHeaderItem
329 // purpose :
330 // =======================================================================
setHeaderItem(const int theColumnId,const TreeModel_HeaderSection & theSection)331 void TreeModel_ModelBase::setHeaderItem (const int theColumnId, const TreeModel_HeaderSection& theSection)
332 {
333 if (theSection.IsEmpty())
334 {
335 // remove section
336 myHeaderValues.remove (theColumnId);
337 myRootItems.remove (theColumnId);
338 }
339
340 myHeaderValues[theColumnId] = theSection;
341 createRoot (theColumnId);
342 }
343
344 // =======================================================================
345 // function : getIndexValue
346 // purpose :
347 // =======================================================================
getIndexValue(const TreeModel_ItemBasePtr & theItem)348 void* TreeModel_ModelBase::getIndexValue (const TreeModel_ItemBasePtr& theItem)
349 {
350 return theItem.data();
351 }
352