mirror of
https://github.com/zealdocs/zeal.git
synced 2024-11-27 11:44:56 +03:00
ui: Make external link behavior configurable (fixes #416)
This commit is contained in:
parent
8fa793a6f6
commit
3b2a395728
@ -47,6 +47,8 @@ using namespace Zeal::Core;
|
||||
Settings::Settings(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
qRegisterMetaTypeStreamOperators<ExternalLinkPolicy>("ExternalLinkPolicy");
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
@ -88,6 +90,8 @@ void Settings::load()
|
||||
darkModeEnabled = settings->value(QStringLiteral("dark_mode"), false).toBool();
|
||||
highlightOnNavigateEnabled = settings->value(QStringLiteral("highlight_on_navigate"), true).toBool();
|
||||
customCssFile = settings->value(QStringLiteral("custom_css_file")).toString();
|
||||
externalLinkPolicy = settings->value(QStringLiteral("external_link_policy"),
|
||||
QVariant::fromValue(ExternalLinkPolicy::Ask)).value<ExternalLinkPolicy>();
|
||||
isAdDisabled = settings->value(QStringLiteral("disable_ad"), false).toBool();
|
||||
settings->endGroup();
|
||||
|
||||
@ -157,6 +161,7 @@ void Settings::save()
|
||||
settings->setValue(QStringLiteral("dark_mode"), darkModeEnabled);
|
||||
settings->setValue(QStringLiteral("highlight_on_navigate"), highlightOnNavigateEnabled);
|
||||
settings->setValue(QStringLiteral("custom_css_file"), customCssFile);
|
||||
settings->setValue(QStringLiteral("external_link_policy"), QVariant::fromValue(externalLinkPolicy));
|
||||
settings->setValue(QStringLiteral("disable_ad"), isAdDisabled);
|
||||
settings->endGroup();
|
||||
|
||||
@ -254,3 +259,17 @@ QSettings *Settings::qsettings(QObject *parent)
|
||||
QSettings::IniFormat, parent);
|
||||
#endif
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const Settings::ExternalLinkPolicy &policy)
|
||||
{
|
||||
out << static_cast<std::underlying_type<Settings::ExternalLinkPolicy>::type>(policy);
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, Settings::ExternalLinkPolicy &policy)
|
||||
{
|
||||
std::underlying_type<Settings::ExternalLinkPolicy>::type value;
|
||||
in >> value;
|
||||
policy = static_cast<Settings::ExternalLinkPolicy>(value);
|
||||
return in;
|
||||
}
|
||||
|
@ -60,6 +60,14 @@ public:
|
||||
bool fuzzySearchEnabled;
|
||||
|
||||
// Content
|
||||
enum class ExternalLinkPolicy : unsigned int {
|
||||
Ask = 0,
|
||||
Open,
|
||||
OpenInSystemBrowser
|
||||
};
|
||||
Q_ENUM(ExternalLinkPolicy)
|
||||
ExternalLinkPolicy externalLinkPolicy = ExternalLinkPolicy::Ask;
|
||||
|
||||
int minimumFontSize;
|
||||
bool darkModeEnabled;
|
||||
bool highlightOnNavigateEnabled;
|
||||
@ -118,4 +126,9 @@ private:
|
||||
} // namespace Core
|
||||
} // namespace Zeal
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const Zeal::Core::Settings::ExternalLinkPolicy &policy);
|
||||
QDataStream &operator>>(QDataStream &in, Zeal::Core::Settings::ExternalLinkPolicy &policy);
|
||||
|
||||
Q_DECLARE_METATYPE(Zeal::Core::Settings::ExternalLinkPolicy)
|
||||
|
||||
#endif // ZEAL_CORE_SETTINGS_H
|
||||
|
@ -604,13 +604,6 @@ void MainWindow::attachTab(TabState *tabState)
|
||||
m_tabBar->setTabToolTip(m_tabBar->currentIndex(), title);
|
||||
});
|
||||
|
||||
connect(tabState->widget, &WebViewTab::linkClicked, this, [this](const QUrl &url) {
|
||||
const QString message = tr("Do you want to open an external link?<br>URL: <b>%1</b>");
|
||||
int ret = QMessageBox::question(this, QStringLiteral("Zeal"), message.arg(url.toString()));
|
||||
if (ret == QMessageBox::Yes)
|
||||
QDesktopServices::openUrl(url);
|
||||
});
|
||||
|
||||
ui->lineEdit->setText(tabState->searchQuery);
|
||||
ui->tocListView->setModel(tabState->tocModel);
|
||||
|
||||
|
@ -112,6 +112,18 @@ void SettingsDialog::loadSettings()
|
||||
ui->customCssFileEdit->setText(QDir::toNativeSeparators(settings->customCssFile));
|
||||
ui->disableAdCheckBox->setChecked(settings->isAdDisabled);
|
||||
|
||||
switch (settings->externalLinkPolicy) {
|
||||
case Core::Settings::ExternalLinkPolicy::Ask:
|
||||
ui->radioExternalLinkAsk->setChecked(true);
|
||||
break;
|
||||
case Core::Settings::ExternalLinkPolicy::Open:
|
||||
ui->radioExternalLinkOpen->setChecked(true);
|
||||
break;
|
||||
case Core::Settings::ExternalLinkPolicy::OpenInSystemBrowser:
|
||||
ui->radioExternalLinkOpenDesktop->setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// Network Tab
|
||||
switch (settings->proxyType) {
|
||||
case Core::Settings::ProxyType::None:
|
||||
@ -161,6 +173,14 @@ void SettingsDialog::saveSettings()
|
||||
settings->customCssFile = QDir::fromNativeSeparators(ui->customCssFileEdit->text());
|
||||
settings->isAdDisabled = ui->disableAdCheckBox->isChecked();
|
||||
|
||||
if (ui->radioExternalLinkAsk->isChecked()) {
|
||||
settings->externalLinkPolicy = Core::Settings::ExternalLinkPolicy::Ask;
|
||||
} else if (ui->radioExternalLinkOpen->isChecked()) {
|
||||
settings->externalLinkPolicy = Core::Settings::ExternalLinkPolicy::Open;
|
||||
} else if (ui->radioExternalLinkOpenDesktop->isChecked()) {
|
||||
settings->externalLinkPolicy = Core::Settings::ExternalLinkPolicy::OpenInSystemBrowser;
|
||||
}
|
||||
|
||||
// Network Tab
|
||||
// Proxy settings
|
||||
if (ui->noProxySettings->isChecked())
|
||||
|
@ -313,6 +313,39 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>External Link Behavior</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioExternalLinkAsk">
|
||||
<property name="text">
|
||||
<string>Ask Everytime</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioExternalLinkOpenDesktop">
|
||||
<property name="text">
|
||||
<string>Open in Desktop Browser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioExternalLinkOpen">
|
||||
<property name="text">
|
||||
<string>Open in Zeal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
|
@ -27,10 +27,14 @@
|
||||
#include "../mainwindow.h"
|
||||
|
||||
#include <core/application.h>
|
||||
#include <core/settings.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QWheelEvent>
|
||||
|
||||
using namespace Zeal::WidgetUi;
|
||||
@ -39,7 +43,6 @@ WebView::WebView(QWidget *parent)
|
||||
: QWebView(parent)
|
||||
{
|
||||
setAttribute(Qt::WA_AcceptTouchEvents, false);
|
||||
page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);
|
||||
page()->setNetworkAccessManager(Core::Application::instance()->networkManager());
|
||||
}
|
||||
|
||||
@ -107,8 +110,8 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)
|
||||
|
||||
// Return standard menu for input fields.
|
||||
if (hitTestResult.isContentEditable()) {
|
||||
QWebView::contextMenuEvent(event);
|
||||
return;
|
||||
QWebView::contextMenuEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
@ -176,9 +179,6 @@ void WebView::mousePressEvent(QMouseEvent *event)
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::LeftButton:
|
||||
if (!(event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::ShiftModifier)) {
|
||||
break;
|
||||
}
|
||||
case Qt::MiddleButton:
|
||||
m_clickedLink = hitTestContent(event->pos()).linkUrl();
|
||||
if (!m_clickedLink.isValid()) {
|
||||
@ -196,20 +196,78 @@ void WebView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
void WebView::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
switch (event->button()) {
|
||||
case Qt::LeftButton:
|
||||
if (!(event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::ShiftModifier)) {
|
||||
if (event->button() != Qt::LeftButton && event->button() != Qt::MiddleButton) {
|
||||
QWebView::mouseReleaseEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
const QUrl clickedLink = hitTestContent(event->pos()).linkUrl();
|
||||
if (!clickedLink.isValid() || clickedLink != m_clickedLink) {
|
||||
QWebView::mouseReleaseEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUrlExternal(clickedLink)) {
|
||||
switch (Core::Application::instance()->settings()->externalLinkPolicy) {
|
||||
case Core::Settings::ExternalLinkPolicy::Open:
|
||||
break;
|
||||
case Core::Settings::ExternalLinkPolicy::Ask: {
|
||||
QScopedPointer<QMessageBox> mb(new QMessageBox());
|
||||
mb->setIcon(QMessageBox::Question);
|
||||
mb->setText(tr("How do you want to open the external link?<br>URL: <b>%1</b>")
|
||||
.arg(clickedLink.toString()));
|
||||
|
||||
|
||||
QCheckBox *checkBox = new QCheckBox("Do ¬ ask again");
|
||||
mb->setCheckBox(checkBox);
|
||||
|
||||
QPushButton *openInBrowserButton = mb->addButton(tr("Open in &Desktop Browser"),
|
||||
QMessageBox::ActionRole);
|
||||
QPushButton *openInZealButton = mb->addButton(tr("Open in &Zeal"),
|
||||
QMessageBox::ActionRole);
|
||||
mb->addButton(QMessageBox::Cancel);
|
||||
|
||||
mb->setDefaultButton(openInBrowserButton);
|
||||
|
||||
if (mb->exec() == QMessageBox::Cancel) {
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mb->clickedButton() == openInZealButton) {
|
||||
if (checkBox->isChecked()) {
|
||||
Core::Application::instance()->settings()->externalLinkPolicy
|
||||
= Core::Settings::ExternalLinkPolicy::Open;
|
||||
Core::Application::instance()->settings()->save();
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (mb->clickedButton() == openInBrowserButton) {
|
||||
if (checkBox->isChecked()) {
|
||||
Core::Application::instance()->settings()->externalLinkPolicy
|
||||
= Core::Settings::ExternalLinkPolicy::OpenInSystemBrowser;
|
||||
Core::Application::instance()->settings()->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
case Qt::MiddleButton:
|
||||
if (!m_clickedLink.isEmpty() && m_clickedLink == hitTestContent(event->pos()).linkUrl()) {
|
||||
QWebView *webView = createWindow(QWebPage::WebBrowserWindow);
|
||||
webView->load(m_clickedLink);
|
||||
case Core::Settings::ExternalLinkPolicy::OpenInSystemBrowser:
|
||||
QDesktopServices::openUrl(clickedLink);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
switch (event->button()) {
|
||||
case Qt::LeftButton:
|
||||
if (!(event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::ShiftModifier)) {
|
||||
load(clickedLink);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
case Qt::MiddleButton:
|
||||
createWindow(QWebPage::WebBrowserWindow)->load(clickedLink);
|
||||
event->accept();
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -242,3 +300,9 @@ QWebHitTestResult WebView::hitTestContent(const QPoint &pos) const
|
||||
{
|
||||
return page()->mainFrame()->hitTestContent(pos);
|
||||
}
|
||||
|
||||
bool WebView::isUrlExternal(const QUrl &url)
|
||||
{
|
||||
const QString scheme = url.scheme();
|
||||
return !scheme.isEmpty() && scheme != QLatin1String("file") && scheme != QLatin1String("qrc");
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ protected:
|
||||
private:
|
||||
QWebHitTestResult hitTestContent(const QPoint &pos) const;
|
||||
|
||||
static bool isUrlExternal(const QUrl &url);
|
||||
|
||||
QMenu *m_contextMenu = nullptr;
|
||||
QUrl m_clickedLink;
|
||||
int m_zoomLevel = defaultZoomLevel();
|
||||
|
@ -52,7 +52,6 @@ WebViewTab::WebViewTab(QWidget *parent)
|
||||
setToolTip(link);
|
||||
});
|
||||
|
||||
connect(m_webView, &QWebView::linkClicked, this, &WebViewTab::linkClicked);
|
||||
connect(m_webView, &QWebView::titleChanged, this, &WebViewTab::titleChanged);
|
||||
connect(m_webView, &QWebView::urlChanged, this, &WebViewTab::urlChanged);
|
||||
|
||||
|
@ -55,7 +55,6 @@ public:
|
||||
void setZoomLevel(int level);
|
||||
|
||||
signals:
|
||||
void linkClicked(const QUrl &url);
|
||||
void titleChanged(const QString &title);
|
||||
void urlChanged(const QUrl &url);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user