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

KDE's Doxygen guidelines are available online.