bit better reload with images
This commit is contained in:
parent
3e827ab954
commit
ec983c1243
3 changed files with 121 additions and 76 deletions
|
@ -378,7 +378,7 @@ Typical post-processing filter might do things like advanced CSS formatting, loc
|
||||||
It's completely up to you if you decide to only use script as `Source` of the script or separate your custom functionality between `Source` script and `Post-process` script. Sometimes you might need different `Source` scripts for different online sources and the same `Post-process` script and vice versa.
|
It's completely up to you if you decide to only use script as `Source` of the script or separate your custom functionality between `Source` script and `Post-process` script. Sometimes you might need different `Source` scripts for different online sources and the same `Post-process` script and vice versa.
|
||||||
|
|
||||||
### Notifications <a id="notif"></a>
|
### Notifications <a id="notif"></a>
|
||||||
RSS Guard allows you to configure behavior of desktop notifications. There is a number of events which can be configured:
|
RSS Guard allows you to customize desktop notifications. There are a number of events which can be configured:
|
||||||
* New (unread) articles fetched.
|
* New (unread) articles fetched.
|
||||||
* Fetching of articles is started.
|
* Fetching of articles is started.
|
||||||
* Login OAuth tokens are refreshed.
|
* Login OAuth tokens are refreshed.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "gui/webviewers/qtextbrowser/textbrowserviewer.h"
|
#include "gui/webviewers/qtextbrowser/textbrowserviewer.h"
|
||||||
|
|
||||||
|
#include "gui/dialogs/formmain.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
#include "gui/webbrowser.h"
|
#include "gui/webbrowser.h"
|
||||||
#include "miscellaneous/application.h"
|
#include "miscellaneous/application.h"
|
||||||
|
@ -15,9 +16,10 @@
|
||||||
#include <QContextMenuEvent>
|
#include <QContextMenuEvent>
|
||||||
#include <QFileIconProvider>
|
#include <QFileIconProvider>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
TextBrowserViewer::TextBrowserViewer(QWidget* parent)
|
TextBrowserViewer::TextBrowserViewer(QWidget* parent)
|
||||||
: QTextBrowser(parent), m_downloader(new Downloader(this)), m_reloadingWithResources(false) {
|
: QTextBrowser(parent), m_downloader(new Downloader(this)), m_document(new TextBrowserDocument(this)) {
|
||||||
setAutoFillBackground(true);
|
setAutoFillBackground(true);
|
||||||
setFrameShape(QFrame::Shape::NoFrame);
|
setFrameShape(QFrame::Shape::NoFrame);
|
||||||
setFrameShadow(QFrame::Shadow::Plain);
|
setFrameShadow(QFrame::Shadow::Plain);
|
||||||
|
@ -25,26 +27,12 @@ TextBrowserViewer::TextBrowserViewer(QWidget* parent)
|
||||||
setOpenLinks(false);
|
setOpenLinks(false);
|
||||||
viewport()->setAutoFillBackground(true);
|
viewport()->setAutoFillBackground(true);
|
||||||
|
|
||||||
|
setDocument(m_document.data());
|
||||||
|
|
||||||
connect(this, &QTextBrowser::anchorClicked, this, &TextBrowserViewer::onAnchorClicked);
|
connect(this, &QTextBrowser::anchorClicked, this, &TextBrowserViewer::onAnchorClicked);
|
||||||
connect(this, QOverload<const QUrl&>::of(&QTextBrowser::highlighted), this, &TextBrowserViewer::linkMouseHighlighted);
|
connect(this, QOverload<const QUrl&>::of(&QTextBrowser::highlighted), this, &TextBrowserViewer::linkMouseHighlighted);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TextBrowserViewer::loadResource(int type, const QUrl& name) {
|
|
||||||
if (!m_reloadingWithResources) {
|
|
||||||
if (type == QTextDocument::ResourceType::ImageResource) {
|
|
||||||
m_resourcesForHtml.append(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
else if (m_loadedResources.contains(name)) {
|
|
||||||
return QImage::fromData(m_loadedResources.value(name));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize TextBrowserViewer::sizeHint() const {
|
QSize TextBrowserViewer::sizeHint() const {
|
||||||
auto doc_size = document()->size().toSize();
|
auto doc_size = document()->size().toSize();
|
||||||
|
|
||||||
|
@ -222,21 +210,6 @@ void TextBrowserViewer::setUrl(const QUrl& url) {
|
||||||
emit loadingFinished(!is_error);
|
emit loadingFinished(!is_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserViewer::setHtml(const QString& html, const QUrl& base_url) {
|
|
||||||
m_currentUrl = base_url;
|
|
||||||
|
|
||||||
if (!m_reloadingWithResources) {
|
|
||||||
m_resourcesForHtml.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextBrowser::setHtml(html);
|
|
||||||
|
|
||||||
setZoomFactor(m_zoomFactor);
|
|
||||||
|
|
||||||
emit pageTitleChanged(documentTitle());
|
|
||||||
emit pageUrlChanged(base_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString TextBrowserViewer::html() const {
|
QString TextBrowserViewer::html() const {
|
||||||
return QTextBrowser::toHtml();
|
return QTextBrowser::toHtml();
|
||||||
}
|
}
|
||||||
|
@ -300,14 +273,29 @@ void TextBrowserViewer::contextMenuEvent(QContextMenuEvent* event) {
|
||||||
m_actionReloadWithImages.reset(new QAction(qApp->icons()->fromTheme(QSL("viewimage"), QSL("view-refresh")),
|
m_actionReloadWithImages.reset(new QAction(qApp->icons()->fromTheme(QSL("viewimage"), QSL("view-refresh")),
|
||||||
tr("Reload with images"),
|
tr("Reload with images"),
|
||||||
this));
|
this));
|
||||||
|
m_actionOpenExternalBrowser.reset(new QAction(qApp->icons()->fromTheme(QSL("document-open")),
|
||||||
|
tr("Open in external browser"),
|
||||||
|
this));
|
||||||
|
m_actionDownloadLink.reset(new QAction(qApp->icons()->fromTheme(QSL("download")), tr("Download"), this));
|
||||||
|
|
||||||
connect(m_actionReloadWithImages.data(), &QAction::triggered, this, &TextBrowserViewer::reloadWithImages);
|
connect(m_actionReloadWithImages.data(), &QAction::triggered, this, &TextBrowserViewer::reloadWithImages);
|
||||||
|
connect(m_actionOpenExternalBrowser.data(),
|
||||||
|
&QAction::triggered,
|
||||||
|
this,
|
||||||
|
&TextBrowserViewer::openLinkInExternalBrowser);
|
||||||
|
connect(m_actionDownloadLink.data(), &QAction::triggered, this, &TextBrowserViewer::downloadLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->addAction(m_actionReloadWithImages.data());
|
menu->addAction(m_actionReloadWithImages.data());
|
||||||
|
menu->addAction(m_actionOpenExternalBrowser.data());
|
||||||
|
menu->addAction(m_actionDownloadLink.data());
|
||||||
|
|
||||||
auto anchor = anchorAt(event->pos());
|
auto anchor = anchorAt(event->pos());
|
||||||
|
|
||||||
|
m_lastContextMenuPos = event->pos();
|
||||||
|
m_actionOpenExternalBrowser.data()->setEnabled(!anchor.isEmpty());
|
||||||
|
m_actionDownloadLink.data()->setEnabled(!anchor.isEmpty());
|
||||||
|
|
||||||
if (!anchor.isEmpty()) {
|
if (!anchor.isEmpty()) {
|
||||||
QFileIconProvider icon_provider;
|
QFileIconProvider icon_provider;
|
||||||
QMenu* menu_ext_tools = new QMenu(tr("Open with external tool"), menu);
|
QMenu* menu_ext_tools = new QMenu(tr("Open with external tool"), menu);
|
||||||
|
@ -358,11 +346,11 @@ void TextBrowserViewer::wheelEvent(QWheelEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserViewer::reloadWithImages() {
|
void TextBrowserViewer::reloadWithImages() {
|
||||||
m_reloadingWithResources = true;
|
m_document.data()->m_reloadingWithResources = true;
|
||||||
m_loadedResources.clear();
|
m_document.data()->m_loadedResources.clear();
|
||||||
|
|
||||||
for (const QUrl& url : m_resourcesForHtml) {
|
for (const QUrl& url : m_document.data()->m_resourcesForHtml) {
|
||||||
if (m_loadedResources.contains(url)) {
|
if (m_document.data()->m_loadedResources.contains(url)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,13 +362,39 @@ void TextBrowserViewer::reloadWithImages() {
|
||||||
loop.exec();
|
loop.exec();
|
||||||
|
|
||||||
if (m_downloader->lastOutputError() == QNetworkReply::NetworkError::NoError) {
|
if (m_downloader->lastOutputError() == QNetworkReply::NetworkError::NoError) {
|
||||||
m_loadedResources.insert(url, m_downloader->lastOutputData());
|
m_document.data()->m_loadedResources.insert(url, m_downloader->lastOutputData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setHtml(html(), m_currentUrl);
|
auto scrolled = verticalScrollBar()->value();
|
||||||
|
|
||||||
m_reloadingWithResources = false;
|
setHtmlPrivate(html(), m_currentUrl);
|
||||||
|
|
||||||
|
verticalScrollBar()->setValue(scrolled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::openLinkInExternalBrowser() {
|
||||||
|
auto link = anchorAt(m_lastContextMenuPos);
|
||||||
|
|
||||||
|
if (!link.isEmpty()) {
|
||||||
|
qApp->web()->openUrlInExternalBrowser(link);
|
||||||
|
|
||||||
|
if (qApp->settings()
|
||||||
|
->value(GROUP(Messages), SETTING(Messages::BringAppToFrontAfterMessageOpenedExternally))
|
||||||
|
.toBool()) {
|
||||||
|
QTimer::singleShot(1000, qApp, []() {
|
||||||
|
qApp->mainForm()->display();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::downloadLink() {
|
||||||
|
auto link = anchorAt(m_lastContextMenuPos);
|
||||||
|
|
||||||
|
if (!link.isEmpty()) {
|
||||||
|
qApp->downloadManager()->download(link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
|
void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
|
||||||
|
@ -392,38 +406,7 @@ void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
|
||||||
qApp->web()->openUrlInExternalBrowser(url.toString());
|
qApp->web()->openUrlInExternalBrowser(url.toString());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// User clicked some URL. Open it in external browser or download?
|
setUrl(url);
|
||||||
MsgBox box(qApp->mainFormWidget());
|
|
||||||
|
|
||||||
box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser."));
|
|
||||||
box.setInformativeText(tr("What action do you want to take?"));
|
|
||||||
box.setDetailedText(url.toString());
|
|
||||||
|
|
||||||
QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ButtonRole::ActionRole);
|
|
||||||
QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ButtonRole::ActionRole);
|
|
||||||
QAbstractButton* btn_cancel = box.addButton(QMessageBox::StandardButton::Cancel);
|
|
||||||
bool always = false;
|
|
||||||
|
|
||||||
MsgBox::setCheckBox(&box, tr("Always open links in external browser."), &always);
|
|
||||||
|
|
||||||
box.setDefaultButton(QMessageBox::StandardButton::Cancel);
|
|
||||||
box.exec();
|
|
||||||
|
|
||||||
if (box.clickedButton() != box.button(QMessageBox::StandardButton::Cancel)) {
|
|
||||||
// Store selected checkbox value.
|
|
||||||
qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (box.clickedButton() == btn_open) {
|
|
||||||
qApp->web()->openUrlInExternalBrowser(url.toString());
|
|
||||||
}
|
|
||||||
else if (box.clickedButton() == btn_download) {
|
|
||||||
qApp->downloadManager()->download(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
btn_download->deleteLater();
|
|
||||||
btn_open->deleteLater();
|
|
||||||
btn_cancel->deleteLater();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -433,3 +416,44 @@ void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
|
||||||
tr("Selected hyperlink is invalid."));
|
tr("Selected hyperlink is invalid."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::setHtml(const QString& html, const QUrl& base_url) {
|
||||||
|
m_document.data()->m_reloadingWithResources = false;
|
||||||
|
m_document.data()->m_loadedResources.clear();
|
||||||
|
m_document.data()->m_resourcesForHtml.clear();
|
||||||
|
|
||||||
|
setHtmlPrivate(html, base_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBrowserViewer::setHtmlPrivate(const QString& html, const QUrl& base_url) {
|
||||||
|
m_currentUrl = base_url;
|
||||||
|
|
||||||
|
if (!m_document.data()->m_reloadingWithResources) {
|
||||||
|
m_document.data()->m_resourcesForHtml.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextBrowser::setHtml(html);
|
||||||
|
|
||||||
|
setZoomFactor(m_zoomFactor);
|
||||||
|
|
||||||
|
emit pageTitleChanged(documentTitle());
|
||||||
|
emit pageUrlChanged(base_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBrowserDocument::TextBrowserDocument(QObject* parent) : QTextDocument(parent), m_reloadingWithResources(false) {}
|
||||||
|
|
||||||
|
QVariant TextBrowserDocument::loadResource(int type, const QUrl& name) {
|
||||||
|
if (!m_reloadingWithResources) {
|
||||||
|
if (type == QTextDocument::ResourceType::ImageResource && !m_resourcesForHtml.contains(name)) {
|
||||||
|
m_resourcesForHtml.append(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QTextDocument::loadResource(type, name);
|
||||||
|
}
|
||||||
|
else if (m_loadedResources.contains(name)) {
|
||||||
|
return QImage::fromData(m_loadedResources.value(name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QTextDocument::loadResource(type, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,23 @@ class QResizeEvent;
|
||||||
class WebBrowser;
|
class WebBrowser;
|
||||||
class Downloader;
|
class Downloader;
|
||||||
|
|
||||||
|
class TextBrowserDocument : public QTextDocument {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class TextBrowserViewer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TextBrowserDocument(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual QVariant loadResource(int type, const QUrl& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_reloadingWithResources;
|
||||||
|
QList<QUrl> m_resourcesForHtml;
|
||||||
|
QMap<QUrl, QByteArray> m_loadedResources;
|
||||||
|
};
|
||||||
|
|
||||||
class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_INTERFACES(WebViewer)
|
Q_INTERFACES(WebViewer)
|
||||||
|
@ -23,7 +40,6 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
public:
|
public:
|
||||||
explicit TextBrowserViewer(QWidget* parent = nullptr);
|
explicit TextBrowserViewer(QWidget* parent = nullptr);
|
||||||
|
|
||||||
virtual QVariant loadResource(int type, const QUrl& name);
|
|
||||||
virtual QSize sizeHint() const;
|
virtual QSize sizeHint() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -48,6 +64,8 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void reloadWithImages();
|
void reloadWithImages();
|
||||||
|
void openLinkInExternalBrowser();
|
||||||
|
void downloadLink();
|
||||||
void onAnchorClicked(const QUrl& url);
|
void onAnchorClicked(const QUrl& url);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -62,6 +80,8 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
void closeWindowRequested();
|
void closeWindowRequested();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setHtmlPrivate(const QString& html, const QUrl& base_url);
|
||||||
|
|
||||||
BlockingResult blockedWithAdblock(const QUrl& url);
|
BlockingResult blockedWithAdblock(const QUrl& url);
|
||||||
QScopedPointer<Downloader> m_downloader;
|
QScopedPointer<Downloader> m_downloader;
|
||||||
QPair<QString, QUrl> prepareHtmlForMessage(const QList<Message>& messages, RootItem* selected_item) const;
|
QPair<QString, QUrl> prepareHtmlForMessage(const QList<Message>& messages, RootItem* selected_item) const;
|
||||||
|
@ -72,9 +92,10 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
QFont m_baseFont;
|
QFont m_baseFont;
|
||||||
qreal m_zoomFactor = 1.0;
|
qreal m_zoomFactor = 1.0;
|
||||||
QScopedPointer<QAction> m_actionReloadWithImages;
|
QScopedPointer<QAction> m_actionReloadWithImages;
|
||||||
bool m_reloadingWithResources;
|
QScopedPointer<QAction> m_actionOpenExternalBrowser;
|
||||||
QList<QUrl> m_resourcesForHtml;
|
QScopedPointer<QAction> m_actionDownloadLink;
|
||||||
QMap<QUrl, QByteArray> m_loadedResources;
|
QScopedPointer<TextBrowserDocument> m_document;
|
||||||
|
QPoint m_lastContextMenuPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TEXTBROWSERVIEWER_H
|
#endif // TEXTBROWSERVIEWER_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue