Akonadi

agenttypewidget.cpp
1 /*
2  Copyright (c) 2006-2008 Tobias Koenig <[email protected]>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "agenttypewidget.h"
21 
22 #include <QApplication>
23 #include <QHBoxLayout>
24 #include <QListView>
25 #include <QPainter>
26 
27 #include "agentfilterproxymodel.h"
28 #include "agenttype.h"
29 #include "agenttypemodel.h"
30 
31 namespace Akonadi
32 {
33 namespace Internal
34 {
35 
39 class AgentTypeWidgetDelegate : public QAbstractItemDelegate
40 {
41  Q_OBJECT
42 public:
43  explicit AgentTypeWidgetDelegate(QObject *parent = nullptr);
44 
45  void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
46  QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
47 
48 private:
49  void drawFocus(QPainter *, const QStyleOptionViewItem &, QRect) const;
50 };
51 
52 }
53 
54 using Akonadi::Internal::AgentTypeWidgetDelegate;
55 
59 class Q_DECL_HIDDEN AgentTypeWidget::Private
60 {
61 public:
62  Private(AgentTypeWidget *parent)
63  : mParent(parent),
64  mView(nullptr),
65  mModel(nullptr),
66  proxyModel(nullptr)
67  {
68  }
69 
70  void currentAgentTypeChanged(const QModelIndex &, const QModelIndex &);
71 
72  void typeActivated(const QModelIndex &index)
73  {
74  if (index.flags() & (Qt::ItemIsSelectable | Qt::ItemIsEnabled)) {
75  Q_EMIT mParent->activated();
76  }
77  }
78 
79  AgentTypeWidget *mParent = nullptr;
80  QListView *mView = nullptr;
81  AgentTypeModel *mModel = nullptr;
82  AgentFilterProxyModel *proxyModel = nullptr;
83 };
84 
85 void AgentTypeWidget::Private::currentAgentTypeChanged(const QModelIndex &currentIndex, const QModelIndex &previousIndex)
86 {
87  AgentType currentType;
88  if (currentIndex.isValid()) {
89  currentType = currentIndex.data(AgentTypeModel::TypeRole).value<AgentType>();
90  }
91 
92  AgentType previousType;
93  if (previousIndex.isValid()) {
94  previousType = previousIndex.data(AgentTypeModel::TypeRole).value<AgentType>();
95  }
96 
97  Q_EMIT mParent->currentChanged(currentType, previousType);
98 }
99 
101  : QWidget(parent)
102  , d(new Private(this))
103 {
104  QHBoxLayout *layout = new QHBoxLayout(this);
105  layout->setContentsMargins(0, 0, 0, 0);
106 
107  d->mView = new QListView(this);
108  d->mView->setItemDelegate(new AgentTypeWidgetDelegate(d->mView));
109  d->mView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
110  d->mView->setAlternatingRowColors(true);
111  layout->addWidget(d->mView);
112 
113  d->mModel = new AgentTypeModel(d->mView);
114  d->proxyModel = new AgentFilterProxyModel(this);
115  d->proxyModel->setSourceModel(d->mModel);
116  d->proxyModel->sort(0);
117  d->mView->setModel(d->proxyModel);
118 
119  d->mView->selectionModel()->setCurrentIndex(d->mView->model()->index(0, 0), QItemSelectionModel::Select);
120  d->mView->scrollTo(d->mView->model()->index(0, 0));
121  connect(d->mView->selectionModel(), &QItemSelectionModel::currentChanged,
122  this, [this](const QModelIndex &start, const QModelIndex &end) {d->currentAgentTypeChanged(start, end);});
123  connect(d->mView, QOverload<const QModelIndex &>::of(&QListView::activated),
124  this, [this](const QModelIndex &index) { d->typeActivated(index); });
125 }
126 
128 {
129  delete d;
130 }
131 
133 {
134  QItemSelectionModel *selectionModel = d->mView->selectionModel();
135  if (!selectionModel) {
136  return AgentType();
137  }
138 
139  QModelIndex index = selectionModel->currentIndex();
140  if (!index.isValid()) {
141  return AgentType();
142  }
143 
144  return index.data(AgentTypeModel::TypeRole).value<AgentType>();
145 }
146 
148 {
149  return d->proxyModel;
150 }
151 
156 AgentTypeWidgetDelegate::AgentTypeWidgetDelegate(QObject *parent)
157  : QAbstractItemDelegate(parent)
158 {
159 }
160 
161 void AgentTypeWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
162 {
163  if (!index.isValid()) {
164  return;
165  }
166 
167  painter->setRenderHint(QPainter::Antialiasing);
168 
169  const QString name = index.model()->data(index, Qt::DisplayRole).toString();
170  const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString();
171 
172  const QVariant data = index.model()->data(index, Qt::DecorationRole);
173 
174  QPixmap pixmap;
175  if (data.isValid() && data.type() == QVariant::Icon) {
176  pixmap = qvariant_cast<QIcon>(data).pixmap(64, 64);
177  }
178 
179  const QFont oldFont = painter->font();
180  QFont boldFont(oldFont);
181  boldFont.setBold(true);
182  painter->setFont(boldFont);
183  QFontMetrics fm = painter->fontMetrics();
184  int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height();
185  int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width();
186  painter->setFont(oldFont);
187 
188  fm = painter->fontMetrics();
189  int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height();
190  int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width();
191  int wp = pixmap.width();
192 
193  QStyleOptionViewItem opt(option);
194  opt.showDecorationSelected = true;
195  QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
196 
197  QPen pen = painter->pen();
198  QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
199  ? QPalette::Normal : QPalette::Disabled;
200  if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) {
201  cg = QPalette::Inactive;
202  }
203  if (option.state & QStyle::State_Selected) {
204  painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
205  } else {
206  painter->setPen(option.palette.color(cg, QPalette::Text));
207  }
208 
209  painter->setFont(option.font);
210 
211  painter->drawPixmap(option.rect.x() + 5, option.rect.y() + 5, pixmap);
212 
213  painter->setFont(boldFont);
214  if (!name.isEmpty()) {
215  painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7, wn, hn, Qt::AlignLeft, name);
216  }
217  painter->setFont(oldFont);
218 
219  if (!comment.isEmpty()) {
220  painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7 + hn, wc, hc, Qt::AlignLeft, comment);
221  }
222 
223  painter->setPen(pen);
224 
225  drawFocus(painter, option, option.rect);
226 }
227 
228 QSize AgentTypeWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
229 {
230  if (!index.isValid()) {
231  return QSize(0, 0);
232  }
233 
234  const QString name = index.model()->data(index, Qt::DisplayRole).toString();
235  const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString();
236 
237  QFontMetrics fm = option.fontMetrics;
238  int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height();
239  int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width();
240  int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height();
241  int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width();
242 
243  int width = 0;
244  int height = 0;
245 
246  if (!name.isEmpty()) {
247  height += hn;
248  width = qMax(width, wn);
249  }
250 
251  if (!comment.isEmpty()) {
252  height += hc;
253  width = qMax(width, wc);
254  }
255 
256  height = qMax(height, 64) + 10;
257  width += 64 + 15;
258 
259  return QSize(width, height);
260 }
261 
262 void AgentTypeWidgetDelegate::drawFocus(QPainter *painter, const QStyleOptionViewItem &option, QRect rect) const
263 {
264  if (option.state & QStyle::State_HasFocus) {
266  o.QStyleOption::operator=(option);
267  o.rect = rect;
268  o.state |= QStyle::State_KeyboardFocusChange;
269  QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
270  ? QPalette::Normal : QPalette::Disabled;
271  o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
272  ? QPalette::Highlight : QPalette::Window);
273  QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
274  }
275 }
276 
277 }
278 
279 #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.
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)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
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)
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
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
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Jun 5 2020 23:08:53 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.