This commit is contained in:
Martin Rotter 2022-04-26 14:43:28 +02:00
parent cec08b4eb5
commit 4c0aee2ef4
2 changed files with 75 additions and 67 deletions

View file

@ -19,7 +19,9 @@
#include <QTimer>
TextBrowserViewer::TextBrowserViewer(QWidget* parent)
: QTextBrowser(parent), m_downloader(new Downloader(this)), m_document(new TextBrowserDocument(this)) {
: QTextBrowser(parent), m_resourcesEnabled(false), m_resourceDownloader(new Downloader(this)),
m_placeholderImage(qApp->icons()->miscPixmap("image-placeholder")), m_downloader(new Downloader(this)),
m_document(new TextBrowserDocument(this)) {
setAutoFillBackground(true);
setFrameShape(QFrame::Shape::NoFrame);
setFrameShadow(QFrame::Shadow::Plain);
@ -27,16 +29,20 @@ TextBrowserViewer::TextBrowserViewer(QWidget* parent)
setOpenLinks(false);
viewport()->setAutoFillBackground(true);
m_document.data()->setResourcesEnabled(qApp->settings()
->value(GROUP(Messages), SETTING(Messages::ShowResourcesInArticles))
.toBool());
m_resourceTimer.setSingleShot(false);
m_resourceTimer.setInterval(300);
setResourcesEnabled(qApp->settings()->value(GROUP(Messages), SETTING(Messages::ShowResourcesInArticles)).toBool());
setDocument(m_document.data());
connect(m_document.data(), &TextBrowserDocument::reloadDocument, this, [this]() {
connect(this, &TextBrowserViewer::reloadDocument, this, [this]() {
const auto scr = verticalScrollBarPosition();
setHtmlPrivate(html(), m_currentUrl);
setVerticalScrollBarPosition(scr);
});
connect(&m_resourceTimer, &QTimer::timeout, this, &TextBrowserViewer::reloadHtmlDelayed);
connect(m_resourceDownloader.data(), &Downloader::completed, this, &TextBrowserViewer::resourceDownloaded);
connect(this, &QTextBrowser::anchorClicked, this, &TextBrowserViewer::onAnchorClicked);
connect(this, QOverload<const QUrl&>::of(&QTextBrowser::highlighted), this, &TextBrowserViewer::linkMouseHighlighted);
}
@ -48,6 +54,31 @@ QSize TextBrowserViewer::sizeHint() const {
return doc_size;
}
QVariant TextBrowserViewer::loadOneResource(int type, const QUrl& name) {
if (type != QTextDocument::ResourceType::ImageResource) {
return {};
}
if (!m_resourcesEnabled) {
// Resources are not enabled.
return m_placeholderImage;
}
if (m_loadedResources.contains(name)) {
// Resources are enabled and we already have the resource.
return QImage::fromData(m_loadedResources.value(name));
}
else {
// Resources are not enabled and we need to download the resource.
if (!m_neededResources.contains(name) && m_resourceTimer.isActive()) {
m_neededResources.append(name);
m_resourceTimer.start();
}
return m_placeholderImage;
}
}
QPair<QString, QUrl> TextBrowserViewer::prepareHtmlForMessage(const QList<Message>& messages,
RootItem* selected_item) const {
QString html;
@ -282,7 +313,7 @@ void TextBrowserViewer::contextMenuEvent(QContextMenuEvent* event) {
m_actionDownloadLink.reset(new QAction(qApp->icons()->fromTheme(QSL("download")), tr("Download"), this));
m_actionEnableResources.data()->setCheckable(true);
m_actionEnableResources.data()->setChecked(m_document.data()->resourcesEnabled());
m_actionEnableResources.data()->setChecked(resourcesEnabled());
connect(m_actionOpenExternalBrowser.data(),
&QAction::triggered,
@ -353,7 +384,7 @@ void TextBrowserViewer::wheelEvent(QWheelEvent* event) {
void TextBrowserViewer::enableResources(bool enable) {
qApp->settings()->setValue(GROUP(Messages), Messages::ShowResourcesInArticles, enable);
m_document.data()->setResourcesEnabled(enable);
setResourcesEnabled(enable);
}
void TextBrowserViewer::openLinkInExternalBrowser() {
@ -397,9 +428,9 @@ void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
}
void TextBrowserViewer::setHtml(const QString& html, const QUrl& base_url) {
m_document.data()->m_resourceTimer.stop();
m_document.data()->m_neededResources.clear();
m_document.data()->m_resourceTimer.start();
m_resourceTimer.stop();
m_neededResources.clear();
m_resourceTimer.start();
setHtmlPrivate(html, base_url);
@ -424,43 +455,15 @@ void TextBrowserViewer::setHtmlPrivate(const QString& html, const QUrl& base_url
emit pageUrlChanged(base_url);
}
TextBrowserDocument::TextBrowserDocument(QObject* parent)
: QTextDocument(parent), m_resourcesEnabled(false), m_resourceDownloader(new Downloader(this)),
m_placeholderImage(qApp->icons()->miscPixmap("image-placeholder")) {
connect(&m_resourceTimer, &QTimer::timeout, this, &TextBrowserDocument::reloadHtmlDelayed);
connect(m_resourceDownloader.data(), &Downloader::completed, this, &TextBrowserDocument::resourceDownloaded);
m_resourceTimer.setSingleShot(false);
m_resourceTimer.setInterval(300);
TextBrowserDocument::TextBrowserDocument(TextBrowserViewer* parent) : QTextDocument(parent) {
m_viewer = parent;
}
QVariant TextBrowserDocument::loadResource(int type, const QUrl& name) {
if (type != QTextDocument::ResourceType::ImageResource) {
return {};
}
if (!m_resourcesEnabled) {
// Resources are not enabled.
return m_placeholderImage;
}
if (m_loadedResources.contains(name)) {
// Resources are enabled and we already have the resource.
return QImage::fromData(m_loadedResources.value(name));
}
else {
// Resources are not enabled and we need to download the resource.
if (!m_neededResources.contains(name) && m_resourceTimer.isActive()) {
m_neededResources.append(name);
m_resourceTimer.start();
}
return m_placeholderImage;
}
return m_viewer->loadOneResource(type, name);
}
void TextBrowserDocument::reloadHtmlDelayed() {
void TextBrowserViewer::reloadHtmlDelayed() {
// Timer has elapsed, we do not wait for other resources,
// we download what we know about.
m_resourceTimer.stop();
@ -470,7 +473,7 @@ void TextBrowserDocument::reloadHtmlDelayed() {
}
}
void TextBrowserDocument::downloadNextNeededResource() {
void TextBrowserViewer::downloadNextNeededResource() {
if (m_neededResources.isEmpty()) {
// Everything is downloaded.
emit reloadDocument();
@ -483,7 +486,7 @@ void TextBrowserDocument::downloadNextNeededResource() {
}
}
void TextBrowserDocument::resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents) {
void TextBrowserViewer::resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents) {
if (status == QNetworkReply::NetworkError::NoError && !m_loadedResources.contains(url)) {
m_loadedResources.insert(url, contents);
}
@ -491,10 +494,10 @@ void TextBrowserDocument::resourceDownloaded(const QUrl& url, QNetworkReply::Net
downloadNextNeededResource();
}
bool TextBrowserDocument::resourcesEnabled() const {
bool TextBrowserViewer::resourcesEnabled() const {
return m_resourcesEnabled;
}
void TextBrowserDocument::setResourcesEnabled(bool enabled) {
void TextBrowserViewer::setResourcesEnabled(bool enabled) {
m_resourcesEnabled = enabled;
}

View file

@ -19,36 +19,19 @@ class QResizeEvent;
class WebBrowser;
class Downloader;
class TextBrowserViewer;
class TextBrowserDocument : public QTextDocument {
Q_OBJECT
friend class TextBrowserViewer;
public:
explicit TextBrowserDocument(QObject* parent = nullptr);
bool resourcesEnabled() const;
void setResourcesEnabled(bool enabled);
explicit TextBrowserDocument(TextBrowserViewer* parent = nullptr);
protected:
virtual QVariant loadResource(int type, const QUrl& name);
signals:
void loadingProgress(int progress);
void reloadDocument();
private slots:
void reloadHtmlDelayed();
void downloadNextNeededResource();
void resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
private:
bool m_resourcesEnabled;
QTimer m_resourceTimer;
QList<QUrl> m_neededResources;
QScopedPointer<Downloader> m_resourceDownloader;
QMap<QUrl, QByteArray> m_loadedResources;
QPixmap m_placeholderImage;
QPointer<TextBrowserViewer> m_viewer;
};
class TextBrowserViewer : public QTextBrowser, public WebViewer {
@ -60,6 +43,9 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
virtual QSize sizeHint() const;
public:
QVariant loadOneResource(int type, const QUrl& name);
public:
virtual void bindToBrowser(WebBrowser* browser);
virtual void findText(const QString& text, bool backwards);
@ -86,6 +72,25 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
void downloadLink();
void onAnchorClicked(const QUrl& url);
bool resourcesEnabled() const;
void setResourcesEnabled(bool enabled);
signals:
void reloadDocument();
private slots:
void reloadHtmlDelayed();
void downloadNextNeededResource();
void resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
private:
bool m_resourcesEnabled;
QTimer m_resourceTimer;
QList<QUrl> m_neededResources;
QScopedPointer<Downloader> m_resourceDownloader;
QMap<QUrl, QByteArray> m_loadedResources;
QPixmap m_placeholderImage;
signals:
void pageTitleChanged(const QString& new_title);
void pageUrlChanged(const QUrl& url);