From 0f7a9c681c4f7336362bf8a5d1c41f2bc8ed9215 Mon Sep 17 00:00:00 2001 From: Wagner Soares Date: Thu, 19 Feb 2026 17:57:02 -0300 Subject: viewproperties: Add per-folder zoom Adds ZoomLevel flag to the directory and uses it instead of global settings when globalViewProps is set to false. CCBUG: 169405 --- .../dolphin_directoryviewpropertysettings.kcfg | 6 +++ src/tests/dolphinmainwindowtest.cpp | 44 +++++++++++++++++++ src/views/dolphinitemlistview.cpp | 21 ++++++--- src/views/dolphinitemlistview.h | 2 + src/views/dolphinview.cpp | 50 +++++++++++++++++++--- src/views/dolphinview.h | 8 ++++ src/views/viewproperties.cpp | 15 +++++++ src/views/viewproperties.h | 4 ++ 8 files changed, 139 insertions(+), 11 deletions(-) diff --git a/src/settings/dolphin_directoryviewpropertysettings.kcfg b/src/settings/dolphin_directoryviewpropertysettings.kcfg index bae1f409f..3b23918ef 100644 --- a/src/settings/dolphin_directoryviewpropertysettings.kcfg +++ b/src/settings/dolphin_directoryviewpropertysettings.kcfg @@ -27,6 +27,12 @@ DolphinView::IconsView + + + Zoom level of the folder. + -1 + + When this option is enabled, a preview of the file content is shown as an icon. diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp index f68f07cbc..fd207c09a 100644 --- a/src/tests/dolphinmainwindowtest.cpp +++ b/src/tests/dolphinmainwindowtest.cpp @@ -1144,6 +1144,9 @@ void DolphinMainWindowTest::testViewModeAfterDynamicView() QCOMPARE(view->m_mode, DolphinView::DetailsView); QVERIFY(!ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + // store parent current zoom level + const int parentZoomLevel = view->zoomLevel(); + // go to child folder and make sure view mode change to "Details" is permanent m_mainWindow->openFiles({testDirUrl + "/a"}, false); view->m_model->loadDirectory(QUrl(testDirUrl + "/a")); @@ -1151,6 +1154,47 @@ void DolphinMainWindowTest::testViewModeAfterDynamicView() QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); QCOMPARE(view->m_mode, DolphinView::DetailsView); QVERIFY(ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // still on child, change view zoom level + const int childZoomLevel = view->zoomLevel(); + view->setZoomLevel(childZoomLevel + 2); + + // go back to parent folder and check for zoom level + m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Back))->trigger(); + view->m_model->loadDirectory(testDir->url()); + view->setUrl(testDir->url()); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + QCOMPARE(view->zoomLevel(), parentZoomLevel); + QVERIFY(!ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // go to child and check if zoom level is permanent + m_mainWindow->openFiles({testDirUrl + "/a"}, false); + view->m_model->loadDirectory(QUrl(testDirUrl + "/a")); + view->setUrl(QUrl(testDirUrl + "/a")); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + QCOMPARE(view->zoomLevel(), childZoomLevel + 2); + QVERIFY(ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // test for global views + settings->setGlobalViewProps(true); + settings->save(); + + // go back to parent folder and set zoom level + m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Back))->trigger(); + view->m_model->loadDirectory(testDir->url()); + view->setUrl(testDir->url()); + view->setZoomLevel(parentZoomLevel + 1); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + QTRY_COMPARE_WITH_TIMEOUT(view->zoomLevel(), parentZoomLevel + 1, 400); + QTRY_VERIFY_WITH_TIMEOUT(ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed(), 400); + + // go to child and check if zoom level remains the same + m_mainWindow->openFiles({testDirUrl + "/a"}, false); + view->m_model->loadDirectory(QUrl(testDirUrl + "/a")); + view->setUrl(QUrl(testDirUrl + "/a")); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + QTRY_COMPARE_WITH_TIMEOUT(view->zoomLevel(), parentZoomLevel + 1, 400); + QTRY_VERIFY_WITH_TIMEOUT(ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed(), 400); } void DolphinMainWindowTest::testActivationAndTabTitleAfterRenameOpeningFolder() diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp index f9e710a31..b3ec65eac 100644 --- a/src/views/dolphinitemlistview.cpp +++ b/src/views/dolphinitemlistview.cpp @@ -45,13 +45,22 @@ void DolphinItemListView::setZoomLevel(int level) m_zoomLevel = level; + const bool useGlobalViewProps = GeneralSettings::globalViewProps(); ViewModeSettings settings(itemLayout()); + if (previewsShown()) { - const int previewSize = ZoomLevelInfo::iconSizeForZoomLevel(level); - settings.setPreviewSize(previewSize); + m_previewSize = ZoomLevelInfo::iconSizeForZoomLevel(level); + // Only update the icon size settings if we're using global view props + // to prevent inconsistent state on zoom level changes + if (useGlobalViewProps) { + settings.setPreviewSize(m_previewSize); + } } else { - const int iconSize = ZoomLevelInfo::iconSizeForZoomLevel(level); - settings.setIconSize(iconSize); + // Same as above + m_iconSize = ZoomLevelInfo::iconSizeForZoomLevel(level); + if (useGlobalViewProps) { + settings.setIconSize(m_iconSize); + } } updateGridSize(); @@ -167,9 +176,11 @@ void DolphinItemListView::updateFont() void DolphinItemListView::updateGridSize() { const ViewModeSettings settings(itemLayout()); + const bool useGlobalViewProps = GeneralSettings::globalViewProps(); // Calculate the size of the icon - const int iconSize = previewsShown() ? settings.previewSize() : settings.iconSize(); + // Only use zoom stored in settings if we're using global view props + const int iconSize = useGlobalViewProps ? (previewsShown() ? settings.previewSize() : settings.iconSize()) : (previewsShown() ? m_previewSize : m_iconSize); m_zoomLevel = ZoomLevelInfo::zoomLevelForIconSize(QSize(iconSize, iconSize)); KItemListStyleOption option = styleOption(); diff --git a/src/views/dolphinitemlistview.h b/src/views/dolphinitemlistview.h index 0483c0644..7ac7a4fad 100644 --- a/src/views/dolphinitemlistview.h +++ b/src/views/dolphinitemlistview.h @@ -62,6 +62,8 @@ private: private: int m_zoomLevel; + int m_previewSize = 0; + int m_iconSize = 0; }; #endif diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index b01833d69..b48e1ae74 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -479,9 +479,16 @@ void DolphinView::selectItems(const QRegularExpression ®exp, bool enabled) void DolphinView::setZoomLevel(int level) { + if (m_defaultZoomLevel < 0) { + updateDefaultZoomLevel(); + } + const int oldZoomLevel = zoomLevel(); m_view->setZoomLevel(level); if (zoomLevel() != oldZoomLevel) { + ViewProperties props(viewPropertiesUrl()); + props.setZoomLevel(level == m_defaultZoomLevel ? -1 : level); + hideToolTip(); Q_EMIT zoomLevelChanged(zoomLevel(), oldZoomLevel); } @@ -1798,10 +1805,10 @@ Qt::SortOrder DolphinView::defaultSortOrderForRole(const QByteArray &role) void DolphinView::resetZoomLevel() { - ViewModeSettings settings{m_mode}; - const int userDefaultIconSize = settings.iconSize(); - - setZoomLevel(ZoomLevelInfo::zoomLevelForIconSize(QSize(userDefaultIconSize, userDefaultIconSize))); + if (m_defaultZoomLevel < 0) { + updateDefaultZoomLevel(); + } + setZoomLevel(m_defaultZoomLevel); } void DolphinView::selectFileOnceAvailable(const QUrl &url, const std::function &condition) @@ -2312,11 +2319,16 @@ void DolphinView::applyViewProperties(const ViewProperties &props) { m_view->beginTransaction(); + // Caches old zoom level change for signal emitting + int zoomLevelChangeFrom = -1; + const Mode mode = props.viewMode(); if (m_mode != mode) { const Mode previousMode = m_mode; m_mode = mode; + updateDefaultZoomLevel(); + // Changing the mode might result in changing // the zoom level. Remember the old zoom level so // that zoomLevelChanged() can get emitted. @@ -2326,7 +2338,7 @@ void DolphinView::applyViewProperties(const ViewProperties &props) Q_EMIT modeChanged(m_mode, previousMode); if (m_view->zoomLevel() != oldZoomLevel) { - Q_EMIT zoomLevelChanged(m_view->zoomLevel(), oldZoomLevel); + zoomLevelChangeFrom = oldZoomLevel; } } @@ -2383,10 +2395,28 @@ void DolphinView::applyViewProperties(const ViewProperties &props) // Changing the preview-state might result in a changed zoom-level if (oldZoomLevel != zoomLevel()) { - Q_EMIT zoomLevelChanged(zoomLevel(), oldZoomLevel); + zoomLevelChangeFrom = oldZoomLevel; } } + // Only check for folder zoom changes if we're using local view props + if (!GeneralSettings::globalViewProps()) { + const int propZoomLevel = props.zoomLevel(); + if (m_defaultZoomLevel < 0) { + updateDefaultZoomLevel(); + } + + const int nextZoomLevel = propZoomLevel < 0 ? m_defaultZoomLevel : propZoomLevel; + if (nextZoomLevel != m_view->zoomLevel()) { + zoomLevelChangeFrom = m_view->zoomLevel(); + m_view->setZoomLevel(nextZoomLevel); + } + } + + if (zoomLevelChangeFrom > -1) { + Q_EMIT zoomLevelChanged(m_view->zoomLevel(), zoomLevelChangeFrom); + } + KItemListView *itemListView = m_container->controller()->view(); if (itemListView->isHeaderVisible()) { KItemListHeader *header = itemListView->header(); @@ -2409,6 +2439,14 @@ void DolphinView::applyViewProperties(const ViewProperties &props) m_view->endTransaction(); } +void DolphinView::updateDefaultZoomLevel() +{ + ViewModeSettings settings{m_mode}; + const int userDefaultIconSize = settings.iconSize(); + + m_defaultZoomLevel = ZoomLevelInfo::zoomLevelForIconSize(QSize(userDefaultIconSize, userDefaultIconSize)); +} + void DolphinView::applyModeToView() { switch (m_mode) { diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index e3f83979c..67233b668 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -790,6 +790,11 @@ private Q_SLOTS: */ void updateSortFoldersFirst(bool foldersFirst); + /** + * Cache out zoom mode changes to prevent constant Settings requests + */ + void updateDefaultZoomLevel(); + /** * Updates the view properties of the current URL to the * sorting of hidden files given by \a hiddenLast. @@ -1007,6 +1012,9 @@ private: // resolution scroll wheels) int m_controlWheelAccumulatedDelta; + // Cached out default zoom level after view mode changes + int m_defaultZoomLevel = -1; + QList m_selectedUrls; // Used for making the view to remember selections after F5 and file operations bool m_clearSelectionBeforeSelectingNewItems; bool m_markFirstNewlySelectedItemAsCurrent; diff --git a/src/views/viewproperties.cpp b/src/views/viewproperties.cpp index 03ab2bd58..3d33a805b 100644 --- a/src/views/viewproperties.cpp +++ b/src/views/viewproperties.cpp @@ -229,6 +229,7 @@ ViewProperties::ViewProperties(const QUrl &url) } else { m_changedProps = false; } + setZoomLevel(-1); } if (m_node->version() < CurrentViewPropertiesVersion) { @@ -269,6 +270,19 @@ ViewProperties::~ViewProperties() m_node = nullptr; } +void ViewProperties::setZoomLevel(int zoomLevel) +{ + if (m_node->zoomLevel() != zoomLevel) { + m_node->setZoomLevel(zoomLevel); + update(); + } +} + +int ViewProperties::zoomLevel() const +{ + return m_node->zoomLevel(); +} + void ViewProperties::setViewMode(DolphinView::Mode mode) { if (m_node->viewMode() != mode) { @@ -487,6 +501,7 @@ QList ViewProperties::headerColumnWidths() const void ViewProperties::setDirProperties(const ViewProperties &props) { setViewMode(props.viewMode()); + setZoomLevel(props.zoomLevel()); setPreviewsShown(props.previewsShown()); setHiddenFilesShown(props.hiddenFilesShown()); setGroupedSorting(props.groupedSorting()); diff --git a/src/views/viewproperties.h b/src/views/viewproperties.h index bee1e7330..622a1c87e 100644 --- a/src/views/viewproperties.h +++ b/src/views/viewproperties.h @@ -44,6 +44,10 @@ public: void setViewMode(DolphinView::Mode mode); DolphinView::Mode viewMode() const; + void setZoomLevel(int zoomLevel); + /// -1 is the default zoom + int zoomLevel() const; + void setPreviewsShown(bool show); bool previewsShown() const; -- cgit v1.3