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