aboutsummaryrefslogtreecommitdiff
path: root/lib/webengine/webviewcontextmenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/webengine/webviewcontextmenu.cpp')
-rw-r--r--lib/webengine/webviewcontextmenu.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/lib/webengine/webviewcontextmenu.cpp b/lib/webengine/webviewcontextmenu.cpp
new file mode 100644
index 0000000..c9d809f
--- /dev/null
+++ b/lib/webengine/webviewcontextmenu.cpp
@@ -0,0 +1,233 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "webviewcontextmenu.h"
+#include "webprofilemanager.h"
+#include "webview.h"
+#include "util.h"
+#include <QContextMenuEvent>
+#include <QDialog>
+#include <QMenu>
+#include <QSlider>
+#include <QStyle>
+#include <QToolButton>
+#include <QVBoxLayout>
+#include <QWebEngineContextMenuData>
+#include <QWebEngineHistory>
+#include <QWidgetAction>
+
+constexpr int min_width = 250;
+constexpr QSize button_size(32, 32);
+
+inline QAction *historyAction(QWebEngineView *view, const QWebEngineHistoryItem &item)
+{
+ auto *action = new QAction(view);
+ if(item.title().isEmpty()) {
+ action->setText(item.url().toString());
+ } else {
+ action->setText(QObject::tr("%1 (%2)").arg(item.title(), item.url().toString()));
+ }
+
+ QObject::connect(action, &QAction::triggered, view, [view, item]() {
+ view->history()->goToItem(item);
+ });
+ return action;
+}
+
+WebViewContextMenu::WebViewContextMenu(WebView *view)
+ : QMenu(view)
+{
+ setMinimumWidth(min_width);
+
+ auto *navButtons = new QWidgetAction(this);
+
+ auto *buttons = new QWidget(this);
+ auto *buttonsLayout = new QHBoxLayout;
+ buttonsLayout->setContentsMargins(8, 0, 8, 0);
+ buttonsLayout->setSpacing(2);
+
+ auto *backButton = new QToolButton(this);
+ backButton->setMinimumSize(button_size);
+ backButton->setEnabled(view->history()->canGoBack());
+ backButton->setIcon(Util::icon<QStyle::SP_ArrowBack>());
+ connect(backButton, &QToolButton::clicked, view, [this, view]() {
+ view->back();
+ this->close();
+ });
+ buttonsLayout->addWidget(backButton);
+
+ auto *forwardButton = new QToolButton(this);
+ forwardButton->setMinimumSize(button_size);
+ forwardButton->setEnabled(view->history()->canGoForward());
+ forwardButton->setIcon(Util::icon<QStyle::SP_ArrowForward>());
+ connect(forwardButton, &QToolButton::clicked, view, [this, view]() {
+ view->forward();
+ this->close();
+ });
+ buttonsLayout->addWidget(forwardButton);
+
+ auto *refreshButton = new QToolButton(this);
+ refreshButton->setMinimumSize(button_size);
+ refreshButton->setIcon(Util::icon<QStyle::SP_BrowserReload>());
+ connect(refreshButton, &QToolButton::clicked, view, [view, this]() {
+ view->reload();
+ this->close();
+ });
+ buttonsLayout->addWidget(refreshButton);
+
+ buttonsLayout->addStretch();
+
+ auto *muteButton = new QToolButton(this);
+ muteButton->setMinimumSize(button_size);
+ muteButton->setCheckable(true);
+ muteButton->setChecked(view->page()->isAudioMuted());
+ muteButton->setIcon(Util::icon<QStyle::SP_MediaVolume>());
+ connect(muteButton, &QToolButton::clicked, view, [view, this](bool checked) {
+ view->page()->setAudioMuted(checked);
+ this->close();
+ });
+ buttonsLayout->addWidget(muteButton);
+
+ buttons->setLayout(buttonsLayout);
+ navButtons->setDefaultWidget(buttons);
+
+ this->addAction(navButtons);
+ this->addSeparator();
+
+ const auto ctxdata = view->page()->contextMenuData();
+
+ if(ctxdata.mediaType() == QWebEngineContextMenuData::MediaTypeNone) {
+ auto *backMenu = this->addMenu(tr("Back"));
+ if(!view->history()->canGoBack()) {
+ backMenu->setEnabled(false);
+ } else {
+ connect(backMenu, &QMenu::aboutToShow, view, [view, backMenu]() {
+ backMenu->clear();
+ const auto backItems = view->history()->backItems(10);
+ for(const QWebEngineHistoryItem &item : backItems) {
+ backMenu->addAction(historyAction(view, item));
+ }
+ });
+ }
+
+ auto *forwardMenu = this->addMenu(tr("Forward"));
+ if(!view->history()->canGoForward()) {
+ forwardMenu->setEnabled(false);
+ } else {
+ connect(forwardMenu, &QMenu::aboutToShow, view, [view, forwardMenu]() {
+ forwardMenu->clear();
+ const auto forwardItems = view->history()->forwardItems(10);
+ for(const QWebEngineHistoryItem &item : forwardItems) {
+ forwardMenu->addAction(historyAction(view, item));
+ }
+ });
+ }
+
+ connect(this->addAction(tr("Reload")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::Reload);
+ });
+ connect(this->addAction(tr("Reload and bypass Cache")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::ReloadAndBypassCache);
+ });
+
+ this->addSeparator();
+
+ connect(this->addAction(tr("Select All")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::SelectAll);
+ });
+ connect(this->addAction(tr("Clear Selection")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::Unselect);
+ });
+ connect(this->addAction(tr("Copy to clipboard")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::Copy);
+ });
+
+ } else if(ctxdata.mediaType() == QWebEngineContextMenuData::MediaTypeImage) {
+ connect(this->addAction(tr("Copy image to clipboard")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::CopyImageToClipboard);
+ });
+ connect(this->addAction(tr("Copy image URL to clipboard")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::CopyImageUrlToClipboard);
+ });
+ if(!ctxdata.mediaUrl().isEmpty()) {
+ if(view->url() != ctxdata.mediaUrl()) {
+ connect(this->addAction(tr("Open image")), &QAction::triggered, view, [view, ctxdata]() {
+ view->load(ctxdata.mediaUrl());
+ });
+ connect(this->addAction(tr("Open image in new tab")), &QAction::triggered, view, [view, ctxdata]() {
+ view->createWindow(QWebEnginePage::WebBrowserTab)->load(ctxdata.mediaUrl());
+ });
+ }
+ connect(this->addAction(tr("Save image")), &QAction::triggered, view, [view, ctxdata]() {
+ view->page()->download(ctxdata.mediaUrl());
+ });
+ }
+
+ } else {
+ addMenu(view->page()->createStandardContextMenu());
+ }
+
+ if(!ctxdata.linkUrl().isEmpty()) {
+ this->addSeparator();
+ connect(this->addAction(tr("Open link in new tab")), &QAction::triggered, view, [view, ctxdata]() {
+ view->createWindow(QWebEnginePage::WebBrowserTab)->load(ctxdata.linkUrl());
+ });
+
+ auto *newTabMenu = this->addMenu(tr("Open link in new tab with profile"));
+ profileMenu(newTabMenu, [view, ctxdata](WebProfile *profile) {
+ auto *v = view->createWindow(QWebEnginePage::WebBrowserTab);
+ v->setProfile(profile);
+ v->load(ctxdata.linkUrl());
+ });
+
+ connect(this->addAction(tr("Open link in new window")), &QAction::triggered, view, [view, ctxdata]() {
+ view->createWindow(QWebEnginePage::WebBrowserWindow)->load(ctxdata.linkUrl());
+ });
+
+ connect(this->addAction(tr("Copy link address")), &QAction::triggered, view, [view]() {
+ view->page()->triggerAction(QWebEnginePage::CopyLinkToClipboard);
+ });
+ }
+
+ // zoom widget
+ {
+ this->addSeparator();
+
+ auto *zoomSlider = new QSlider(Qt::Horizontal);
+ zoomSlider->setMinimum(5);
+ zoomSlider->setMaximum(50);
+ zoomSlider->setValue(static_cast<int>(view->zoomFactor() * 10));
+
+ auto *zoomAction = this->addAction(tr("Zoom: %1x").arg(view->zoomFactor()));
+ connect(zoomAction, &QAction::triggered, view, [zoomSlider]() {
+ zoomSlider->setValue(10);
+ });
+
+ connect(zoomSlider, &QSlider::valueChanged, view, [view, zoomAction](int value) {
+ zoomAction->setText(tr("Zoom: %1x").arg(static_cast<qreal>(value) / 10));
+ view->setZoomFactor(static_cast<qreal>(value) / 10);
+ });
+
+ auto *zoomWidgetAction = new QWidgetAction(this);
+ zoomWidgetAction->setDefaultWidget(zoomSlider);
+
+ this->addAction(zoomWidgetAction);
+ }
+
+#ifndef NDEBUG
+ /*
+ {
+ this->addSeparator();
+ auto *autofillAction = this->addAction(tr("Autofill form"));
+ connect(autofillAction, &QAction::triggered, view, [view]() {
+ Wallet::autocompleteForm(view);
+ });
+ };
+ */
+#endif
+}