File indexing completed on 2024-12-15 04:54:42

0001 /******************************************************************************
0002  *
0003  *  SPDX-FileCopyrightText: 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  *
0007  *******************************************************************************/
0008 
0009 #pragma once
0010 
0011 #include <QColor>
0012 #include <QRect>
0013 #include <QStyledItemDelegate>
0014 
0015 #include "core/item.h"
0016 #include "core/theme.h"
0017 
0018 class QAbstractItemView;
0019 
0020 namespace MessageList
0021 {
0022 namespace Core
0023 {
0024 class Item;
0025 
0026 /**
0027  * The ThemeDelegate paints the message list view message and group items by
0028  * using the supplied Theme.
0029  */
0030 class ThemeDelegate : public QStyledItemDelegate
0031 {
0032     Q_OBJECT
0033 
0034 public:
0035     explicit ThemeDelegate(QAbstractItemView *parent);
0036     ~ThemeDelegate() override;
0037     /**
0038      * Called when the global fonts change (from systemsettings)
0039      */
0040     void generalFontChanged();
0041 
0042 private:
0043     const Theme *mTheme = nullptr; ///< Shallow pointer to the current theme
0044     QAbstractItemView *const mItemView;
0045 
0046     QColor mGroupHeaderBackgroundColor; // cache
0047 
0048     // hitTest results
0049     QModelIndex mHitIndex;
0050     Item *mHitItem = nullptr;
0051     QRect mHitItemRect;
0052     const Theme::Column *mHitColumn = nullptr;
0053     const Theme::Row *mHitRow = nullptr;
0054     int mHitRowIndex;
0055     bool mHitRowIsMessageRow;
0056     QRect mHitRowRect;
0057     bool mHitContentItemRight;
0058     const Theme::ContentItem *mHitContentItem = nullptr;
0059     QRect mHitContentItemRect;
0060 
0061     mutable QSize mCachedMessageItemSizeHint;
0062     mutable QSize mCachedGroupHeaderItemSizeHint;
0063 
0064 public:
0065     const Theme *theme() const;
0066     void setTheme(const Theme *theme);
0067 
0068     /**
0069      * Returns a heuristic sizeHint() for the specified item type and column.
0070      * The hint is based on the contents of the theme (and not of any message or group header).
0071      */
0072     QSize sizeHintForItemTypeAndColumn(Item::Type type, int column, const Item *item = nullptr) const;
0073 
0074     /**
0075      * Performs a hit test on the specified viewport point.
0076      * Returns true if the point hit something and false otherwise.
0077      * When the hit test is successful then the hitIndex(), hitItem(), hitColumn(), hitRow(), and hitContentItem()
0078      * function will return information about the item that was effectively hit.
0079      * If exact is set to true then hitTest() will return true only if the viewportPoint
0080      * is exactly over an item. If exact is set to false then the hitTest() function
0081      * will do its best to find the closest object to be actually "hit": this is useful,
0082      * for example, in drag and drop operations.
0083      */
0084     bool hitTest(const QPoint &viewportPoint, bool exact = true);
0085 
0086     /**
0087      * Returns the model index that was reported as hit by the previous call to hitTest().
0088      * The result of this function is valid only if hitTest() returned true and only
0089      * within the same calling function.
0090      */
0091     const QModelIndex &hitIndex() const;
0092 
0093     /**
0094      * Returns the Item that was reported as hit by the previous call to hitTest().
0095      * The result of this function is valid only if hitTest() returned true and only
0096      * within the same calling function.
0097      */
0098     Item *hitItem() const;
0099 
0100     /**
0101      * Returns the visual rectangle of the item that was reported as hit by the previous call to hitTest().
0102      * The result of this function is valid only if hitTest() returned true and only
0103      * within the same calling function. Please note that this rectangle refers
0104      * to a specific item column (and not all of the columns).
0105      */
0106     QRect hitItemRect() const;
0107 
0108     /**
0109      * Returns the theme column that was reported as hit by the previous call to hitTest().
0110      * The result of this function is valid only if hitTest() returned true and only
0111      * within the same calling function.
0112      */
0113     const Theme::Column *hitColumn() const;
0114 
0115     /**
0116      * Returns the index of the theme column that was reported as hit by the previous call to hitTest().
0117      * The result of this function is valid only if hitTest() returned true and only
0118      * within the same calling function.
0119      * This is the same as hitIndex().column().
0120      */
0121     int hitColumnIndex() const;
0122 
0123     /**
0124      * Returns the theme row that was reported as hit by the previous call to hitTest().
0125      * The result of this function is valid only if hitTest() returned true and only
0126      * within the same calling function. This function may also return a null row
0127      * when hitTest() returned true. This means that the item was globally hit
0128      * but no row was exactly hit (the user probably hit the margin instead).
0129      */
0130     const Theme::Row *hitRow() const;
0131 
0132     /**
0133      * Returns the index of the theme row that was reported as hit by the previous call to hitTest().
0134      * The result of this function is valid only if hitRow() returns a non null value.
0135      */
0136     int hitRowIndex() const;
0137 
0138     /**
0139      * Returns the rectangle of the row that was reported as hit by the previous call to hitTest().
0140      * The result of this function is valid only if hitTest() returned true and only
0141      * within the same calling function. The result of this function is also invalid
0142      * if hitRow() returns 0.
0143      */
0144     QRect hitRowRect() const;
0145 
0146     /**
0147      * Returns true if the hitRow() is a message row, false otherwise.
0148      * The result of this function has a meaning only if hitRow() returns a non zero result.
0149      */
0150     bool hitRowIsMessageRow() const;
0151 
0152     /**
0153      * Returns the theme content item that was reported as hit by the previous call to hitTest().
0154      * The result of this function is valid only if hitTest() returned true and only
0155      * within the same calling function. This function may also return a null content item
0156      * when hitTest() returned true. This means that the item was globally hit
0157      * but no content item was exactly hit (the user might have clicked inside a blank unused space instead).
0158      */
0159     const Theme::ContentItem *hitContentItem() const;
0160 
0161     /**
0162      * Returns true if the hit theme content item was a right item and false otherwise.
0163      * The result of this function is valid only if hitContentItem() returns true.
0164      */
0165     bool hitContentItemRight() const;
0166 
0167     /**
0168      * Returns the bounding rect of the content item that was reported as hit by the previous call to hitTest().
0169      * The result of this function is valid only if hitTest() returned true and only
0170      * within the same calling function. The result of this function is to be considered
0171      * invalid also when hitContentItem() returns 0.
0172      */
0173     QRect hitContentItemRect() const;
0174 
0175 protected:
0176     /**
0177      * Returns the Item for the specified model index. Pure virtual: must be reimplemented
0178      * by derived classes.
0179      */
0180     virtual Item *itemFromIndex(const QModelIndex &index) const = 0;
0181 
0182     /**
0183      * Reimplemented from QStyledItemDelegate
0184      */
0185     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
0186 
0187     /**
0188      * Reimplemented from QStyledItemDelegate
0189      */
0190     QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
0191 };
0192 } // namespace Core
0193 } // namespace MessageList