Akonadi

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

KDE's Doxygen guidelines are available online.