OwnCloud plugin can delete feeds.
This commit is contained in:
parent
75fb8fa9b1
commit
0b2cb88bf6
@ -8,6 +8,7 @@ Main:
|
||||
|
||||
Added:
|
||||
|
||||
▪ ownCloud plugin now can delete feeds.
|
||||
▪ Global auto-update feed interval spinbox now has better format. (issue #176)
|
||||
▪ Message preview's font is now fully adjustable in settings. (issue #177)
|
||||
▪ RSS Guard now automatically switches to SQLite backend if MySQL is not available on program startup.
|
||||
|
@ -975,5 +975,26 @@ Assignment DatabaseQueries::getOwnCloudFeeds(QSqlDatabase db, int account_id, bo
|
||||
return feeds;
|
||||
}
|
||||
|
||||
bool DatabaseQueries::deleteFeed(QSqlDatabase db, int feed_custom_id, int account_id) {
|
||||
QSqlQuery query_remove(db);
|
||||
query_remove.setForwardOnly(true);
|
||||
|
||||
// Remove all messages from this feed.
|
||||
query_remove.prepare(QSL("DELETE FROM Messages WHERE feed = :feed AND account_id = :account_id;"));
|
||||
query_remove.bindValue(QSL(":feed"), feed_custom_id);
|
||||
query_remove.bindValue(QSL(":account_id"), account_id);
|
||||
|
||||
if (!query_remove.exec()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove feed itself.
|
||||
query_remove.prepare(QSL("DELETE FROM Feeds WHERE custom_id = :feed AND account_id = :account_id;"));
|
||||
query_remove.bindValue(QSL(":feed"), feed_custom_id);
|
||||
query_remove.bindValue(QSL(":account_id"), account_id);
|
||||
|
||||
return query_remove.exec();
|
||||
}
|
||||
|
||||
DatabaseQueries::DatabaseQueries() {
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ class DatabaseQueries {
|
||||
static int createAccount(QSqlDatabase db, const QString &code, bool *ok = NULL);
|
||||
static Assignment getOwnCloudCategories(QSqlDatabase db, int account_id, bool *ok = NULL);
|
||||
static Assignment getOwnCloudFeeds(QSqlDatabase db, int account_id, bool *ok = NULL);
|
||||
static bool deleteFeed(QSqlDatabase db, int feed_custom_id, int account_id);
|
||||
|
||||
private:
|
||||
explicit DatabaseQueries();
|
||||
|
@ -39,33 +39,12 @@ Downloader::~Downloader() {
|
||||
|
||||
void Downloader::downloadFile(const QString &url, int timeout, bool protected_contents, const QString &username,
|
||||
const QString &password) {
|
||||
QNetworkRequest request;
|
||||
QString non_const_url = url;
|
||||
|
||||
foreach (const QByteArray &header_name, m_customHeaders.keys()) {
|
||||
request.setRawHeader(header_name, m_customHeaders.value(header_name));
|
||||
}
|
||||
|
||||
// Set url for this request and fire it up.
|
||||
m_timer->setInterval(timeout);
|
||||
|
||||
if (non_const_url.startsWith(URI_SCHEME_FEED)) {
|
||||
qDebug("Replacing URI schemes for '%s'.", qPrintable(non_const_url));
|
||||
request.setUrl(non_const_url.replace(QRegExp(QString('^') + URI_SCHEME_FEED), QString(URI_SCHEME_HTTP)));
|
||||
}
|
||||
else {
|
||||
request.setUrl(non_const_url);
|
||||
}
|
||||
|
||||
m_targetProtected = protected_contents;
|
||||
m_targetUsername = username;
|
||||
m_targetPassword = password;
|
||||
|
||||
runGetRequest(request);
|
||||
manipulateData(url, QNetworkAccessManager::GetOperation, QByteArray(), timeout,
|
||||
protected_contents, username, password);
|
||||
}
|
||||
|
||||
void Downloader::uploadData(const QString &url, const QByteArray &data, QNetworkAccessManager::Operation operation,
|
||||
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) {
|
||||
QNetworkRequest request;
|
||||
QString non_const_url = url;
|
||||
|
||||
@ -93,9 +72,15 @@ void Downloader::uploadData(const QString &url, const QByteArray &data, QNetwork
|
||||
if (operation == QNetworkAccessManager::PostOperation) {
|
||||
runPostRequest(request, m_inputData);
|
||||
}
|
||||
else {
|
||||
else if (operation == QNetworkAccessManager::GetOperation) {
|
||||
runGetRequest(request);
|
||||
}
|
||||
else if (operation == QNetworkAccessManager::PutOperation) {
|
||||
runPutRequest(request, m_inputData);
|
||||
}
|
||||
else if (operation == QNetworkAccessManager::DeleteOperation) {
|
||||
runDeleteRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::finished() {
|
||||
@ -131,6 +116,9 @@ void Downloader::finished() {
|
||||
else if (reply_operation == QNetworkAccessManager::PutOperation) {
|
||||
runPutRequest(request, m_inputData);
|
||||
}
|
||||
else if (reply_operation == QNetworkAccessManager::DeleteOperation) {
|
||||
runDeleteRequest(request);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No redirection is indicated. Final file is obtained in our "reply" object.
|
||||
@ -161,6 +149,18 @@ void Downloader::timeout() {
|
||||
}
|
||||
}
|
||||
|
||||
void Downloader::runDeleteRequest(const QNetworkRequest &request) {
|
||||
m_timer->start();
|
||||
m_activeReply = m_downloadManager->deleteResource(request);
|
||||
|
||||
m_activeReply->setProperty("protected", m_targetProtected);
|
||||
m_activeReply->setProperty("username", m_targetUsername);
|
||||
m_activeReply->setProperty("password", m_targetPassword);
|
||||
|
||||
connect(m_activeReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(progressInternal(qint64,qint64)));
|
||||
connect(m_activeReply, SIGNAL(finished()), this, SLOT(finished()));
|
||||
}
|
||||
|
||||
void Downloader::runPutRequest(const QNetworkRequest &request, const QByteArray &data) {
|
||||
m_timer->start();
|
||||
m_activeReply = m_downloadManager->put(request, data);
|
||||
|
@ -52,9 +52,10 @@ class Downloader : public QObject {
|
||||
// Performs asynchronous upload of given data as HTTP POST.
|
||||
// User needs to setup "Content-Encoding" header which
|
||||
// matches encoding of the data.
|
||||
void uploadData(const QString &url, const QByteArray &data, QNetworkAccessManager::Operation operation,
|
||||
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 = QByteArray(),
|
||||
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
|
||||
const QString &username = QString(), const QString &password = QString());
|
||||
|
||||
signals:
|
||||
// Emitted when new progress is known.
|
||||
@ -72,6 +73,7 @@ class Downloader : public QObject {
|
||||
void timeout();
|
||||
|
||||
private:
|
||||
void runDeleteRequest(const QNetworkRequest &request);
|
||||
void runPutRequest(const QNetworkRequest &request, const QByteArray &data);
|
||||
void runPostRequest(const QNetworkRequest &request, const QByteArray &data);
|
||||
void runGetRequest(const QNetworkRequest &request);
|
||||
|
@ -167,8 +167,7 @@ NetworkResult NetworkFactory::uploadData(const QString &url, int timeout, const
|
||||
// We need to quit event loop when the download finishes.
|
||||
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
|
||||
|
||||
downloader.uploadData(url, input_data, operation,
|
||||
timeout, protected_contents, username, password);
|
||||
downloader.manipulateData(url, operation, input_data, timeout, protected_contents, username, password);
|
||||
loop.exec();
|
||||
output = downloader.lastOutputData();
|
||||
result.first = downloader.lastOutputError();
|
||||
@ -227,3 +226,31 @@ NetworkResult NetworkFactory::downloadFile(const QString &url, int timeout,
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NetworkResult NetworkFactory::deleteResource(const QString &url, int timeout, bool protected_contents,
|
||||
const QString &username, const QString &password, bool set_basic_header) {
|
||||
// Here, we want to achieve "synchronous" approach because we want synchronous download API for
|
||||
// some use-cases too.
|
||||
Downloader downloader;
|
||||
QEventLoop loop;
|
||||
NetworkResult result;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// We need to quit event loop when the download finishes.
|
||||
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
|
||||
|
||||
downloader.manipulateData(url, QNetworkAccessManager::DeleteOperation, QByteArray(),
|
||||
timeout, protected_contents, username, password);
|
||||
loop.exec();
|
||||
|
||||
result.first = downloader.lastOutputError();
|
||||
result.second = downloader.lastContentType();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -58,6 +58,10 @@ class NetworkFactory {
|
||||
static NetworkResult downloadFile(const QString &url, int timeout, QByteArray &output,
|
||||
bool protected_contents = false, const QString &username = QString(),
|
||||
const QString &password = QString(), bool set_basic_header = false);
|
||||
|
||||
static NetworkResult deleteResource(const QString &url, int timeout,
|
||||
bool protected_contents = false, const QString &username = QString(),
|
||||
const QString &password = QString(), bool set_basic_header = false);
|
||||
};
|
||||
|
||||
#endif // NETWORKFACTORY_H
|
||||
|
@ -33,7 +33,7 @@ OwnCloudNetworkFactory::OwnCloudNetworkFactory()
|
||||
: m_url(QString()), m_fixedUrl(QString()), m_forceServerSideUpdate(false),
|
||||
m_authUsername(QString()), m_authPassword(QString()), m_urlUser(QString()), m_urlStatus(QString()),
|
||||
m_urlFolders(QString()), m_urlFeeds(QString()), m_urlMessages(QString()), m_urlFeedsUpdate(QString()),
|
||||
m_userId(QString()) {
|
||||
m_urlDeleteFeed(QString()), m_userId(QString()) {
|
||||
}
|
||||
|
||||
OwnCloudNetworkFactory::~OwnCloudNetworkFactory() {
|
||||
@ -60,6 +60,7 @@ void OwnCloudNetworkFactory::setUrl(const QString &url) {
|
||||
m_urlFeeds = m_fixedUrl + API_PATH + "feeds";
|
||||
m_urlMessages = m_fixedUrl + API_PATH + "items?id=%1&batchSize=%2&type=%3";
|
||||
m_urlFeedsUpdate = m_fixedUrl + API_PATH + "feeds/update?userId=%1&feedId=%2";
|
||||
m_urlDeleteFeed = m_fixedUrl + API_PATH + "feeds/%1";
|
||||
|
||||
setUserId(QString());
|
||||
}
|
||||
@ -168,6 +169,24 @@ OwnCloudGetFeedsCategoriesResponse OwnCloudNetworkFactory::feedsCategories() {
|
||||
return OwnCloudGetFeedsCategoriesResponse(content_categories, content_feeds);
|
||||
}
|
||||
|
||||
bool OwnCloudNetworkFactory::deleteFeed(int feed_id) {
|
||||
QString final_url = m_urlDeleteFeed.arg(QString::number(feed_id));
|
||||
NetworkResult network_reply = NetworkFactory::deleteResource(final_url,
|
||||
qApp->settings()->value(GROUP(Feeds),
|
||||
SETTING(Feeds::UpdateTimeout)).toInt(),
|
||||
true, m_authUsername, m_authPassword, true);
|
||||
|
||||
m_lastError = network_reply.first;
|
||||
|
||||
if (network_reply.first != QNetworkReply::NoError) {
|
||||
qWarning("ownCloud: Obtaining of categories failed with error %d.", network_reply.first);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
OwnCloudGetMessagesResponse OwnCloudNetworkFactory::getMessages(int feed_id) {
|
||||
if (forceServerSideUpdate()) {
|
||||
triggerFeedUpdate(feed_id);
|
||||
|
@ -119,6 +119,9 @@ class OwnCloudNetworkFactory {
|
||||
// Get feeds & categories (used for sync-in).
|
||||
OwnCloudGetFeedsCategoriesResponse feedsCategories();
|
||||
|
||||
// Delete a feed.
|
||||
bool deleteFeed(int feed_id);
|
||||
|
||||
// Get messages for given feed.
|
||||
OwnCloudGetMessagesResponse getMessages(int feed_id);
|
||||
|
||||
@ -143,6 +146,7 @@ class OwnCloudNetworkFactory {
|
||||
QString m_urlFeeds;
|
||||
QString m_urlMessages;
|
||||
QString m_urlFeedsUpdate;
|
||||
QString m_urlDeleteFeed;
|
||||
QString m_userId;
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "services/owncloud/owncloudfeed.h"
|
||||
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "services/owncloud/owncloudserviceroot.h"
|
||||
#include "services/owncloud/network/owncloudnetworkfactory.h"
|
||||
#include "services/owncloud/gui/formeditowncloudfeed.h"
|
||||
@ -53,6 +54,23 @@ bool OwnCloudFeed::editViaGui() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OwnCloudFeed::canBeDeleted() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OwnCloudFeed::deleteViaGui() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
|
||||
|
||||
if (serviceRoot()->network()->deleteFeed(customId()) &&
|
||||
DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId())) {
|
||||
serviceRoot()->requestItemRemoval(this);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool OwnCloudFeed::markAsReadUnread(RootItem::ReadStatus status) {
|
||||
QStringList ids = getParentServiceRoot()->customIDSOfMessagesForItem(this);
|
||||
QNetworkReply::NetworkError response = serviceRoot()->network()->markMessagesRead(status, ids);
|
||||
|
@ -33,6 +33,8 @@ class OwnCloudFeed : public Feed {
|
||||
|
||||
bool canBeEdited() const;
|
||||
bool editViaGui();
|
||||
bool canBeDeleted() const;
|
||||
bool deleteViaGui();
|
||||
|
||||
bool markAsReadUnread(ReadStatus status);
|
||||
bool cleanMessages(bool clear_only_read);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "gui/dialogs/formmain.h"
|
||||
@ -200,23 +201,8 @@ bool TtRssFeed::removeItself() {
|
||||
if (response.code() == UFF_OK) {
|
||||
// Feed was removed online from server, remove local data.
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
|
||||
QSqlQuery query_remove(database);
|
||||
|
||||
query_remove.setForwardOnly(true);
|
||||
|
||||
// Remove all messages from this standard feed.
|
||||
query_remove.prepare(QSL("DELETE FROM Messages WHERE feed = :feed;"));
|
||||
query_remove.bindValue(QSL(":feed"), customId());
|
||||
|
||||
if (!query_remove.exec()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove feed itself.
|
||||
query_remove.prepare(QSL("DELETE FROM Feeds WHERE id = :feed;"));
|
||||
query_remove.bindValue(QSL(":feed"), id());
|
||||
|
||||
return query_remove.exec();
|
||||
return DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId());
|
||||
}
|
||||
else {
|
||||
qWarning("TT-RSS: Unsubscribing from feed failed, received JSON: '%s'", qPrintable(response.toString()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user