File indexing completed on 2024-04-28 04:41:47
0001 /*************************************************************************** 0002 * Copyright (C) 2017 by Emmanuel Lepage Vallee * 0003 * Author : Emmanuel Lepage Vallee <emmanuel.lepage@kde.org> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 3 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0017 **************************************************************************/ 0018 #ifndef KQUICKITEMVIEWS_ABSTRACTITEMADAPTER_H 0019 #define KQUICKITEMVIEWS_ABSTRACTITEMADAPTER_H 0020 0021 #include <QtCore/QPersistentModelIndex> 0022 #include <QtCore/QRectF> 0023 class QQuickItem; 0024 class QQmlContext; 0025 0026 class AbstractItemAdapterPrivate; 0027 namespace StateTracker { 0028 class ViewItem; 0029 class ModelItem; 0030 } 0031 0032 class ViewBase; 0033 class Viewport; 0034 class ContextExtension; 0035 0036 /** 0037 * This class must be extended by the views to bind QModelIndex with a GUI element. 0038 * 0039 * This is the class implementation should use to navigate the model indices. It 0040 * provides a simple geometric linked list between indices and provide built-in 0041 * memory management, including recycling. 0042 * 0043 * This is optionally a template class to avoid having to perform static casts 0044 * when implementing. 0045 * 0046 * All moderately cartesian views such as list, table, trees and most charts 0047 * should use this class along with `ViewBase`. Graphs and advanced 0048 * visualizations should probably use a lower level API. 0049 * 0050 * These objects are created if and only if those 2 conditions are met: 0051 * 0052 * * The QModelIndex is currently part of a tracked range (see Viewport). 0053 * * It didn't fail to load. 0054 * 0055 * If the overloaded functions returns false, then the consumer of this 0056 * class should no longer use the object as it may have been deleted or 0057 * recycled. 0058 * 0059 * Note that this should **NEVER** be stored and an instance may be reused for 0060 * other indices or deleted without prior notice. The memory management of this 0061 * class is designed for high performance, not ease of use. If you are 0062 * implementing views in C++, then this is probably what you want, so think 0063 * twice before cursing at how low level this is. 0064 * 0065 * Note that this object usage should be strictly limited to its overloaded 0066 * functions and external usage (from the view class or elsewhere) is 0067 * strongly discouraged. If you think the provided interface isn't enough, 0068 * report a bug rather than work around it to avoid crashes. 0069 */ 0070 class AbstractItemAdapter 0071 { 0072 friend struct StateTracker::ModelItem; //state tracking 0073 friend class StateTracker::ViewItem; //its internally shared properties 0074 friend class AbstractItemAdapterPrivate; // like (Q_DECLARE_PRIVATE) 0075 public: 0076 explicit AbstractItemAdapter(Viewport* r); 0077 virtual ~AbstractItemAdapter(); 0078 0079 ViewBase* view() const; 0080 0081 /** 0082 * The QML context for the `item`. 0083 * 0084 * This is lazy loaded. 0085 */ 0086 virtual QQmlContext *context() const; 0087 0088 /** 0089 * The QQuickItem used to wrap the content item. 0090 * 0091 * A container is useful 0092 * because there can be decorations around the "real" delegate and they 0093 * are provided by the view, not the delegate. 0094 */ 0095 virtual QQuickItem *container() const; 0096 0097 /** 0098 * The delegate instance. 0099 * 0100 * This is a children of the `container` item. 0101 */ 0102 virtual QQuickItem *content() const; 0103 0104 Viewport *viewport() const; 0105 0106 /** 0107 * The external state if the item. 0108 * 0109 * This is different from the internal state and only has a subset the 0110 * consumer (views) care about. Note that internally, it can be part of a 0111 * recycling pool or other types of caches. 0112 */ 0113 enum class State { 0114 BUFFER , /*!< Is close enough to the visible area to have been loaded */ 0115 VISIBLE, /*!< Is currently displayed */ 0116 INVALID, /*!< You should not use this instance */ 0117 }; 0118 0119 /** 0120 * Get the nearby element on the edge of this item. 0121 * 0122 * Note that this applies a Cartesian projection on the whole model, so 0123 * a nearby element can be a parent, children or sibling. Also note that 0124 * elements are lazy loaded and recycled, so there is no guarantee that 0125 * the element will exits and it should never be stored. 0126 */ 0127 AbstractItemAdapter *next(Qt::Edge e) const; 0128 0129 /** 0130 * This method return the item representing the QModelIndex parent. 0131 * 0132 * It will return it **ONLY IF THE PARENT IS PART OF THE VISIBLE RANGE**. 0133 */ 0134 AbstractItemAdapter* parent() const; 0135 0136 /** 0137 * The item row. 0138 * 0139 * Note that this doesn't always match QModelIndex::row() because this 0140 * value is updated when the `rowsAboutToBeModed` signal is sent rather 0141 * than after the change takes effect. 0142 */ 0143 int row() const; 0144 0145 /** 0146 * The item column. 0147 * 0148 * Note that this doesn't always match QModelIndex::column() because this 0149 * value is updated when the `columnsAboutToBeModed` signal is sent rather 0150 * than after the change takes effect. 0151 */ 0152 int column() const; 0153 0154 /** 0155 * The model index. 0156 * 0157 * Please do not use .row() and .column() on the index and rather use 0158 * ::row() and ::column() provided by this class. Otherwise items being 0159 * moved wont be rendered correctly. 0160 */ 0161 QPersistentModelIndex index() const; 0162 0163 // Actions 0164 0165 /** 0166 * Force the position to be computed again. 0167 * 0168 * The item position is managed by the implementation. However external 0169 * events such as resizing the window or switching from mobile to desktop 0170 * mode can require the position to be reconsidered. 0171 * 0172 * This will call `AbstractItemAdapter::move` and all the actions such 0173 * as moving the children items, updating the visible range and general 0174 * housekeeping tasks so the view implementation does not have to care 0175 * about them. 0176 */ 0177 void resetPosition(); 0178 0179 struct SelectionLocker {}; 0180 0181 /** 0182 * Get a pointer for this item. 0183 * 0184 * The SelectionLocker (first element of the pair) will be nullptr if the 0185 * item no longer belong to the same QModelIndex as when it was acquired. 0186 * 0187 * Keep in mind that these objects are recycled, so comparing the 0188 * AbstractItemAdapter pointer tells nothing. 0189 * 0190 * **DO NOT STORE IT AS A QSharedPointer**. This is only intended to be 0191 * stored as a QWeakPointer. It will 0192 */ 0193 QPair<QWeakPointer<SelectionLocker>, AbstractItemAdapter*> weakReference() const; 0194 0195 /** 0196 * The size and position necessary to draw this item. 0197 * 0198 * The default implementation uses the item() geometry. 0199 */ 0200 virtual QRectF geometry() const; 0201 0202 QRectF decoratedGeometry() const; 0203 0204 /** 0205 * In many case, it is useful or necessary to place additional components 0206 * or just empty space around a delegate instance. 0207 * 0208 * This can be, for example, the treeview vertical indentation/expand 0209 * indicator or the listview category delegate. 0210 * 0211 * Note that the top and bottom edge decoration include the width of the 0212 * left and right ones. 0213 */ 0214 qreal borderDecoration(Qt::Edge e) const; 0215 0216 void setBorderDecoration(Qt::Edge e, qreal r); 0217 0218 /** 0219 * Set if the children of this item should be skipped from the view. 0220 */ 0221 void setCollapsed(bool v); 0222 bool isCollapsed() const; 0223 0224 /** 0225 * Implement this function when selecting an item require extra operations 0226 * to be executed. 0227 * 0228 * The default implementation does nothing. 0229 */ 0230 virtual void setSelected(bool s); 0231 0232 void updateGeometry(); 0233 0234 virtual QSizeF sizeHint() const; 0235 0236 void dismissCacheEntry(ContextExtension* e, int id); 0237 0238 // Shared private data 0239 StateTracker::ViewItem *s_ptr; 0240 protected: 0241 /** 0242 * This instance is about to be added to the view. 0243 * 0244 * The default implementation calls move, but some views might need to 0245 * perform extra operations only when the item is added to the viewport. 0246 */ 0247 virtual bool attach (); 0248 0249 /** 0250 * Update the delegate instance when the model index changes. 0251 * 0252 * The default implementation refreshes the role values to the context. 0253 */ 0254 virtual bool refresh(); 0255 0256 /** 0257 * Move the delegate instance when it moves itself or its siblings change. 0258 */ 0259 virtual bool move (); 0260 0261 /** 0262 * This instance is about to be recycled, if it holds a state, remove it. 0263 * 0264 * The default implementation does nothing. 0265 */ 0266 virtual bool flush (); 0267 0268 /** 0269 * This instance is going to be removed from the view. 0270 */ 0271 virtual bool remove (); 0272 private: 0273 AbstractItemAdapterPrivate* d_ptr; 0274 }; 0275 0276 #endif