2 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
4 * Based on the Itemviews NG project from Trolltech Labs
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "kitemlistwidget.h"
11 #include "kitemlistview.h"
12 #include "private/kitemlistselectiontoggle.h"
14 #include <KConfigGroup>
15 #include <KSharedConfig>
17 #include <QApplication>
19 #include <QPropertyAnimation>
20 #include <QStyleOption>
22 KItemListWidgetInformant::KItemListWidgetInformant()
26 KItemListWidgetInformant::~KItemListWidgetInformant()
30 KItemListWidget::KItemListWidget(KItemListWidgetInformant
*informant
, QGraphicsItem
*parent
)
31 : QGraphicsWidget(parent
)
32 , m_informant(informant
)
37 , m_expansionAreaHovered(false)
38 , m_alternateBackground(false)
39 , m_enabledSelectionToggle(false)
48 , m_hoverCache(nullptr)
49 , m_hoverSequenceIndex(0)
50 , m_selectionToggle(nullptr)
54 connect(&m_hoverSequenceTimer
, &QTimer::timeout
, this, &KItemListWidget::slotHoverSequenceTimerTimeout
);
57 KItemListWidget::~KItemListWidget()
62 void KItemListWidget::setIndex(int index
)
64 if (m_index
!= index
) {
65 delete m_selectionToggle
;
66 m_selectionToggle
= nullptr;
76 int KItemListWidget::index() const
81 void KItemListWidget::setData(const QHash
<QByteArray
, QVariant
> &data
, const QSet
<QByteArray
> &roles
)
84 if (roles
.isEmpty()) {
88 for (const QByteArray
&role
: roles
) {
89 m_data
[role
] = data
[role
];
91 dataChanged(m_data
, roles
);
96 QHash
<QByteArray
, QVariant
> KItemListWidget::data() const
101 QVariant
KItemListWidget::value(const QByteArray
&key
) const
103 return m_data
.value(key
);
106 void KItemListWidget::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*option
, QWidget
*widget
)
110 if (m_alternateBackground
) {
111 QColor backgroundColor
= m_styleOption
.palette
.color(QPalette::AlternateBase
);
112 if (!widget
->hasFocus()) {
113 QColor baseColor
= m_styleOption
.palette
.color(QPalette::Base
);
114 if (baseColor
.lightnessF() > 0.5) {
116 backgroundColor
= backgroundColor
.lighter(101);
119 backgroundColor
= backgroundColor
.darker(101);
123 const QRectF
backgroundRect(0, 0, size().width(), size().height());
124 painter
->fillRect(backgroundRect
, backgroundColor
);
127 if (m_selected
&& m_editedRole
.isEmpty()) {
128 const QStyle::State
activeState(isActiveWindow() && widget
->hasFocus() ? QStyle::State_Active
: 0);
129 drawItemStyleOption(painter
, widget
, activeState
| QStyle::State_Enabled
| QStyle::State_Selected
| QStyle::State_Item
);
132 if (m_current
&& m_editedRole
.isEmpty()) {
133 QStyleOptionFocusRect focusRectOption
;
134 initStyleOption(&focusRectOption
);
135 focusRectOption
.rect
= textFocusRect().toRect();
136 focusRectOption
.state
= QStyle::State_Enabled
| QStyle::State_Item
| QStyle::State_KeyboardFocusChange
;
137 if (m_selected
&& widget
->hasFocus()) {
138 focusRectOption
.state
|= QStyle::State_Selected
;
141 style()->drawPrimitive(QStyle::PE_FrameFocusRect
, &focusRectOption
, painter
, widget
);
144 if (m_hoverOpacity
> 0.0) {
146 // Initialize the m_hoverCache pixmap to improve the drawing performance
147 // when fading the hover background
148 m_hoverCache
= new QPixmap(size().toSize());
149 m_hoverCache
->fill(Qt::transparent
);
151 QPainter
pixmapPainter(m_hoverCache
);
152 const QStyle::State
activeState(isActiveWindow() && widget
->hasFocus() ? QStyle::State_Active
| QStyle::State_Enabled
: 0);
153 drawItemStyleOption(&pixmapPainter
, widget
, activeState
| QStyle::State_MouseOver
| QStyle::State_Item
);
156 const qreal opacity
= painter
->opacity();
157 painter
->setOpacity(m_hoverOpacity
* opacity
);
158 painter
->drawPixmap(0, 0, *m_hoverCache
);
159 painter
->setOpacity(opacity
);
163 void KItemListWidget::setVisibleRoles(const QList
<QByteArray
> &roles
)
165 const QList
<QByteArray
> previousRoles
= m_visibleRoles
;
166 m_visibleRoles
= roles
;
168 visibleRolesChanged(roles
, previousRoles
);
172 QList
<QByteArray
> KItemListWidget::visibleRoles() const
174 return m_visibleRoles
;
177 void KItemListWidget::setColumnWidth(const QByteArray
&role
, qreal width
)
179 const qreal previousWidth
= m_columnWidths
.value(role
);
180 if (previousWidth
!= width
) {
181 m_columnWidths
.insert(role
, width
);
182 columnWidthChanged(role
, width
, previousWidth
);
187 qreal
KItemListWidget::columnWidth(const QByteArray
&role
) const
189 return m_columnWidths
.value(role
);
192 void KItemListWidget::setSidePadding(qreal leftPaddingWidth
, qreal rightPaddingWidth
)
194 bool changed
= false;
195 if (m_leftPadding
!= leftPaddingWidth
) {
196 m_leftPadding
= leftPaddingWidth
;
200 if (m_rightPadding
!= rightPaddingWidth
) {
201 m_rightPadding
= rightPaddingWidth
;
209 sidePaddingChanged(leftPaddingWidth
, rightPaddingWidth
);
213 qreal
KItemListWidget::leftPadding() const
215 return m_leftPadding
;
218 qreal
KItemListWidget::rightPadding() const
220 return m_rightPadding
;
223 void KItemListWidget::setStyleOption(const KItemListStyleOption
&option
)
225 if (m_styleOption
== option
) {
229 const KItemListStyleOption previous
= m_styleOption
;
231 m_styleOption
= option
;
232 styleOptionChanged(option
, previous
);
236 const KItemListStyleOption
&KItemListWidget::styleOption() const
238 return m_styleOption
;
241 void KItemListWidget::setSelected(bool selected
)
243 if (m_selected
!= selected
) {
244 m_selected
= selected
;
245 if (m_selectionToggle
) {
246 m_selectionToggle
->setChecked(selected
);
248 selectedChanged(selected
);
253 bool KItemListWidget::isSelected() const
258 void KItemListWidget::setCurrent(bool current
)
260 if (m_current
!= current
) {
262 currentChanged(current
);
267 bool KItemListWidget::isCurrent() const
272 void KItemListWidget::setHovered(bool hovered
)
274 if (hovered
== m_hovered
) {
280 m_hoverSequenceIndex
= 0;
283 setHoverOpacity(1.0);
285 if (m_enabledSelectionToggle
&& !(QApplication::mouseButtons() & Qt::LeftButton
)) {
286 initializeSelectionToggle();
289 hoverSequenceStarted();
291 const KConfigGroup
globalConfig(KSharedConfig::openConfig(), QStringLiteral("PreviewSettings"));
292 const int interval
= globalConfig
.readEntry("HoverSequenceInterval", 700);
294 m_hoverSequenceTimer
.start(interval
);
296 setHoverOpacity(0.0);
298 if (m_selectionToggle
) {
299 m_selectionToggle
->deleteLater();
300 m_selectionToggle
= nullptr;
303 hoverSequenceEnded();
304 m_hoverSequenceTimer
.stop();
307 hoveredChanged(hovered
);
311 bool KItemListWidget::isHovered() const
316 void KItemListWidget::setExpansionAreaHovered(bool hovered
)
318 if (hovered
== m_expansionAreaHovered
) {
321 m_expansionAreaHovered
= hovered
;
325 bool KItemListWidget::expansionAreaHovered() const
327 return m_expansionAreaHovered
;
330 void KItemListWidget::setHoverPosition(const QPointF
&pos
)
332 if (m_selectionToggle
) {
333 m_selectionToggle
->setHovered(selectionToggleRect().contains(pos
));
337 void KItemListWidget::setAlternateBackground(bool enable
)
339 if (m_alternateBackground
!= enable
) {
340 m_alternateBackground
= enable
;
341 alternateBackgroundChanged(enable
);
346 bool KItemListWidget::alternateBackground() const
348 return m_alternateBackground
;
351 void KItemListWidget::setEnabledSelectionToggle(bool enable
)
353 if (m_enabledSelectionToggle
!= enable
) {
354 m_enabledSelectionToggle
= enable
;
356 // We want the change to take effect immediately.
357 if (m_enabledSelectionToggle
) {
359 initializeSelectionToggle();
361 } else if (m_selectionToggle
) {
362 m_selectionToggle
->deleteLater();
363 m_selectionToggle
= nullptr;
370 bool KItemListWidget::enabledSelectionToggle() const
372 return m_enabledSelectionToggle
;
375 void KItemListWidget::setSiblingsInformation(const QBitArray
&siblings
)
377 const QBitArray previous
= m_siblingsInfo
;
378 m_siblingsInfo
= siblings
;
379 siblingsInformationChanged(m_siblingsInfo
, previous
);
383 QBitArray
KItemListWidget::siblingsInformation() const
385 return m_siblingsInfo
;
388 void KItemListWidget::setEditedRole(const QByteArray
&role
)
390 if (m_editedRole
!= role
) {
391 const QByteArray previous
= m_editedRole
;
393 editedRoleChanged(role
, previous
);
397 QByteArray
KItemListWidget::editedRole() const
402 void KItemListWidget::setIconSize(int iconSize
)
404 if (m_iconSize
!= iconSize
) {
405 const int previousIconSize
= m_iconSize
;
406 m_iconSize
= iconSize
;
407 iconSizeChanged(iconSize
, previousIconSize
);
411 int KItemListWidget::iconSize() const
416 bool KItemListWidget::contains(const QPointF
&point
) const
418 if (!QGraphicsWidget::contains(point
)) {
422 return iconRect().contains(point
) || textRect().contains(point
) || expansionToggleRect().contains(point
) || selectionToggleRect().contains(point
);
425 QRectF
KItemListWidget::textFocusRect() const
430 QRectF
KItemListWidget::selectionToggleRect() const
435 QRectF
KItemListWidget::expansionToggleRect() const
440 QPixmap
KItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem
*option
, QWidget
*widget
)
442 QPixmap
pixmap(size().toSize() * widget
->devicePixelRatio());
443 pixmap
.setDevicePixelRatio(widget
->devicePixelRatio());
444 pixmap
.fill(Qt::transparent
);
446 QPainter
painter(&pixmap
);
448 const bool oldAlternateBackground
= m_alternateBackground
;
449 const bool wasSelected
= m_selected
;
450 const bool wasHovered
= m_hovered
;
452 setAlternateBackground(false);
455 paint(&painter
, option
, widget
);
457 setAlternateBackground(oldAlternateBackground
);
458 setSelected(wasSelected
);
459 setHovered(wasHovered
);
464 void KItemListWidget::startActivateSoonAnimation(int timeUntilActivation
)
466 Q_UNUSED(timeUntilActivation
)
469 void KItemListWidget::dataChanged(const QHash
<QByteArray
, QVariant
> ¤t
, const QSet
<QByteArray
> &roles
)
475 void KItemListWidget::visibleRolesChanged(const QList
<QByteArray
> ¤t
, const QList
<QByteArray
> &previous
)
481 void KItemListWidget::columnWidthChanged(const QByteArray
&role
, qreal current
, qreal previous
)
488 void KItemListWidget::sidePaddingChanged(qreal leftPaddingWidth
, qreal rightPaddingWidth
)
490 Q_UNUSED(leftPaddingWidth
)
491 Q_UNUSED(rightPaddingWidth
)
494 void KItemListWidget::styleOptionChanged(const KItemListStyleOption
¤t
, const KItemListStyleOption
&previous
)
498 // set the initial value of m_iconSize if not set
499 if (m_iconSize
== -1) {
500 m_iconSize
= current
.iconSize
;
504 void KItemListWidget::currentChanged(bool current
)
509 void KItemListWidget::selectedChanged(bool selected
)
514 void KItemListWidget::hoveredChanged(bool hovered
)
519 void KItemListWidget::alternateBackgroundChanged(bool enabled
)
524 void KItemListWidget::siblingsInformationChanged(const QBitArray
¤t
, const QBitArray
&previous
)
530 void KItemListWidget::editedRoleChanged(const QByteArray
¤t
, const QByteArray
&previous
)
536 void KItemListWidget::iconSizeChanged(int current
, int previous
)
542 void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent
*event
)
544 QGraphicsWidget::resizeEvent(event
);
547 if (m_selectionToggle
) {
548 const QRectF
&toggleRect
= selectionToggleRect();
549 m_selectionToggle
->setPos(toggleRect
.topLeft());
550 m_selectionToggle
->resize(toggleRect
.size());
554 void KItemListWidget::hoverSequenceStarted()
558 void KItemListWidget::hoverSequenceIndexChanged(int sequenceIndex
)
560 Q_UNUSED(sequenceIndex
);
563 void KItemListWidget::hoverSequenceEnded()
567 qreal
KItemListWidget::hoverOpacity() const
569 return m_hoverOpacity
;
572 int KItemListWidget::hoverSequenceIndex() const
574 return m_hoverSequenceIndex
;
577 void KItemListWidget::slotHoverSequenceTimerTimeout()
579 m_hoverSequenceIndex
++;
580 hoverSequenceIndexChanged(m_hoverSequenceIndex
);
583 void KItemListWidget::initializeSelectionToggle()
585 Q_ASSERT(m_enabledSelectionToggle
);
587 if (!m_selectionToggle
) {
588 m_selectionToggle
= new KItemListSelectionToggle(this);
591 const QRectF toggleRect
= selectionToggleRect();
592 m_selectionToggle
->setPos(toggleRect
.topLeft());
593 m_selectionToggle
->resize(toggleRect
.size());
595 m_selectionToggle
->setChecked(isSelected());
598 void KItemListWidget::setHoverOpacity(qreal opacity
)
600 m_hoverOpacity
= opacity
;
601 if (m_selectionToggle
) {
602 m_selectionToggle
->setOpacity(opacity
);
605 if (m_hoverOpacity
<= 0.0) {
607 m_hoverCache
= nullptr;
613 void KItemListWidget::clearHoverCache()
616 m_hoverCache
= nullptr;
619 void KItemListWidget::drawItemStyleOption(QPainter
*painter
, QWidget
*widget
, QStyle::State styleState
)
621 QStyleOptionViewItem viewItemOption
;
622 initStyleOption(&viewItemOption
);
623 viewItemOption
.state
= styleState
;
624 viewItemOption
.viewItemPosition
= QStyleOptionViewItem::OnlyOne
;
625 viewItemOption
.showDecorationSelected
= true;
626 viewItemOption
.rect
= selectionRect().toRect();
627 style()->drawPrimitive(QStyle::PE_PanelItemViewItem
, &viewItemOption
, painter
, widget
);
630 #include "moc_kitemlistwidget.cpp"