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 #ifndef TreeModel_ItemBase_H
17 #define TreeModel_ItemBase_H
18 
19 #include <NCollection_List.hxx>
20 #include <Standard.hxx>
21 #include <Standard_Macro.hxx>
22 #include <Standard_Handle.hxx>
23 #include <Standard_OStream.hxx>
24 #include <Standard_SStream.hxx>
25 
26 #include <inspector/TreeModel_ItemRole.hxx>
27 
28 #include <Standard_WarningsDisable.hxx>
29 #include <QExplicitlySharedDataPointer>
30 #include <QHash>
31 #include <QMap>
32 #include <QModelIndex>
33 #include <QObject>
34 #include <QPair>
35 #include <QSharedData>
36 #include <QVariant>
37 #include <Standard_WarningsRestore.hxx>
38 
39 class TreeModel_ItemBase;
40 class TreeModel_ItemProperties;
41 
42 typedef QExplicitlySharedDataPointer<TreeModel_ItemBase> TreeModel_ItemBasePtr;
43 
44 //! \class TreeModel_ItemBase
45 //! \brief Declaration of an abstract interface of model item.
46 //!
47 //! The TreeModel_ItemBase class defines the standard interface that model items must use
48 //! to be able to provide the model information in the tree view architecture.
49 //! It is not supposed to be instantiated directly. Instead, you should subclass it to
50 //! create new items.
51 //!
52 //! The goal of the item is to be an data container of a custom model, based on the
53 //! QAbstractItemModel. It provides the items architecture in order to realize the model
54 //! functionality to find a parent model index by a child index and vice versa.
55 //!
56 //! The item should be created by the model and is saved in the internal pointer of the
57 //! QModelIndex. Only model knows when the index is removed/created. By this cause,
58 //! the item is wrapped in the QExplicitlySharedDataPointer. It is a counter on the pointer
59 //! and if there is no index that refers to the item, it is removed automatically. So,
60 //! there is no necessity to remove the item manually.
61 //!
62 //! The item knows a pointer to the parent item and its position into.
63 //! Some methods of the item should be realized to fill the item content.
64 //! These are: the children count, a child creation and a child data.
65 //!
66 //! The best way of the item using is to request the content of the item from some
67 //! information object without the caching it. But it can be very expensive realisation,
68 //! because method data, for example, is called by the viewer repaint, in other words,
69 //! constantly.
70 //!
71 //! It is possible to cache some information in the item. Do not give it through the item
72 //! constructor. Realize method Init() to save the values in the item internal fields.
73 //! If the information model is changed, call Reset() for this item, or the item's parent.
74 //! It leads the item to non initialized state and by the next get of the item content,
75 //! call Init() method to fulfill the item content again.
76 class TreeModel_ItemBase : public QSharedData
77 {
78 public:
79 
80   //! Destructor
~TreeModel_ItemBase()81   virtual ~TreeModel_ItemBase() {}
82 
83   //! Gets whether the item is already initialized.The initialized state is thrown down
84   //! by the reset method and get back after the method Init().
85   //!  \return if the item is initialized
IsInitialized() const86   bool IsInitialized() const { return m_bInitialized; }
87 
88   //! Sets the item internal initialized state to the true. If the item has internal values,
89   //! there should be initialized here.
90   Standard_EXPORT virtual void Init();
91 
92   //! Returns data object of the item.
93   //! \return object
94   Standard_EXPORT virtual const Handle(Standard_Transient)& Object() const;
95 
96   //! Resets the item and the child items content. Sets the initialized state to false.
97   //! If the item has internal values, they should be reset here.
98   Standard_EXPORT virtual void Reset();
99 
100   //! Resets the item cached value for the parameter role.
101   //! \param theRole an item role
102   Standard_EXPORT virtual void Reset(int theRole);
103 
104   //! Returns stream value of the item to fulfill property panel.
105   //! \return stream value or dummy
Stream() const106   const Standard_SStream& Stream() const { return myStream; }
107 
108   //! Returns stream value of the item to fulfill property panel.
109   //! \return stream value or dummy
SetStream(const Standard_SStream & theSStream,Standard_Integer & theStartPos,Standard_Integer & theLastPos) const110   virtual bool SetStream (const Standard_SStream& theSStream, Standard_Integer& theStartPos,
111                           Standard_Integer& theLastPos) const
112   { (void)theSStream; (void)theStartPos; (void)theLastPos; return false; }
113 
114   //! Gets the parent of the item, or TreeModel_ItemBasePtr() if it has no parent.
115   //! \return pointer to the item
Parent() const116   TreeModel_ItemBasePtr Parent() const { return m_pParent; };
117 
118   //! Gets the row of the item in the parent
119   //! \return the row position
Row() const120   int Row() const { return m_iRow; }
121 
122   //! Gets the column of the item in the parent
123   //! \return the column position
Column() const124   int Column() const { return m_iColumn; }
125 
126   //! Gets a child tree item in the given position. Find an item in the children hash.
127   //! Creates a new child item, if there is no a cached item in the given position and
128   //! if the flag about the creation is true.
129   //! \param theRow the row of the child item
130   //! \param theColumn the column of the child item
131   //! \param isToCreate the flag whether the item should be created if it is not created yet
132   //! \return the child item or TreeModel_ItemBasePtr() if it does not exist
133   Standard_EXPORT TreeModel_ItemBasePtr Child (int theRow, int theColumn, const bool isToCreate = true);
134 
135   //! Sets a custom value for the role in an internal cache
136   //! \param theValue a value
137   //! \param theRole a value role
SetCustomData(const QVariant & theValue,int theRole)138   void SetCustomData(const QVariant& theValue, int theRole) { myCachedValues.insert (theRole, theValue); }
139 
140   //! Returns the data stored under the given role for the current item
141   //! \param theIndex the item model index
142   //! \param theRole the item model role
data(const QModelIndex & theIndex,int theRole=Qt::DisplayRole) const143   virtual QVariant data (const QModelIndex& theIndex, int theRole = Qt::DisplayRole) const
144   { (void)theIndex; return cachedValue(theRole); }
145 
146   //! Returns number of rows where the children are
147   //! \return the row count
rowCount() const148   int rowCount() const { return cachedValue(TreeModel_ItemRole_RowCountRole).toInt(); }
149 
150   //! Returns the item properties
Handle(TreeModel_ItemProperties)151   const Handle(TreeModel_ItemProperties)& Properties() const { return myProperties; }
152 
153   //! Updates item by the item properties value
StoreItemProperties(const int theRow,const int theColumn,const QVariant & theValue)154   virtual void StoreItemProperties (const int theRow, const int theColumn, const QVariant& theValue)
155     { (void)theRow, (void)theColumn; (void)theValue; }
156 
157   //! Returns presentation of the item to be visualized in the view
158   //! \thePresentations [out] container of presentation handles
159   Standard_EXPORT virtual void Presentations (NCollection_List<Handle(Standard_Transient)>& thePresentations);
160 protected:
161 
162   //! \param theParent the parent item
163   //! \param theRow the item row position in the parent item
164   //! \param theColumn the item column position in the parent item
165   Standard_EXPORT TreeModel_ItemBase (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn);
166 
167   //! Initializes the current item. It creates a backup of the specific item information
initItem() const168   virtual void initItem() const {}
169 
170   //! Creates a child item in the given position.
171   //! \param theRow the child row position
172   //! \param theColumn the child column position
173   //! \return the created item
createChild(int theRow,int theColumn)174   virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn)
175   { (void)theRow; (void)theColumn; return TreeModel_ItemBasePtr(); }
176 
177   //! Wraps the current item by shared pointer
178   //! \return the shared pointer to the current item
179   Standard_EXPORT const TreeModel_ItemBasePtr currentItem();
180 
181   //! Returns the cached value for the role. Init the value if it is requested the first time
182   //! By default, it calls initRowCount(TreeModel_ItemRole_RowCountRole) or initValue for the item role
183   //! \param theItemRole a value role
184   //! \return the value
185   Standard_EXPORT QVariant cachedValue (const int theItemRole) const;
186 
187   //! \return number of children. It should be reimplemented in child
188   virtual int initRowCount() const = 0;
189 
190   //! \return number of children. It should be reimplemented in child
191   Standard_EXPORT int initStreamRowCount();
192 
193   //! Returns data value for the role. It should be reimplemented in child
194   //! \param theItemRole a value role
195   //! \return the value
196   Standard_EXPORT virtual QVariant initValue (const int theItemRole) const;
197 
198   //! Returns stream value of the item to fulfill property panel.
199   //! \return stream value or dummy
initStream(Standard_OStream & theOStream) const200   virtual void initStream (Standard_OStream& theOStream) const { (void)theOStream; }
201 
202 protected:
203   Handle(TreeModel_ItemProperties) myProperties; //!< the properties
204   int m_iStreamChildren; //!< the count of stream items
205   Standard_SStream myStream; //!< stream value
206 
207 private:
208 
209   typedef QHash< QPair<int, int>, TreeModel_ItemBasePtr > PositionToItemHash;
210   PositionToItemHash m_ChildItems; //!< the hash of item children
211 
212   mutable QMap<int, QVariant> myCachedValues; //!< cached values, should be cleared by reset
213   TreeModel_ItemBasePtr m_pParent; //!< the parent item
214   int m_iRow;          //!< the item row position in the parent item
215   int m_iColumn;       //!< the item column position in the parent item
216   bool m_bInitialized; //!< the state whether the item content is already initialized
217 };
218 
219 //! Returns an explicitly shared pointer to the pointer held by other, using a
220 //! dynamic cast to type X to obtain an internal pointer of the appropriate type.
221 //! If the dynamic_cast fails, the object returned will be null.
222 //! Example of using:
223 //! TreeModel_ItemBase* aParent;
224 //! TreeModel_CustomItemPtr aParentItem = itemDynamicCast<TreeModel_CustomItem>(aParent);
225 //! \param theItem a source item
226 //! \return a converted item
itemDynamicCast(const QExplicitlySharedDataPointer<T> & theItem)227 template <class X, class T> QExplicitlySharedDataPointer<X> itemDynamicCast (const QExplicitlySharedDataPointer<T>& theItem)
228 {
229   X* ptr = dynamic_cast<X*> (theItem.data());
230 
231   QExplicitlySharedDataPointer<X> result;
232   result = ptr;
233 
234   return result;
235 }
236 
237 #endif
238