From 5e35194b00d84db6aea3370ee8bb0ad560428c62 Mon Sep 17 00:00:00 2001 From: Pan Zhang Date: Mon, 23 Mar 2026 10:12:10 +0800 Subject: kitemviews: Preserve inline rename when item scrolls out of view Inline rename was canceled when the edited item scrolled out of view. Scrolling could both finish the edit and recycle the item widget, causing the typed name to be lost. Keep the inline rename editor alive while the item is temporarily offscreen. Update the editor geometry on scroll, avoid recycling the widget while it is being edited, and suppress the temporary FocusOut triggered by hiding the editor. If the user interacts with another item while the edited one is offscreen, finish the hidden edit first so normal selection behavior is preserved. BUG: 506884 --- src/kitemviews/kstandarditemlistwidget.cpp | 43 ++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'src/kitemviews/kstandarditemlistwidget.cpp') diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 9195f4e77..ddbb8b6a1 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -854,7 +854,7 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray ¤t, const { Q_UNUSED(previous) - QGraphicsView *parent = scene()->views()[0]; + QGraphicsView *parent = !scene() || scene()->views().isEmpty() ? nullptr : scene()->views()[0]; if (current.isEmpty() || !parent || current != "text") { if (m_roleEditor) { Q_EMIT roleEditingCanceled(index(), current, data().value(current)); @@ -891,16 +891,7 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray ¤t, const connect(m_roleEditor, &KItemListRoleEditor::roleEditingCanceled, this, &KStandardItemListWidget::slotRoleEditingCanceled); connect(m_roleEditor, &KItemListRoleEditor::roleEditingFinished, this, &KStandardItemListWidget::slotRoleEditingFinished); - // Adjust the geometry of the editor - QRectF rect = roleEditingRect(current); - const int frameWidth = m_roleEditor->frameWidth(); - rect.adjust(-frameWidth, -frameWidth, frameWidth, frameWidth); - rect.translate(pos()); - if (rect.right() > parent->width()) { - rect.setWidth(parent->width() - rect.left()); - } - m_roleEditor->setGeometry(rect.toRect()); - m_roleEditor->autoAdjustSize(); + updateRoleEditorGeometry(); m_roleEditor->show(); m_roleEditor->setFocus(); setHovered(false); @@ -932,6 +923,13 @@ void KStandardItemListWidget::showEvent(QShowEvent *event) { KItemListWidget::showEvent(event); + if (m_roleEditor) { + m_roleEditor->setFinishedSignalBlocked(false); + updateRoleEditorGeometry(); + m_roleEditor->show(); + m_roleEditor->setFocus(); + } + // Listen to changes of the clipboard to mark the item as cut/uncut KFileItemClipboard *clipboard = KFileItemClipboard::instance(); @@ -943,6 +941,11 @@ void KStandardItemListWidget::showEvent(QShowEvent *event) void KStandardItemListWidget::hideEvent(QHideEvent *event) { + if (m_roleEditor) { + m_roleEditor->setFinishedSignalBlocked(true); + m_roleEditor->hide(); + } + disconnect(KFileItemClipboard::instance(), &KFileItemClipboard::cutItemsChanged, this, &KStandardItemListWidget::slotCutItemsChanged); KItemListWidget::hideEvent(event); @@ -971,6 +974,24 @@ void KStandardItemListWidget::cancelRoleEditing() } } +void KStandardItemListWidget::updateRoleEditorGeometry() +{ + if (!m_roleEditor || editedRole().isEmpty() || !scene() || scene()->views().isEmpty()) { + return; + } + + auto *parent = scene()->views()[0]; + QRectF rect = roleEditingRect(editedRole()); + const int frameWidth = m_roleEditor->frameWidth(); + rect.adjust(-frameWidth, -frameWidth, frameWidth, frameWidth); + rect.translate(pos()); + if (rect.right() > parent->width()) { + rect.setWidth(parent->width() - rect.left()); + } + m_roleEditor->setGeometry(rect.toRect()); + m_roleEditor->autoAdjustSize(); +} + void KStandardItemListWidget::slotCutItemsChanged() { const QUrl itemUrl = data().value("url").toUrl(); -- cgit v1.3