From c4b95a7798e2fb5930cc0a286457aa44f6f7e37b Mon Sep 17 00:00:00 2001 From: Heiko Becker Date: Sat, 7 Oct 2023 17:15:48 +0200 Subject: GIT_SILENT Update Appstream for new release (cherry picked from commit 825804a8a6d45df62db7665b021b65b99cb28856) --- src/org.kde.dolphin.appdata.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/org.kde.dolphin.appdata.xml b/src/org.kde.dolphin.appdata.xml index 83840d35f..f04032497 100644 --- a/src/org.kde.dolphin.appdata.xml +++ b/src/org.kde.dolphin.appdata.xml @@ -494,10 +494,10 @@ dolphin + - -- cgit v1.3 From 2f39eb51b6d92172905a4c39f3c1bcd8053f593b Mon Sep 17 00:00:00 2001 From: Amol Godbole Date: Tue, 10 Oct 2023 22:39:03 -0500 Subject: DolphinView: get rid of writeStateChanged signal in setActive() The signal writeStateChanged() was not working because it is not connected to slotWriteStateChanged() slots when the active view changes. Replace the signal with direct calls to the slots. Also, do not delay openRequest signal in DolphinSearchBox::slotSearchTextChanged. It's no longer required. BUG: 440366 --- src/dolphinmainwindow.cpp | 1 + src/search/dolphinsearchbox.cpp | 4 +--- src/views/dolphinview.cpp | 6 +++++- src/views/dolphinview.h | 7 ++++++- src/views/dolphinviewactionhandler.cpp | 1 + 5 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 744ad8f0a..ca0038586 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -2387,6 +2387,7 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer *container) { connect(container, &DolphinViewContainer::showFilterBarChanged, this, &DolphinMainWindow::updateFilterBarAction); connect(container, &DolphinViewContainer::writeStateChanged, this, &DolphinMainWindow::slotWriteStateChanged); + slotWriteStateChanged(container->view()->isFolderWritable()); connect(container, &DolphinViewContainer::searchModeEnabledChanged, this, &DolphinMainWindow::updateSearchAction); connect(container, &DolphinViewContainer::captionChanged, this, &DolphinMainWindow::updateWindowTitle); connect(container, &DolphinViewContainer::tabRequested, this, &DolphinMainWindow::openNewTab); diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index a09f25293..a3cec6fe7 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -265,9 +265,7 @@ void DolphinSearchBox::slotSearchTextChanged(const QString &text) if (text.isEmpty()) { // Restore URL when search box is cleared by closing and reopening the box. emitCloseRequest(); - QTimer::singleShot(0, this, [this] { - Q_EMIT openRequest(); - }); + Q_EMIT openRequest(); } else { m_startSearchTimer->start(); } diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index d8eab142d..ace763b15 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -270,7 +270,6 @@ void DolphinView::setActive(bool active) if (active) { m_container->setFocus(); Q_EMIT activated(); - Q_EMIT writeStateChanged(m_isFolderWritable); } } @@ -2246,6 +2245,11 @@ void DolphinView::updateWritableState() } } +bool DolphinView::isFolderWritable() const +{ + return m_isFolderWritable; +} + QUrl DolphinView::viewPropertiesUrl() const { if (m_viewPropertiesContext.isEmpty()) { diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index 05b9e009c..0b0c83487 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -344,6 +344,11 @@ public: /** Activates the view if the item list container gets focus. */ bool eventFilter(QObject *watched, QEvent *event) override; + /** + * Returns whether the folder represented by the current URL is writable. + */ + bool isFolderWritable() const; + public Q_SLOTS: void reload(); @@ -880,7 +885,7 @@ private: /** * Updates m_isFolderWritable dependent on whether the folder represented by * the current URL is writable. If the state has changed, the signal - * writeableStateChanged() will be emitted. + * writeStateChanged() will be emitted. */ void updateWritableState(); diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp index 7117e9e1b..f73c613e0 100644 --- a/src/views/dolphinviewactionhandler.cpp +++ b/src/views/dolphinviewactionhandler.cpp @@ -60,6 +60,7 @@ void DolphinViewActionHandler::setCurrentView(DolphinView *view) connect(view, &DolphinView::sortRoleChanged, this, &DolphinViewActionHandler::slotSortRoleChanged); connect(view, &DolphinView::zoomLevelChanged, this, &DolphinViewActionHandler::slotZoomLevelChanged); connect(view, &DolphinView::writeStateChanged, this, &DolphinViewActionHandler::slotWriteStateChanged); + slotWriteStateChanged(view->isFolderWritable()); connect(view, &DolphinView::selectionModeChangeRequested, this, [this](bool enabled) { Q_EMIT selectionModeChangeTriggered(enabled); }); -- cgit v1.3 From a59d9f85fa770a00d10e66025e102c736e18fa70 Mon Sep 17 00:00:00 2001 From: Amol Godbole Date: Fri, 13 Oct 2023 21:08:35 -0500 Subject: KItemListView: add view position in scrollToItem() An item, on being scrolled to, is always located at the nearest edge of the view. This is not always convenient. Allow specifying where the item should be positioned with respect to the view in scrollToItem(). BUG: 423884 --- src/kitemviews/kitemlistcontroller.cpp | 2 +- src/kitemviews/kitemlistview.cpp | 60 +++++++++++++++++++++++++++------- src/kitemviews/kitemlistview.h | 8 +++-- src/views/dolphinview.cpp | 2 +- 4 files changed, 56 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index be7a63e09..0016bb22a 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -539,7 +539,7 @@ void KItemListController::slotChangeCurrentItem(const QString &text, bool search m_selectionManager->beginAnchoredSelection(index); } - m_view->scrollToItem(index); + m_view->scrollToItem(index, KItemListView::ViewItemPosition::Beginning); } } diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 457c02ec5..be22b91cc 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -537,7 +537,7 @@ bool KItemListView::isElided(int index) const return m_sizeHintResolver->isElided(index); } -void KItemListView::scrollToItem(int index) +void KItemListView::scrollToItem(int index, ViewItemPosition viewItemPosition) { QRectF viewGeometry = geometry(); if (m_headerWidget->isVisible()) { @@ -546,29 +546,65 @@ void KItemListView::scrollToItem(int index) } QRectF currentRect = itemRect(index); - // Fix for Bug 311099 - View the underscore when using Ctrl + PagDown + // Fix for Bug 311099 - View the underscore when using Ctrl + PageDown currentRect.adjust(-m_styleOption.horizontalMargin, -m_styleOption.verticalMargin, m_styleOption.horizontalMargin, m_styleOption.verticalMargin); - if (!viewGeometry.contains(currentRect)) { - qreal newOffset = scrollOffset(); - if (scrollOrientation() == Qt::Vertical) { + qreal newOffset = scrollOffset(); + if (scrollOrientation() == Qt::Vertical && (currentRect.top() < viewGeometry.top() || currentRect.bottom() > viewGeometry.bottom())) { + switch (viewItemPosition) { + case Beginning: + newOffset += currentRect.top() - viewGeometry.top(); + break; + case Middle: + newOffset += 0.5 * (currentRect.top() + currentRect.bottom() - (viewGeometry.top() + viewGeometry.bottom())); + break; + case End: + newOffset += currentRect.bottom() - viewGeometry.bottom(); + break; + case Nearest: if (currentRect.top() < viewGeometry.top()) { newOffset += currentRect.top() - viewGeometry.top(); - } else if (currentRect.bottom() > viewGeometry.bottom()) { + } else { newOffset += currentRect.bottom() - viewGeometry.bottom(); } - } else { + break; + default: + Q_UNREACHABLE(); + } + } else if (scrollOrientation() == Qt::Horizontal && (currentRect.left() < viewGeometry.left() || currentRect.right() > viewGeometry.right())) { + switch (viewItemPosition) { + case Beginning: + if (layoutDirection() == Qt::RightToLeft) { + newOffset += currentRect.right() - viewGeometry.right(); + } else { + newOffset += currentRect.left() - viewGeometry.left(); + } + break; + case Middle: + newOffset += 0.5 * (currentRect.left() + currentRect.right() - (viewGeometry.left() + viewGeometry.right())); + break; + case End: + if (layoutDirection() == Qt::RightToLeft) { + newOffset += currentRect.left() - viewGeometry.left(); + } else { + newOffset += currentRect.right() - viewGeometry.right(); + } + break; + case Nearest: if (currentRect.left() < viewGeometry.left()) { newOffset += currentRect.left() - viewGeometry.left(); - } else if (currentRect.right() > viewGeometry.right()) { + } else { newOffset += currentRect.right() - viewGeometry.right(); } + break; + default: + Q_UNREACHABLE(); } + } - if (newOffset != scrollOffset()) { - Q_EMIT scrollTo(newOffset); - return; - } + if (newOffset != scrollOffset()) { + Q_EMIT scrollTo(newOffset); + return; } Q_EMIT scrollingStopped(); diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 7bcaec704..8812eb8cc 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -59,6 +59,9 @@ class DOLPHIN_EXPORT KItemListView : public QGraphicsWidget Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset NOTIFY itemOffsetChanged) public: + /** The position in the view to which an item should be scrolled to. */ + enum ViewItemPosition { Beginning, Middle, End, Nearest }; + explicit KItemListView(QGraphicsWidget *parent = nullptr); ~KItemListView() override; @@ -251,9 +254,10 @@ public: /** * Scrolls to the item with the index \a index so that the item - * will be fully visible. + * will be fully visible. The item is positioned within the view + * as specified by \a viewItemPosition. */ - void scrollToItem(int index); + void scrollToItem(int index, ViewItemPosition viewItemPosition = ViewItemPosition::Nearest); /** * If several properties of KItemListView are changed synchronously, it is diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index ace763b15..0a1d70bf1 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -1761,7 +1761,7 @@ void DolphinView::updateViewState() // scroll to current item and reset the state if (m_scrollToCurrentItem) { - m_view->scrollToItem(currentIndex); + m_view->scrollToItem(currentIndex, KItemListView::ViewItemPosition::Middle); m_scrollToCurrentItem = false; } m_currentItemUrl = QUrl(); -- cgit v1.3 From f38d788a97fe195e3257bccdd351162bd14c1ac9 Mon Sep 17 00:00:00 2001 From: Felix Ernst Date: Mon, 16 Oct 2023 16:50:07 +0200 Subject: Never show status bar context menu away from status bar The status bar context menu was hard-coded to always appear at the cursor position. However, context menus can also be triggered by keyboard, for example with the Menu key, in which case it makes no sense to show the context menu at whatever random position the mouse cursor currently is. Instead invoke the context menu in the middle of the status bar when it is opened by keyboard. --- src/statusbar/dolphinstatusbar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/statusbar/dolphinstatusbar.cpp b/src/statusbar/dolphinstatusbar.cpp index 9c101b3fa..9830960dc 100644 --- a/src/statusbar/dolphinstatusbar.cpp +++ b/src/statusbar/dolphinstatusbar.cpp @@ -269,7 +269,7 @@ void DolphinStatusBar::contextMenuEvent(QContextMenuEvent *event) showSpaceInfoAction->setCheckable(true); showSpaceInfoAction->setChecked(GeneralSettings::showSpaceInfo()); - const QAction *action = menu.exec(QCursor::pos()); + const QAction *action = menu.exec(event->reason() == QContextMenuEvent::Reason::Mouse ? QCursor::pos() : mapToGlobal(QPoint(width() / 2, height() / 2))); if (action == showZoomSliderAction) { const bool visible = showZoomSliderAction->isChecked(); GeneralSettings::setShowZoomSlider(visible); -- cgit v1.3 From 5c7887a763ea1a58ebcf93c047ab39b00eb6a8eb Mon Sep 17 00:00:00 2001 From: Felix Ernst Date: Mon, 23 Oct 2023 14:26:52 +0000 Subject: Fix rubberband selection on icon in icon view mode As an unintended side-effect of d9a18b04ea0b1b4e427f45083fdc0cdec87cbbfd items would no longer be selected in icon view mode when the selection rectangle intersected with the item's icon. This commit fixes this. --- src/kitemviews/kitemlistcontroller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 0016bb22a..5abf1830b 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -1299,7 +1299,8 @@ void KItemListController::slotRubberBandChanged() if (widgetRect.intersects(rubberBandRect)) { // Select the full row intersecting with the rubberband rectangle const QRectF selectionRect = widget->selectionRect().translated(widgetRect.topLeft()); - if (selectionRect.intersects(rubberBandRect)) { + const QRectF iconRect = widget->iconRect().translated(widgetRect.topLeft()); + if (selectionRect.intersects(rubberBandRect) || iconRect.intersects(rubberBandRect)) { selectedItems.insert(index); } } -- cgit v1.3 From 8ef3c7bc42bad4397bed0711f4317ebad9c0f8f1 Mon Sep 17 00:00:00 2001 From: Yifan Zhu Date: Sun, 22 Oct 2023 11:54:51 -0700 Subject: Display newline in filename as Unicode line break BUG: 422998 CCBUG: 444747 --- src/kitemviews/kstandarditemlistwidget.cpp | 15 +++++++++++++-- src/kitemviews/kstandarditemlistwidget.h | 7 +++++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 01b135038..0088e4116 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -1205,6 +1205,16 @@ QString KStandardItemListWidget::elideRightKeepExtension(const QString &text, in return m_customizedFontMetrics.elidedText(text, Qt::ElideRight, elidingWidth); } +QString KStandardItemListWidget::escapeString(const QString &text) const +{ + QString escaped(text); + + const QChar returnSymbol(0x21b5); + escaped.replace('\n', returnSymbol); + + return escaped; +} + void KStandardItemListWidget::updateIconsLayoutTextCache() { // +------+ @@ -1227,7 +1237,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() // Initialize properties for the "text" role. It will be used as anchor // for initializing the position of the other roles. TextInfo *nameTextInfo = m_textInfo.value("text"); - const QString nameText = KStringHandler::preProcessWrap(values["text"].toString()); + const QString nameText = KStringHandler::preProcessWrap(escapeString(values["text"].toString())); nameTextInfo->staticText.setText(nameText); // Calculate the number of lines required for the name and the required width @@ -1348,7 +1358,7 @@ void KStandardItemListWidget::updateCompactLayoutTextCache() qreal y = qRound((widgetHeight - textLinesHeight) / 2); const qreal maxWidth = size().width() - x - option.padding; for (const QByteArray &role : qAsConst(m_sortedVisibleRoles)) { - const QString text = roleText(role, values); + const QString text = escapeString(roleText(role, values)); TextInfo *textInfo = m_textInfo.value(role); textInfo->staticText.setText(text); @@ -1407,6 +1417,7 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache() const bool isTextRole = (role == "text"); if (isTextRole) { + text = escapeString(text); availableTextWidth -= firstColumnInc - sidePadding(); } diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index c4f80af1d..52cde1423 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -208,6 +208,13 @@ private: QString elideRightKeepExtension(const QString &text, int elidingWidth) const; + /** + * Escapes text for display purposes. + * + * Replaces '\n' with Unicode line break (U+21B5). + */ + QString escapeString(const QString &text) const; + /** * Closes the role editor and returns the focus back * to the KItemListContainer. -- cgit v1.3 From ef59e42c40df5e873a1a1b6c2173d5b55641a783 Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Thu, 19 Oct 2023 00:58:15 +0200 Subject: Process correct model when applying service menu changes The listview's model is a filter model, we must iterate through the source, otherwise we get incorrect results BUG: 475547 --- src/settings/contextmenu/contextmenusettingspage.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/settings/contextmenu/contextmenusettingspage.cpp b/src/settings/contextmenu/contextmenusettingspage.cpp index 23ddfba31..c81078095 100644 --- a/src/settings/contextmenu/contextmenusettingspage.cpp +++ b/src/settings/contextmenu/contextmenusettingspage.cpp @@ -176,15 +176,14 @@ void ContextMenuSettingsPage::applySettings() QStringList enabledPlugins; - const QAbstractItemModel *model = m_listView->model(); - for (int i = 0; i < model->rowCount(); ++i) { - const QModelIndex index = model->index(i, 0); - const QString service = model->data(index, ServiceModel::DesktopEntryNameRole).toString(); - const bool checked = model->data(index, Qt::CheckStateRole).toBool(); + for (int i = 0; i < m_serviceModel->rowCount(); ++i) { + const QModelIndex index = m_serviceModel->index(i, 0); + const QString service = m_serviceModel->data(index, ServiceModel::DesktopEntryNameRole).toString(); + const bool checked = m_serviceModel->data(index, Qt::CheckStateRole).toBool(); if (service.startsWith(VersionControlServicePrefix)) { if (checked) { - enabledPlugins.append(model->data(index, Qt::DisplayRole).toString()); + enabledPlugins.append(m_serviceModel->data(index, Qt::DisplayRole).toString()); } } else if (service == QLatin1String(DeleteService)) { KSharedConfig::Ptr globalConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::NoGlobals); @@ -229,14 +228,13 @@ void ContextMenuSettingsPage::applySettings() void ContextMenuSettingsPage::restoreDefaults() { - QAbstractItemModel *model = m_listView->model(); - for (int i = 0; i < model->rowCount(); ++i) { - const QModelIndex index = model->index(i, 0); - const QString service = model->data(index, ServiceModel::DesktopEntryNameRole).toString(); + for (int i = 0; i < m_serviceModel->rowCount(); ++i) { + const QModelIndex index = m_serviceModel->index(i, 0); + const QString service = m_serviceModel->data(index, ServiceModel::DesktopEntryNameRole).toString(); const bool checked = !service.startsWith(VersionControlServicePrefix) && service != QLatin1String(DeleteService) && service != QLatin1String(CopyToMoveToService); - model->setData(index, checked, Qt::CheckStateRole); + m_serviceModel->setData(index, checked, Qt::CheckStateRole); } } -- cgit v1.3