rough implementation of automatic image loading in articles

This commit is contained in:
Martin Rotter 2022-04-26 12:37:03 +02:00
parent 7910bde52d
commit cec08b4eb5
10 changed files with 311 additions and 224 deletions

View File

@ -17,8 +17,7 @@
#include <windows.h>
#endif
FormUpdate::FormUpdate(QWidget* parent)
: QDialog(parent) {
FormUpdate::FormUpdate(QWidget* parent) : QDialog(parent) {
m_ui.setupUi(this);
m_ui.m_lblCurrentRelease->setText(QSL(APP_VERSION));
m_ui.m_tabInfo->removeTab(1);
@ -35,7 +34,8 @@ FormUpdate::FormUpdate(QWidget* parent)
m_btnUpdate->setToolTip(tr("Download new installation files."));
}
else {
m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ButtonRole::ActionRole);
m_btnUpdate =
m_ui.m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ButtonRole::ActionRole);
m_btnUpdate->setToolTip(tr("Go to application website to get update packages manually."));
}
@ -57,49 +57,49 @@ void FormUpdate::checkForUpdates() {
&SystemFactory::updatesChecked,
this,
[this](const QPair<QList<UpdateInfo>, QNetworkReply::NetworkError>& update) {
m_ui.m_buttonBox->setEnabled(true);
disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr);
m_ui.m_buttonBox->setEnabled(true);
disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr);
if (update.second != QNetworkReply::NoError) {
m_updateInfo = UpdateInfo();
m_ui.m_tabInfo->setEnabled(false);
if (update.second != QNetworkReply::NoError) {
m_updateInfo = UpdateInfo();
m_ui.m_tabInfo->setEnabled(false);
//: Unknown release.
m_ui.m_lblAvailableRelease->setText(tr("unknown"));
m_ui.m_txtChanges->clear();
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Error,
tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)),
tr("List with updates was not\ndownloaded successfully."));
}
else {
const bool self_update_supported = isSelfUpdateSupported();
m_updateInfo = update.first.at(0);
m_ui.m_tabInfo->setEnabled(true);
m_ui.m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion);
//: Unknown release.
m_ui.m_lblAvailableRelease->setText(tr("unknown"));
m_ui.m_txtChanges->clear();
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Error,
tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)),
tr("List with updates was not\ndownloaded successfully."));
}
else {
const bool self_update_supported = isSelfUpdateSupported();
m_updateInfo = update.first.at(0);
m_ui.m_tabInfo->setEnabled(true);
m_ui.m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion);
#if QT_VERSION >= 0x050E00 // Qt >= 5.14.0
m_ui.m_txtChanges->setMarkdown(m_updateInfo.m_changes);
m_ui.m_txtChanges->setMarkdown(m_updateInfo.m_changes);
#else
m_ui.m_txtChanges->setText(m_updateInfo.m_changes);
#endif
if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, QSL(APP_VERSION))) {
m_btnUpdate->setVisible(true);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Ok,
tr("New release available."),
tr("This is new version which can be\ndownloaded."));
if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, QSL(APP_VERSION))) {
m_btnUpdate->setVisible(true);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Ok,
tr("New release available."),
tr("This is new version which can be\ndownloaded."));
if (self_update_supported) {
loadAvailableFiles();
}
}
else {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Warning,
tr("No new release available."),
tr("This release is not newer than\ncurrently installed one."));
}
}
});
if (self_update_supported) {
loadAvailableFiles();
}
}
else {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Warning,
tr("No new release available."),
tr("This release is not newer than\ncurrently installed one."));
}
}
});
qApp->system()->checkForUpdates();
}
@ -107,14 +107,11 @@ void FormUpdate::checkForUpdates() {
void FormUpdate::updateProgress(qint64 bytes_received, qint64 bytes_total) {
if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Information,
tr("Downloaded %1% (update size is %2 kB).").arg(QString::number(bytes_total == 0L
? 0L
: (bytes_received * 100.0) / bytes_total,
'f',
2),
QString::number(bytes_total / 1000.0,
'f',
2)),
tr("Downloaded %1% (update size is %2 kB).")
.arg(QString::number(bytes_total == 0L ? 0L : (bytes_received * 100.0) / bytes_total,
'f',
2),
QString::number(bytes_total / 1000.0, 'f', 2)),
tr("Downloading update..."));
m_ui.m_lblStatus->repaint();
m_lastDownloadedBytes = bytes_received;
@ -140,9 +137,7 @@ void FormUpdate::saveUpdateFile(const QByteArray& file_contents) {
m_readyToInstall = true;
}
else {
qDebugNN << LOGSEC_GUI
<< "Cannot save downloaded update file because target temporary file '"
<< output_file_name
qDebugNN << LOGSEC_GUI << "Cannot save downloaded update file because target temporary file '" << output_file_name
<< "' cannot be opened for writing.";
}
}
@ -175,21 +170,24 @@ void FormUpdate::loadAvailableFiles() {
m_ui.m_tabInfo->setCurrentIndex(1);
}
void FormUpdate::updateCompleted(QNetworkReply::NetworkError status, const QByteArray& contents) {
qDebugNN << LOGSEC_GUI
<< "Download of application update file was completed with code '" << status << "'.";
void FormUpdate::updateCompleted(const QUrl& url, QNetworkReply::NetworkError status, const QByteArray& contents) {
Q_UNUSED(url)
qDebugNN << LOGSEC_GUI << "Download of application update file was completed with code" << QUOTE_W_SPACE_DOT(status);
switch (status) {
case QNetworkReply::NetworkError::NoError:
saveUpdateFile(contents);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Ok, tr("Downloaded successfully"),
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Ok,
tr("Downloaded successfully"),
tr("Package was downloaded successfully.\nYou can install it now."));
m_btnUpdate->setText(tr("Install"));
m_btnUpdate->setEnabled(true);
break;
default:
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Error, tr("Error occured"),
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Error,
tr("Error occured"),
tr("Error occured during downloading of the package."));
m_btnUpdate->setText(tr("Error occured"));
break;
@ -210,32 +208,32 @@ void FormUpdate::startUpdate() {
if (m_readyToInstall) {
close();
qDebugNN << LOGSEC_GUI
<< "Preparing to launch external installer '"
<< QDir::toNativeSeparators(m_updateFilePath)
qDebugNN << LOGSEC_GUI << "Preparing to launch external installer '" << QDir::toNativeSeparators(m_updateFilePath)
<< "'.";
#if defined(Q_OS_WIN)
HINSTANCE exec_result = ShellExecute(nullptr,
nullptr,
reinterpret_cast<const WCHAR*>(QDir::toNativeSeparators(m_updateFilePath).utf16()),
nullptr,
nullptr,
SW_NORMAL);
HINSTANCE exec_result =
ShellExecute(nullptr,
nullptr,
reinterpret_cast<const WCHAR*>(QDir::toNativeSeparators(m_updateFilePath).utf16()),
nullptr,
nullptr,
SW_NORMAL);
if (exec_result <= HINSTANCE(32)) {
qDebugNN << LOGSEC_GUI << "External updater was not launched due to error.";
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
tr("Cannot update application"),
tr("Cannot launch external updater. Update application manually."),
QSystemTrayIcon::MessageIcon::Warning },
{}, {}, this);
qApp->showGuiMessage(Notification::Event::GeneralEvent,
{tr("Cannot update application"),
tr("Cannot launch external updater. Update application manually."),
QSystemTrayIcon::MessageIcon::Warning},
{},
{},
this);
}
else {
qApp->quit();
}
#endif
}
else if (update_for_this_system) {
updateProgress(0, 100);

View File

@ -32,7 +32,7 @@ class RSSGUARD_DLLSPEC FormUpdate : public QDialog {
void startUpdate();
void updateProgress(qint64 bytes_received, qint64 bytes_total);
void updateCompleted(QNetworkReply::NetworkError status, const QByteArray& contents);
void updateCompleted(const QUrl &url, QNetworkReply::NetworkError status, const QByteArray& contents);
void saveUpdateFile(const QByteArray& file_contents);
private:

View File

@ -27,8 +27,16 @@ TextBrowserViewer::TextBrowserViewer(QWidget* parent)
setOpenLinks(false);
viewport()->setAutoFillBackground(true);
m_document.data()->setResourcesEnabled(qApp->settings()
->value(GROUP(Messages), SETTING(Messages::ShowResourcesInArticles))
.toBool());
setDocument(m_document.data());
connect(m_document.data(), &TextBrowserDocument::reloadDocument, this, [this]() {
setHtmlPrivate(html(), m_currentUrl);
});
connect(this, &QTextBrowser::anchorClicked, this, &TextBrowserViewer::onAnchorClicked);
connect(this, QOverload<const QUrl&>::of(&QTextBrowser::highlighted), this, &TextBrowserViewer::linkMouseHighlighted);
}
@ -264,24 +272,27 @@ void TextBrowserViewer::contextMenuEvent(QContextMenuEvent* event) {
return;
}
if (m_actionReloadWithImages.isNull()) {
m_actionReloadWithImages.reset(new QAction(qApp->icons()->fromTheme(QSL("viewimage"), QSL("view-refresh")),
tr("Reload with images"),
this));
if (m_actionEnableResources.isNull()) {
m_actionEnableResources.reset(new QAction(qApp->icons()->fromTheme(QSL("viewimage"), QSL("image-x-generic")),
tr("Enable external resources"),
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);
m_actionEnableResources.data()->setCheckable(true);
m_actionEnableResources.data()->setChecked(m_document.data()->resourcesEnabled());
connect(m_actionOpenExternalBrowser.data(),
&QAction::triggered,
this,
&TextBrowserViewer::openLinkInExternalBrowser);
connect(m_actionDownloadLink.data(), &QAction::triggered, this, &TextBrowserViewer::downloadLink);
connect(m_actionEnableResources.data(), &QAction::toggled, this, &TextBrowserViewer::enableResources);
}
menu->addAction(m_actionReloadWithImages.data());
menu->addAction(m_actionEnableResources.data());
menu->addAction(m_actionOpenExternalBrowser.data());
menu->addAction(m_actionDownloadLink.data());
@ -340,34 +351,9 @@ void TextBrowserViewer::wheelEvent(QWheelEvent* event) {
updateMicroFocus();
}
void TextBrowserViewer::reloadWithImages() {
m_document.data()->m_reloadingWithResources = true;
m_document.data()->m_loadedResources.clear();
QEventLoop loop;
for (const QUrl& url : m_document.data()->m_neededResourcesForHtml) {
if (m_document.data()->m_loadedResources.contains(url)) {
continue;
}
QUrl resolved_url = m_currentUrl.resolved(url);
connect(m_downloader.data(), &Downloader::completed, &loop, &QEventLoop::quit);
m_downloader->manipulateData(resolved_url.toString(), QNetworkAccessManager::Operation::GetOperation, {}, 5000);
loop.exec();
if (m_downloader->lastOutputError() == QNetworkReply::NetworkError::NoError) {
m_document.data()->m_loadedResources.insert(url, m_downloader->lastOutputData());
}
}
auto scrolled = verticalScrollBarPosition();
setHtmlPrivate(html(), m_currentUrl);
setVerticalScrollBarPosition(scrolled);
void TextBrowserViewer::enableResources(bool enable) {
qApp->settings()->setValue(GROUP(Messages), Messages::ShowResourcesInArticles, enable);
m_document.data()->setResourcesEnabled(enable);
}
void TextBrowserViewer::openLinkInExternalBrowser() {
@ -411,9 +397,9 @@ void TextBrowserViewer::onAnchorClicked(const QUrl& url) {
}
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_neededResourcesForHtml.clear();
m_document.data()->m_resourceTimer.stop();
m_document.data()->m_neededResources.clear();
m_document.data()->m_resourceTimer.start();
setHtmlPrivate(html, base_url);
@ -431,12 +417,7 @@ void TextBrowserViewer::setHtml(const QString& html, const QUrl& 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_neededResourcesForHtml.clear();
}
QTextBrowser::setHtml(html);
setZoomFactor(m_zoomFactor);
emit pageTitleChanged(documentTitle());
@ -444,21 +425,76 @@ void TextBrowserViewer::setHtmlPrivate(const QString& html, const QUrl& base_url
}
TextBrowserDocument::TextBrowserDocument(QObject* parent)
: QTextDocument(parent), m_reloadingWithResources(false),
m_placeholderImage(qApp->icons()->miscPixmap("image-placeholder")) {}
: 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);
}
QVariant TextBrowserDocument::loadResource(int type, const QUrl& name) {
if (!m_reloadingWithResources) {
if (type == QTextDocument::ResourceType::ImageResource && !m_neededResourcesForHtml.contains(name)) {
m_neededResourcesForHtml.append(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;
}
else if (m_loadedResources.contains(name)) {
return QImage::fromData(m_loadedResources.value(name));
}
else {
return m_placeholderImage;
}
void TextBrowserDocument::reloadHtmlDelayed() {
// Timer has elapsed, we do not wait for other resources,
// we download what we know about.
m_resourceTimer.stop();
if (!m_neededResources.isEmpty()) {
downloadNextNeededResource();
}
}
void TextBrowserDocument::downloadNextNeededResource() {
if (m_neededResources.isEmpty()) {
// Everything is downloaded.
emit reloadDocument();
}
else {
m_resourceDownloader.data()->manipulateData(m_neededResources.takeFirst().toString(),
QNetworkAccessManager::Operation::GetOperation,
{},
5000);
}
}
void TextBrowserDocument::resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents) {
if (status == QNetworkReply::NetworkError::NoError && !m_loadedResources.contains(url)) {
m_loadedResources.insert(url, contents);
}
downloadNextNeededResource();
}
bool TextBrowserDocument::resourcesEnabled() const {
return m_resourcesEnabled;
}
void TextBrowserDocument::setResourcesEnabled(bool enabled) {
m_resourcesEnabled = enabled;
}

View File

@ -9,8 +9,10 @@
#include "network-web/adblock/adblockmanager.h"
#include <QNetworkReply>
#include <QPixmap>
#include <QPointer>
#include <QTimer>
class QContextMenuEvent;
class QResizeEvent;
@ -25,12 +27,26 @@ class TextBrowserDocument : public QTextDocument {
public:
explicit TextBrowserDocument(QObject* parent = nullptr);
bool resourcesEnabled() const;
void setResourcesEnabled(bool enabled);
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_reloadingWithResources;
QList<QUrl> m_neededResourcesForHtml;
bool m_resourcesEnabled;
QTimer m_resourceTimer;
QList<QUrl> m_neededResources;
QScopedPointer<Downloader> m_resourceDownloader;
QMap<QUrl, QByteArray> m_loadedResources;
QPixmap m_placeholderImage;
};
@ -65,7 +81,7 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
virtual void wheelEvent(QWheelEvent* event);
private slots:
void reloadWithImages();
void enableResources(bool enable);
void openLinkInExternalBrowser();
void downloadLink();
void onAnchorClicked(const QUrl& url);
@ -93,7 +109,7 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
QPointer<RootItem> m_root;
QFont m_baseFont;
qreal m_zoomFactor = 1.0;
QScopedPointer<QAction> m_actionReloadWithImages;
QScopedPointer<QAction> m_actionEnableResources;
QScopedPointer<QAction> m_actionOpenExternalBrowser;
QScopedPointer<QAction> m_actionDownloadLink;
QScopedPointer<TextBrowserDocument> m_document;

View File

@ -49,11 +49,10 @@ DKEY AdBlock::AdBlockEnabled = "enabled";
DVALUE(bool) AdBlock::AdBlockEnabledDef = false;
DKEY AdBlock::FilterLists = "filter_lists";
DVALUE(QStringList) AdBlock::FilterListsDef = {
QSL("https://easylist.to/easylist/easylist.txt"),
QSL("https://easylist.to/easylist/easyprivacy.txt"),
QSL("https://easylist.to/easylist/fanboy-social.txt")
};
DVALUE(QStringList)
AdBlock::FilterListsDef = {QSL("https://easylist.to/easylist/easylist.txt"),
QSL("https://easylist.to/easylist/easyprivacy.txt"),
QSL("https://easylist.to/easylist/fanboy-social.txt")};
DKEY AdBlock::CustomFilters = "custom_filters";
DVALUE(QStringList) AdBlock::CustomFiltersDef = {};
@ -117,6 +116,9 @@ DVALUE(bool) Messages::DisplayEnclosuresInMessageDef = false;
DKEY Messages::EnableMessagePreview = "enable_message_preview";
DVALUE(bool) Messages::EnableMessagePreviewDef = true;
DKEY Messages::ShowResourcesInArticles = "enable_message_resources";
DVALUE(bool) Messages::ShowResourcesInArticlesDef = false;
DKEY Messages::Zoom = "zoom";
DVALUE(qreal) Messages::ZoomDef = double(1.0);
@ -207,11 +209,14 @@ DKEY GUI::HeightRowFeeds = "height_row_feeds";
DVALUE(int) GUI::HeightRowFeedsDef = -1;
DKEY GUI::FeedsToolbarActions = "feeds_toolbar";
DVALUE(char*) GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionMarkAllItemsRead,spacer,search";
DVALUE(char*)
GUI::FeedsToolbarActionsDef =
"m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionMarkAllItemsRead,spacer,search";
DKEY GUI::StatusbarActions = "status_bar";
DVALUE(char*) GUI::StatusbarActionsDef =
"m_barProgressDownloadAction,m_barProgressFeedsAction,m_actionUpdateAllItems,m_actionUpdateSelectedItems,m_actionStopRunningItemsUpdate,m_actionFullscreen,m_actionQuit";
DVALUE(char*)
GUI::StatusbarActionsDef = "m_barProgressDownloadAction,m_barProgressFeedsAction,m_actionUpdateAllItems,m_"
"actionUpdateSelectedItems,m_actionStopRunningItemsUpdate,m_actionFullscreen,m_actionQuit";
DKEY GUI::SettingsWindowInitialSize = "settings_window_size";
DKEY GUI::MainWindowInitialSize = "window_size";
@ -283,8 +288,10 @@ DKEY GUI::HideTabBarIfOnlyOneTab = "hide_tabbar_one_tab";
DVALUE(bool) GUI::HideTabBarIfOnlyOneTabDef = false;
DKEY GUI::MessagesToolbarDefaultButtons = "messages_toolbar";
DVALUE(char*) GUI::MessagesToolbarDefaultButtonsDef =
"m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,separator,highlighter,filter,spacer,search";
DVALUE(char*)
GUI::MessagesToolbarDefaultButtonsDef =
"m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,"
"separator,highlighter,filter,spacer,search";
DKEY GUI::DefaultSortColumnFeeds = "default_sort_column_feeds";
DVALUE(int) GUI::DefaultSortColumnFeedsDef = FDS_MODEL_TITLE_INDEX;
@ -451,8 +458,8 @@ QSettings::Status Settings::checkSettings() {
bool Settings::initiateRestoration(const QString& settings_backup_file_path) {
return IOFactory::copyFile(settings_backup_file_path,
QFileInfo(fileName()).absolutePath() + QDir::separator() +
BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS);
QFileInfo(fileName()).absolutePath() + QDir::separator() + BACKUP_NAME_SETTINGS +
BACKUP_SUFFIX_SETTINGS);
}
void Settings::finishRestoration(const QString& desired_settings_file_path) {
@ -460,9 +467,7 @@ void Settings::finishRestoration(const QString& desired_settings_file_path) {
BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS;
if (QFile::exists(backup_settings_file)) {
qWarningNN << LOGSEC_CORE
<< "Backup settings file"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(backup_settings_file))
qWarningNN << LOGSEC_CORE << "Backup settings file" << QUOTE_W_SPACE(QDir::toNativeSeparators(backup_settings_file))
<< "was detected. Restoring it.";
if (IOFactory::copyFile(backup_settings_file, desired_settings_file_path)) {
@ -489,22 +494,16 @@ Settings* Settings::setupSettings(QObject* parent) {
new_settings = new Settings(properties.m_absoluteSettingsFileName, QSettings::IniFormat, properties.m_type, parent);
if (properties.m_type == SettingsProperties::SettingsType::Portable) {
qDebugNN << LOGSEC_CORE
<< "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))
<< "(portable way).";
qDebugNN << LOGSEC_CORE << "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)) << "(portable way).";
}
else if (properties.m_type == SettingsProperties::SettingsType::Custom) {
qDebugNN << LOGSEC_CORE
<< "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))
<< "(custom way).";
qDebugNN << LOGSEC_CORE << "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)) << "(custom way).";
}
else {
qDebugNN << LOGSEC_CORE
<< "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))
<< "(non-portable way).";
qDebugNN << LOGSEC_CORE << "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)) << "(non-portable way).";
}
return new_settings;

View File

@ -22,8 +22,8 @@
#define NON_CONST_VALUE(x) extern x
#define DVALUE(x) const x
#define NON_CONST_DVALUE(x) x
#define SETTING(x) x, x ## Def
#define DEFAULT_VALUE(x) x ## Def
#define SETTING(x) x, x##Def
#define DEFAULT_VALUE(x) x##Def
#define GROUP(x) x::ID
#if defined(USE_WEBENGINE)
@ -47,7 +47,7 @@ namespace Node {
KEY PackageFolder;
VALUE(QString) PackageFolderDef;
}
} // namespace Node
namespace AdBlock {
KEY ID;
@ -60,7 +60,7 @@ namespace AdBlock {
KEY CustomFilters;
VALUE(QStringList) CustomFiltersDef;
}
} // namespace AdBlock
// Feeds.
namespace Feeds {
@ -109,7 +109,7 @@ namespace Feeds {
VALUE(bool) OnlyBasicShortcutsInListsDef;
KEY ListFont;
}
} // namespace Feeds
// Messages.
namespace Messages {
@ -124,6 +124,9 @@ namespace Messages {
KEY EnableMessagePreview;
VALUE(bool) EnableMessagePreviewDef;
KEY ShowResourcesInArticles;
VALUE(bool) ShowResourcesInArticlesDef;
KEY Zoom;
VALUE(qreal) ZoomDef;
@ -176,7 +179,7 @@ namespace Messages {
NON_CONST_VALUE(QString) PreviewerFontStandardDef;
KEY ListFont;
}
} // namespace Messages
// Custom skin colors.
namespace CustomSkinColors {
@ -186,7 +189,7 @@ namespace CustomSkinColors {
VALUE(bool) EnabledDef;
KEY CustomSkinColors;
}
} // namespace CustomSkinColors
// GUI.
namespace GUI {
@ -311,7 +314,7 @@ namespace GUI {
KEY Style;
VALUE(char*) StyleDef;
}
} // namespace GUI
// General.
namespace General {
@ -325,7 +328,7 @@ namespace General {
KEY Language;
VALUE(QString) LanguageDef;
}
} // namespace General
// Downloads.
namespace Downloads {
@ -353,7 +356,7 @@ namespace Downloads {
KEY ItemUrl;
KEY ItemLocation;
KEY ItemDone;
}
} // namespace Downloads
// Proxy.
namespace Proxy {
@ -377,7 +380,7 @@ namespace Proxy {
KEY Port;
VALUE(int) PortDef;
}
} // namespace Proxy
// Database.
namespace Database {
@ -413,7 +416,7 @@ namespace Database {
KEY ActiveDriver;
VALUE(char*) ActiveDriverDef;
}
} // namespace Database
// Keyboard.
namespace Keyboard {
@ -463,7 +466,7 @@ namespace Browser {
KEY CustomExternalEmailArguments;
VALUE(char*) CustomExternalEmailArgumentsDef;
}
} // namespace Browser
// Categories.
namespace CategoriesExpandStates {
@ -471,10 +474,9 @@ namespace CategoriesExpandStates {
}
class Settings : public QSettings {
Q_OBJECT
Q_OBJECT
public:
// Destructor.
virtual ~Settings();
@ -510,9 +512,11 @@ class Settings : public QSettings {
static SettingsProperties determineProperties();
private:
// Constructor.
explicit Settings(const QString& file_name, Format format, SettingsProperties::SettingsType type, QObject* parent = nullptr);
explicit Settings(const QString& file_name,
Format format,
SettingsProperties::SettingsType type,
QObject* parent = nullptr);
SettingsProperties::SettingsType m_initializationStatus;
};

View File

@ -16,9 +16,9 @@
Downloader::Downloader(QObject* parent)
: QObject(parent), m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)), m_inputData(QByteArray()),
m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()),
m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError) {
m_timer(new QTimer(this)), m_inputData(QByteArray()), m_inputMultipartData(nullptr), m_targetProtected(false),
m_targetUsername(QString()), m_targetPassword(QString()), m_lastOutputData(QByteArray()),
m_lastOutputError(QNetworkReply::NoError) {
m_timer->setInterval(DOWNLOAD_TIMEOUT);
m_timer->setSingleShot(true);
@ -32,25 +32,52 @@ Downloader::~Downloader() {
qDebugNN << LOGSEC_NETWORK << "Destroying Downloader instance.";
}
void Downloader::downloadFile(const QString& url, int timeout, bool protected_contents, const QString& username,
void Downloader::downloadFile(const QString& url,
int timeout,
bool protected_contents,
const QString& username,
const QString& password) {
manipulateData(url, QNetworkAccessManager::GetOperation, QByteArray(), timeout,
protected_contents, username, password);
manipulateData(url,
QNetworkAccessManager::GetOperation,
QByteArray(),
timeout,
protected_contents,
username,
password);
}
void Downloader::uploadFile(const QString& url, const QByteArray& data, int timeout,
bool protected_contents, const QString& username, const QString& password) {
manipulateData(url, QNetworkAccessManager::Operation::PostOperation, data, timeout, protected_contents, username, password);
void Downloader::uploadFile(const QString& url,
const QByteArray& data,
int timeout,
bool protected_contents,
const QString& username,
const QString& password) {
manipulateData(url,
QNetworkAccessManager::Operation::PostOperation,
data,
timeout,
protected_contents,
username,
password);
}
void Downloader::manipulateData(const QString& url, QNetworkAccessManager::Operation operation,
QHttpMultiPart* multipart_data, int timeout,
bool protected_contents, const QString& username, const QString& password) {
void Downloader::manipulateData(const QString& url,
QNetworkAccessManager::Operation operation,
QHttpMultiPart* multipart_data,
int timeout,
bool protected_contents,
const QString& username,
const QString& password) {
manipulateData(url, operation, QByteArray(), multipart_data, timeout, protected_contents, username, password);
}
void Downloader::manipulateData(const QString& url, QNetworkAccessManager::Operation operation, const QByteArray& data,
int timeout, bool protected_contents, const QString& username, const QString& password) {
void Downloader::manipulateData(const QString& url,
QNetworkAccessManager::Operation operation,
const QByteArray& data,
int timeout,
bool protected_contents,
const QString& username,
const QString& password) {
manipulateData(url, operation, data, nullptr, timeout, protected_contents, username, password);
}
@ -123,20 +150,13 @@ void Downloader::finished() {
// Setup redirection URL and download again.
QNetworkRequest request = reply->request();
qWarningNN << LOGSEC_NETWORK
<< "Network layer indicates HTTP redirection is needed.";
qWarningNN << LOGSEC_NETWORK
<< "Origin URL:"
<< QUOTE_W_SPACE_DOT(request.url().toString());
qWarningNN << LOGSEC_NETWORK
<< "Proposed redirection URL:"
<< QUOTE_W_SPACE_DOT(redirection_url.toString());
qWarningNN << LOGSEC_NETWORK << "Network layer indicates HTTP redirection is needed.";
qWarningNN << LOGSEC_NETWORK << "Origin URL:" << QUOTE_W_SPACE_DOT(request.url().toString());
qWarningNN << LOGSEC_NETWORK << "Proposed redirection URL:" << QUOTE_W_SPACE_DOT(redirection_url.toString());
redirection_url = request.url().resolved(redirection_url);
qWarningNN << LOGSEC_NETWORK
<< "Resolved redirection URL:"
<< QUOTE_W_SPACE_DOT(redirection_url.toString());
qWarningNN << LOGSEC_NETWORK << "Resolved redirection URL:" << QUOTE_W_SPACE_DOT(redirection_url.toString());
request.setUrl(redirection_url);
@ -191,7 +211,7 @@ void Downloader::finished() {
m_inputMultipartData->deleteLater();
}
emit completed(m_lastOutputError, m_lastOutputData);
emit completed(reply->url(), m_lastOutputError, m_lastOutputData);
}
}
@ -237,9 +257,8 @@ QList<HttpResponse> Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
int start_of_headers = http_response_str.indexOf(QRegularExpression(QSL("\\r\\r?\\n")), start_of_http);
int start_of_body = http_response_str.indexOf(QRegularExpression(QSL("(\\r\\r?\\n){2,}")), start_of_headers + 2);
QString body = http_response_str.mid(start_of_body);
QString headers = http_response_str.mid(start_of_headers,
start_of_body - start_of_headers).replace(QRegularExpression(QSL("[\\n\\r]+")),
QSL("\n"));
QString headers = http_response_str.mid(start_of_headers, start_of_body - start_of_headers)
.replace(QRegularExpression(QSL("[\\n\\r]+")), QSL("\n"));
auto header_lines = headers.split(QL1C('\n'),
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
@ -312,11 +331,8 @@ QVariant Downloader::lastContentType() const {
}
void Downloader::setProxy(const QNetworkProxy& proxy) {
qWarningNN << LOGSEC_NETWORK
<< "Setting specific downloader proxy, address:"
<< QUOTE_W_SPACE_COMMA(proxy.hostName())
<< " type:"
<< QUOTE_W_SPACE_DOT(proxy.type());
qWarningNN << LOGSEC_NETWORK << "Setting specific downloader proxy, address:" << QUOTE_W_SPACE_COMMA(proxy.hostName())
<< " type:" << QUOTE_W_SPACE_DOT(proxy.type());
m_downloadManager->setProxy(proxy);
}

View File

@ -17,7 +17,7 @@ class SilentNetworkAccessManager;
class QTimer;
class Downloader : public QObject {
Q_OBJECT
Q_OBJECT
public:
explicit Downloader(QObject* parent = nullptr);
@ -38,28 +38,39 @@ class Downloader : public QObject {
void appendRawHeader(const QByteArray& name, const QByteArray& value);
// Performs asynchronous download of given file. Redirections are handled.
void downloadFile(const QString& url, int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
const QString& username = QString(), const QString& password = QString());
void downloadFile(const QString& url,
int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString());
void uploadFile(const QString& url, const QByteArray& data, int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false, const QString& username = QString(),
void uploadFile(const QString& url,
const QByteArray& data,
int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString());
void manipulateData(const QString& url, QNetworkAccessManager::Operation operation,
void manipulateData(const QString& url,
QNetworkAccessManager::Operation operation,
QHttpMultiPart* multipart_data,
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
const QString& username = QString(), const QString& password = QString());
int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString());
void manipulateData(const QString& url, QNetworkAccessManager::Operation operation,
void manipulateData(const QString& url,
QNetworkAccessManager::Operation operation,
const QByteArray& data = QByteArray(),
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
const QString& username = QString(), const QString& password = QString());
int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString());
signals:
// Emitted when new progress is known.
void progress(qint64 bytes_received, qint64 bytes_total);
void completed(QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
void completed(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
private slots:
@ -72,10 +83,14 @@ class Downloader : public QObject {
private:
void setCustomPropsToReply(QNetworkReply* reply);
QList<HttpResponse> decodeMultipartAnswer(QNetworkReply* reply);
void manipulateData(const QString& url, QNetworkAccessManager::Operation operation,
const QByteArray& data, QHttpMultiPart* multipart_data,
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
const QString& username = QString(), const QString& password = QString());
void manipulateData(const QString& url,
QNetworkAccessManager::Operation operation,
const QByteArray& data,
QHttpMultiPart* multipart_data,
int timeout = DOWNLOAD_TIMEOUT,
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString());
void runDeleteRequest(const QNetworkRequest& request);
void runPutRequest(const QNetworkRequest& request, const QByteArray& data);
void runPostRequest(const QNetworkRequest& request, QHttpMultiPart* multipart_data);

View File

@ -44,7 +44,8 @@
#include <QXmlStreamReader>
GoogleSuggest::GoogleSuggest(LocationLineEdit* editor, QObject* parent)
: QObject(parent), editor(editor), m_downloader(new Downloader(this)), popup(new QListWidget()), m_enteredText(QString()) {
: QObject(parent), editor(editor), m_downloader(new Downloader(this)), popup(new QListWidget()),
m_enteredText(QString()) {
popup->setWindowFlags(Qt::WindowType::Popup);
popup->setFocusPolicy(Qt::FocusPolicy::NoFocus);
popup->setFocusProxy(editor);
@ -155,7 +156,9 @@ void GoogleSuggest::autoSuggest() {
m_downloader->downloadFile(url);
}
void GoogleSuggest::handleNetworkData(QNetworkReply::NetworkError status, const QByteArray& contents) {
void GoogleSuggest::handleNetworkData(const QUrl& url, QNetworkReply::NetworkError status, const QByteArray& contents) {
Q_UNUSED(url)
if (status == QNetworkReply::NetworkError::NoError) {
QStringList choices;
QDomDocument xml;

View File

@ -42,7 +42,7 @@ class LocationLineEdit;
class QTimer;
class GoogleSuggest : public QObject {
Q_OBJECT
Q_OBJECT
public:
explicit GoogleSuggest(LocationLineEdit* editor, QObject* parent = nullptr);
@ -54,7 +54,7 @@ class GoogleSuggest : public QObject {
void doneCompletion();
void preventSuggest();
void autoSuggest();
void handleNetworkData(QNetworkReply::NetworkError status, const QByteArray& contents);
void handleNetworkData(const QUrl& url, QNetworkReply::NetworkError status, const QByteArray& contents);
private:
LocationLineEdit* editor;