File indexing completed on 2024-04-28 05:45:10

0001 /*
0002  * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
0003  *
0004  * Based on the Itemviews NG project from Trolltech Labs
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef KITEMLISTWIDGET_H
0010 #define KITEMLISTWIDGET_H
0011 
0012 #include "dolphin_export.h"
0013 #include "kitemviews/kitemliststyleoption.h"
0014 
0015 #include <QBitArray>
0016 #include <QGraphicsWidget>
0017 #include <QStyle>
0018 #include <QTimer>
0019 
0020 class KItemListSelectionToggle;
0021 class KItemListView;
0022 class QPropertyAnimation;
0023 
0024 /**
0025  * @brief Provides information for creating an instance of KItemListWidget.
0026  *
0027  * KItemListView only creates KItemListWidget instances for the visible
0028  * area. For calculating the required size of all items the expected
0029  * size for the invisible items must be accessible. KItemListWidgetInformant
0030  * provides this information.
0031  */
0032 class DOLPHIN_EXPORT KItemListWidgetInformant
0033 {
0034 public:
0035     KItemListWidgetInformant();
0036     virtual ~KItemListWidgetInformant();
0037 
0038     virtual void calculateItemSizeHints(QVector<std::pair<qreal, bool>> &logicalHeightHints, qreal &logicalWidthHint, const KItemListView *view) const = 0;
0039 
0040     virtual qreal preferredRoleColumnWidth(const QByteArray &role, int index, const KItemListView *view) const = 0;
0041 };
0042 
0043 /**
0044  * @brief Widget that shows a visible item from the model.
0045  *
0046  * For showing an item from a custom model it is required to at least overwrite KItemListWidget::paint().
0047  * All properties are set by KItemListView, for each property there is a corresponding
0048  * virtual protected method that allows to react on property changes.
0049  */
0050 class DOLPHIN_EXPORT KItemListWidget : public QGraphicsWidget
0051 {
0052     Q_OBJECT
0053 
0054     Q_PROPERTY(int iconSize READ iconSize WRITE setIconSize)
0055 
0056 public:
0057     KItemListWidget(KItemListWidgetInformant *informant, QGraphicsItem *parent);
0058     ~KItemListWidget() override;
0059 
0060     void setIndex(int index);
0061     int index() const;
0062 
0063     void setData(const QHash<QByteArray, QVariant> &data, const QSet<QByteArray> &roles = QSet<QByteArray>());
0064     QHash<QByteArray, QVariant> data() const;
0065 
0066     /**
0067      * Draws the hover-rectangle if the item is hovered. Overwrite this method
0068      * to show the data of the custom model provided by KItemListWidget::data().
0069      * @reimp
0070      */
0071     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
0072 
0073     void setVisibleRoles(const QList<QByteArray> &roles);
0074     QList<QByteArray> visibleRoles() const;
0075 
0076     /**
0077      * Sets the width of a role that should be used if the alignment of the content
0078      * should be done in columns.
0079      */
0080     void setColumnWidth(const QByteArray &role, qreal width);
0081     qreal columnWidth(const QByteArray &role) const;
0082 
0083     void setSidePadding(qreal width);
0084     qreal sidePadding() const;
0085 
0086     void setStyleOption(const KItemListStyleOption &option);
0087     const KItemListStyleOption &styleOption() const;
0088 
0089     // TODO: Hides QGraphicsItem::setSelected()/isSelected(). Replace
0090     // this by using the default mechanism.
0091     void setSelected(bool selected);
0092     bool isSelected() const;
0093 
0094     void setCurrent(bool current);
0095     bool isCurrent() const;
0096 
0097     void setHovered(bool hovered);
0098     bool isHovered() const;
0099 
0100     void setExpansionAreaHovered(bool hover);
0101     bool expansionAreaHovered() const;
0102 
0103     void setHoverPosition(const QPointF &pos);
0104 
0105     void setAlternateBackground(bool enable);
0106     bool alternateBackground() const;
0107 
0108     void setEnabledSelectionToggle(bool enabled);
0109     bool enabledSelectionToggle() const;
0110 
0111     /**
0112      * Sets the sibling information for the item and all of its parents.
0113      * The sibling information of the upper most parent is represented by
0114      * the first bit, the sibling information of the item by the last bit.
0115      * The sibling information is useful for drawing the branches in
0116      * tree views.
0117      */
0118     void setSiblingsInformation(const QBitArray &siblings);
0119     QBitArray siblingsInformation() const;
0120 
0121     /**
0122      * Allows the user to edit the role \a role. The signals
0123      * roleEditingCanceled() or roleEditingFinished() will be
0124      * emitted after editing. An ongoing editing gets canceled if
0125      * the role is empty. Derived classes must implement
0126      * editedRoleChanged().
0127      */
0128     void setEditedRole(const QByteArray &role);
0129     QByteArray editedRole() const;
0130 
0131     /**
0132      * Contains the actual icon size used to draw the icon.
0133      * Also used during icon resizing animation.
0134      */
0135     void setIconSize(int iconSize);
0136     int iconSize() const;
0137 
0138     /**
0139      * @return True if \a point is inside KItemListWidget::hoverRect(),
0140      *         KItemListWidget::textRect(), KItemListWidget::selectionToggleRect()
0141      *         or KItemListWidget::expansionToggleRect().
0142      * @reimp
0143      */
0144     bool contains(const QPointF &point) const override;
0145 
0146     /**
0147      * @return Rectangle for the area that shows the icon.
0148      */
0149     virtual QRectF iconRect() const = 0;
0150 
0151     /**
0152      * @return Rectangle for the area that contains the text-properties.
0153      */
0154     virtual QRectF textRect() const = 0;
0155 
0156     /**
0157      * @return Focus rectangle for indicating the current item. Per default
0158      *         textRect() will be returned. Overwrite this method if textRect()
0159      *         provides a larger rectangle than the actual text (e.g. to
0160      *         be aligned with the iconRect()). The textFocusRect() may not be
0161      *         outside the boundaries of textRect().
0162      */
0163     virtual QRectF textFocusRect() const;
0164 
0165     /**
0166      * @return Rectangle around which a selection box should be drawn if the item is selected.
0167      */
0168     virtual QRectF selectionRect() const = 0;
0169 
0170     /**
0171      * @return Rectangle for the selection-toggle that is used to select or deselect an item.
0172      *         Per default an empty rectangle is returned which means that no selection-toggle
0173      *         is available.
0174      */
0175     virtual QRectF selectionToggleRect() const;
0176 
0177     /**
0178      * @return Rectangle for the expansion-toggle that is used to open a sub-tree of the model.
0179      *         Per default an empty rectangle is returned which means that no opening of sub-trees
0180      *         is supported.
0181      */
0182     virtual QRectF expansionToggleRect() const;
0183 
0184     /**
0185      * @return Pixmap that is used when dragging an item. Per default the current state of the
0186      *         widget is returned as pixmap.
0187      */
0188     virtual QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
0189 
0190 Q_SIGNALS:
0191     void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value);
0192     void roleEditingFinished(int index, const QByteArray &role, const QVariant &value);
0193 
0194 protected:
0195     virtual void dataChanged(const QHash<QByteArray, QVariant> &current, const QSet<QByteArray> &roles = QSet<QByteArray>());
0196     virtual void visibleRolesChanged(const QList<QByteArray> &current, const QList<QByteArray> &previous);
0197     virtual void columnWidthChanged(const QByteArray &role, qreal current, qreal previous);
0198     virtual void sidePaddingChanged(qreal width);
0199     virtual void styleOptionChanged(const KItemListStyleOption &current, const KItemListStyleOption &previous);
0200     virtual void currentChanged(bool current);
0201     virtual void selectedChanged(bool selected);
0202     virtual void hoveredChanged(bool hovered);
0203     virtual void alternateBackgroundChanged(bool enabled);
0204     virtual void siblingsInformationChanged(const QBitArray &current, const QBitArray &previous);
0205     virtual void editedRoleChanged(const QByteArray &current, const QByteArray &previous);
0206     virtual void iconSizeChanged(int current, int previous);
0207     void resizeEvent(QGraphicsSceneResizeEvent *event) override;
0208     void clearHoverCache();
0209 
0210     /**
0211      * Called when the user starts hovering this item.
0212      */
0213     virtual void hoverSequenceStarted();
0214 
0215     /**
0216      * Called in regular intervals while the user is hovering this item.
0217      *
0218      * @param sequenceIndex An index that increases over time while the user hovers.
0219      */
0220     virtual void hoverSequenceIndexChanged(int sequenceIndex);
0221 
0222     /**
0223      * Called when the user stops hovering this item.
0224      */
0225     virtual void hoverSequenceEnded();
0226 
0227     /**
0228      * @return The current opacity of the hover-animation. When implementing a custom painting-code for a hover-state
0229      *         this opacity value should be respected.
0230      */
0231     qreal hoverOpacity() const;
0232 
0233     int hoverSequenceIndex() const;
0234 
0235     const KItemListWidgetInformant *informant() const;
0236 
0237 private Q_SLOTS:
0238     void slotHoverSequenceTimerTimeout();
0239 
0240 private:
0241     void initializeSelectionToggle();
0242     void setHoverOpacity(qreal opacity);
0243     void drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState);
0244 
0245 private:
0246     Q_PROPERTY(qreal hoverOpacity READ hoverOpacity WRITE setHoverOpacity)
0247 
0248     KItemListWidgetInformant *m_informant;
0249     int m_index;
0250     bool m_selected;
0251     bool m_current;
0252     bool m_hovered;
0253     bool m_expansionAreaHovered;
0254     bool m_alternateBackground;
0255     bool m_enabledSelectionToggle;
0256     QHash<QByteArray, QVariant> m_data;
0257     QList<QByteArray> m_visibleRoles;
0258     QHash<QByteArray, qreal> m_columnWidths;
0259     qreal m_sidePadding;
0260     KItemListStyleOption m_styleOption;
0261     QBitArray m_siblingsInfo;
0262 
0263     qreal m_hoverOpacity;
0264     mutable QPixmap *m_hoverCache;
0265 
0266     int m_hoverSequenceIndex;
0267     QTimer m_hoverSequenceTimer;
0268 
0269     KItemListSelectionToggle *m_selectionToggle;
0270 
0271     QByteArray m_editedRole;
0272     int m_iconSize;
0273 };
0274 
0275 inline const KItemListWidgetInformant *KItemListWidget::informant() const
0276 {
0277     return m_informant;
0278 }
0279 
0280 #endif