OwnCloud plugin can delete feeds.
This commit is contained in:
parent
75fb8fa9b1
commit
0b2cb88bf6
@ -8,6 +8,7 @@ Main:
|
|||||||
|
|
||||||
Added:
|
Added:
|
||||||
|
|
||||||
|
▪ ownCloud plugin now can delete feeds.
|
||||||
▪ Global auto-update feed interval spinbox now has better format. (issue #176)
|
▪ Global auto-update feed interval spinbox now has better format. (issue #176)
|
||||||
▪ Message preview's font is now fully adjustable in settings. (issue #177)
|
▪ 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.
|
▪ 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;
|
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() {
|
DatabaseQueries::DatabaseQueries() {
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ class DatabaseQueries {
|
|||||||
static int createAccount(QSqlDatabase db, const QString &code, bool *ok = NULL);
|
static int createAccount(QSqlDatabase db, const QString &code, bool *ok = NULL);
|
||||||
static Assignment getOwnCloudCategories(QSqlDatabase db, int account_id, 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 Assignment getOwnCloudFeeds(QSqlDatabase db, int account_id, bool *ok = NULL);
|
||||||
|
static bool deleteFeed(QSqlDatabase db, int feed_custom_id, int account_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DatabaseQueries();
|
explicit DatabaseQueries();
|
||||||
|
@ -39,32 +39,11 @@ Downloader::~Downloader() {
|
|||||||
|
|
||||||
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) {
|
const QString &password) {
|
||||||
QNetworkRequest request;
|
manipulateData(url, QNetworkAccessManager::GetOperation, QByteArray(), timeout,
|
||||||
QString non_const_url = url;
|
protected_contents, username, password);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downloader::uploadData(const QString &url, const QByteArray &data, QNetworkAccessManager::Operation operation,
|
void Downloader::manipulateData(const QString &url, QNetworkAccessManager::Operation operation, const QByteArray &data,
|
||||||
int timeout, bool protected_contents, const QString &username, const QString &password) {
|
int timeout, bool protected_contents, const QString &username, const QString &password) {
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
QString non_const_url = url;
|
QString non_const_url = url;
|
||||||
@ -93,9 +72,15 @@ void Downloader::uploadData(const QString &url, const QByteArray &data, QNetwork
|
|||||||
if (operation == QNetworkAccessManager::PostOperation) {
|
if (operation == QNetworkAccessManager::PostOperation) {
|
||||||
runPostRequest(request, m_inputData);
|
runPostRequest(request, m_inputData);
|
||||||
}
|
}
|
||||||
else {
|
else if (operation == QNetworkAccessManager::GetOperation) {
|
||||||
|
runGetRequest(request);
|
||||||
|
}
|
||||||
|
else if (operation == QNetworkAccessManager::PutOperation) {
|
||||||
runPutRequest(request, m_inputData);
|
runPutRequest(request, m_inputData);
|
||||||
}
|
}
|
||||||
|
else if (operation == QNetworkAccessManager::DeleteOperation) {
|
||||||
|
runDeleteRequest(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downloader::finished() {
|
void Downloader::finished() {
|
||||||
@ -131,6 +116,9 @@ void Downloader::finished() {
|
|||||||
else if (reply_operation == QNetworkAccessManager::PutOperation) {
|
else if (reply_operation == QNetworkAccessManager::PutOperation) {
|
||||||
runPutRequest(request, m_inputData);
|
runPutRequest(request, m_inputData);
|
||||||
}
|
}
|
||||||
|
else if (reply_operation == QNetworkAccessManager::DeleteOperation) {
|
||||||
|
runDeleteRequest(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No redirection is indicated. Final file is obtained in our "reply" object.
|
// 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) {
|
void Downloader::runPutRequest(const QNetworkRequest &request, const QByteArray &data) {
|
||||||
m_timer->start();
|
m_timer->start();
|
||||||
m_activeReply = m_downloadManager->put(request, data);
|
m_activeReply = m_downloadManager->put(request, data);
|
||||||
|
@ -52,7 +52,8 @@ class Downloader : public QObject {
|
|||||||
// Performs asynchronous upload of given data as HTTP POST.
|
// Performs asynchronous upload of given data as HTTP POST.
|
||||||
// User needs to setup "Content-Encoding" header which
|
// User needs to setup "Content-Encoding" header which
|
||||||
// matches encoding of the data.
|
// matches encoding of the data.
|
||||||
void uploadData(const QString &url, const QByteArray &data, QNetworkAccessManager::Operation operation,
|
void manipulateData(const QString &url, QNetworkAccessManager::Operation operation,
|
||||||
|
const QByteArray &data = QByteArray(),
|
||||||
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
|
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
|
||||||
const QString &username = QString(), const QString &password = QString());
|
const QString &username = QString(), const QString &password = QString());
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ class Downloader : public QObject {
|
|||||||
void timeout();
|
void timeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void runDeleteRequest(const QNetworkRequest &request);
|
||||||
void runPutRequest(const QNetworkRequest &request, const QByteArray &data);
|
void runPutRequest(const QNetworkRequest &request, const QByteArray &data);
|
||||||
void runPostRequest(const QNetworkRequest &request, const QByteArray &data);
|
void runPostRequest(const QNetworkRequest &request, const QByteArray &data);
|
||||||
void runGetRequest(const QNetworkRequest &request);
|
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.
|
// We need to quit event loop when the download finishes.
|
||||||
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
|
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
|
||||||
|
|
||||||
downloader.uploadData(url, input_data, operation,
|
downloader.manipulateData(url, operation, input_data, timeout, protected_contents, username, password);
|
||||||
timeout, protected_contents, username, password);
|
|
||||||
loop.exec();
|
loop.exec();
|
||||||
output = downloader.lastOutputData();
|
output = downloader.lastOutputData();
|
||||||
result.first = downloader.lastOutputError();
|
result.first = downloader.lastOutputError();
|
||||||
@ -227,3 +226,31 @@ NetworkResult NetworkFactory::downloadFile(const QString &url, int timeout,
|
|||||||
|
|
||||||
return result;
|
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,
|
static NetworkResult downloadFile(const QString &url, int timeout, QByteArray &output,
|
||||||
bool protected_contents = false, const QString &username = QString(),
|
bool protected_contents = false, const QString &username = QString(),
|
||||||
const QString &password = QString(), bool set_basic_header = false);
|
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
|
#endif // NETWORKFACTORY_H
|
||||||
|
@ -33,7 +33,7 @@ OwnCloudNetworkFactory::OwnCloudNetworkFactory()
|
|||||||
: m_url(QString()), m_fixedUrl(QString()), m_forceServerSideUpdate(false),
|
: m_url(QString()), m_fixedUrl(QString()), m_forceServerSideUpdate(false),
|
||||||
m_authUsername(QString()), m_authPassword(QString()), m_urlUser(QString()), m_urlStatus(QString()),
|
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_urlFolders(QString()), m_urlFeeds(QString()), m_urlMessages(QString()), m_urlFeedsUpdate(QString()),
|
||||||
m_userId(QString()) {
|
m_urlDeleteFeed(QString()), m_userId(QString()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnCloudNetworkFactory::~OwnCloudNetworkFactory() {
|
OwnCloudNetworkFactory::~OwnCloudNetworkFactory() {
|
||||||
@ -60,6 +60,7 @@ void OwnCloudNetworkFactory::setUrl(const QString &url) {
|
|||||||
m_urlFeeds = m_fixedUrl + API_PATH + "feeds";
|
m_urlFeeds = m_fixedUrl + API_PATH + "feeds";
|
||||||
m_urlMessages = m_fixedUrl + API_PATH + "items?id=%1&batchSize=%2&type=%3";
|
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_urlFeedsUpdate = m_fixedUrl + API_PATH + "feeds/update?userId=%1&feedId=%2";
|
||||||
|
m_urlDeleteFeed = m_fixedUrl + API_PATH + "feeds/%1";
|
||||||
|
|
||||||
setUserId(QString());
|
setUserId(QString());
|
||||||
}
|
}
|
||||||
@ -168,6 +169,24 @@ OwnCloudGetFeedsCategoriesResponse OwnCloudNetworkFactory::feedsCategories() {
|
|||||||
return OwnCloudGetFeedsCategoriesResponse(content_categories, content_feeds);
|
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) {
|
OwnCloudGetMessagesResponse OwnCloudNetworkFactory::getMessages(int feed_id) {
|
||||||
if (forceServerSideUpdate()) {
|
if (forceServerSideUpdate()) {
|
||||||
triggerFeedUpdate(feed_id);
|
triggerFeedUpdate(feed_id);
|
||||||
|
@ -119,6 +119,9 @@ class OwnCloudNetworkFactory {
|
|||||||
// Get feeds & categories (used for sync-in).
|
// Get feeds & categories (used for sync-in).
|
||||||
OwnCloudGetFeedsCategoriesResponse feedsCategories();
|
OwnCloudGetFeedsCategoriesResponse feedsCategories();
|
||||||
|
|
||||||
|
// Delete a feed.
|
||||||
|
bool deleteFeed(int feed_id);
|
||||||
|
|
||||||
// Get messages for given feed.
|
// Get messages for given feed.
|
||||||
OwnCloudGetMessagesResponse getMessages(int feed_id);
|
OwnCloudGetMessagesResponse getMessages(int feed_id);
|
||||||
|
|
||||||
@ -143,6 +146,7 @@ class OwnCloudNetworkFactory {
|
|||||||
QString m_urlFeeds;
|
QString m_urlFeeds;
|
||||||
QString m_urlMessages;
|
QString m_urlMessages;
|
||||||
QString m_urlFeedsUpdate;
|
QString m_urlFeedsUpdate;
|
||||||
|
QString m_urlDeleteFeed;
|
||||||
QString m_userId;
|
QString m_userId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "services/owncloud/owncloudfeed.h"
|
#include "services/owncloud/owncloudfeed.h"
|
||||||
|
|
||||||
#include "miscellaneous/iconfactory.h"
|
#include "miscellaneous/iconfactory.h"
|
||||||
|
#include "miscellaneous/databasequeries.h"
|
||||||
#include "services/owncloud/owncloudserviceroot.h"
|
#include "services/owncloud/owncloudserviceroot.h"
|
||||||
#include "services/owncloud/network/owncloudnetworkfactory.h"
|
#include "services/owncloud/network/owncloudnetworkfactory.h"
|
||||||
#include "services/owncloud/gui/formeditowncloudfeed.h"
|
#include "services/owncloud/gui/formeditowncloudfeed.h"
|
||||||
@ -53,6 +54,23 @@ bool OwnCloudFeed::editViaGui() {
|
|||||||
return false;
|
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) {
|
bool OwnCloudFeed::markAsReadUnread(RootItem::ReadStatus status) {
|
||||||
QStringList ids = getParentServiceRoot()->customIDSOfMessagesForItem(this);
|
QStringList ids = getParentServiceRoot()->customIDSOfMessagesForItem(this);
|
||||||
QNetworkReply::NetworkError response = serviceRoot()->network()->markMessagesRead(status, ids);
|
QNetworkReply::NetworkError response = serviceRoot()->network()->markMessagesRead(status, ids);
|
||||||
|
@ -33,6 +33,8 @@ class OwnCloudFeed : public Feed {
|
|||||||
|
|
||||||
bool canBeEdited() const;
|
bool canBeEdited() const;
|
||||||
bool editViaGui();
|
bool editViaGui();
|
||||||
|
bool canBeDeleted() const;
|
||||||
|
bool deleteViaGui();
|
||||||
|
|
||||||
bool markAsReadUnread(ReadStatus status);
|
bool markAsReadUnread(ReadStatus status);
|
||||||
bool cleanMessages(bool clear_only_read);
|
bool cleanMessages(bool clear_only_read);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "definitions/definitions.h"
|
#include "definitions/definitions.h"
|
||||||
#include "miscellaneous/application.h"
|
#include "miscellaneous/application.h"
|
||||||
#include "miscellaneous/databasefactory.h"
|
#include "miscellaneous/databasefactory.h"
|
||||||
|
#include "miscellaneous/databasequeries.h"
|
||||||
#include "miscellaneous/iconfactory.h"
|
#include "miscellaneous/iconfactory.h"
|
||||||
#include "miscellaneous/textfactory.h"
|
#include "miscellaneous/textfactory.h"
|
||||||
#include "gui/dialogs/formmain.h"
|
#include "gui/dialogs/formmain.h"
|
||||||
@ -200,23 +201,8 @@ bool TtRssFeed::removeItself() {
|
|||||||
if (response.code() == UFF_OK) {
|
if (response.code() == UFF_OK) {
|
||||||
// Feed was removed online from server, remove local data.
|
// Feed was removed online from server, remove local data.
|
||||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
|
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
|
||||||
QSqlQuery query_remove(database);
|
|
||||||
|
|
||||||
query_remove.setForwardOnly(true);
|
return DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId());
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qWarning("TT-RSS: Unsubscribing from feed failed, received JSON: '%s'", qPrintable(response.toString()));
|
qWarning("TT-RSS: Unsubscribing from feed failed, received JSON: '%s'", qPrintable(response.toString()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user