From fae5fec96454fbc848f5402b1d1d758bd7ff2d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Sat, 2 Sep 2023 11:30:25 +0200 Subject: [PATCH] Add focusOut and focusIn event support for KFileItemListView and update selected widget on focus change --- src/kitemviews/kfileitemlistview.cpp | 25 ++++++++++++++++++++++ src/kitemviews/kfileitemlistview.h | 4 ++++ src/kitemviews/kfileitemlistwidget.cpp | 11 ++++++++++ src/kitemviews/kfileitemlistwidget.h | 3 +++ src/kitemviews/kitemlistcontainer.cpp | 16 ++++++++++++++ src/kitemviews/kitemlistcontainer.h | 2 ++ src/kitemviews/kitemlistview.cpp | 12 +++++++++++ src/kitemviews/kitemlistwidget.cpp | 4 ++-- src/kitemviews/kstandarditemlistwidget.cpp | 9 ++++---- src/kitemviews/kstandarditemlistwidget.h | 5 ++--- 10 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 2ff5c9fb93..954e6ab881 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -326,6 +326,31 @@ void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent *event) triggerVisibleIndexRangeUpdate(); } +void KFileItemListView::focusInEvent(QFocusEvent *event) +{ + Q_UNUSED(event) + updateSelectedWidgets(); +} + +void KFileItemListView::focusOutEvent(QFocusEvent *event) +{ + Q_UNUSED(event) + updateSelectedWidgets(); +} + +void KFileItemListView::updateSelectedWidgets() +{ + const auto visibleWidgets = visibleItemListWidgets(); + for (KItemListWidget *widget : visibleWidgets) { + if (widget->isSelected()) { + auto w = qobject_cast(widget); + if (w) { + w->forceUpdate(); + } + } + } +} + void KFileItemListView::slotItemsRemoved(const KItemRangeList &itemRanges) { KStandardItemListView::slotItemsRemoved(itemRanges); diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h index b4be0093e7..4c48c52ab2 100644 --- a/src/kitemviews/kfileitemlistview.h +++ b/src/kitemviews/kfileitemlistview.h @@ -98,6 +98,8 @@ protected: void onTransactionBegin() override; void onTransactionEnd() override; void resizeEvent(QGraphicsSceneResizeEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; protected Q_SLOTS: void slotItemsRemoved(const KItemRangeList &itemRanges) override; @@ -127,6 +129,8 @@ private: QSize availableIconSize() const; private: + void updateSelectedWidgets(); + KFileItemModelRolesUpdater *m_modelRolesUpdater; QTimer *m_updateVisibleIndexRangeTimer; QTimer *m_updateIconSizeTimer; diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 771403b701..9802ca7d16 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -203,6 +203,17 @@ void KFileItemListWidget::hoverSequenceStarted() view->setHoverSequenceState(itemUrl, 0); } +void KFileItemListWidget::forceUpdate() +{ + updateAdditionalInfoTextColor(); + // icon layout does not include the icons in the item selection rectangle + // so its icon does not need updating + if (listView()->itemLayout() != KStandardItemListView::ItemLayout::IconsLayout) { + invalidateIconCache(); + } + update(); +} + void KFileItemListWidget::hoverSequenceIndexChanged(int sequenceIndex) { KFileItemListView *view = listView(); diff --git a/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h index 27fcf7f29d..7f33c54870 100644 --- a/src/kitemviews/kfileitemlistwidget.h +++ b/src/kitemviews/kfileitemlistwidget.h @@ -35,6 +35,9 @@ public: static KItemListWidgetInformant *createInformant(); + /// Force-update the displayed icon + void forceUpdate(); + protected: virtual void hoverSequenceStarted() override; virtual void hoverSequenceIndexChanged(int sequenceIndex) override; diff --git a/src/kitemviews/kitemlistcontainer.cpp b/src/kitemviews/kitemlistcontainer.cpp index 3893ceaea0..f89a6c8ce3 100644 --- a/src/kitemviews/kitemlistcontainer.cpp +++ b/src/kitemviews/kitemlistcontainer.cpp @@ -175,6 +175,22 @@ void KItemListContainer::wheelEvent(QWheelEvent *event) smoothScroller->handleWheelEvent(event); } +void KItemListContainer::focusInEvent(QFocusEvent *event) +{ + KItemListView *view = m_controller->view(); + if (view) { + QApplication::sendEvent(view, event); + } +} + +void KItemListContainer::focusOutEvent(QFocusEvent *event) +{ + KItemListView *view = m_controller->view(); + if (view) { + QApplication::sendEvent(view, event); + } +} + void KItemListContainer::slotScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous) { Q_UNUSED(previous) diff --git a/src/kitemviews/kitemlistcontainer.h b/src/kitemviews/kitemlistcontainer.h index 6bb28469e9..40b0753764 100644 --- a/src/kitemviews/kitemlistcontainer.h +++ b/src/kitemviews/kitemlistcontainer.h @@ -50,6 +50,8 @@ protected: void resizeEvent(QResizeEvent *event) override; void scrollContentsBy(int dx, int dy) override; void wheelEvent(QWheelEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; private Q_SLOTS: void slotScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 7a3cbbcb6a..5363fa253e 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -961,6 +961,18 @@ bool KItemListView::event(QEvent *event) updateFont(); break; + case QEvent::FocusIn: + focusInEvent(static_cast(event)); + event->accept(); + return true; + break; + + case QEvent::FocusOut: + focusOutEvent(static_cast(event)); + event->accept(); + return true; + break; + default: // Forward all other events to the controller and handle them there if (!m_editingRole && m_controller && m_controller->processEvent(event, transform())) { diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index cc3cf0dfa6..cfaf891752 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -115,12 +115,12 @@ void KItemListWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o drawItemStyleOption(painter, widget, activeState | QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Item); } - if (m_current && m_editedRole.isEmpty() && widget->hasFocus()) { + if (m_current && m_editedRole.isEmpty()) { QStyleOptionFocusRect focusRectOption; initStyleOption(&focusRectOption); focusRectOption.rect = textFocusRect().toRect(); focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item | QStyle::State_KeyboardFocusChange; - if (m_selected) { + if (m_selected && widget->hasFocus()) { focusRectOption.state |= QStyle::State_Selected; } diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 24a9864193..01b135038d 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -386,7 +386,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic } painter->setFont(m_customizedFont); - painter->setPen(textColor(widget)); + painter->setPen(textColor(*widget)); const TextInfo *textInfo = m_textInfo.value("text"); if (!textInfo) { @@ -645,7 +645,7 @@ void KStandardItemListWidget::setTextColor(const QColor &color) } } -QColor KStandardItemListWidget::textColor(QWidget *widget) const +QColor KStandardItemListWidget::textColor(const QWidget &widget) const { if (!isSelected()) { if (m_isHidden) { @@ -655,7 +655,7 @@ QColor KStandardItemListWidget::textColor(QWidget *widget) const } } - const QPalette::ColorGroup group = isActiveWindow() && widget->hasFocus() ? QPalette::Active : QPalette::Inactive; + const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); return styleOption().palette.color(group, role); } @@ -1436,9 +1436,10 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() void KStandardItemListWidget::updateAdditionalInfoTextColor() { QColor c1; + const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); if (m_customTextColor.isValid()) { c1 = m_customTextColor; - } else if (isSelected() && (m_layout != DetailsLayout || m_highlightEntireRow)) { + } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { // The detail text colour needs to match the main text (HighlightedText) for the same level // of readability. We short circuit early here to avoid interpolating with another colour. m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index d146a02fb9..c4f80af1dd 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -139,7 +139,7 @@ protected: virtual QPalette::ColorRole normalTextColorRole() const; void setTextColor(const QColor &color); - QColor textColor(QWidget *widget) const; + QColor textColor(const QWidget &widget) const; void setOverlay(const QPixmap &overlay); QPixmap overlay() const; @@ -181,6 +181,7 @@ protected: QPointF pos; QStaticText staticText; }; + void updateAdditionalInfoTextColor(); public Q_SLOTS: void finishRoleEditing(); @@ -200,8 +201,6 @@ private: void updateCompactLayoutTextCache(); void updateDetailsLayoutTextCache(); - void updateAdditionalInfoTextColor(); - void drawPixmap(QPainter *painter, const QPixmap &pixmap); void drawSiblingsInformation(QPainter *painter);