simple custom data SQL layer for accounts, something similar will come for feeds too maybe
This commit is contained in:
parent
9d6c42002d
commit
3469e457ca
@ -1 +1 @@
|
||||
Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9
|
||||
Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749
|
@ -13,27 +13,8 @@ CREATE TABLE Accounts (
|
||||
proxy_port INTEGER,
|
||||
proxy_username TEXT,
|
||||
proxy_password TEXT,
|
||||
/* Custom attributes dynamically mapped to actual account data fields. */
|
||||
custom_data_1 TEXT,
|
||||
custom_data_2 TEXT,
|
||||
custom_data_3 TEXT,
|
||||
custom_data_4 TEXT,
|
||||
custom_data_5 TEXT,
|
||||
custom_data_6 TEXT,
|
||||
custom_data_7 TEXT,
|
||||
custom_data_8 TEXT,
|
||||
custom_data_9 TEXT,
|
||||
custom_data_10 TEXT,
|
||||
custom_data_11 TEXT,
|
||||
custom_data_12 TEXT,
|
||||
custom_data_13 TEXT,
|
||||
custom_data_14 TEXT,
|
||||
custom_data_15 TEXT,
|
||||
custom_data_16 TEXT,
|
||||
custom_data_17 TEXT,
|
||||
custom_data_18 TEXT,
|
||||
custom_data_19 TEXT,
|
||||
custom_data_20 TEXT
|
||||
/* Custom column for (serialized) custom account-specific data. */
|
||||
custom_data TEXT
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE Categories (
|
||||
|
@ -1677,32 +1677,12 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot
|
||||
|
||||
// Now we construct the SQL update query.
|
||||
auto proxy = account->networkProxy();
|
||||
QString sql_statement = QSL("UPDATE Accounts "
|
||||
"SET proxy_type = :proxy_type, proxy_host = :proxy_host, proxy_port = :proxy_port, "
|
||||
" proxy_username = :proxy_username, proxy_password = :proxy_password%1 "
|
||||
"WHERE id = :id");
|
||||
auto custom_attributes = account->customDatabaseAttributes();
|
||||
QStringList custom_sql_clauses;
|
||||
|
||||
for (int i = 0; i < custom_attributes.size(); i++) {
|
||||
QString target_data = account->property(custom_attributes.at(i).m_name.toLocal8Bit()).toString();
|
||||
|
||||
if (custom_attributes.at(i).m_encrypted) {
|
||||
target_data = TextFactory::encrypt(target_data);
|
||||
}
|
||||
|
||||
custom_sql_clauses.append(QSL("custom_data_%1 = '%2'").arg(QString::number(i + 1),
|
||||
target_data));
|
||||
}
|
||||
|
||||
if (!custom_sql_clauses.isEmpty()) {
|
||||
sql_statement = sql_statement.arg(QSL(", ") + custom_sql_clauses.join(QSL(", ")));
|
||||
}
|
||||
else {
|
||||
sql_statement = sql_statement.arg(QString());
|
||||
}
|
||||
|
||||
q.prepare(sql_statement);
|
||||
q.prepare(QSL("UPDATE Accounts "
|
||||
"SET proxy_type = :proxy_type, proxy_host = :proxy_host, proxy_port = :proxy_port, "
|
||||
" proxy_username = :proxy_username, proxy_password = :proxy_password, "
|
||||
" custom_data = :custom_data "
|
||||
"WHERE id = :id"));
|
||||
q.bindValue(QSL(":proxy_type"), proxy.type());
|
||||
q.bindValue(QSL(":proxy_host"), proxy.hostName());
|
||||
q.bindValue(QSL(":proxy_port"), proxy.port());
|
||||
@ -1710,6 +1690,9 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot
|
||||
q.bindValue(QSL(":proxy_password"), TextFactory::encrypt(proxy.password()));
|
||||
q.bindValue(QSL(":id"), account->accountId());
|
||||
|
||||
q.bindValue(QSL(":custom_data"),
|
||||
QString::fromUtf8(QJsonDocument::fromVariant(account->customDatabaseData()).toJson(QJsonDocument::JsonFormat::Indented)));
|
||||
|
||||
if (!q.exec()) {
|
||||
throw ApplicationException(q.lastError().text());
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "services/abstract/serviceroot.h"
|
||||
#include "services/standard/standardfeed.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMultiMap>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
@ -197,20 +199,7 @@ QList<ServiceRoot*> DatabaseQueries::getAccounts(const QSqlDatabase& db, const Q
|
||||
TextFactory::decrypt(query.value(QSL("proxy_password")).toString()));
|
||||
|
||||
root->setNetworkProxy(proxy);
|
||||
|
||||
// Load account-specific custom data.
|
||||
auto custom_attributes = root->customDatabaseAttributes();
|
||||
|
||||
for (int i = 0; i < custom_attributes.size(); i++) {
|
||||
const QString target_db_attribute = QSL("custom_data_%1").arg(QString::number(i + 1));
|
||||
QString target_data = query.value(target_db_attribute).toString();
|
||||
|
||||
if (custom_attributes.at(i).m_encrypted) {
|
||||
target_data = TextFactory::decrypt(target_data);
|
||||
}
|
||||
|
||||
root->setProperty(custom_attributes.at(i).m_name.toLocal8Bit(), target_data);
|
||||
}
|
||||
root->setCustomDatabaseData(QJsonDocument::fromJson(query.value(QSL("custom_data")).toString().toUtf8()).object().toVariantHash());
|
||||
|
||||
roots.append(root);
|
||||
}
|
||||
|
@ -260,16 +260,20 @@ ServiceRoot::LabelOperation ServiceRoot::supportedLabelOperations() const {
|
||||
return LabelOperation::Adding | LabelOperation::Editing | LabelOperation::Deleting;
|
||||
}
|
||||
|
||||
QList<CustomDatabaseEntry> ServiceRoot::customDatabaseAttributes() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void ServiceRoot::saveAccountDataToDatabase() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteAccount(database, this);
|
||||
}
|
||||
|
||||
QVariantHash ServiceRoot::customDatabaseData() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void ServiceRoot::setCustomDatabaseData(const QVariantHash& data) const {
|
||||
Q_UNUSED(data)
|
||||
}
|
||||
|
||||
void ServiceRoot::itemChanged(const QList<RootItem*>& items) {
|
||||
emit dataChanged(items);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "core/messagefilter.h"
|
||||
#include "definitions/typedefs.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QNetworkProxy>
|
||||
#include <QPair>
|
||||
|
||||
@ -59,8 +60,9 @@ class ServiceRoot : public RootItem {
|
||||
virtual bool supportsFeedAdding() const;
|
||||
virtual bool supportsCategoryAdding() const;
|
||||
virtual LabelOperation supportedLabelOperations() const;
|
||||
virtual QList<CustomDatabaseEntry> customDatabaseAttributes() const;
|
||||
virtual void saveAccountDataToDatabase();
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& json) const;
|
||||
|
||||
// Returns list of specific actions for "Add new item" main window menu.
|
||||
// So typical list of returned actions could look like:
|
||||
|
@ -185,11 +185,30 @@ void TtRssServiceRoot::saveAllCachedData(bool ignore_errors) {
|
||||
}
|
||||
}
|
||||
|
||||
QList<CustomDatabaseEntry> TtRssServiceRoot::customDatabaseAttributes() const {
|
||||
return {
|
||||
{ QSL("username") }, { QSL("password"), true }, { QSL("auth_protected") }, { QSL("auth_username") },
|
||||
{ QSL("auth_password"), true }, { QSL("url") }, { QSL("force_update") }, { QSL("download_only_unread") }
|
||||
};
|
||||
QVariantHash TtRssServiceRoot::customDatabaseData() const {
|
||||
QVariantHash data;
|
||||
|
||||
data["username"] = m_network->username();
|
||||
data["password"] = TextFactory::encrypt(m_network->password());
|
||||
data["auth_protected"] = m_network->authIsUsed();
|
||||
data["auth_username"] = m_network->authUsername();
|
||||
data["auth_password"] = TextFactory::encrypt(m_network->authPassword());
|
||||
data["url"] = m_network->url();
|
||||
data["force_update"] = m_network->forceServerSideUpdate();
|
||||
data["download_only_unread"] = m_network->downloadOnlyUnreadMessages();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setCustomDatabaseData(const QVariantHash& data) const {
|
||||
m_network->setUsername( data["username"].toString());
|
||||
m_network->setPassword(TextFactory::decrypt(data["password"].toString()));
|
||||
m_network->setAuthIsUsed(data["auth_protected"].toBool());
|
||||
m_network->setAuthUsername(data["auth_username"].toString());
|
||||
m_network->setAuthPassword(TextFactory::decrypt(data["auth_password"].toString()));
|
||||
m_network->setUrl(data["url"].toString());
|
||||
m_network->setForceServerSideUpdate(data["force_update"].toBool());
|
||||
m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool());
|
||||
}
|
||||
|
||||
QString TtRssServiceRoot::additionalTooltip() const {
|
||||
@ -216,70 +235,6 @@ void TtRssServiceRoot::updateTitle() {
|
||||
setTitle(TextFactory::extractUsernameFromEmail(m_network->username()) + QSL(" (Tiny Tiny RSS)"));
|
||||
}
|
||||
|
||||
QString TtRssServiceRoot::username() const {
|
||||
return m_network->username();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setUsername(const QString& username) {
|
||||
m_network->setUsername(username);
|
||||
}
|
||||
|
||||
QString TtRssServiceRoot::password() const {
|
||||
return m_network->password();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setPassword(const QString& password) {
|
||||
m_network->setPassword(password);
|
||||
}
|
||||
|
||||
bool TtRssServiceRoot::authProtected() const {
|
||||
return m_network->authIsUsed();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setAuthProtected(bool auth_protected) {
|
||||
m_network->setAuthIsUsed(auth_protected);
|
||||
}
|
||||
|
||||
QString TtRssServiceRoot::authUsername() const {
|
||||
return m_network->authUsername();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setAuthUsername(const QString& auth_username) {
|
||||
m_network->setAuthUsername(auth_username);
|
||||
}
|
||||
|
||||
QString TtRssServiceRoot::authPassword() const {
|
||||
return m_network->authPassword();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setAuthPassword(const QString& auth_password) {
|
||||
m_network->setAuthPassword(auth_password);
|
||||
}
|
||||
|
||||
QString TtRssServiceRoot::url() const {
|
||||
return m_network->url();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setUrl(const QString& url) {
|
||||
m_network->setUrl(url);
|
||||
}
|
||||
|
||||
bool TtRssServiceRoot::forceUpdate() const {
|
||||
return m_network->forceServerSideUpdate();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setForceUpdate(bool force_update) {
|
||||
m_network->setForceServerSideUpdate(force_update);
|
||||
}
|
||||
|
||||
bool TtRssServiceRoot::downloadOnlyUnread() const {
|
||||
return m_network->downloadOnlyUnreadMessages();
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::setDownloadOnlyUnread(bool download_only_unread) {
|
||||
m_network->setDownloadOnlyUnreadMessages(download_only_unread);
|
||||
}
|
||||
|
||||
RootItem* TtRssServiceRoot::obtainNewTreeForSyncIn() const {
|
||||
TtRssGetFeedsCategoriesResponse feed_cats = m_network->getFeedsCategories(networkProxy());
|
||||
TtRssGetLabelsResponse labels = m_network->getLabels(networkProxy());
|
||||
|
@ -14,14 +14,6 @@ class TtRssNetworkFactory;
|
||||
|
||||
class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString username READ username WRITE setUsername)
|
||||
Q_PROPERTY(QString password READ password WRITE setPassword)
|
||||
Q_PROPERTY(bool auth_protected READ authProtected WRITE setAuthProtected)
|
||||
Q_PROPERTY(QString auth_username READ authUsername WRITE setAuthUsername)
|
||||
Q_PROPERTY(QString auth_password READ authPassword WRITE setAuthPassword)
|
||||
Q_PROPERTY(QString url READ url WRITE setUrl)
|
||||
Q_PROPERTY(bool force_update READ forceUpdate WRITE setForceUpdate)
|
||||
Q_PROPERTY(bool download_only_unread READ downloadOnlyUnread WRITE setDownloadOnlyUnread)
|
||||
|
||||
public:
|
||||
explicit TtRssServiceRoot(RootItem* parent = nullptr);
|
||||
@ -39,41 +31,18 @@ class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual void addNewFeed(RootItem* selected_item, const QString& url = QString());
|
||||
virtual QString additionalTooltip() const;
|
||||
virtual void saveAllCachedData(bool ignore_errors);
|
||||
virtual QList<CustomDatabaseEntry> customDatabaseAttributes() const;
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data) const;
|
||||
|
||||
// Access to network.
|
||||
TtRssNetworkFactory* network() const;
|
||||
|
||||
void updateTitle();
|
||||
|
||||
// Support for dynamic DB attributes.
|
||||
QString username() const;
|
||||
void setUsername(const QString& username);
|
||||
|
||||
QString password() const;
|
||||
void setPassword(const QString& password);
|
||||
|
||||
bool authProtected() const;
|
||||
void setAuthProtected(bool auth_protected);
|
||||
|
||||
QString authUsername() const;
|
||||
void setAuthUsername(const QString& auth_username);
|
||||
|
||||
QString authPassword() const;
|
||||
void setAuthPassword(const QString& auth_password);
|
||||
|
||||
QString url() const;
|
||||
void setUrl(const QString& url);
|
||||
|
||||
bool forceUpdate() const;
|
||||
void setForceUpdate(bool force_update);
|
||||
|
||||
bool downloadOnlyUnread() const;
|
||||
void setDownloadOnlyUnread(bool download_only_unread);
|
||||
|
||||
protected:
|
||||
virtual RootItem* obtainNewTreeForSyncIn() const;
|
||||
|
||||
private:
|
||||
void updateTitle();
|
||||
|
||||
private:
|
||||
TtRssNetworkFactory* m_network;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user