]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kitemlistwidget.cpp
Prepare view-engine for non-KFileItem usecase
[dolphin.git] / src / kitemviews / kitemlistwidget.cpp
1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
3 * *
4 * Based on the Itemviews NG project from Trolltech Labs: *
5 * http://qt.gitorious.org/qt-labs/itemviews-ng *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
21 ***************************************************************************/
22
23 #include "kitemlistwidget.h"
24
25 #include "kitemlistview.h"
26 #include "kitemmodelbase.h"
27
28 #include "private/kitemlistselectiontoggle.h"
29
30 #include <KDebug>
31
32 #include <KGlobalSettings>
33 #include <QApplication>
34 #include <QPainter>
35 #include <QPropertyAnimation>
36 #include <QStyleOption>
37
38 KItemListWidgetInformant::KItemListWidgetInformant()
39 {
40 }
41
42 KItemListWidgetInformant::~KItemListWidgetInformant()
43 {
44 }
45
46 KItemListWidget::KItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) :
47 QGraphicsWidget(parent, 0),
48 m_informant(informant),
49 m_index(-1),
50 m_selected(false),
51 m_current(false),
52 m_hovered(false),
53 m_alternateBackground(false),
54 m_enabledSelectionToggle(false),
55 m_data(),
56 m_visibleRoles(),
57 m_columnWidths(),
58 m_styleOption(),
59 m_siblingsInfo(),
60 m_hoverOpacity(0),
61 m_hoverCache(0),
62 m_hoverAnimation(0),
63 m_selectionToggle(0),
64 m_editedRole()
65 {
66 }
67
68 KItemListWidget::~KItemListWidget()
69 {
70 clearHoverCache();
71 }
72
73 void KItemListWidget::setIndex(int index)
74 {
75 if (m_index != index) {
76 delete m_selectionToggle;
77 m_selectionToggle = 0;
78
79 if (m_hoverAnimation) {
80 m_hoverAnimation->stop();
81 m_hoverOpacity = 0;
82 }
83 clearHoverCache();
84
85 m_index = index;
86 }
87 }
88
89 int KItemListWidget::index() const
90 {
91 return m_index;
92 }
93
94 void KItemListWidget::setData(const QHash<QByteArray, QVariant>& data,
95 const QSet<QByteArray>& roles)
96 {
97 clearHoverCache();
98 if (roles.isEmpty()) {
99 m_data = data;
100 dataChanged(m_data);
101 } else {
102 foreach (const QByteArray& role, roles) {
103 m_data[role] = data[role];
104 }
105 dataChanged(m_data, roles);
106 }
107 update();
108 }
109
110 QHash<QByteArray, QVariant> KItemListWidget::data() const
111 {
112 return m_data;
113 }
114
115 void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
116 {
117 Q_UNUSED(option);
118
119 if (m_alternateBackground) {
120 const QColor backgroundColor = m_styleOption.palette.color(QPalette::AlternateBase);
121 const QRectF backgroundRect(0, 0, size().width(), size().height());
122 painter->fillRect(backgroundRect, backgroundColor);
123 }
124
125 if (m_selected && m_editedRole.isEmpty()) {
126 const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0);
127 drawItemStyleOption(painter, widget, activeState |
128 QStyle::State_Enabled |
129 QStyle::State_Selected |
130 QStyle::State_Item);
131 }
132
133 if (m_current && m_editedRole.isEmpty()) {
134 QStyleOptionFocusRect focusRectOption;
135 focusRectOption.initFrom(widget);
136 focusRectOption.rect = textFocusRect().toRect();
137 focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item | QStyle::State_KeyboardFocusChange;
138 if (m_selected) {
139 focusRectOption.state |= QStyle::State_Selected;
140 }
141
142 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusRectOption, painter, widget);
143 }
144
145 if (m_hoverOpacity > 0.0) {
146 if (!m_hoverCache) {
147 // Initialize the m_hoverCache pixmap to improve the drawing performance
148 // when fading the hover background
149 m_hoverCache = new QPixmap(size().toSize());
150 m_hoverCache->fill(Qt::transparent);
151
152 QPainter pixmapPainter(m_hoverCache);
153 const QStyle::State activeState(isActiveWindow() ? QStyle::State_Active : 0);
154 drawItemStyleOption(&pixmapPainter, widget, activeState |
155 QStyle::State_Enabled |
156 QStyle::State_MouseOver |
157 QStyle::State_Item);
158 }
159
160 const qreal opacity = painter->opacity();
161 painter->setOpacity(m_hoverOpacity * opacity);
162 painter->drawPixmap(0, 0, *m_hoverCache);
163 painter->setOpacity(opacity);
164 }
165 }
166
167 void KItemListWidget::setVisibleRoles(const QList<QByteArray>& roles)
168 {
169 const QList<QByteArray> previousRoles = m_visibleRoles;
170 m_visibleRoles = roles;
171
172 visibleRolesChanged(roles, previousRoles);
173 update();
174 }
175
176 QList<QByteArray> KItemListWidget::visibleRoles() const
177 {
178 return m_visibleRoles;
179 }
180
181
182 void KItemListWidget::setColumnWidth(const QByteArray& role, qreal width)
183 {
184 if (m_columnWidths.value(role) != width) {
185 const qreal previousWidth = width;
186 m_columnWidths.insert(role, width);
187 columnWidthChanged(role, width, previousWidth);
188 update();
189 }
190 }
191
192 qreal KItemListWidget::columnWidth(const QByteArray& role) const
193 {
194 return m_columnWidths.value(role);
195 }
196
197 void KItemListWidget::setStyleOption(const KItemListStyleOption& option)
198 {
199 const KItemListStyleOption previous = m_styleOption;
200 clearHoverCache();
201 m_styleOption = option;
202
203 styleOptionChanged(option, previous);
204 update();
205 }
206
207 const KItemListStyleOption& KItemListWidget::styleOption() const
208 {
209 return m_styleOption;
210 }
211
212 void KItemListWidget::setSelected(bool selected)
213 {
214 if (m_selected != selected) {
215 m_selected = selected;
216 if (m_selectionToggle) {
217 m_selectionToggle->setChecked(selected);
218 }
219 selectedChanged(selected);
220 update();
221 }
222 }
223
224 bool KItemListWidget::isSelected() const
225 {
226 return m_selected;
227 }
228
229 void KItemListWidget::setCurrent(bool current)
230 {
231 if (m_current != current) {
232 m_current = current;
233 currentChanged(current);
234 update();
235 }
236 }
237
238 bool KItemListWidget::isCurrent() const
239 {
240 return m_current;
241 }
242
243 void KItemListWidget::setHovered(bool hovered)
244 {
245 if (hovered == m_hovered) {
246 return;
247 }
248
249 m_hovered = hovered;
250
251 if (!m_hoverAnimation) {
252 m_hoverAnimation = new QPropertyAnimation(this, "hoverOpacity", this);
253 const int duration = (KGlobalSettings::graphicEffectsLevel() == KGlobalSettings::NoEffects) ? 1 : 200;
254 m_hoverAnimation->setDuration(duration);
255 connect(m_hoverAnimation, SIGNAL(finished()), this, SLOT(slotHoverAnimationFinished()));
256 }
257 m_hoverAnimation->stop();
258
259 if (hovered) {
260 const qreal startValue = qMax(hoverOpacity(), qreal(0.1));
261 m_hoverAnimation->setStartValue(startValue);
262 m_hoverAnimation->setEndValue(1.0);
263 if (m_enabledSelectionToggle && !(QApplication::mouseButtons() & Qt::LeftButton)) {
264 initializeSelectionToggle();
265 }
266 } else {
267 m_hoverAnimation->setStartValue(hoverOpacity());
268 m_hoverAnimation->setEndValue(0.0);
269 }
270
271 m_hoverAnimation->start();
272
273 hoveredChanged(hovered);
274 update();
275 }
276
277 bool KItemListWidget::isHovered() const
278 {
279 return m_hovered;
280 }
281
282 void KItemListWidget::setAlternateBackground(bool enable)
283 {
284 if (m_alternateBackground != enable) {
285 m_alternateBackground = enable;
286 alternateBackgroundChanged(enable);
287 update();
288 }
289 }
290
291 bool KItemListWidget::alternateBackground() const
292 {
293 return m_alternateBackground;
294 }
295
296 void KItemListWidget::setEnabledSelectionToggle(bool enable)
297 {
298 if (m_enabledSelectionToggle != enable) {
299 m_enabledSelectionToggle = enable;
300 update();
301 }
302 }
303
304 bool KItemListWidget::enabledSelectionToggle() const
305 {
306 return m_enabledSelectionToggle;
307 }
308
309 void KItemListWidget::setSiblingsInformation(const QBitArray& siblings)
310 {
311 const QBitArray previous = m_siblingsInfo;
312 m_siblingsInfo = siblings;
313 siblingsInformationChanged(m_siblingsInfo, previous);
314 update();
315 }
316
317 QBitArray KItemListWidget::siblingsInformation() const
318 {
319 return m_siblingsInfo;
320 }
321
322 void KItemListWidget::setEditedRole(const QByteArray& role)
323 {
324 if (m_editedRole != role) {
325 const QByteArray previous = m_editedRole;
326 m_editedRole = role;
327 editedRoleChanged(role, previous);
328 }
329 }
330
331 QByteArray KItemListWidget::editedRole() const
332 {
333 return m_editedRole;
334 }
335
336 bool KItemListWidget::contains(const QPointF& point) const
337 {
338 if (!QGraphicsWidget::contains(point)) {
339 return false;
340 }
341
342 return iconRect().contains(point) ||
343 textRect().contains(point) ||
344 expansionToggleRect().contains(point) ||
345 selectionToggleRect().contains(point);
346 }
347
348 QRectF KItemListWidget::textFocusRect() const
349 {
350 return textRect();
351 }
352
353 QRectF KItemListWidget::selectionToggleRect() const
354 {
355 return QRectF();
356 }
357
358 QRectF KItemListWidget::expansionToggleRect() const
359 {
360 return QRectF();
361 }
362
363 void KItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current,
364 const QSet<QByteArray>& roles)
365 {
366 Q_UNUSED(current);
367 Q_UNUSED(roles);
368 }
369
370 void KItemListWidget::visibleRolesChanged(const QList<QByteArray>& current,
371 const QList<QByteArray>& previous)
372 {
373 Q_UNUSED(current);
374 Q_UNUSED(previous);
375 }
376
377 void KItemListWidget::columnWidthChanged(const QByteArray& role,
378 qreal current,
379 qreal previous)
380 {
381 Q_UNUSED(role);
382 Q_UNUSED(current);
383 Q_UNUSED(previous);
384 }
385
386 void KItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
387 const KItemListStyleOption& previous)
388 {
389 Q_UNUSED(current);
390 Q_UNUSED(previous);
391 }
392
393 void KItemListWidget::currentChanged(bool current)
394 {
395 Q_UNUSED(current);
396 }
397
398 void KItemListWidget::selectedChanged(bool selected)
399 {
400 Q_UNUSED(selected);
401 }
402
403 void KItemListWidget::hoveredChanged(bool hovered)
404 {
405 Q_UNUSED(hovered);
406 }
407
408 void KItemListWidget::alternateBackgroundChanged(bool enabled)
409 {
410 Q_UNUSED(enabled);
411 }
412
413 void KItemListWidget::siblingsInformationChanged(const QBitArray& current, const QBitArray& previous)
414 {
415 Q_UNUSED(current);
416 Q_UNUSED(previous);
417 }
418
419 void KItemListWidget::editedRoleChanged(const QByteArray& current, const QByteArray& previous)
420 {
421 Q_UNUSED(current);
422 Q_UNUSED(previous);
423 }
424
425 void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
426 {
427 QGraphicsWidget::resizeEvent(event);
428 clearHoverCache();
429 }
430
431 qreal KItemListWidget::hoverOpacity() const
432 {
433 return m_hoverOpacity;
434 }
435
436 void KItemListWidget::slotHoverAnimationFinished()
437 {
438 if (!m_hovered) {
439 delete m_selectionToggle;
440 m_selectionToggle = 0;
441 }
442 }
443
444 void KItemListWidget::initializeSelectionToggle()
445 {
446 Q_ASSERT(m_enabledSelectionToggle);
447
448 if (!m_selectionToggle) {
449 m_selectionToggle = new KItemListSelectionToggle(this);
450 }
451
452 const QRectF toggleRect = selectionToggleRect();
453 m_selectionToggle->setPos(toggleRect.topLeft());
454 m_selectionToggle->resize(toggleRect.size());
455
456 m_selectionToggle->setChecked(isSelected());
457 }
458
459 void KItemListWidget::setHoverOpacity(qreal opacity)
460 {
461 m_hoverOpacity = opacity;
462 if (m_selectionToggle) {
463 m_selectionToggle->setOpacity(opacity);
464 }
465
466 if (m_hoverOpacity <= 0.0) {
467 delete m_hoverCache;
468 m_hoverCache = 0;
469 }
470
471 update();
472 }
473
474 void KItemListWidget::clearHoverCache()
475 {
476 delete m_hoverCache;
477 m_hoverCache = 0;
478 }
479
480 void KItemListWidget::drawItemStyleOption(QPainter* painter, QWidget* widget, QStyle::State styleState)
481 {
482 QStyleOptionViewItemV4 viewItemOption;
483 viewItemOption.initFrom(widget);
484 viewItemOption.state = styleState;
485 viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
486 viewItemOption.showDecorationSelected = true;
487 viewItemOption.rect = textRect().toRect();
488 widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget);
489 }
490
491 #include "kitemlistwidget.moc"