1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
4 * Based on the Itemviews NG project from Trolltech Labs *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20 ***************************************************************************/
22 #include "kitemlistwidget.h"
24 #include "kitemlistview.h"
25 #include "private/kitemlistselectiontoggle.h"
27 #include <QApplication>
29 #include <QPropertyAnimation>
30 #include <QStyleOption>
32 KItemListWidgetInformant::KItemListWidgetInformant()
36 KItemListWidgetInformant::~KItemListWidgetInformant()
40 KItemListWidget::KItemListWidget(KItemListWidgetInformant
* informant
, QGraphicsItem
* parent
) :
41 QGraphicsWidget(parent
),
42 m_informant(informant
),
47 m_alternateBackground(false),
48 m_enabledSelectionToggle(false),
55 m_hoverCache(nullptr),
56 m_hoverAnimation(nullptr),
57 m_selectionToggle(nullptr),
62 KItemListWidget::~KItemListWidget()
67 void KItemListWidget::setIndex(int index
)
69 if (m_index
!= index
) {
70 delete m_selectionToggle
;
71 m_selectionToggle
= nullptr;
73 if (m_hoverAnimation
) {
74 m_hoverAnimation
->stop();
83 int KItemListWidget::index() const
88 void KItemListWidget::setData(const QHash
<QByteArray
, QVariant
>& data
,
89 const QSet
<QByteArray
>& roles
)
92 if (roles
.isEmpty()) {
96 foreach (const QByteArray
& role
, roles
) {
97 m_data
[role
] = data
[role
];
99 dataChanged(m_data
, roles
);
104 QHash
<QByteArray
, QVariant
> KItemListWidget::data() const
109 void KItemListWidget::paint(QPainter
* painter
, const QStyleOptionGraphicsItem
* option
, QWidget
* widget
)
113 if (m_alternateBackground
) {
114 const QColor backgroundColor
= m_styleOption
.palette
.color(QPalette::AlternateBase
);
115 const QRectF
backgroundRect(0, 0, size().width(), size().height());
116 painter
->fillRect(backgroundRect
, backgroundColor
);
119 if (m_selected
&& m_editedRole
.isEmpty()) {
120 const QStyle::State
activeState(isActiveWindow() ? QStyle::State_Active
: 0);
121 drawItemStyleOption(painter
, widget
, activeState
|
122 QStyle::State_Enabled
|
123 QStyle::State_Selected
|
127 if (m_current
&& m_editedRole
.isEmpty()) {
128 QStyleOptionFocusRect focusRectOption
;
129 initStyleOption(&focusRectOption
);
130 focusRectOption
.rect
= textFocusRect().toRect();
131 focusRectOption
.state
= QStyle::State_Enabled
| QStyle::State_Item
| QStyle::State_KeyboardFocusChange
;
133 focusRectOption
.state
|= QStyle::State_Selected
;
136 style()->drawPrimitive(QStyle::PE_FrameFocusRect
, &focusRectOption
, painter
, widget
);
139 if (m_hoverOpacity
> 0.0) {
141 // Initialize the m_hoverCache pixmap to improve the drawing performance
142 // when fading the hover background
143 m_hoverCache
= new QPixmap(size().toSize());
144 m_hoverCache
->fill(Qt::transparent
);
146 QPainter
pixmapPainter(m_hoverCache
);
147 const QStyle::State
activeState(isActiveWindow() ? QStyle::State_Active
: 0);
148 drawItemStyleOption(&pixmapPainter
, widget
, activeState
|
149 QStyle::State_Enabled
|
150 QStyle::State_MouseOver
|
154 const qreal opacity
= painter
->opacity();
155 painter
->setOpacity(m_hoverOpacity
* opacity
);
156 painter
->drawPixmap(0, 0, *m_hoverCache
);
157 painter
->setOpacity(opacity
);
161 void KItemListWidget::setVisibleRoles(const QList
<QByteArray
>& roles
)
163 const QList
<QByteArray
> previousRoles
= m_visibleRoles
;
164 m_visibleRoles
= roles
;
166 visibleRolesChanged(roles
, previousRoles
);
170 QList
<QByteArray
> KItemListWidget::visibleRoles() const
172 return m_visibleRoles
;
176 void KItemListWidget::setColumnWidth(const QByteArray
& role
, qreal width
)
178 const qreal previousWidth
= m_columnWidths
.value(role
);
179 if (previousWidth
!= width
) {
180 m_columnWidths
.insert(role
, width
);
181 columnWidthChanged(role
, width
, previousWidth
);
186 qreal
KItemListWidget::columnWidth(const QByteArray
& role
) const
188 return m_columnWidths
.value(role
);
191 void KItemListWidget::setStyleOption(const KItemListStyleOption
& option
)
193 if (m_styleOption
== option
) {
197 const KItemListStyleOption previous
= m_styleOption
;
199 m_styleOption
= option
;
200 styleOptionChanged(option
, previous
);
204 const KItemListStyleOption
& KItemListWidget::styleOption() const
206 return m_styleOption
;
209 void KItemListWidget::setSelected(bool selected
)
211 if (m_selected
!= selected
) {
212 m_selected
= selected
;
213 if (m_selectionToggle
) {
214 m_selectionToggle
->setChecked(selected
);
216 selectedChanged(selected
);
221 bool KItemListWidget::isSelected() const
226 void KItemListWidget::setCurrent(bool current
)
228 if (m_current
!= current
) {
230 currentChanged(current
);
235 bool KItemListWidget::isCurrent() const
240 void KItemListWidget::setHovered(bool hovered
)
242 if (hovered
== m_hovered
) {
248 if (!m_hoverAnimation
) {
249 m_hoverAnimation
= new QPropertyAnimation(this, "hoverOpacity", this);
250 const int duration
= style()->styleHint(QStyle::SH_Widget_Animate
) ? 200 : 1;
251 m_hoverAnimation
->setDuration(duration
);
252 connect(m_hoverAnimation
, &QPropertyAnimation::finished
, this, &KItemListWidget::slotHoverAnimationFinished
);
254 m_hoverAnimation
->stop();
257 const qreal startValue
= qMax(hoverOpacity(), qreal(0.1));
258 m_hoverAnimation
->setStartValue(startValue
);
259 m_hoverAnimation
->setEndValue(1.0);
260 if (m_enabledSelectionToggle
&& !(QApplication::mouseButtons() & Qt::LeftButton
)) {
261 initializeSelectionToggle();
264 m_hoverAnimation
->setStartValue(hoverOpacity());
265 m_hoverAnimation
->setEndValue(0.0);
268 m_hoverAnimation
->start();
270 hoveredChanged(hovered
);
274 bool KItemListWidget::isHovered() const
279 void KItemListWidget::setHoverPosition(const QPointF
& pos
)
281 if (m_selectionToggle
) {
282 m_selectionToggle
->setHovered(selectionToggleRect().contains(pos
));
286 void KItemListWidget::setAlternateBackground(bool enable
)
288 if (m_alternateBackground
!= enable
) {
289 m_alternateBackground
= enable
;
290 alternateBackgroundChanged(enable
);
295 bool KItemListWidget::alternateBackground() const
297 return m_alternateBackground
;
300 void KItemListWidget::setEnabledSelectionToggle(bool enable
)
302 if (m_enabledSelectionToggle
!= enable
) {
303 m_enabledSelectionToggle
= enable
;
308 bool KItemListWidget::enabledSelectionToggle() const
310 return m_enabledSelectionToggle
;
313 void KItemListWidget::setSiblingsInformation(const QBitArray
& siblings
)
315 const QBitArray previous
= m_siblingsInfo
;
316 m_siblingsInfo
= siblings
;
317 siblingsInformationChanged(m_siblingsInfo
, previous
);
321 QBitArray
KItemListWidget::siblingsInformation() const
323 return m_siblingsInfo
;
326 void KItemListWidget::setEditedRole(const QByteArray
& role
)
328 if (m_editedRole
!= role
) {
329 const QByteArray previous
= m_editedRole
;
331 editedRoleChanged(role
, previous
);
335 QByteArray
KItemListWidget::editedRole() const
340 bool KItemListWidget::contains(const QPointF
& point
) const
342 if (!QGraphicsWidget::contains(point
)) {
346 return iconRect().contains(point
) ||
347 textRect().contains(point
) ||
348 expansionToggleRect().contains(point
) ||
349 selectionToggleRect().contains(point
);
352 QRectF
KItemListWidget::textFocusRect() const
357 QRectF
KItemListWidget::selectionToggleRect() const
362 QRectF
KItemListWidget::expansionToggleRect() const
367 QPixmap
KItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem
* option
,
370 QPixmap
pixmap(size().toSize() * widget
->devicePixelRatio());
371 pixmap
.setDevicePixelRatio(widget
->devicePixelRatio());
372 pixmap
.fill(Qt::transparent
);
374 QPainter
painter(&pixmap
);
376 const bool oldAlternateBackground
= m_alternateBackground
;
377 const bool wasSelected
= m_selected
;
378 const bool wasHovered
= m_hovered
;
380 setAlternateBackground(false);
383 paint(&painter
, option
, widget
);
385 setAlternateBackground(oldAlternateBackground
);
386 setSelected(wasSelected
);
387 setHovered(wasHovered
);
392 void KItemListWidget::dataChanged(const QHash
<QByteArray
, QVariant
>& current
,
393 const QSet
<QByteArray
>& roles
)
399 void KItemListWidget::visibleRolesChanged(const QList
<QByteArray
>& current
,
400 const QList
<QByteArray
>& previous
)
406 void KItemListWidget::columnWidthChanged(const QByteArray
& role
,
415 void KItemListWidget::styleOptionChanged(const KItemListStyleOption
& current
,
416 const KItemListStyleOption
& previous
)
422 void KItemListWidget::currentChanged(bool current
)
427 void KItemListWidget::selectedChanged(bool selected
)
432 void KItemListWidget::hoveredChanged(bool hovered
)
437 void KItemListWidget::alternateBackgroundChanged(bool enabled
)
442 void KItemListWidget::siblingsInformationChanged(const QBitArray
& current
, const QBitArray
& previous
)
448 void KItemListWidget::editedRoleChanged(const QByteArray
& current
, const QByteArray
& previous
)
454 void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent
* event
)
456 QGraphicsWidget::resizeEvent(event
);
459 if (m_selectionToggle
) {
460 const QRectF
& toggleRect
= selectionToggleRect();
461 m_selectionToggle
->setPos(toggleRect
.topLeft());
462 m_selectionToggle
->resize(toggleRect
.size());
466 qreal
KItemListWidget::hoverOpacity() const
468 return m_hoverOpacity
;
471 void KItemListWidget::slotHoverAnimationFinished()
473 if (!m_hovered
&& m_selectionToggle
) {
474 m_selectionToggle
->deleteLater();
475 m_selectionToggle
= nullptr;
479 void KItemListWidget::initializeSelectionToggle()
481 Q_ASSERT(m_enabledSelectionToggle
);
483 if (!m_selectionToggle
) {
484 m_selectionToggle
= new KItemListSelectionToggle(this);
487 const QRectF toggleRect
= selectionToggleRect();
488 m_selectionToggle
->setPos(toggleRect
.topLeft());
489 m_selectionToggle
->resize(toggleRect
.size());
491 m_selectionToggle
->setChecked(isSelected());
494 void KItemListWidget::setHoverOpacity(qreal opacity
)
496 m_hoverOpacity
= opacity
;
497 if (m_selectionToggle
) {
498 m_selectionToggle
->setOpacity(opacity
);
501 if (m_hoverOpacity
<= 0.0) {
503 m_hoverCache
= nullptr;
509 void KItemListWidget::clearHoverCache()
512 m_hoverCache
= nullptr;
515 void KItemListWidget::drawItemStyleOption(QPainter
* painter
, QWidget
* widget
, QStyle::State styleState
)
517 QStyleOptionViewItem viewItemOption
;
518 initStyleOption(&viewItemOption
);
519 viewItemOption
.state
= styleState
;
520 viewItemOption
.viewItemPosition
= QStyleOptionViewItem::OnlyOne
;
521 viewItemOption
.showDecorationSelected
= true;
522 viewItemOption
.rect
= selectionRect().toRect();
523 style()->drawPrimitive(QStyle::PE_PanelItemViewItem
, &viewItemOption
, painter
, widget
);