From ed8dfe7e0d48f7b161eea3a66f4fceb17f1c2ba2 Mon Sep 17 00:00:00 2001 From: Alexander Sashnov Date: Tue, 24 Aug 2021 00:48:36 +0700 Subject: [PATCH] Closes #3: Back/Forward buttons now have menus with history items --- resources/css/style.css | 35 ++++++++++++----- src/kiwixapp.h | 1 - src/mainwindow.cpp | 3 ++ src/searchbar.cpp | 1 + src/topwidget.cpp | 36 +++++++++++++++++ src/topwidget.h | 14 +++++-- src/webview.cpp | 87 ++++++++++++++++++++++++++++++++++++++++- src/webview.h | 30 ++++++++++++++ src/zimview.h | 2 +- 9 files changed, 192 insertions(+), 17 deletions(-) diff --git a/resources/css/style.css b/resources/css/style.css index 74eb2ff..b511e49 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -50,10 +50,6 @@ SearchBar > QPushButton { width: 32px; } -/* ---------------------------------------- - Menu -*/ - TopWidget QToolButton:pressed, TopWidget QToolButton::hover { border: 1px solid #3366CC; @@ -70,18 +66,26 @@ TopWidget QToolButton::menu-arrow { image: none; } -TopWidget QToolButton#leftHistoryButton { - margin-left: 4px; +TopWidget QToolButton::menu-indicator { + width: 0px; /* it can be hidden at all by setting 0px */ + height: 0px; + subcontrol-origin: padding; } -TopWidget QToolButton#rightHistoryButton { - margin-right: 4px; +TopWidget QToolButton#backButton { + margin-left: 6px; /* see also: void WebViewBackMenu::showEvent(QShowEvent *) { geo.setX(geo.x() + 6); } */ } TopWidget QToolButton#fullScreenButton { margin-right: 6px; } + + +/* ---------------------------------------- + Menu +*/ + QMenu { border: none; min-width: 320px; @@ -92,7 +96,7 @@ QMenu::item { min-height: 40px; max-height: 40px; border: 1px solid transparent; - padding: 2px 12px 2px 40px; + padding: 2px 12px 2px 40px; /* top right bottom left */ } QMenu::icon { @@ -105,12 +109,23 @@ QMenu::item:selected { border: 1px solid #3366CC; } -QMenu::indicator { + +MainMenu::indicator { color: #666666; width: 13px; height: 13px; } +WebViewForwardMenu::item, WebViewBackMenu::item { + padding: 2px 12px; +} + +WebViewForwardMenu::icon, WebViewBackMenu::icon { + min-width: 2px; + min-height: 2px; +} + + /* ----------------------------------------- TabWidget */ diff --git a/src/kiwixapp.h b/src/kiwixapp.h index 098e79a..9e8d14f 100644 --- a/src/kiwixapp.h +++ b/src/kiwixapp.h @@ -6,7 +6,6 @@ #include "mainwindow.h" #include "kiwix/downloader.h" #include -#include "tabbar.h" #include "kprofile.h" #include "urlschemehandler.h" #include "settingsmanager.h" diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 03c2a58..e94bc2b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -49,6 +49,9 @@ MainWindow::MainWindow(QWidget *parent) : } QWindowsWindowFunctions::setHasBorderInFullScreen(window, true); #endif + + connect(mp_ui->tabBar, &QTabBar::currentChanged, + mp_ui->mainToolBar, &TopWidget::updateBackForwardButtons); } MainWindow::~MainWindow() diff --git a/src/searchbar.cpp b/src/searchbar.cpp index f7f76e3..b3213aa 100644 --- a/src/searchbar.cpp +++ b/src/searchbar.cpp @@ -90,6 +90,7 @@ SearchBar::SearchBar(QWidget *parent) : }); connect(this, &QLineEdit::textChanged, this, [=](const QString &text) { + Q_UNUSED(text) if (m_returnPressed) { this->setText(m_searchbarInput); } diff --git a/src/topwidget.cpp b/src/topwidget.cpp index 5692ba9..3249a7e 100644 --- a/src/topwidget.cpp +++ b/src/topwidget.cpp @@ -3,9 +3,11 @@ #include "kconstants.h" #include "kiwixapp.h" #include "mainmenu.h" +#include "tabbar.h" #include #include +#include TopWidget::TopWidget(QWidget *parent) : QToolBar(parent) @@ -51,6 +53,10 @@ TopWidget::TopWidget(QWidget *parent) : addAction(menuAction); setContextMenuPolicy( Qt::PreventContextMenu ); + // This signal emited more often than the history really updated + // but for now we have no better signal for it. + connect(KiwixApp::instance(), &KiwixApp::currentTitleChanged, + this, &TopWidget::updateBackForwardButtons); #if !SYSTEMTITLEBAR addAction(QIcon(":/icons/minimize.svg"), "minimize", parent, SLOT(showMinimized())); @@ -102,3 +108,33 @@ void TopWidget::mouseMoveEvent(QMouseEvent *event) { parentWidget()->move(delta); event->accept(); } + +QToolButton* TopWidget::getBackButton() const +{ + auto app = KiwixApp::instance(); + QAction *back = app->getAction(KiwixApp::HistoryBackAction); + return qobject_cast(widgetForAction(back)); +} + +QToolButton* TopWidget::getForwardButton() const +{ + auto app = KiwixApp::instance(); + QAction *forward = app->getAction(KiwixApp::HistoryForwardAction); + return qobject_cast(widgetForAction(forward)); +} + +void TopWidget::updateBackForwardButtons() +{ + WebView *webview = KiwixApp::instance()->getTabWidget()->currentWebView(); + + if (webview) { + back_menu.reset(webview->getHistoryBackMenu()); + forward_menu.reset(webview->getHistoryForwardMenu()); + } else { + back_menu.reset(); + forward_menu.reset(); + } + + getBackButton()->setMenu(back_menu.data()); + getForwardButton()->setMenu(forward_menu.data()); +} diff --git a/src/topwidget.h b/src/topwidget.h index d2cb912..e4a6f41 100644 --- a/src/topwidget.h +++ b/src/topwidget.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "searchbar.h" @@ -15,19 +16,24 @@ public: virtual ~TopWidget(); SearchBar &getSearchBar() { return m_searchEntry; }; + +public slots: + void handleWebActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled); + void updateBackForwardButtons(); + protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); private: SearchBar m_searchEntry; - QAction* mp_historyBackAction; - QAction* mp_historyForwardAction; QPoint m_cursorPos; ulong m_timestamp; + QScopedPointer back_menu; + QScopedPointer forward_menu; -public slots: - void handleWebActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled); + QToolButton* getBackButton() const; + QToolButton* getForwardButton() const; }; #endif // TOPWIDGET_H diff --git a/src/webview.cpp b/src/webview.cpp index 4f5493e..e546ee6 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -1,15 +1,46 @@ #include "webview.h" #include -#include #include #include #include "kiwixapp.h" #include "webpage.h" #include #include +#include #include + +void WebViewBackMenu::showEvent(QShowEvent *) +{ + /* In Qt 5.12 CSS options for shifting this menu didn't work. + * In particular: + * - toolbar->setContentsMargins(0,0,0,0); + * - toolbar->layout()->setContentsMargins(0,0,0,0); + * - QToolBar { padding-left: } + * - QToolBar { margin-left; } + * - QToolBar { padding: 5px 12px 5px 12px; } + * - QToolBar::separator:first { width: 10px; } + * (that was attempts to set some spacing on left and right in toolbar + * so back button will be shifted right. + * If in Qt 6.x QToolButton shows its menu in the right position + * this code can be removed. + */ + + QRect geo = geometry(); + geo.moveLeft(geo.left() + 6); // see also: style.css: QToolButton#backButton { margin-left: 6px; } + geo.moveTop(geo.top() + 2); + setGeometry(geo); +} + +void WebViewForwardMenu::showEvent(QShowEvent *) +{ + QRect geo = geometry(); + geo.moveTop(geo.top() + 2); + setGeometry(geo); +} + + WebView::WebView(QWidget *parent) : QWebEngineView(parent) { @@ -28,6 +59,60 @@ bool WebView::isWebActionEnabled(QWebEnginePage::WebAction webAction) const return page()->action(webAction)->isEnabled(); } +QMenu* WebView::getHistoryBackMenu() const +{ + QWebEngineHistory *h = history(); + + const int cur = h->currentItemIndex(); + if (cur <= 0) { + return Q_NULLPTR; + } + + auto ret = new WebViewBackMenu(); + for (int i = cur - 1 ; i >= 0 ; i--) { + addHistoryItemAction(ret, h->itemAt(i), i); + } + return ret; +} + +QMenu* WebView::getHistoryForwardMenu() const +{ + QWebEngineHistory *h = history(); + + const int cur = h->currentItemIndex(); + if (cur + 1 >= h->count()) { + return Q_NULLPTR; + } + + auto ret = new WebViewForwardMenu(); + for (int i = cur + 1 ; i < h->count() ; i++) { + addHistoryItemAction(ret, h->itemAt(i), i); + } + return ret; +} + +void WebView::addHistoryItemAction(QMenu *menu, const QWebEngineHistoryItem &item, int n) const +{ + QAction *a = menu->addAction(item.title()); + a->setData(QVariant::fromValue(n)); + connect(a, &QAction::triggered, this, &WebView::gotoTriggeredHistoryItemAction); +} + +void WebView::gotoTriggeredHistoryItemAction() +{ + QAction *a = qobject_cast(QObject::sender()); + if (!a) + return; + + int n = a->data().toInt(); + QWebEngineHistory *h = history(); + if (n < 0 || n >= h->count()) + return; + + h->goToItem(h->itemAt(n)); +} + + QWebEngineView* WebView::createWindow(QWebEnginePage::WebWindowType type) { if ( type==QWebEnginePage::WebBrowserBackgroundTab diff --git a/src/webview.h b/src/webview.h index 20f7109..fdde56c 100644 --- a/src/webview.h +++ b/src/webview.h @@ -4,10 +4,31 @@ #include #include #include +#include #include #include "findinpagebar.h" +class QWebEngineHistoryItem; + + +class WebViewBackMenu : public QMenu +{ + Q_OBJECT +public: + WebViewBackMenu(QWidget* parent=nullptr) : QMenu(parent) {} + void showEvent(QShowEvent *); +}; + +class WebViewForwardMenu : public QMenu +{ + Q_OBJECT +public: + WebViewForwardMenu(QWidget* parent=nullptr) : QMenu(parent) {} + void showEvent(QShowEvent *); +}; + + class WebView : public QWebEngineView { Q_OBJECT @@ -22,6 +43,9 @@ public: const QIcon &icon() { return m_icon; } const QString &zimId() { return m_currentZimId; } + QMenu* getHistoryBackMenu() const; + QMenu* getHistoryForwardMenu() const; + public slots: void onUrlChanged(const QUrl& url); @@ -39,6 +63,12 @@ protected: QString m_currentZimId; QIcon m_icon; QString m_linkHovered; + +private slots: + void gotoTriggeredHistoryItemAction(); + +private: + void addHistoryItemAction(QMenu *menu, const QWebEngineHistoryItem &item, int n) const; }; #endif // WEBVIEW_H diff --git a/src/zimview.h b/src/zimview.h index e369ed8..c6e88bc 100644 --- a/src/zimview.h +++ b/src/zimview.h @@ -2,10 +2,10 @@ #define ZIMVIEW_H #include -#include "webview.h" #include "findinpagebar.h" class TabBar; +class WebView; class ZimView : public QWidget {