From d3835d8f50ce19a7579b1b03c665e7a94d288428 Mon Sep 17 00:00:00 2001 From: Serge45 Date: Fri, 7 Aug 2020 17:00:37 +0800 Subject: [PATCH 1/2] feat(ui): add menu button for zoom actions An event filter was also added to prevent pop-up menu closing while zoom in/out actions triggered. --- src/libs/ui/browsertab.cpp | 49 ++++++++++++++++++++++++++++++++++++++ src/libs/ui/browsertab.h | 5 ++++ src/libs/ui/mainwindow.cpp | 13 +++++----- src/libs/ui/mainwindow.ui | 20 +++++++++++++++- 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/libs/ui/browsertab.cpp b/src/libs/ui/browsertab.cpp index 9f618151d..4d6a4013f 100644 --- a/src/libs/ui/browsertab.cpp +++ b/src/libs/ui/browsertab.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -124,6 +125,28 @@ BrowserTab::BrowserTab(QWidget *parent) label->setText(title); }); + m_browserActionButton = new QToolButton(); + m_browserActionButton->setAutoRaise(true); + m_browserActionButton->setText(QStringLiteral("⋮")); + m_browserActionButton->setArrowType(Qt::NoArrow); + m_browserActionButton->setPopupMode(QToolButton::InstantPopup); + + auto browserActionsMenu = new QMenu(m_browserActionButton); + + m_browserZoomInAction = browserActionsMenu->addAction(tr("Zoom In"), [this] () { + m_webControl->zoomIn(); + }); + + m_browserZoomOutAction = browserActionsMenu->addAction(tr("Zoom Out"), [this] () { + m_webControl->zoomOut(); + }); + + m_browserResetZoomAction = browserActionsMenu->addAction(tr("Reset Zoom"), [this] () { + m_webControl->resetZoom(); + }); + + m_browserActionButton->setMenu(browserActionsMenu); + browserActionsMenu->installEventFilter(this); auto toolBarLayout = new QHBoxLayout(); toolBarLayout->setContentsMargins(4, 0, 4, 0); @@ -132,6 +155,7 @@ BrowserTab::BrowserTab(QWidget *parent) toolBarLayout->addWidget(m_backButton); toolBarLayout->addWidget(m_forwardButton); toolBarLayout->addWidget(label, 1); + toolBarLayout->addWidget(m_browserActionButton); auto toolBarFrame = new ToolBarFrame(); toolBarFrame->setLayout(toolBarLayout); @@ -222,3 +246,28 @@ QIcon BrowserTab::docsetIcon(const QUrl &url) const Registry::Docset *docset = Core::Application::instance()->docsetRegistry()->docsetForUrl(url); return docset ? docset->icon() : QIcon(QStringLiteral(":/icons/logo/icon.png")); } + +bool BrowserTab::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_browserActionButton->menu()) { + QAction *triggeredAction = nullptr; + + if (event->type() == QEvent::MouseButtonRelease) { + triggeredAction = m_browserActionButton->menu()->activeAction(); + } else if (event->type() == QEvent::KeyPress) { + const auto *keyEvent = static_cast(event); + + if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { + triggeredAction = m_browserActionButton->menu()->activeAction(); + } + } + + if (triggeredAction + && (triggeredAction == m_browserZoomInAction || triggeredAction == m_browserZoomOutAction)) { + triggeredAction->trigger(); + return true; + } + } + + return false; +} diff --git a/src/libs/ui/browsertab.h b/src/libs/ui/browsertab.h index 540af0419..ec5e3b63d 100644 --- a/src/libs/ui/browsertab.h +++ b/src/libs/ui/browsertab.h @@ -66,12 +66,17 @@ public slots: private: QIcon docsetIcon(const QUrl &url) const; + bool eventFilter(QObject *watched, QEvent *event) override; // Widgets. SearchSidebar *m_searchSidebar = nullptr; Browser::WebControl *m_webControl = nullptr; + QAction *m_browserZoomInAction = nullptr; + QAction *m_browserZoomOutAction = nullptr; + QAction *m_browserResetZoomAction = nullptr; QToolButton *m_backButton = nullptr; QToolButton *m_forwardButton = nullptr; + QToolButton *m_browserActionButton = nullptr; }; } // namespace WidgetUi diff --git a/src/libs/ui/mainwindow.cpp b/src/libs/ui/mainwindow.cpp index 440aaf67f..00a6ab011 100644 --- a/src/libs/ui/mainwindow.cpp +++ b/src/libs/ui/mainwindow.cpp @@ -139,14 +139,15 @@ MainWindow::MainWindow(Core::Application *app, QWidget *parent) connect(shortcut, &QShortcut::activated, this, [this]() { currentTab()->webControl()->back(); }); shortcut = new QShortcut(QKeySequence::Forward, this); connect(shortcut, &QShortcut::activated, this, [this]() { currentTab()->webControl()->forward(); }); - shortcut = new QShortcut(QKeySequence::ZoomIn, this); - connect(shortcut, &QShortcut::activated, this, [this]() { currentTab()->webControl()->zoomIn(); }); shortcut = new QShortcut(QStringLiteral("Ctrl+="), this); connect(shortcut, &QShortcut::activated, this, [this]() { currentTab()->webControl()->zoomIn(); }); - shortcut = new QShortcut(QKeySequence::ZoomOut, this); - connect(shortcut, &QShortcut::activated, this, [this]() { currentTab()->webControl()->zoomOut(); }); - shortcut = new QShortcut(QStringLiteral("Ctrl+0"), this); - connect(shortcut, &QShortcut::activated, this, [this]() { currentTab()->webControl()->resetZoom(); }); + + ui->actionResetZoom->setShortcut(QKeySequence(QStringLiteral("Ctrl+0"))); + ui->actionZoomIn->setShortcut(QKeySequence::ZoomIn); + ui->actionZoomOut->setShortcut(QKeySequence::ZoomOut); + connect(ui->actionResetZoom, &QAction::triggered, this, [this] { currentTab()->webControl()->resetZoom(); }); + connect(ui->actionZoomIn, &QAction::triggered, this, [this] { currentTab()->webControl()->zoomIn(); }); + connect(ui->actionZoomOut, &QAction::triggered, this, [this] { currentTab()->webControl()->zoomOut(); }); // Tools Menu connect(ui->actionDocsets, &QAction::triggered, this, [this]() { diff --git a/src/libs/ui/mainwindow.ui b/src/libs/ui/mainwindow.ui index ed423fbe9..1bd3463c7 100644 --- a/src/libs/ui/mainwindow.ui +++ b/src/libs/ui/mainwindow.ui @@ -65,7 +65,7 @@ 0 0 900 - 20 + 23 @@ -91,6 +91,9 @@ &Edit + + + @@ -180,6 +183,21 @@ &Docsets… + + + Zoon &In + + + + + Zoom &Out + + + + + &Reset Zoom + + From ee6c552a922fdd984553a8435c6510160c756fb8 Mon Sep 17 00:00:00 2001 From: Serge45 Date: Mon, 7 Sep 2020 17:40:47 +0800 Subject: [PATCH 2/2] feat(ui): use QWidgetAction to implement zoom actions A custom QStyleSheet must be applied to BrowserZoomWidget since QMenu does not handle item highlighting of QWidget in QWidgetAction. --- src/libs/browser/webcontrol.cpp | 5 ++ src/libs/browser/webcontrol.h | 1 + src/libs/ui/browsertab.cpp | 54 ++++++++-------- src/libs/ui/browsertab.h | 1 - src/libs/ui/mainwindow.ui | 12 +++- src/libs/ui/widgets/CMakeLists.txt | 1 + src/libs/ui/widgets/browserzoomwidget.cpp | 75 +++++++++++++++++++++++ src/libs/ui/widgets/browserzoomwidget.h | 26 ++++++++ 8 files changed, 141 insertions(+), 34 deletions(-) create mode 100644 src/libs/ui/widgets/browserzoomwidget.cpp create mode 100644 src/libs/ui/widgets/browserzoomwidget.h diff --git a/src/libs/browser/webcontrol.cpp b/src/libs/browser/webcontrol.cpp index 2b1b6e7be..86db53dad 100644 --- a/src/libs/browser/webcontrol.cpp +++ b/src/libs/browser/webcontrol.cpp @@ -73,6 +73,11 @@ int WebControl::zoomLevel() const return m_webView->zoomLevel(); } +int WebControl::zoomLevelPercentage() const +{ + return m_webView->availableZoomLevels().at(zoomLevel()); +} + void WebControl::setZoomLevel(int level) { m_webView->setZoomLevel(level); diff --git a/src/libs/browser/webcontrol.h b/src/libs/browser/webcontrol.h index 87a211a05..309e6ef08 100644 --- a/src/libs/browser/webcontrol.h +++ b/src/libs/browser/webcontrol.h @@ -54,6 +54,7 @@ class WebControl final : public QWidget QByteArray saveHistory() const; int zoomLevel() const; + int zoomLevelPercentage() const; void setZoomLevel(int level); void setJavaScriptEnabled(bool enabled); diff --git a/src/libs/ui/browsertab.cpp b/src/libs/ui/browsertab.cpp index 4d6a4013f..e6e72523d 100644 --- a/src/libs/ui/browsertab.cpp +++ b/src/libs/ui/browsertab.cpp @@ -25,6 +25,7 @@ #include "searchsidebar.h" #include "widgets/layouthelper.h" #include "widgets/toolbarframe.h" +#include "widgets/browserzoomwidget.h" #include #include @@ -37,10 +38,12 @@ #include #include #include +#include #include #include #include #include +#include using namespace Zeal; using namespace Zeal::WidgetUi; @@ -131,22 +134,38 @@ BrowserTab::BrowserTab(QWidget *parent) m_browserActionButton->setArrowType(Qt::NoArrow); m_browserActionButton->setPopupMode(QToolButton::InstantPopup); - auto browserActionsMenu = new QMenu(m_browserActionButton); + auto zoomActionWidget = new BrowserZoomWidget(); - m_browserZoomInAction = browserActionsMenu->addAction(tr("Zoom In"), [this] () { + connect(zoomActionWidget->zoomInButton(), &QPushButton::clicked, [this, zoomActionWidget]() { m_webControl->zoomIn(); + const auto zoomLevel = QString("%1%").arg(m_webControl->zoomLevelPercentage()); + zoomActionWidget->zoomLevelLabel()->setText(zoomLevel); }); - m_browserZoomOutAction = browserActionsMenu->addAction(tr("Zoom Out"), [this] () { + connect(zoomActionWidget->zoomOutButton(), &QPushButton::clicked, [this, zoomActionWidget]() { m_webControl->zoomOut(); + const auto zoomLevel = QString("%1%").arg(m_webControl->zoomLevelPercentage()); + zoomActionWidget->zoomLevelLabel()->setText(zoomLevel); }); - m_browserResetZoomAction = browserActionsMenu->addAction(tr("Reset Zoom"), [this] () { + connect(zoomActionWidget->resetZoomButton(), &QPushButton::clicked, [this, zoomActionWidget]() { m_webControl->resetZoom(); + const auto zoomLevel = QString("%1%").arg(m_webControl->zoomLevelPercentage()); + zoomActionWidget->zoomLevelLabel()->setText(zoomLevel); + }); + + auto zoomWidgetAction = new QWidgetAction(this); + zoomWidgetAction->setDefaultWidget(zoomActionWidget); + + auto browserActionsMenu = new QMenu(m_browserActionButton); + browserActionsMenu->addAction(zoomWidgetAction); + + connect(browserActionsMenu, &QMenu::aboutToShow, [this, zoomActionWidget] () { + const auto zoomLevel = QString("%1%").arg(m_webControl->zoomLevelPercentage()); + zoomActionWidget->zoomLevelLabel()->setText(zoomLevel); }); m_browserActionButton->setMenu(browserActionsMenu); - browserActionsMenu->installEventFilter(this); auto toolBarLayout = new QHBoxLayout(); toolBarLayout->setContentsMargins(4, 0, 4, 0); @@ -246,28 +265,3 @@ QIcon BrowserTab::docsetIcon(const QUrl &url) const Registry::Docset *docset = Core::Application::instance()->docsetRegistry()->docsetForUrl(url); return docset ? docset->icon() : QIcon(QStringLiteral(":/icons/logo/icon.png")); } - -bool BrowserTab::eventFilter(QObject *watched, QEvent *event) -{ - if (watched == m_browserActionButton->menu()) { - QAction *triggeredAction = nullptr; - - if (event->type() == QEvent::MouseButtonRelease) { - triggeredAction = m_browserActionButton->menu()->activeAction(); - } else if (event->type() == QEvent::KeyPress) { - const auto *keyEvent = static_cast(event); - - if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { - triggeredAction = m_browserActionButton->menu()->activeAction(); - } - } - - if (triggeredAction - && (triggeredAction == m_browserZoomInAction || triggeredAction == m_browserZoomOutAction)) { - triggeredAction->trigger(); - return true; - } - } - - return false; -} diff --git a/src/libs/ui/browsertab.h b/src/libs/ui/browsertab.h index ec5e3b63d..ac370a9d1 100644 --- a/src/libs/ui/browsertab.h +++ b/src/libs/ui/browsertab.h @@ -66,7 +66,6 @@ public slots: private: QIcon docsetIcon(const QUrl &url) const; - bool eventFilter(QObject *watched, QEvent *event) override; // Widgets. SearchSidebar *m_searchSidebar = nullptr; diff --git a/src/libs/ui/mainwindow.ui b/src/libs/ui/mainwindow.ui index 1bd3463c7..bb78353f0 100644 --- a/src/libs/ui/mainwindow.ui +++ b/src/libs/ui/mainwindow.ui @@ -90,10 +90,16 @@ &Edit + + + &Zoom + + + + + - - - + diff --git a/src/libs/ui/widgets/CMakeLists.txt b/src/libs/ui/widgets/CMakeLists.txt index 09d12dd0b..0a4865087 100644 --- a/src/libs/ui/widgets/CMakeLists.txt +++ b/src/libs/ui/widgets/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(Widgets STATIC searchedit.cpp shortcutedit.cpp toolbarframe.cpp + browserzoomwidget.cpp ) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) diff --git a/src/libs/ui/widgets/browserzoomwidget.cpp b/src/libs/ui/widgets/browserzoomwidget.cpp new file mode 100644 index 000000000..e227e2f4a --- /dev/null +++ b/src/libs/ui/widgets/browserzoomwidget.cpp @@ -0,0 +1,75 @@ +#include "browserzoomwidget.h" +#include +#include +#include +#include +#include +#include + +BrowserZoomWidget::BrowserZoomWidget(QWidget *parent) +: QWidget(parent) +{ + const auto highlightedBackgroundColor = palette().highlight().color().name(); + const auto highlightedTextColor = palette().highlightedText().color().name(); + const auto styleSheet + = QString("QPushButton:hover { background-color: %1; color: %2; border: none; }").arg(highlightedBackgroundColor) + .arg(highlightedTextColor); + setStyleSheet(styleSheet); + setMouseTracking(true); + auto zoomLabel = new QLabel(tr("Zoom")); + zoomLabel->setMouseTracking(true); + zoomLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + + constexpr int maxButtonWidth = 32; + + m_zoomOutButton = new QPushButton(QStringLiteral("-")); + m_zoomOutButton->setMouseTracking(true); + m_zoomOutButton->setMaximumWidth(maxButtonWidth); + m_zoomOutButton->setToolTip(tr("Zoom out")); + + m_zoomOutButton->setFlat(true); + m_zoomLevelLabel = new QLabel("100%"); + m_zoomLevelLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_zoomLevelLabel->setMouseTracking(true); + m_zoomLevelLabel->setToolTip(tr("Current zoom level")); + + m_zoomInButton = new QPushButton(QStringLiteral("+")); + m_zoomInButton->setFlat(true); + m_zoomInButton->setMouseTracking(true); + m_zoomInButton->setMaximumWidth(maxButtonWidth); + m_zoomInButton->setToolTip(tr("Zoom in")); + + m_resetZoomButton = new QPushButton(QStringLiteral("↻")); + m_resetZoomButton->setFlat(true); + m_resetZoomButton->setMouseTracking(true); + m_resetZoomButton->setMaximumWidth(maxButtonWidth); + m_resetZoomButton->setToolTip(tr("Reset zoom level")); + + auto layout = new QHBoxLayout(this); + layout->setSpacing(2); + layout->addWidget(zoomLabel); + layout->addWidget(m_zoomOutButton); + layout->addWidget(m_zoomLevelLabel); + layout->addWidget(m_zoomInButton); + layout->addWidget(m_resetZoomButton); +} + +QPushButton *BrowserZoomWidget::zoomOutButton() +{ + return m_zoomOutButton; +} + +QPushButton *BrowserZoomWidget::zoomInButton() +{ + return m_zoomInButton; +} + +QPushButton *BrowserZoomWidget::resetZoomButton() +{ + return m_resetZoomButton; +} + +QLabel *BrowserZoomWidget::zoomLevelLabel() +{ + return m_zoomLevelLabel; +} diff --git a/src/libs/ui/widgets/browserzoomwidget.h b/src/libs/ui/widgets/browserzoomwidget.h new file mode 100644 index 000000000..6d65a8352 --- /dev/null +++ b/src/libs/ui/widgets/browserzoomwidget.h @@ -0,0 +1,26 @@ +#ifndef BROWSERZOOMWIDGET_H +#define BROWSERZOOMWIDGET_H + +#include + +class QPushButton; +class QLabel; + +class BrowserZoomWidget : public QWidget +{ + Q_OBJECT +public: + explicit BrowserZoomWidget(QWidget *parent = nullptr); + QPushButton *zoomOutButton(); + QPushButton *zoomInButton(); + QPushButton *resetZoomButton(); + QLabel *zoomLevelLabel(); + +private: + QPushButton *m_zoomOutButton{nullptr}; + QPushButton *m_zoomInButton{nullptr}; + QPushButton *m_resetZoomButton{nullptr}; + QLabel *m_zoomLevelLabel{nullptr}; +}; + +#endif // BROWSERZOOMWIDGETACTION_H