1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2006, 2007 Andreas Hartmetz <ahartmetz@gmail.com>
4 SPDX-FileCopyrightText: 2008 Urs Wolfer <uwolfer@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#ifndef KEXTENDABLEITEMDELEGATE_H
10#define KEXTENDABLEITEMDELEGATE_H
11
12#include <QStyledItemDelegate>
13#include <memory>
14
15#include <kitemviews_export.h>
16
17class QAbstractItemView;
18
19/*!
20 * \class KExtendableItemDelegate
21 * \inmodule KItemViews
22 *
23 * \brief This delegate makes it possible to display an arbitrary QWidget ("extender") that spans all columns below a line of items.
24 *
25 * The extender will logically belong to a column in the row above it.
26 *
27 * It is your responsibility to devise a way to trigger extension and contraction of items, by calling
28 * extendItem() and contractItem(). You can e.g. reimplement itemActivated() and similar functions.
29 *
30 * \warning extendItem() reparents the provided widget \a extender to the
31 * viewport of the itemview it belongs to. The \a extender is destroyed when
32 * you call contractItem() for the associated index. If you fail to do that
33 * and the associated item gets deleted you're in trouble. It remains as a
34 * visible artefact in your treeview. Additionally when closing your
35 * application you get an assertion failure from KExtendableItemDelegate. Make
36 * sure that you always call contractItem for indices before you delete them.
37 *
38 * \since 4.1
39 */
40class KITEMVIEWS_EXPORT KExtendableItemDelegate : public QStyledItemDelegate
41{
42 Q_OBJECT
43
44public:
45 /*!
46 * \value ShowExtensionIndicatorRole
47 */
48 enum auxDataRoles {
49 ShowExtensionIndicatorRole = Qt::UserRole + 200,
50 };
51
52 /*!
53 * Create a new KExtendableItemDelegate that belongs to \a parent. In contrast to generic
54 * QAbstractItemDelegates, an instance of this class can only ever be the delegate for one
55 * instance of af QAbstractItemView subclass.
56 */
57 KExtendableItemDelegate(QAbstractItemView *parent);
58 ~KExtendableItemDelegate() override;
59
60 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
61
62 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
63
64 /*!
65 * Insert the \a extender for item at \a index into the view.
66 * If you need a parent for the extender at construction time, use the itemview's viewport().
67 * The delegate takes ownership of the extender; the extender will also be reparented and
68 * resized to the viewport.
69 */
70 void extendItem(QWidget *extender, const QModelIndex &index);
71
72 /*!
73 * Remove the extender of item at \a index from the view. The extender widget
74 * will be deleted.
75 */
76 void contractItem(const QModelIndex &index);
77
78 /*!
79 * Close all extenders and delete all extender widgets.
80 */
81 void contractAll();
82
83 /*!
84 * Return whether there is an extender that belongs to \a index.
85 */
86 bool isExtended(const QModelIndex &index) const;
87
88 /*!
89 * Reimplement this function to adjust the internal geometry of the extender.
90 * The external geometry of the extender will be set by the delegate.
91 */
92 virtual void updateExtenderGeometry(QWidget *extender, const QStyleOptionViewItem &option, const QModelIndex &index) const;
93
94Q_SIGNALS:
95 /*!
96 * This signal indicates that the item at \a index was extended with \a extender.
97 */
98 void extenderCreated(QWidget *extender, const QModelIndex &index);
99
100 /*!
101 * This signal indicates that the \a extender belonging to \a index has emitted the destroyed() signal.
102 */
103 void extenderDestroyed(QWidget *extender, const QModelIndex &index);
104
105protected:
106 /*!
107 * Reimplement this function to fine-tune the position of the extender. \a option.rect will be a rectangle
108 * that is as wide as the viewport and as high as the usual item height plus the extender size hint's height.
109 * Its upper left corner will be at the upper left corner of the usual item.
110 * You can place the returned rectangle of this function anywhere inside that area.
111 */
112 QRect extenderRect(QWidget *extender, const QStyleOptionViewItem &option, const QModelIndex &index) const;
113
114 /*!
115 * The pixmap that is displayed to extend an item. \a pixmap must have the same size as the pixmap in setContractPixmap.
116 */
117 void setExtendPixmap(const QPixmap &pixmap);
118
119 /*!
120 * The pixmap that is displayed to contract an item. \a pixmap must have the same size as the pixmap in setExtendPixmap.
121 */
122 void setContractPixmap(const QPixmap &pixmap);
123
124 /*!
125 * Return the pixmap that is displayed to extend an item.
126 */
127 QPixmap extendPixmap();
128
129 /*!
130 * Return the pixmap that is displayed to contract an item.
131 */
132 QPixmap contractPixmap();
133
134private:
135 friend class KExtendableItemDelegatePrivate;
136 std::unique_ptr<class KExtendableItemDelegatePrivate> const d;
137
138 Q_PRIVATE_SLOT(d, void _k_extenderDestructionHandler(QObject *destroyed))
139 Q_PRIVATE_SLOT(d, void _k_verticalScroll())
140};
141#endif // KEXTENDABLEITEMDELEGATE_H
142

source code of kitemviews/src/kextendableitemdelegate.h