From 2e40aef45245bcc14bef59c4b93998d7ae2b0195 Mon Sep 17 00:00:00 2001 From: Gleb Kasachou Date: Fri, 27 Jun 2025 10:47:21 +0300 Subject: [PATCH] Combine the zoom menu entries into one Line Replaced a KActionMenu that contained separate Zoom In, Zoom Out and Reset Zoom actions with a single QWidgetAction that provides the same functionality using three buttons arranged in a single line. Keyboard shortcuts for the three actions are preserved, and the actions still appear separately in the View submenu in the menubar. --- src/CMakeLists.txt | 2 + src/views/dolphinviewactionhandler.cpp | 12 +- src/views/zoomwidgetaction.cpp | 171 +++++++++++++++++++++++++ src/views/zoomwidgetaction.h | 33 +++++ 4 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 src/views/zoomwidgetaction.cpp create mode 100644 src/views/zoomwidgetaction.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b02a0f76..bf1ed0101 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -117,6 +117,7 @@ target_sources(dolphinprivate PRIVATE views/viewmodecontroller.cpp views/viewproperties.cpp views/zoomlevelinfo.cpp + views/zoomwidgetaction.cpp dolphinremoveaction.cpp middleclickactioneventfilter.cpp dolphinnewfilemenu.cpp @@ -170,6 +171,7 @@ target_sources(dolphinprivate PRIVATE views/viewmodecontroller.h views/viewproperties.h views/zoomlevelinfo.h + views/zoomwidgetaction.h dolphinremoveaction.h middleclickactioneventfilter.h dolphinnewfilemenu.h diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp index ce698a178..e504fd831 100644 --- a/src/views/dolphinviewactionhandler.cpp +++ b/src/views/dolphinviewactionhandler.cpp @@ -12,6 +12,7 @@ #include "selectionmode/actiontexthelper.h" #include "settings/viewpropertiesdialog.h" #include "views/zoomlevelinfo.h" +#include "views/zoomwidgetaction.h" #if HAVE_BALOO #include @@ -251,13 +252,8 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac QAction *zoomOutAction = KStandardAction::zoomOut(this, &DolphinViewActionHandler::zoomOut, m_actionCollection); zoomOutAction->setWhatsThis(i18nc("@info:whatsthis zoom out", "This reduces the icon size.")); - KActionMenu *zoomMenu = m_actionCollection->add(QStringLiteral("zoom")); - zoomMenu->setText(i18nc("@action:inmenu menu of zoom actions", "Zoom")); - zoomMenu->setIcon(QIcon::fromTheme(QStringLiteral("zoom"))); - zoomMenu->setPopupMode(QToolButton::InstantPopup); - zoomMenu->addAction(zoomInAction); - zoomMenu->addAction(zoomResetAction); - zoomMenu->addAction(zoomOutAction); + ZoomWidgetAction *zoomWidgetAction = new ZoomWidgetAction(zoomInAction, zoomResetAction, zoomOutAction, m_actionCollection); + m_actionCollection->addAction(QStringLiteral("zoom"), zoomWidgetAction); KToggleAction *showPreview = m_actionCollection->add(QStringLiteral("show_preview")); showPreview->setText(i18nc("@action:intoolbar", "Show Previews")); @@ -369,7 +365,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac viewSettings->addAction(action); } viewSettings->addSeparator(); - viewSettings->addAction(zoomMenu); + viewSettings->addAction(zoomWidgetAction); viewSettings->addAction(sortByActionMenu); viewSettings->addAction(visibleRolesMenu); viewSettings->addAction(showPreview); diff --git a/src/views/zoomwidgetaction.cpp b/src/views/zoomwidgetaction.cpp new file mode 100644 index 000000000..7bd66e300 --- /dev/null +++ b/src/views/zoomwidgetaction.cpp @@ -0,0 +1,171 @@ +/* + * SPDX-FileCopyrightText: 2025 Gleb Kasachou + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "zoomwidgetaction.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ZoomWidget : public QWidget +{ +public: + ZoomWidget(QWidget *parent) + : QWidget(parent) + { + } + +protected: + void paintEvent(QPaintEvent *event) override + { + Q_UNUSED(event); + + QStylePainter painter(this); + QStyleOptionMenuItem option; + option.initFrom(this); + option.menuHasCheckableItems = true; + option.checkType = QStyleOptionMenuItem::NotCheckable; + option.text = i18nc("@action:inmenu", "Zoom"); + option.icon = QIcon::fromTheme(QStringLiteral("zoom")); + option.reservedShortcutWidth = 0; + option.menuItemType = QStyleOptionMenuItem::Normal; + + option.maxIconWidth = 0; + for (QAction *action : qobject_cast(parent())->actions()) { + if (!action->icon().isNull()) { + option.maxIconWidth = style()->pixelMetric(QStyle::PM_SmallIconSize) + 4; + break; + } + } + + painter.drawControl(QStyle::CE_MenuItem, option); + } +}; + +ZoomWidgetAction::ZoomWidgetAction(QAction *zoomInAction, QAction *zoomResetAction, QAction *zoomOutAction, QObject *parent) + : KToolBarPopupAction(QIcon::fromTheme(QStringLiteral("zoom")), i18nc("@action:intoolbar", "Zoom"), parent) + , m_zoomInAction(zoomInAction) + , m_zoomResetAction(zoomResetAction) + , m_zoomOutAction(zoomOutAction) +{ + // This is a property that KXMLGui reads to determine whether this action + // should be included in the shortcut configuration UI + setProperty("isShortcutConfigurable", false); + setPopupMode(InstantPopup); + popupMenu()->addActions({zoomInAction, zoomResetAction, zoomOutAction}); +} + +bool ZoomWidgetAction::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() != QEvent::KeyPress) { + return false; + } + + QKeyEvent *keyEvent = static_cast(event); + QWidget *widget = qobject_cast(object); + + if (keyEvent->keyCombination() == QKeyCombination(Qt::Modifier::SHIFT, Qt::Key_Backtab) || keyEvent->key() == Qt::Key_Left + || keyEvent->key() == Qt::Key_Up) { + QWidget *previous = widget->previousInFocusChain(); + if (previous == widget->parentWidget() || !qobject_cast(previous)->isEnabled()) { + return false; + } + + previous->setFocus(Qt::BacktabFocusReason); + event->accept(); + return true; + } + + if (keyEvent->keyCombination() == QKeyCombination(Qt::Key_Tab) || keyEvent->key() == Qt::Key_Right || keyEvent->key() == Qt::Key_Down) { + QWidget *next = widget->nextInFocusChain(); + if (next->parentWidget() != widget->parentWidget() || !qobject_cast(next)->isEnabled()) { + return false; + } + + next->setFocus(Qt::TabFocusReason); + event->accept(); + return true; + } + + return false; +} + +QWidget *ZoomWidgetAction::createWidget(QWidget *parent) +{ + if (qobject_cast(parent)) { + return KToolBarPopupAction::createWidget(parent); + } + + ZoomWidget *zoomWidget = new ZoomWidget(parent); + QHBoxLayout *zoomWidgetLayout = new QHBoxLayout; + zoomWidgetLayout->setContentsMargins(0, 0, 0, 0); + zoomWidget->setLayout(zoomWidgetLayout); + zoomWidget->setFocusPolicy(Qt::StrongFocus); + + QSpacerItem *zoomSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + zoomWidgetLayout->addSpacerItem(zoomSpacer); + + int maxButtonSize = parent->style()->pixelMetric(QStyle::PM_ButtonIconSize) + 10; + + QToolButton *zoomOutButton = new QToolButton(zoomWidget); + zoomOutButton->setMaximumSize(maxButtonSize, maxButtonSize); + zoomOutButton->setDefaultAction(m_zoomOutAction); + zoomOutButton->installEventFilter(this); + zoomWidgetLayout->addWidget(zoomOutButton); + zoomWidget->setFocusProxy(zoomOutButton); + + QIcon zoomOutIcon; + QPixmap zoomOutPixmapNormal = m_zoomOutAction->icon().pixmap(zoomOutButton->iconSize(), QIcon::Normal); + QPixmap zoomOutPixmapDisabled = m_zoomOutAction->icon().pixmap(zoomOutButton->iconSize(), QIcon::Disabled); + QPixmap zoomOutPixmapActive = m_zoomOutAction->icon().pixmap(zoomOutButton->iconSize(), QIcon::Active); + zoomOutIcon.addPixmap(zoomOutPixmapNormal, QIcon::Normal); + zoomOutIcon.addPixmap(zoomOutPixmapDisabled, QIcon::Disabled); + zoomOutIcon.addPixmap(zoomOutPixmapActive, QIcon::Active); + zoomOutIcon.addPixmap(zoomOutPixmapNormal, QIcon::Selected); + m_zoomOutAction->setIcon(zoomOutIcon); + + QToolButton *zoomResetButton = new QToolButton(zoomWidget); + zoomResetButton->setMaximumSize(maxButtonSize, maxButtonSize); + zoomResetButton->setDefaultAction(m_zoomResetAction); + zoomResetButton->installEventFilter(this); + zoomWidgetLayout->addWidget(zoomResetButton); + + QIcon zoomResetIcon; + QPixmap zoomResetPixmapNormal = m_zoomResetAction->icon().pixmap(zoomResetButton->iconSize(), QIcon::Normal); + QPixmap zoomResetPixmapDisabled = m_zoomResetAction->icon().pixmap(zoomResetButton->iconSize(), QIcon::Disabled); + QPixmap zoomResetPixmapActive = m_zoomResetAction->icon().pixmap(zoomResetButton->iconSize(), QIcon::Active); + zoomResetIcon.addPixmap(zoomResetPixmapNormal, QIcon::Normal); + zoomResetIcon.addPixmap(zoomResetPixmapDisabled, QIcon::Disabled); + zoomResetIcon.addPixmap(zoomResetPixmapActive, QIcon::Active); + zoomResetIcon.addPixmap(zoomResetPixmapNormal, QIcon::Selected); + m_zoomResetAction->setIcon(zoomResetIcon); + + QToolButton *zoomInButton = new QToolButton(zoomWidget); + zoomInButton->setMaximumSize(maxButtonSize, maxButtonSize); + zoomInButton->setDefaultAction(m_zoomInAction); + zoomInButton->installEventFilter(this); + zoomWidgetLayout->addWidget(zoomInButton); + + QIcon zoomInIcon; + QPixmap zoomInPixmapNormal = m_zoomInAction->icon().pixmap(zoomInButton->iconSize(), QIcon::Normal); + QPixmap zoomInPixmapDisabled = m_zoomInAction->icon().pixmap(zoomInButton->iconSize(), QIcon::Disabled); + QPixmap zoomInPixmapActive = m_zoomInAction->icon().pixmap(zoomInButton->iconSize(), QIcon::Active); + zoomInIcon.addPixmap(zoomInPixmapNormal, QIcon::Normal); + zoomInIcon.addPixmap(zoomInPixmapDisabled, QIcon::Disabled); + zoomInIcon.addPixmap(zoomInPixmapActive, QIcon::Active); + zoomInIcon.addPixmap(zoomInPixmapNormal, QIcon::Selected); + m_zoomInAction->setIcon(zoomInIcon); + + return zoomWidget; +} diff --git a/src/views/zoomwidgetaction.h b/src/views/zoomwidgetaction.h new file mode 100644 index 000000000..b55f5e25c --- /dev/null +++ b/src/views/zoomwidgetaction.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2025 Gleb Kasachou + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ZOOM_WIDGET_ACTION_H +#define ZOOM_WIDGET_ACTION_H + +#include + +/** + * This WidgetAction combines the three zoom actions into one line. + * + * This requires less space, logically groups these actions, and keeps the menu open when the user uses the buttons. + */ + +class ZoomWidgetAction : public KToolBarPopupAction +{ +public: + ZoomWidgetAction(QAction *zoomInAction, QAction *zoomResetAction, QAction *zoomOutAction, QObject *parent); + +protected: + QWidget *createWidget(QWidget *parent) override; + bool eventFilter(QObject *object, QEvent *event) override; + +private: + QAction *m_zoomInAction; + QAction *m_zoomResetAction; + QAction *m_zoomOutAction; +}; + +#endif -- 2.47.3