1/*
2 Copyright (c) 2006-2008 Tobias Koenig <tokoe@kde.org>
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 <KDebug>
23
24#include <QApplication>
25#include <QHBoxLayout>
26#include <QListView>
27#include <QPainter>
28
29#include "agentfilterproxymodel.h"
30#include "agenttype.h"
31#include "agenttypemodel.h"
32
33namespace Akonadi {
34namespace Internal {
35
36/**
37 * @internal
38 */
39class AgentTypeWidgetDelegate : public QAbstractItemDelegate
40{
41public:
42 AgentTypeWidgetDelegate(QObject *parent = 0);
43
44 virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
45 virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
46
47private:
48 void drawFocus(QPainter *, const QStyleOptionViewItem &, const QRect &) const;
49};
50
51}
52
53using Akonadi::Internal::AgentTypeWidgetDelegate;
54
55/**
56 * @internal
57 */
58class AgentTypeWidget::Private
59{
60public:
61 Private(AgentTypeWidget *parent)
62 : mParent(parent)
63 {
64 }
65
66 void currentAgentTypeChanged(const QModelIndex &, const QModelIndex &);
67
68 void typeActivated(const QModelIndex &index)
69 {
70 if (index.flags() & (Qt::ItemIsSelectable | Qt::ItemIsEnabled)) {
71 emit mParent->activated();
72 }
73 }
74
75 AgentTypeWidget *mParent;
76 QListView *mView;
77 AgentTypeModel *mModel;
78 AgentFilterProxyModel *proxyModel;
79};
80
81void AgentTypeWidget::Private::currentAgentTypeChanged(const QModelIndex &currentIndex, const QModelIndex &previousIndex)
82{
83 AgentType currentType;
84 if (currentIndex.isValid()) {
85 currentType = currentIndex.data(AgentTypeModel::TypeRole).value<AgentType>();
86 }
87
88 AgentType previousType;
89 if (previousIndex.isValid()) {
90 previousType = previousIndex.data(AgentTypeModel::TypeRole).value<AgentType>();
91 }
92
93 emit mParent->currentChanged(currentType, previousType);
94}
95
96AgentTypeWidget::AgentTypeWidget(QWidget *parent)
97 : QWidget(parent)
98 , d(new Private(this))
99{
100 QHBoxLayout *layout = new QHBoxLayout(this);
101 layout->setMargin(0);
102
103 d->mView = new QListView(this);
104 d->mView->setItemDelegate(new AgentTypeWidgetDelegate(d->mView));
105 d->mView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
106 d->mView->setAlternatingRowColors(true);
107 layout->addWidget(d->mView);
108
109 d->mModel = new AgentTypeModel(d->mView);
110 d->proxyModel = new AgentFilterProxyModel(this);
111 d->proxyModel->setSourceModel(d->mModel);
112 d->proxyModel->sort(0);
113 d->mView->setModel(d->proxyModel);
114
115 d->mView->selectionModel()->setCurrentIndex(d->mView->model()->index(0, 0), QItemSelectionModel::Select);
116 d->mView->scrollTo(d->mView->model()->index(0, 0));
117 connect(d->mView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
118 this, SLOT(currentAgentTypeChanged(QModelIndex,QModelIndex)));
119 connect(d->mView, SIGNAL(activated(QModelIndex)),
120 SLOT(typeActivated(QModelIndex)));
121}
122
123AgentTypeWidget::~AgentTypeWidget()
124{
125 delete d;
126}
127
128AgentType AgentTypeWidget::currentAgentType() const
129{
130 QItemSelectionModel *selectionModel = d->mView->selectionModel();
131 if (!selectionModel) {
132 return AgentType();
133 }
134
135 QModelIndex index = selectionModel->currentIndex();
136 if (!index.isValid()) {
137 return AgentType();
138 }
139
140 return index.data(AgentTypeModel::TypeRole).value<AgentType>();
141}
142
143AgentFilterProxyModel *AgentTypeWidget::agentFilterProxyModel() const
144{
145 return d->proxyModel;
146}
147
148/**
149 * AgentTypeWidgetDelegate
150 */
151
152AgentTypeWidgetDelegate::AgentTypeWidgetDelegate(QObject *parent)
153 : QAbstractItemDelegate(parent)
154{
155}
156
157void AgentTypeWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
158{
159 if (!index.isValid()) {
160 return;
161 }
162
163 painter->setRenderHint(QPainter::Antialiasing);
164
165 const QString name = index.model()->data(index, Qt::DisplayRole).toString();
166 const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString();
167
168 const QVariant data = index.model()->data(index, Qt::DecorationRole);
169
170 QPixmap pixmap;
171 if (data.isValid() && data.type() == QVariant::Icon) {
172 pixmap = qvariant_cast<QIcon>(data).pixmap(64, 64);
173 }
174
175 const QFont oldFont = painter->font();
176 QFont boldFont(oldFont);
177 boldFont.setBold(true);
178 painter->setFont(boldFont);
179 QFontMetrics fm = painter->fontMetrics();
180 int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height();
181 int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width();
182 painter->setFont(oldFont);
183
184 fm = painter->fontMetrics();
185 int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height();
186 int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width();
187 int wp = pixmap.width();
188
189 QStyleOptionViewItemV4 opt(option);
190 opt.showDecorationSelected = true;
191 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
192
193 QPen pen = painter->pen();
194 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
195 ? QPalette::Normal : QPalette::Disabled;
196 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) {
197 cg = QPalette::Inactive;
198 }
199 if (option.state & QStyle::State_Selected) {
200 painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
201 } else {
202 painter->setPen(option.palette.color(cg, QPalette::Text));
203 }
204
205 QFont font = painter->font();
206 painter->setFont(option.font);
207
208 painter->drawPixmap(option.rect.x() + 5, option.rect.y() + 5, pixmap);
209
210 painter->setFont(boldFont);
211 if (!name.isEmpty()) {
212 painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7, wn, hn, Qt::AlignLeft, name);
213 }
214 painter->setFont(oldFont);
215
216 if (!comment.isEmpty()) {
217 painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7 + hn, wc, hc, Qt::AlignLeft, comment);
218 }
219
220 painter->setPen(pen);
221
222 drawFocus(painter, option, option.rect);
223}
224
225QSize AgentTypeWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
226{
227 if (!index.isValid()) {
228 return QSize(0, 0);
229 }
230
231 const QString name = index.model()->data(index, Qt::DisplayRole).toString();
232 const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString();
233
234 QFontMetrics fm = option.fontMetrics;
235 int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height();
236 int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width();
237 int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height();
238 int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width();
239
240 int width = 0;
241 int height = 0;
242
243 if (!name.isEmpty()) {
244 height += hn;
245 width = qMax(width, wn);
246 }
247
248 if (!comment.isEmpty()) {
249 height += hc;
250 width = qMax(width, wc);
251 }
252
253 height = qMax(height, 64) + 10;
254 width += 64 + 15;
255
256 return QSize(width, height);
257}
258
259void AgentTypeWidgetDelegate::drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const
260{
261 if (option.state & QStyle::State_HasFocus) {
262 QStyleOptionFocusRect o;
263 o.QStyleOption::operator=(option);
264 o.rect = rect;
265 o.state |= QStyle::State_KeyboardFocusChange;
266 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
267 ? QPalette::Normal : QPalette::Disabled;
268 o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
269 ? QPalette::Highlight : QPalette::Background);
270 QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
271 }
272}
273
274}
275
276#include "moc_agenttypewidget.cpp"
277