]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kitemlistwidget.cpp
c261bf1d259a02e04005751f6fd2799395b1100e
[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::setHoverPosition(const QPointF& pos)
283 {
284 if (m_selectionToggle) {
285 m_selectionToggle->setHovered(selectionToggleRect().contains(pos));
286 }
287 }
288
289 void KItemListWidget::setAlternateBackground(bool enable)
290 {
291 if (m_alternateBackground != enable) {
292 m_alternateBackground = enable;
293 alternateBackgroundChanged(enable);
294 update();
295 }
296 }
297
298 bool KItemListWidget::alternateBackground() const
299 {
300 return m_alternateBackground;
301 }
302
303 void KItemListWidget::setEnabledSelectionToggle(bool enable)
304 {
305 if (m_enabledSelectionToggle != enable) {
306 m_enabledSelectionToggle = enable;
307 update();
308 }
309 }
310
311 bool KItemListWidget::enabledSelectionToggle() const
312 {
313 return m_enabledSelectionToggle;
314 }
315
316 void KItemListWidget::setSiblingsInformation(const QBitArray& siblings)
317 {
318 const QBitArray previous = m_siblingsInfo;
319 m_siblingsInfo = siblings;
320 siblingsInformationChanged(m_siblingsInfo, previous);
321 update();
322 }
323
324 QBitArray KItemListWidget::siblingsInformation() const
325 {
326 return m_siblingsInfo;
327 }
328
329 void KItemListWidget::setEditedRole(const QByteArray& role)
330 {
331 if (m_editedRole != role) {
332 const QByteArray previous = m_editedRole;
333 m_editedRole = role;
334 editedRoleChanged(role, previous);
335 }
336 }
337
338 QByteArray KItemListWidget::editedRole() const
339 {
340 return m_editedRole;
341 }
342
343 bool KItemListWidget::contains(const QPointF& point) const
344 {
345 if (!QGraphicsWidget::contains(point)) {
346 return false;
347 }
348
349 return iconRect().contains(point) ||
350 textRect().contains(point) ||
351 expansionToggleRect().contains(point) ||
352 selectionToggleRect().contains(point);
353 }
354
355 QRectF KItemListWidget::textFocusRect() const
356 {
357 return textRect();
358 }
359
360 QRectF KItemListWidget::selectionToggleRect() const
361 {
362 return QRectF();
363 }
364
365 QRectF KItemListWidget::expansionToggleRect() const
366 {
367 return QRectF();
368 }
369
370 QPixmap KItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem* option,
371 QWidget* widget)
372 {
373 QPixmap pixmap(size().toSize());
374 pixmap.fill(Qt::transparent);
375
376 QPainter painter(&pixmap);
377
378 const bool oldAlternateBackground = m_alternateBackground;
379 const bool wasSelected = m_selected;
380 const bool wasHovered = m_hovered;
381
382 setAlternateBackground(false);
383 setSelected(false);
384 setHovered(false);
385
386 paint(&painter, option, widget);
387
388 setAlternateBackground(oldAlternateBackground);
389 setSelected(wasSelected);
390 setHovered(wasHovered);
391
392 return pixmap;
393 }
394
395 void KItemListWidget::dataChanged(const QHash<QByteArray, QVariant>& current,
396 const QSet<QByteArray>& roles)
397 {
398 Q_UNUSED(current);
399 Q_UNUSED(roles);
400 }
401
402 void KItemListWidget::visibleRolesChanged(const QList<QByteArray>& current,
403 const QList<QByteArray>& previous)
404 {
405 Q_UNUSED(current);
406 Q_UNUSED(previous);
407 }
408
409 void KItemListWidget::columnWidthChanged(const QByteArray& role,
410 qreal current,
411 qreal previous)
412 {
413 Q_UNUSED(role);
414 Q_UNUSED(current);
415 Q_UNUSED(previous);
416 }
417
418 void KItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
419 const KItemListStyleOption& previous)
420 {
421 Q_UNUSED(current);
422 Q_UNUSED(previous);
423 }
424
425 void KItemListWidget::currentChanged(bool current)
426 {
427 Q_UNUSED(current);
428 }
429
430 void KItemListWidget::selectedChanged(bool selected)
431 {
432 Q_UNUSED(selected);
433 }
434
435 void KItemListWidget::hoveredChanged(bool hovered)
436 {
437 Q_UNUSED(hovered);
438 }
439
440 void KItemListWidget::alternateBackgroundChanged(bool enabled)
441 {
442 Q_UNUSED(enabled);
443 }
444
445 void KItemListWidget::siblingsInformationChanged(const QBitArray& current, const QBitArray& previous)
446 {
447 Q_UNUSED(current);
448 Q_UNUSED(previous);
449 }
450
451 void KItemListWidget::editedRoleChanged(const QByteArray& current, const QByteArray& previous)
452 {
453 Q_UNUSED(current);
454 Q_UNUSED(previous);
455 }
456
457 void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
458 {
459 QGraphicsWidget::resizeEvent(event);
460 clearHoverCache();
461
462 if (m_selectionToggle) {
463 const QRectF& toggleRect = selectionToggleRect();
464 m_selectionToggle->setPos(toggleRect.topLeft());
465 m_selectionToggle->resize(toggleRect.size());
466 }
467 }
468
469 qreal KItemListWidget::hoverOpacity() const
470 {
471 return m_hoverOpacity;
472 }
473
474 void KItemListWidget::slotHoverAnimationFinished()
475 {
476 if (!m_hovered) {
477 delete m_selectionToggle;
478 m_selectionToggle = 0;
479 }
480 }
481
482 void KItemListWidget::initializeSelectionToggle()
483 {
484 Q_ASSERT(m_enabledSelectionToggle);
485
486 if (!m_selectionToggle) {
487 m_selectionToggle = new KItemListSelectionToggle(this);
488 }
489
490 const QRectF toggleRect = selectionToggleRect();
491 m_selectionToggle->setPos(toggleRect.topLeft());
492 m_selectionToggle->resize(toggleRect.size());
493
494 m_selectionToggle->setChecked(isSelected());
495 }
496
497 void KItemListWidget::setHoverOpacity(qreal opacity)
498 {
499 m_hoverOpacity = opacity;
500 if (m_selectionToggle) {
501 m_selectionToggle->setOpacity(opacity);
502 }
503
504 if (m_hoverOpacity <= 0.0) {
505 delete m_hoverCache;
506 m_hoverCache = 0;
507 }
508
509 update();
510 }
511
512 void KItemListWidget::clearHoverCache()
513 {
514 delete m_hoverCache;
515 m_hoverCache = 0;
516 }
517
518 void KItemListWidget::drawItemStyleOption(QPainter* painter, QWidget* widget, QStyle::State styleState)
519 {
520 QStyleOptionViewItemV4 viewItemOption;
521 viewItemOption.initFrom(widget);
522 viewItemOption.state = styleState;
523 viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
524 viewItemOption.showDecorationSelected = true;
525 viewItemOption.rect = textRect().toRect();
526 widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget);
527 }
528
529 #include "kitemlistwidget.moc"