Some polishments, now send via async network on same thread.

This commit is contained in:
Martin Rotter 2017-09-18 10:52:46 +02:00
parent ebddff6fb1
commit 7b62a456a6
9 changed files with 61 additions and 152 deletions

View File

@ -331,7 +331,6 @@ HEADERS += src/core/feeddownloader.h \
src/services/standard/feedparser.h \
src/services/standard/rdfparser.h \
src/services/standard/rssparser.h \
src/miscellaneous/serviceoperator.h \
src/services/abstract/cacheforserviceroot.h \
src/services/tt-rss/gui/formeditttrssaccount.h \
src/gui/guiutilities.h \
@ -458,7 +457,6 @@ SOURCES += src/core/feeddownloader.cpp \
src/services/standard/feedparser.cpp \
src/services/standard/rdfparser.cpp \
src/services/standard/rssparser.cpp \
src/miscellaneous/serviceoperator.cpp \
src/services/abstract/cacheforserviceroot.cpp \
src/services/tt-rss/gui/formeditttrssaccount.cpp \
src/gui/guiutilities.cpp \

View File

@ -38,14 +38,13 @@
FeedReader::FeedReader(QObject* parent)
: 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_dbCleanerThread(nullptr), m_dbCleaner(nullptr) {
m_feedsModel = new FeedsModel(this);
m_feedsProxyModel = new FeedsProxyModel(m_feedsModel, this);
m_messagesModel = new 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);
updateAutoUpdateStatus();
asyncCacheSaveFinished();
@ -213,56 +212,19 @@ void FeedReader::executeNextAutoUpdate() {
}
void FeedReader::checkServicesForAsyncOperations() {
checkServicesForAsyncOperations(false);
}
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();
}
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) {
qDebug("Waiting for saving of cached service data to finish.");
future.waitForFinished();
}
else {
m_cacheSaveFutureWatcher->setFuture(future);
}
}
asyncCacheSaveFinished();
}
void FeedReader::asyncCacheSaveFinished() {
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.");
checkServicesForAsyncOperations(false);
checkServicesForAsyncOperations();
});
}

View File

@ -31,7 +31,6 @@ class MessagesModel;
class MessagesProxyModel;
class FeedsProxyModel;
class ServiceEntryPoint;
class ServiceOperator;
class DatabaseCleaner;
class QTimer;
@ -79,7 +78,6 @@ class FeedReader : public QObject {
// Is executed when next auto-update round could be done.
void executeNextAutoUpdate();
void checkServicesForAsyncOperations();
void checkServicesForAsyncOperations(bool wait_for_future, bool do_on_this_thread = false);
void asyncCacheSaveFinished();
signals:
@ -95,16 +93,12 @@ class FeedReader : public QObject {
MessagesModel* m_messagesModel;
MessagesProxyModel* m_messagesProxyModel;
QFutureWatcher<void>* m_cacheSaveFutureWatcher;
// Auto-update stuff.
QTimer* m_autoUpdateTimer;
bool m_globalAutoUpdateEnabled;
int m_globalAutoUpdateInitialInterval;
int m_globalAutoUpdateRemainingInterval;
ServiceOperator* m_serviceOperator;
QThread* m_feedDownloaderThread;
FeedDownloader* m_feedDownloader;

View File

@ -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() {
}

View File

@ -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

View File

@ -148,6 +148,28 @@ QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList<QString>& u
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,
const QString& input_content_type, QByteArray& output,
QNetworkAccessManager::Operation operation, bool protected_contents,

View File

@ -25,6 +25,7 @@
typedef QPair<QNetworkReply::NetworkError, QVariant> NetworkResult;
class Downloader;
class NetworkFactory {
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
@ -43,6 +44,12 @@ class NetworkFactory {
// given URL belongs to.
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,
const QString& input_content_type, QByteArray& output,
QNetworkAccessManager::Operation operation,

View File

@ -299,10 +299,9 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::triggerFeedUpdate(int feed_i
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;
QJsonArray ids;
QByteArray raw_output;
QString final_url;
if (status == RootItem::Read) {
@ -317,31 +316,25 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesRead(RootItem::R
}
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) {
qWarning("ownCloud: Marking messages as (un)read failed with error %d.", network_reply.first);
}
Downloader* downloader = NetworkFactory::performAsyncNetworkOperation(final_url,
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,
const QStringList& feed_ids,
const QStringList& guid_hashes) {
void OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance,
const QStringList& feed_ids,
const QStringList& guid_hashes) {
QJsonObject json;
QJsonArray ids;
QByteArray raw_output;
QString final_url;
QString final_url;
if (importance == RootItem::Important) {
final_url = m_fixedUrl + API_PATH + "items/star/multiple";
@ -358,21 +351,16 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesStarred(RootItem
}
json["items"] = ids;
NetworkResult network_reply = NetworkFactory::performNetworkOperation(final_url,
qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(),
QJsonDocument(json).toJson(QJsonDocument::Compact),
"application/json",
raw_output,
QNetworkAccessManager::PutOperation,
true, m_authUsername, m_authPassword,
true);
Downloader* downloader = NetworkFactory::performAsyncNetworkOperation(final_url,
qApp->settings()->value(GROUP(Feeds),
SETTING(Feeds::UpdateTimeout)).toInt(),
QJsonDocument(json).toJson(QJsonDocument::Compact),
CONTENT_TYPE,
QNetworkAccessManager::PutOperation,
true, m_authUsername, m_authPassword,
true);
if (network_reply.first != QNetworkReply::NoError) {
qWarning("ownCloud: Marking messages as (un)starred failed with error %d.", network_reply.first);
}
return (m_lastError = network_reply.first);
QObject::connect(downloader, &Downloader::completed, downloader, &Downloader::deleteLater);
}
int OwnCloudNetworkFactory::batchSize() const {

View File

@ -130,9 +130,8 @@ class OwnCloudNetworkFactory {
// Misc methods.
QNetworkReply::NetworkError triggerFeedUpdate(int feed_id);
QNetworkReply::NetworkError markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids);
QNetworkReply::NetworkError markMessagesStarred(RootItem::Importance importance, const QStringList& feed_ids,
const QStringList& guid_hashes);
void markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids);
void markMessagesStarred(RootItem::Importance importance, const QStringList& feed_ids, const QStringList& guid_hashes);
// Gets/sets the amount of messages to obtain during single feed update.
int batchSize() const;