save
This commit is contained in:
parent
cec08b4eb5
commit
4c0aee2ef4
2 changed files with 75 additions and 67 deletions
|
@ -19,7 +19,9 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
TextBrowserViewer::TextBrowserViewer(QWidget* parent)
|
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);
|
setAutoFillBackground(true);
|
||||||
setFrameShape(QFrame::Shape::NoFrame);
|
setFrameShape(QFrame::Shape::NoFrame);
|
||||||
setFrameShadow(QFrame::Shadow::Plain);
|
setFrameShadow(QFrame::Shadow::Plain);
|
||||||
|
@ -27,16 +29,20 @@ TextBrowserViewer::TextBrowserViewer(QWidget* parent)
|
||||||
setOpenLinks(false);
|
setOpenLinks(false);
|
||||||
viewport()->setAutoFillBackground(true);
|
viewport()->setAutoFillBackground(true);
|
||||||
|
|
||||||
m_document.data()->setResourcesEnabled(qApp->settings()
|
m_resourceTimer.setSingleShot(false);
|
||||||
->value(GROUP(Messages), SETTING(Messages::ShowResourcesInArticles))
|
m_resourceTimer.setInterval(300);
|
||||||
.toBool());
|
|
||||||
|
|
||||||
|
setResourcesEnabled(qApp->settings()->value(GROUP(Messages), SETTING(Messages::ShowResourcesInArticles)).toBool());
|
||||||
setDocument(m_document.data());
|
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);
|
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, &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);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +54,31 @@ QSize TextBrowserViewer::sizeHint() const {
|
||||||
return doc_size;
|
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,
|
QPair<QString, QUrl> TextBrowserViewer::prepareHtmlForMessage(const QList<Message>& messages,
|
||||||
RootItem* selected_item) const {
|
RootItem* selected_item) const {
|
||||||
QString html;
|
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_actionDownloadLink.reset(new QAction(qApp->icons()->fromTheme(QSL("download")), tr("Download"), this));
|
||||||
|
|
||||||
m_actionEnableResources.data()->setCheckable(true);
|
m_actionEnableResources.data()->setCheckable(true);
|
||||||
m_actionEnableResources.data()->setChecked(m_document.data()->resourcesEnabled());
|
m_actionEnableResources.data()->setChecked(resourcesEnabled());
|
||||||
|
|
||||||
connect(m_actionOpenExternalBrowser.data(),
|
connect(m_actionOpenExternalBrowser.data(),
|
||||||
&QAction::triggered,
|
&QAction::triggered,
|
||||||
|
@ -353,7 +384,7 @@ void TextBrowserViewer::wheelEvent(QWheelEvent* event) {
|
||||||
|
|
||||||
void TextBrowserViewer::enableResources(bool enable) {
|
void TextBrowserViewer::enableResources(bool enable) {
|
||||||
qApp->settings()->setValue(GROUP(Messages), Messages::ShowResourcesInArticles, enable);
|
qApp->settings()->setValue(GROUP(Messages), Messages::ShowResourcesInArticles, enable);
|
||||||
m_document.data()->setResourcesEnabled(enable);
|
setResourcesEnabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserViewer::openLinkInExternalBrowser() {
|
void TextBrowserViewer::openLinkInExternalBrowser() {
|
||||||
|
@ -397,9 +428,9 @@ void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserViewer::setHtml(const QString& html, const QUrl& base_url) {
|
void TextBrowserViewer::setHtml(const QString& html, const QUrl& base_url) {
|
||||||
m_document.data()->m_resourceTimer.stop();
|
m_resourceTimer.stop();
|
||||||
m_document.data()->m_neededResources.clear();
|
m_neededResources.clear();
|
||||||
m_document.data()->m_resourceTimer.start();
|
m_resourceTimer.start();
|
||||||
|
|
||||||
setHtmlPrivate(html, base_url);
|
setHtmlPrivate(html, base_url);
|
||||||
|
|
||||||
|
@ -424,43 +455,15 @@ void TextBrowserViewer::setHtmlPrivate(const QString& html, const QUrl& base_url
|
||||||
emit pageUrlChanged(base_url);
|
emit pageUrlChanged(base_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextBrowserDocument::TextBrowserDocument(QObject* parent)
|
TextBrowserDocument::TextBrowserDocument(TextBrowserViewer* parent) : QTextDocument(parent) {
|
||||||
: QTextDocument(parent), m_resourcesEnabled(false), m_resourceDownloader(new Downloader(this)),
|
m_viewer = parent;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TextBrowserDocument::loadResource(int type, const QUrl& name) {
|
QVariant TextBrowserDocument::loadResource(int type, const QUrl& name) {
|
||||||
if (type != QTextDocument::ResourceType::ImageResource) {
|
return m_viewer->loadOneResource(type, name);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserDocument::reloadHtmlDelayed() {
|
void TextBrowserViewer::reloadHtmlDelayed() {
|
||||||
// Timer has elapsed, we do not wait for other resources,
|
// Timer has elapsed, we do not wait for other resources,
|
||||||
// we download what we know about.
|
// we download what we know about.
|
||||||
m_resourceTimer.stop();
|
m_resourceTimer.stop();
|
||||||
|
@ -470,7 +473,7 @@ void TextBrowserDocument::reloadHtmlDelayed() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserDocument::downloadNextNeededResource() {
|
void TextBrowserViewer::downloadNextNeededResource() {
|
||||||
if (m_neededResources.isEmpty()) {
|
if (m_neededResources.isEmpty()) {
|
||||||
// Everything is downloaded.
|
// Everything is downloaded.
|
||||||
emit reloadDocument();
|
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)) {
|
if (status == QNetworkReply::NetworkError::NoError && !m_loadedResources.contains(url)) {
|
||||||
m_loadedResources.insert(url, contents);
|
m_loadedResources.insert(url, contents);
|
||||||
}
|
}
|
||||||
|
@ -491,10 +494,10 @@ void TextBrowserDocument::resourceDownloaded(const QUrl& url, QNetworkReply::Net
|
||||||
downloadNextNeededResource();
|
downloadNextNeededResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextBrowserDocument::resourcesEnabled() const {
|
bool TextBrowserViewer::resourcesEnabled() const {
|
||||||
return m_resourcesEnabled;
|
return m_resourcesEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBrowserDocument::setResourcesEnabled(bool enabled) {
|
void TextBrowserViewer::setResourcesEnabled(bool enabled) {
|
||||||
m_resourcesEnabled = enabled;
|
m_resourcesEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,36 +19,19 @@ class QResizeEvent;
|
||||||
class WebBrowser;
|
class WebBrowser;
|
||||||
class Downloader;
|
class Downloader;
|
||||||
|
|
||||||
|
class TextBrowserViewer;
|
||||||
|
|
||||||
class TextBrowserDocument : public QTextDocument {
|
class TextBrowserDocument : public QTextDocument {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class TextBrowserViewer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TextBrowserDocument(QObject* parent = nullptr);
|
explicit TextBrowserDocument(TextBrowserViewer* parent = nullptr);
|
||||||
|
|
||||||
bool resourcesEnabled() const;
|
|
||||||
void setResourcesEnabled(bool enabled);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QVariant loadResource(int type, const QUrl& name);
|
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:
|
private:
|
||||||
bool m_resourcesEnabled;
|
QPointer<TextBrowserViewer> m_viewer;
|
||||||
QTimer m_resourceTimer;
|
|
||||||
QList<QUrl> m_neededResources;
|
|
||||||
QScopedPointer<Downloader> m_resourceDownloader;
|
|
||||||
QMap<QUrl, QByteArray> m_loadedResources;
|
|
||||||
QPixmap m_placeholderImage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
|
@ -60,6 +43,9 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
|
|
||||||
virtual QSize sizeHint() const;
|
virtual QSize sizeHint() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QVariant loadOneResource(int type, const QUrl& name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void bindToBrowser(WebBrowser* browser);
|
virtual void bindToBrowser(WebBrowser* browser);
|
||||||
virtual void findText(const QString& text, bool backwards);
|
virtual void findText(const QString& text, bool backwards);
|
||||||
|
@ -86,6 +72,25 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
|
||||||
void downloadLink();
|
void downloadLink();
|
||||||
void onAnchorClicked(const QUrl& url);
|
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:
|
signals:
|
||||||
void pageTitleChanged(const QString& new_title);
|
void pageTitleChanged(const QString& new_title);
|
||||||
void pageUrlChanged(const QUrl& url);
|
void pageUrlChanged(const QUrl& url);
|
||||||
|
|
Loading…
Add table
Reference in a new issue