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 | |
33 | namespace Akonadi { |
34 | namespace Internal { |
35 | |
36 | /** |
37 | * @internal |
38 | */ |
39 | class AgentTypeWidgetDelegate : public QAbstractItemDelegate |
40 | { |
41 | public: |
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 | |
47 | private: |
48 | void drawFocus(QPainter *, const QStyleOptionViewItem &, const QRect &) const; |
49 | }; |
50 | |
51 | } |
52 | |
53 | using Akonadi::Internal::AgentTypeWidgetDelegate; |
54 | |
55 | /** |
56 | * @internal |
57 | */ |
58 | class AgentTypeWidget::Private |
59 | { |
60 | public: |
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 | |
81 | void AgentTypeWidget::Private::currentAgentTypeChanged(const QModelIndex ¤tIndex, 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 | |
96 | AgentTypeWidget::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 | |
123 | AgentTypeWidget::~AgentTypeWidget() |
124 | { |
125 | delete d; |
126 | } |
127 | |
128 | AgentType 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 | |
143 | AgentFilterProxyModel *AgentTypeWidget::agentFilterProxyModel() const |
144 | { |
145 | return d->proxyModel; |
146 | } |
147 | |
148 | /** |
149 | * AgentTypeWidgetDelegate |
150 | */ |
151 | |
152 | AgentTypeWidgetDelegate::AgentTypeWidgetDelegate(QObject *parent) |
153 | : QAbstractItemDelegate(parent) |
154 | { |
155 | } |
156 | |
157 | void 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 = 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 | |
225 | QSize 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 = 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 | |
259 | void 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 | |