Akonadi

agenttypewidget.cpp
1/*
2 SPDX-FileCopyrightText: 2006-2008 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "agenttypewidget.h"
8
9#include <QApplication>
10#include <QHBoxLayout>
11#include <QListView>
12#include <QPainter>
13
14#include "agentfilterproxymodel.h"
15#include "agenttype.h"
16#include "agenttypemodel.h"
17
18constexpr int iconSize = 32; // use a standard icon size, like 64, 48, 32, ...
19
20namespace Akonadi
21{
22namespace Internal
23{
24/**
25 * @internal
26 */
27class AgentTypeWidgetDelegate : public QAbstractItemDelegate
28{
30public:
31 explicit AgentTypeWidgetDelegate(QObject *parent = nullptr);
32
33 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
34 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
35
36private:
37 void drawFocus(QPainter * /*painter*/, const QStyleOptionViewItem & /*option*/, QRect /*rect*/) const;
38};
39
40} // namespace Internal
41
42using Akonadi::Internal::AgentTypeWidgetDelegate;
43
44/**
45 * @internal
46 */
47class AgentTypeWidgetPrivate
48{
49public:
50 explicit AgentTypeWidgetPrivate(AgentTypeWidget *parent)
51 : mParent(parent)
52 {
53 }
54
55 void currentAgentTypeChanged(const QModelIndex & /*currentIndex*/, const QModelIndex & /*previousIndex*/);
56
57 void typeActivated(const QModelIndex &index)
58 {
60 Q_EMIT mParent->activated();
61 }
62 }
63
64 AgentTypeWidget *const mParent;
65 QListView *mView = nullptr;
66 AgentTypeModel *mModel = nullptr;
67 AgentFilterProxyModel *proxyModel = nullptr;
68};
69
70void AgentTypeWidgetPrivate::currentAgentTypeChanged(const QModelIndex &currentIndex, const QModelIndex &previousIndex)
71{
72 AgentType currentType;
73 if (currentIndex.isValid()) {
74 currentType = currentIndex.data(AgentTypeModel::TypeRole).value<AgentType>();
75 }
76
77 AgentType previousType;
78 if (previousIndex.isValid()) {
79 previousType = previousIndex.data(AgentTypeModel::TypeRole).value<AgentType>();
80 }
81
82 Q_EMIT mParent->currentChanged(currentType, previousType);
83}
84
87 , d(new AgentTypeWidgetPrivate(this))
88{
89 auto layout = new QHBoxLayout(this);
90 layout->setContentsMargins({});
91
92 d->mView = new QListView(this);
93 d->mView->setItemDelegate(new AgentTypeWidgetDelegate(d->mView));
94 d->mView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
95 d->mView->setAlternatingRowColors(true);
96 layout->addWidget(d->mView);
97
98 d->mModel = new AgentTypeModel(d->mView);
99 d->proxyModel = new AgentFilterProxyModel(this);
100 d->proxyModel->setSourceModel(d->mModel);
101 d->proxyModel->sort(0);
102 d->mView->setModel(d->proxyModel);
103
104 d->mView->selectionModel()->setCurrentIndex(d->mView->model()->index(0, 0), QItemSelectionModel::Select);
105 d->mView->scrollTo(d->mView->model()->index(0, 0));
106 connect(d->mView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex &start, const QModelIndex &end) {
107 d->currentAgentTypeChanged(start, end);
108 });
109 connect(d->mView, qOverload<const QModelIndex &>(&QListView::activated), this, [this](const QModelIndex &index) {
110 d->typeActivated(index);
111 });
112}
113
115
117{
118 QItemSelectionModel *selectionModel = d->mView->selectionModel();
119 if (!selectionModel) {
120 return AgentType();
121 }
122
123 const QModelIndex index = selectionModel->currentIndex();
124 if (!index.isValid()) {
125 return AgentType();
126 }
127
129}
130
132{
133 return d->proxyModel;
134}
135
136/**
137 * AgentTypeWidgetDelegate
138 */
139
140AgentTypeWidgetDelegate::AgentTypeWidgetDelegate(QObject *parent)
141 : QAbstractItemDelegate(parent)
142{
143}
144
145void AgentTypeWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
146{
147 if (!index.isValid()) {
148 return;
149 }
150
152
153 const QString name = index.model()->data(index, Qt::DisplayRole).toString();
154 const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString();
155
156 const QVariant data = index.model()->data(index, Qt::DecorationRole);
157
158 QPixmap pixmap;
159 if (data.isValid() && data.typeId() == QMetaType::QIcon) {
160 pixmap = qvariant_cast<QIcon>(data).pixmap(iconSize, iconSize);
161 }
162
163 const QFont oldFont = painter->font();
164 QFont boldFont(oldFont);
165 boldFont.setBold(true);
166 painter->setFont(boldFont);
167 QFontMetrics fm = painter->fontMetrics();
168 int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height();
169 int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width();
170 painter->setFont(oldFont);
171
172 fm = painter->fontMetrics();
173 int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height();
174 int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width();
175 int wp = pixmap.width();
176
177 QStyleOptionViewItem opt(option);
178 opt.showDecorationSelected = true;
180
181 QPen pen = painter->pen();
182 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled;
183 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) {
185 }
186 if (option.state & QStyle::State_Selected) {
187 painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
188 } else {
189 painter->setPen(option.palette.color(cg, QPalette::Text));
190 }
191
192 painter->setFont(option.font);
193
194 painter->drawPixmap(option.rect.x() + 5, option.rect.y() + 5, pixmap);
195
196 painter->setFont(boldFont);
197 if (!name.isEmpty()) {
198 painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7, wn, hn, Qt::AlignLeft, name);
199 }
200 painter->setFont(oldFont);
201
202 if (!comment.isEmpty()) {
203 painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7 + hn, wc, hc, Qt::AlignLeft, comment);
204 }
205
206 painter->setPen(pen);
207
208 drawFocus(painter, option, option.rect);
209}
210
211QSize AgentTypeWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
212{
213 if (!index.isValid()) {
214 return QSize(0, 0);
215 }
216
217 const QString name = index.model()->data(index, Qt::DisplayRole).toString();
218 const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString();
219
220 const QFontMetrics fm = option.fontMetrics;
221 int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height();
222 int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width();
223 int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height();
224 int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width();
225
226 int width = 0;
227 int height = 0;
228
229 if (!name.isEmpty()) {
230 height += hn;
231 width = qMax(width, wn);
232 }
233
234 if (!comment.isEmpty()) {
235 height += hc;
236 width = qMax(width, wc);
237 }
238
239 height = qMax(height, iconSize) + 10;
240 width += iconSize + (iconSize / 4) - 1;
241
242 return QSize(width, height);
243}
244
245void AgentTypeWidgetDelegate::drawFocus(QPainter *painter, const QStyleOptionViewItem &option, QRect rect) const
246{
247 if (option.state & QStyle::State_HasFocus) {
248 QStyleOptionFocusRect o;
249 o.QStyleOption::operator=(option);
250 o.rect = rect;
252 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled;
253 o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Window);
255 }
256}
257
258} // namespace Akonadi
259
260#include "agenttypewidget.moc"
261
262#include "moc_agenttypewidget.cpp"
A proxy model for filtering AgentType or AgentInstance.
Provides a data model for agent types.
@ TypeRole
The agent type itself.
@ DescriptionRole
A description of the agent type.
~AgentTypeWidget() override
Destroys the agent type widget.
AgentType currentAgentType() const
Returns the current agent type or an invalid agent type if no agent type is selected.
AgentFilterProxyModel * agentFilterProxyModel() const
Returns the agent filter proxy model, use this to filter by agent mimetype or capabilities.
AgentTypeWidget(QWidget *parent=nullptr)
Creates a new agent type widget.
A representation of an agent type.
Q_SCRIPTABLE QString start(QString train="")
Helper integration between Akonadi and Qt.
QString name(StandardAction id)
virtual QVariant data(const QModelIndex &index, int role) const const=0
void activated(const QModelIndex &index)
QStyle * style()
QRect boundingRect(QChar ch) const const
void currentChanged(const QModelIndex &current, const QModelIndex &previous)
QModelIndex currentIndex() const const
QVariant data(int role) const const
Qt::ItemFlags flags() const const
bool isValid() const const
const QAbstractItemModel * model() const const
QObject(QObject *parent)
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void drawText(const QPoint &position, const QString &text)
const QFont & font() const const
QFontMetrics fontMetrics() const const
const QPen & pen() const const
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
int width() const const
int height() const const
int width() const const
bool isEmpty() const const
PE_PanelItemViewItem
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
AlignLeft
DisplayRole
ItemIsSelectable
bool isValid() const const
QString toString() const const
int typeId() const const
T value() const const
QWidget(QWidget *parent, Qt::WindowFlags f)
QLayout * layout() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 25 2025 11:47:47 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.