Some polishments, now send via async network on same thread.
This commit is contained in:
parent
ebddff6fb1
commit
7b62a456a6
9 changed files with 61 additions and 152 deletions
|
|
@ -331,7 +331,6 @@ HEADERS += src/core/feeddownloader.h \
|
||||||
src/services/standard/feedparser.h \
|
src/services/standard/feedparser.h \
|
||||||
src/services/standard/rdfparser.h \
|
src/services/standard/rdfparser.h \
|
||||||
src/services/standard/rssparser.h \
|
src/services/standard/rssparser.h \
|
||||||
src/miscellaneous/serviceoperator.h \
|
|
||||||
src/services/abstract/cacheforserviceroot.h \
|
src/services/abstract/cacheforserviceroot.h \
|
||||||
src/services/tt-rss/gui/formeditttrssaccount.h \
|
src/services/tt-rss/gui/formeditttrssaccount.h \
|
||||||
src/gui/guiutilities.h \
|
src/gui/guiutilities.h \
|
||||||
|
|
@ -458,7 +457,6 @@ SOURCES += src/core/feeddownloader.cpp \
|
||||||
src/services/standard/feedparser.cpp \
|
src/services/standard/feedparser.cpp \
|
||||||
src/services/standard/rdfparser.cpp \
|
src/services/standard/rdfparser.cpp \
|
||||||
src/services/standard/rssparser.cpp \
|
src/services/standard/rssparser.cpp \
|
||||||
src/miscellaneous/serviceoperator.cpp \
|
|
||||||
src/services/abstract/cacheforserviceroot.cpp \
|
src/services/abstract/cacheforserviceroot.cpp \
|
||||||
src/services/tt-rss/gui/formeditttrssaccount.cpp \
|
src/services/tt-rss/gui/formeditttrssaccount.cpp \
|
||||||
src/gui/guiutilities.cpp \
|
src/gui/guiutilities.cpp \
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,13 @@
|
||||||
|
|
||||||
FeedReader::FeedReader(QObject* parent)
|
FeedReader::FeedReader(QObject* parent)
|
||||||
: QObject(parent), m_feedServices(QList<ServiceEntryPoint*>()),
|
: QObject(parent), m_feedServices(QList<ServiceEntryPoint*>()),
|
||||||
m_cacheSaveFutureWatcher(new QFutureWatcher<void>(this)), m_autoUpdateTimer(new QTimer(this)),
|
m_autoUpdateTimer(new QTimer(this)),
|
||||||
m_feedDownloaderThread(nullptr), m_feedDownloader(nullptr),
|
m_feedDownloaderThread(nullptr), m_feedDownloader(nullptr),
|
||||||
m_dbCleanerThread(nullptr), m_dbCleaner(nullptr) {
|
m_dbCleanerThread(nullptr), m_dbCleaner(nullptr) {
|
||||||
m_feedsModel = new FeedsModel(this);
|
m_feedsModel = new FeedsModel(this);
|
||||||
m_feedsProxyModel = new FeedsProxyModel(m_feedsModel, this);
|
m_feedsProxyModel = new FeedsProxyModel(m_feedsModel, this);
|
||||||
m_messagesModel = new MessagesModel(this);
|
m_messagesModel = new MessagesModel(this);
|
||||||
m_messagesProxyModel = new MessagesProxyModel(m_messagesModel, this);
|
m_messagesProxyModel = new MessagesProxyModel(m_messagesModel, this);
|
||||||
connect(m_cacheSaveFutureWatcher, &QFutureWatcher<void>::finished, this, &FeedReader::asyncCacheSaveFinished);
|
|
||||||
connect(m_autoUpdateTimer, &QTimer::timeout, this, &FeedReader::executeNextAutoUpdate);
|
connect(m_autoUpdateTimer, &QTimer::timeout, this, &FeedReader::executeNextAutoUpdate);
|
||||||
updateAutoUpdateStatus();
|
updateAutoUpdateStatus();
|
||||||
asyncCacheSaveFinished();
|
asyncCacheSaveFinished();
|
||||||
|
|
@ -213,56 +212,19 @@ void FeedReader::executeNextAutoUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReader::checkServicesForAsyncOperations() {
|
void FeedReader::checkServicesForAsyncOperations() {
|
||||||
checkServicesForAsyncOperations(false);
|
foreach (ServiceRoot* service, m_feedsModel->serviceRoots()) {
|
||||||
}
|
// Store any cached data.
|
||||||
|
service->saveAllCachedData();
|
||||||
void FeedReader::checkServicesForAsyncOperations(bool wait_for_future, bool do_on_this_thread) {
|
|
||||||
if (!do_on_this_thread && m_cacheSaveFutureWatcher->future().isRunning()) {
|
|
||||||
qDebug("Previous future is still running.");
|
|
||||||
|
|
||||||
// If we want to wait for future synchronously, we want to make sure that
|
|
||||||
// we save all cached data (app exit).
|
|
||||||
if (wait_for_future) {
|
|
||||||
qWarning("Waiting for previously started saving of cached service data.");
|
|
||||||
m_cacheSaveFutureWatcher->future().waitForFinished();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning("Some cached service data are being saved now, so aborting this saving cycle.");
|
|
||||||
|
|
||||||
// Some cache saving is now running.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_on_this_thread) {
|
|
||||||
foreach (ServiceRoot* service, m_feedsModel->serviceRoots()) {
|
|
||||||
// Store any cached data.
|
|
||||||
service->saveAllCachedData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
QFuture<void> future = QtConcurrent::run([&] {
|
|
||||||
foreach (ServiceRoot* service, m_feedsModel->serviceRoots()) {
|
|
||||||
// Store any cached data.
|
|
||||||
service->saveAllCachedData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (wait_for_future) {
|
asyncCacheSaveFinished();
|
||||||
qDebug("Waiting for saving of cached service data to finish.");
|
|
||||||
future.waitForFinished();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_cacheSaveFutureWatcher->setFuture(future);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedReader::asyncCacheSaveFinished() {
|
void FeedReader::asyncCacheSaveFinished() {
|
||||||
qDebug("I will start next check for cached service data in 30 seconds.");
|
qDebug("I will start next check for cached service data in 30 seconds.");
|
||||||
QTimer::singleShot(30000, [&] {
|
QTimer::singleShot(60000, [&] {
|
||||||
qDebug("Starting next check for cached service data in NOW.");
|
qDebug("Starting next check for cached service data in NOW.");
|
||||||
checkServicesForAsyncOperations(false);
|
checkServicesForAsyncOperations();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ class MessagesModel;
|
||||||
class MessagesProxyModel;
|
class MessagesProxyModel;
|
||||||
class FeedsProxyModel;
|
class FeedsProxyModel;
|
||||||
class ServiceEntryPoint;
|
class ServiceEntryPoint;
|
||||||
class ServiceOperator;
|
|
||||||
class DatabaseCleaner;
|
class DatabaseCleaner;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
|
|
@ -79,7 +78,6 @@ class FeedReader : public QObject {
|
||||||
// Is executed when next auto-update round could be done.
|
// Is executed when next auto-update round could be done.
|
||||||
void executeNextAutoUpdate();
|
void executeNextAutoUpdate();
|
||||||
void checkServicesForAsyncOperations();
|
void checkServicesForAsyncOperations();
|
||||||
void checkServicesForAsyncOperations(bool wait_for_future, bool do_on_this_thread = false);
|
|
||||||
void asyncCacheSaveFinished();
|
void asyncCacheSaveFinished();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -95,16 +93,12 @@ class FeedReader : public QObject {
|
||||||
MessagesModel* m_messagesModel;
|
MessagesModel* m_messagesModel;
|
||||||
MessagesProxyModel* m_messagesProxyModel;
|
MessagesProxyModel* m_messagesProxyModel;
|
||||||
|
|
||||||
QFutureWatcher<void>* m_cacheSaveFutureWatcher;
|
|
||||||
|
|
||||||
// Auto-update stuff.
|
// Auto-update stuff.
|
||||||
QTimer* m_autoUpdateTimer;
|
QTimer* m_autoUpdateTimer;
|
||||||
bool m_globalAutoUpdateEnabled;
|
bool m_globalAutoUpdateEnabled;
|
||||||
int m_globalAutoUpdateInitialInterval;
|
int m_globalAutoUpdateInitialInterval;
|
||||||
int m_globalAutoUpdateRemainingInterval;
|
int m_globalAutoUpdateRemainingInterval;
|
||||||
|
|
||||||
ServiceOperator* m_serviceOperator;
|
|
||||||
|
|
||||||
QThread* m_feedDownloaderThread;
|
QThread* m_feedDownloaderThread;
|
||||||
FeedDownloader* m_feedDownloader;
|
FeedDownloader* m_feedDownloader;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// This file is part of RSS Guard.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
|
|
||||||
//
|
|
||||||
// RSS Guard is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// RSS Guard is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#include "miscellaneous/serviceoperator.h"
|
|
||||||
|
|
||||||
|
|
||||||
ServiceOperator::ServiceOperator(QObject* parent) : QObject(parent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceOperator::~ServiceOperator() {
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// This file is part of RSS Guard.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
|
|
||||||
//
|
|
||||||
// RSS Guard is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// RSS Guard is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#ifndef SERVICEOPERATOR_H
|
|
||||||
#define SERVICEOPERATOR_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceOperator : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ServiceOperator(QObject* parent = 0);
|
|
||||||
virtual ~ServiceOperator();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SERVICEOPERATOR_H
|
|
||||||
|
|
@ -148,6 +148,28 @@ QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList<QString>& u
|
||||||
return network_result;
|
return network_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Downloader* NetworkFactory::performAsyncNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
|
||||||
|
const QString& input_content_type,
|
||||||
|
QNetworkAccessManager::Operation operation,
|
||||||
|
bool protected_contents, const QString& username,
|
||||||
|
const QString& password, bool set_basic_header) {
|
||||||
|
Downloader* downloader = new Downloader();
|
||||||
|
|
||||||
|
if (!input_content_type.isEmpty()) {
|
||||||
|
downloader->appendRawHeader("Content-Type", input_content_type.toLocal8Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_basic_header) {
|
||||||
|
QString basic_value = username + ":" + password;
|
||||||
|
QString header_value = QString("Basic ") + QString(basic_value.toUtf8().toBase64());
|
||||||
|
|
||||||
|
downloader->appendRawHeader("Authorization", header_value.toLocal8Bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
downloader->manipulateData(url, operation, input_data, timeout, protected_contents, username, password);
|
||||||
|
return downloader;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkResult NetworkFactory::performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
|
NetworkResult NetworkFactory::performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
|
||||||
const QString& input_content_type, QByteArray& output,
|
const QString& input_content_type, QByteArray& output,
|
||||||
QNetworkAccessManager::Operation operation, bool protected_contents,
|
QNetworkAccessManager::Operation operation, bool protected_contents,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
|
|
||||||
typedef QPair<QNetworkReply::NetworkError, QVariant> NetworkResult;
|
typedef QPair<QNetworkReply::NetworkError, QVariant> NetworkResult;
|
||||||
|
class Downloader;
|
||||||
|
|
||||||
class NetworkFactory {
|
class NetworkFactory {
|
||||||
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
|
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
|
||||||
|
|
@ -43,6 +44,12 @@ class NetworkFactory {
|
||||||
// given URL belongs to.
|
// given URL belongs to.
|
||||||
static QNetworkReply::NetworkError downloadIcon(const QList<QString>& urls, int timeout, QIcon& output);
|
static QNetworkReply::NetworkError downloadIcon(const QList<QString>& urls, int timeout, QIcon& output);
|
||||||
|
|
||||||
|
static Downloader* performAsyncNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
|
||||||
|
const QString& input_content_type,
|
||||||
|
QNetworkAccessManager::Operation operation,
|
||||||
|
bool protected_contents = false, const QString& username = QString(),
|
||||||
|
const QString& password = QString(), bool set_basic_header = false);
|
||||||
|
|
||||||
static NetworkResult performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
|
static NetworkResult performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data,
|
||||||
const QString& input_content_type, QByteArray& output,
|
const QString& input_content_type, QByteArray& output,
|
||||||
QNetworkAccessManager::Operation operation,
|
QNetworkAccessManager::Operation operation,
|
||||||
|
|
|
||||||
|
|
@ -299,10 +299,9 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::triggerFeedUpdate(int feed_i
|
||||||
return (m_lastError = network_reply.first);
|
return (m_lastError = network_reply.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids) {
|
void OwnCloudNetworkFactory::markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids) {
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
QJsonArray ids;
|
QJsonArray ids;
|
||||||
QByteArray raw_output;
|
|
||||||
QString final_url;
|
QString final_url;
|
||||||
|
|
||||||
if (status == RootItem::Read) {
|
if (status == RootItem::Read) {
|
||||||
|
|
@ -317,31 +316,25 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesRead(RootItem::R
|
||||||
}
|
}
|
||||||
|
|
||||||
json["items"] = ids;
|
json["items"] = ids;
|
||||||
qDebug() << QSL("Raw output for marking msgs read with Nextcloud is : \n\n") << QString::fromUtf8(raw_output);
|
|
||||||
NetworkResult network_reply = NetworkFactory::performNetworkOperation(final_url,
|
|
||||||
qApp->settings()->value(GROUP(Feeds),
|
|
||||||
SETTING(Feeds::UpdateTimeout)).toInt(),
|
|
||||||
QJsonDocument(json).toJson(QJsonDocument::Compact),
|
|
||||||
QSL("application/json"),
|
|
||||||
raw_output,
|
|
||||||
QNetworkAccessManager::PutOperation,
|
|
||||||
true, m_authUsername, m_authPassword,
|
|
||||||
true);
|
|
||||||
|
|
||||||
if (network_reply.first != QNetworkReply::NoError) {
|
Downloader* downloader = NetworkFactory::performAsyncNetworkOperation(final_url,
|
||||||
qWarning("ownCloud: Marking messages as (un)read failed with error %d.", network_reply.first);
|
qApp->settings()->value(GROUP(Feeds),
|
||||||
}
|
SETTING(Feeds::UpdateTimeout)).toInt(),
|
||||||
|
QJsonDocument(json).toJson(QJsonDocument::Compact),
|
||||||
|
CONTENT_TYPE,
|
||||||
|
QNetworkAccessManager::PutOperation,
|
||||||
|
true, m_authUsername, m_authPassword,
|
||||||
|
true);
|
||||||
|
|
||||||
return (m_lastError = network_reply.first);
|
QObject::connect(downloader, &Downloader::completed, downloader, &Downloader::deleteLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance,
|
void OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance,
|
||||||
const QStringList& feed_ids,
|
const QStringList& feed_ids,
|
||||||
const QStringList& guid_hashes) {
|
const QStringList& guid_hashes) {
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
QJsonArray ids;
|
QJsonArray ids;
|
||||||
QByteArray raw_output;
|
QString final_url;
|
||||||
QString final_url;
|
|
||||||
|
|
||||||
if (importance == RootItem::Important) {
|
if (importance == RootItem::Important) {
|
||||||
final_url = m_fixedUrl + API_PATH + "items/star/multiple";
|
final_url = m_fixedUrl + API_PATH + "items/star/multiple";
|
||||||
|
|
@ -358,21 +351,16 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesStarred(RootItem
|
||||||
}
|
}
|
||||||
|
|
||||||
json["items"] = ids;
|
json["items"] = ids;
|
||||||
NetworkResult network_reply = NetworkFactory::performNetworkOperation(final_url,
|
Downloader* downloader = NetworkFactory::performAsyncNetworkOperation(final_url,
|
||||||
qApp->settings()->value(GROUP(Feeds),
|
qApp->settings()->value(GROUP(Feeds),
|
||||||
SETTING(Feeds::UpdateTimeout)).toInt(),
|
SETTING(Feeds::UpdateTimeout)).toInt(),
|
||||||
QJsonDocument(json).toJson(QJsonDocument::Compact),
|
QJsonDocument(json).toJson(QJsonDocument::Compact),
|
||||||
"application/json",
|
CONTENT_TYPE,
|
||||||
raw_output,
|
QNetworkAccessManager::PutOperation,
|
||||||
QNetworkAccessManager::PutOperation,
|
true, m_authUsername, m_authPassword,
|
||||||
true, m_authUsername, m_authPassword,
|
true);
|
||||||
true);
|
|
||||||
|
|
||||||
if (network_reply.first != QNetworkReply::NoError) {
|
QObject::connect(downloader, &Downloader::completed, downloader, &Downloader::deleteLater);
|
||||||
qWarning("ownCloud: Marking messages as (un)starred failed with error %d.", network_reply.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_lastError = network_reply.first);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int OwnCloudNetworkFactory::batchSize() const {
|
int OwnCloudNetworkFactory::batchSize() const {
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,8 @@ class OwnCloudNetworkFactory {
|
||||||
|
|
||||||
// Misc methods.
|
// Misc methods.
|
||||||
QNetworkReply::NetworkError triggerFeedUpdate(int feed_id);
|
QNetworkReply::NetworkError triggerFeedUpdate(int feed_id);
|
||||||
QNetworkReply::NetworkError markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids);
|
void markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids);
|
||||||
QNetworkReply::NetworkError markMessagesStarred(RootItem::Importance importance, const QStringList& feed_ids,
|
void markMessagesStarred(RootItem::Importance importance, const QStringList& feed_ids, const QStringList& guid_hashes);
|
||||||
const QStringList& guid_hashes);
|
|
||||||
|
|
||||||
// Gets/sets the amount of messages to obtain during single feed update.
|
// Gets/sets the amount of messages to obtain during single feed update.
|
||||||
int batchSize() const;
|
int batchSize() const;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue