/* * 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 #include #include #include #include #include #include #include #include #include #include inline QAction *historyAction(QWebEngineView *view, const QWebEngineHistoryItem &item) { QAction *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(250); 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->setEnabled(view->history()->canGoBack()); backButton->setIcon(style()->standardIcon(QStyle::SP_ArrowBack)); connect(backButton, &QToolButton::clicked, view, [this, view]() { view->back(); this->close(); }); buttonsLayout->addWidget(backButton); auto *forwardButton = new QToolButton(this); forwardButton->setEnabled(view->history()->canGoForward()); forwardButton->setIcon(style()->standardIcon(QStyle::SP_ArrowForward)); connect(forwardButton, &QToolButton::clicked, view, [this, view]() { view->forward(); this->close(); }); buttonsLayout->addWidget(forwardButton); auto *refreshButton = new QToolButton(this); refreshButton->setIcon(style()->standardIcon(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->setCheckable(true); muteButton->setChecked(view->page()->isAudioMuted()); QIcon muteIcon; muteIcon.addPixmap(style()->standardPixmap(QStyle::SP_MediaVolume), QIcon::Normal, QIcon::Off); muteIcon.addPixmap(style()->standardPixmap(QStyle::SP_MediaVolumeMuted), QIcon::Normal, QIcon::On); muteButton->setIcon(muteIcon); 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(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(value) / 10)); view->setZoomFactor(static_cast(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 }