huge work, semi broken state rn, save

This commit is contained in:
Martin Rotter 2021-03-02 12:02:07 +01:00
parent cc8aef4589
commit 8e2eede3ed
21 changed files with 334 additions and 538 deletions

View File

@ -22,7 +22,7 @@ CREATE TABLE Categories (
parent_id INTEGER NOT NULL CHECK (parent_id >= -1), /* Root categories contain -1 here. */ parent_id INTEGER NOT NULL CHECK (parent_id >= -1), /* Root categories contain -1 here. */
title TEXT NOT NULL CHECK (title != ''), title TEXT NOT NULL CHECK (title != ''),
description TEXT, description TEXT,
date_created INTEGER, date_created INTEGER NOT NULL CHECK (date_created >= 0),
icon BLOB, icon BLOB,
account_id INTEGER NOT NULL, account_id INTEGER NOT NULL,
custom_id TEXT, custom_id TEXT,
@ -34,14 +34,16 @@ CREATE TABLE Feeds (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
title TEXT NOT NULL CHECK (title != ''), title TEXT NOT NULL CHECK (title != ''),
description TEXT, description TEXT,
date_created INTEGER, date_created INTEGER NOT NULL CHECK (date_created >= 0),
icon BLOB, icon BLOB,
category INTEGER NOT NULL CHECK (category >= -1), /* Root feeds contain -1 here. */ category INTEGER NOT NULL CHECK (category >= -1), /* Root feeds contain -1 here. */
source TEXT, source TEXT,
update_type INTEGER(1) NOT NULL CHECK (update_type >= 0), update_type INTEGER(1) NOT NULL CHECK (update_type >= 0),
update_interval INTEGER NOT NULL DEFAULT 15 CHECK (update_interval >= 1), update_interval INTEGER NOT NULL DEFAULT 15 CHECK (update_interval >= 1),
account_id INTEGER NOT NULL, account_id INTEGER NOT NULL,
custom_id TEXT, custom_id TEXT NOT NULL CHECK (custom_id != ''), /* Custom ID cannot be empty, it must contain either service-specific ID, or Feeds/id. */
/* Custom column for (serialized) custom account-specific data. */
custom_data TEXT,
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
); );
@ -49,15 +51,15 @@ CREATE TABLE Feeds (
CREATE TABLE Messages ( CREATE TABLE Messages (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
is_read INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_read >= 0 AND is_read <= 1), is_read INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_read >= 0 AND is_read <= 1),
is_deleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_deleted >= 0 AND is_deleted <= 1),
is_important INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_important >= 0 AND is_important <= 1), is_important INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_important >= 0 AND is_important <= 1),
feed TEXT NOT NULL, is_deleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_deleted >= 0 AND is_deleted <= 1),
is_pdeleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_pdeleted >= 0 AND is_pdeleted <= 1),
feed_custom_id TEXT NOT NULL, /* Points to Feeds/custom_id. */
title TEXT NOT NULL CHECK (title != ''), title TEXT NOT NULL CHECK (title != ''),
url TEXT, url TEXT,
author TEXT, author TEXT,
date_created INTEGER NOT NULL CHECK (date_created != 0), date_created INTEGER NOT NULL CHECK (date_created >= 0),
contents TEXT, contents TEXT,
is_pdeleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_pdeleted >= 0 AND is_pdeleted <= 1),
enclosures TEXT, enclosures TEXT,
account_id INTEGER NOT NULL, account_id INTEGER NOT NULL,
custom_id TEXT, custom_id TEXT,
@ -74,7 +76,7 @@ CREATE TABLE MessageFilters (
-- ! -- !
CREATE TABLE MessageFiltersInFeeds ( CREATE TABLE MessageFiltersInFeeds (
filter INTEGER NOT NULL, filter INTEGER NOT NULL,
feed_custom_id TEXT NOT NULL, feed_custom_id TEXT NOT NULL, /* Points to Feeds/custom_id. */
account_id INTEGER NOT NULL, account_id INTEGER NOT NULL,
FOREIGN KEY (filter) REFERENCES MessageFilters (id) ON DELETE CASCADE, FOREIGN KEY (filter) REFERENCES MessageFilters (id) ON DELETE CASCADE,

View File

@ -162,7 +162,7 @@ void FeedsView::addFeedIntoSelectedAccount() {
ServiceRoot* root = selected->getParentServiceRoot(); ServiceRoot* root = selected->getParentServiceRoot();
if (root->supportsFeedAdding()) { if (root->supportsFeedAdding()) {
root->addNewFeed(selected); root->addNewFeed(selected, QGuiApplication::clipboard()->text(QClipboard::Mode::Clipboard));
} }
else { else {
qApp->showGuiMessage(tr("Not supported"), qApp->showGuiMessage(tr("Not supported"),

View File

@ -1483,16 +1483,21 @@ bool DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_ro
QSqlQuery query_category(db); QSqlQuery query_category(db);
QSqlQuery query_feed(db); QSqlQuery query_feed(db);
// TODO: use createOvewriteAccount and createOverwriteFeed
/*
query_category.setForwardOnly(true); query_category.setForwardOnly(true);
query_feed.setForwardOnly(true); query_feed.setForwardOnly(true);
query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) " query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) "
"VALUES (:parent_id, :title, :account_id, :custom_id);"); "VALUES (:parent_id, :title, :account_id, :custom_id);");
query_feed.prepare("INSERT INTO Feeds (title, icon, url, category, protected, update_type, update_interval, account_id, custom_id) " query_feed.prepare("INSERT INTO Feeds (title, icon, url, category, protected, update_type, update_interval, account_id, custom_id) "
"VALUES (:title, :icon, :url, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);"); "VALUES (:title, :icon, :url, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);");
*/
// Iterate all children. // Iterate all children.
for (RootItem* child : tree_root->getSubTree()) { for (RootItem* child : tree_root->getSubTree()) {
if (child->kind() == RootItem::Kind::Category) { if (child->kind() == RootItem::Kind::Category) {
/*
query_category.bindValue(QSL(":parent_id"), child->parent()->id()); query_category.bindValue(QSL(":parent_id"), child->parent()->id());
query_category.bindValue(QSL(":title"), child->title()); query_category.bindValue(QSL(":title"), child->title());
query_category.bindValue(QSL(":account_id"), account_id); query_category.bindValue(QSL(":account_id"), account_id);
@ -1504,8 +1509,12 @@ bool DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_ro
else { else {
return false; return false;
} }
*/
} }
else if (child->kind() == RootItem::Kind::Feed) { else if (child->kind() == RootItem::Kind::Feed) {
createOverwriteFeed(db, child->toFeed(), account_id, child->parent()->id());
/*
Feed* feed = child->toFeed(); Feed* feed = child->toFeed();
query_feed.bindValue(QSL(":title"), feed->title()); query_feed.bindValue(QSL(":title"), feed->title());
@ -1524,6 +1533,7 @@ bool DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_ro
else { else {
return false; return false;
} }
*/
} }
else if (child->kind() == RootItem::Kind::Labels) { else if (child->kind() == RootItem::Kind::Labels) {
// Add all labels. // Add all labels.
@ -1658,6 +1668,51 @@ QStringList DatabaseQueries::customIdsOfMessagesFromFeed(const QSqlDatabase& db,
return ids; return ids;
} }
void DatabaseQueries::createOverwriteFeed(const QSqlDatabase& db, Feed* feed, int account_id, int parent_id) {
QSqlQuery q(db);
if (feed->id() <= 0) {
// We need to insert feed first.
q.prepare(QSL("INSERT INTO "
"Feeds (title, date_created, category, update_type, update_interval, account_id, custom_id) "
"VALUES ('new', 0, 0, 0, 1, 0, 'new');"));
if (!q.exec()) {
throw ApplicationException(q.lastError().text());
}
else {
feed->setId(q.lastInsertId().toInt());
}
}
q.prepare("UPDATE Feeds "
"SET title = :title, description = :description, date_created = :date_created, "
" icon = :icon, category = :category, source = :source, update_type = :update_type, "
" update_interval = :update_interval, account_id = :account_id, "
" custom_id = :custom_id, custom_data = :custom_data "
"WHERE id = :id;");
q.bindValue(QSL(":title"), feed->title());
q.bindValue(QSL(":description"), feed->description());
q.bindValue(QSL(":date_created"), feed->creationDate().toMSecsSinceEpoch());
q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon()));
q.bindValue(QSL(":category"), parent_id);
q.bindValue(QSL(":source"), feed->source());
q.bindValue(QSL(":update_type"), int(feed->autoUpdateType()));
q.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval());
q.bindValue(QSL(":account_id"), account_id);
q.bindValue(QSL(":custom_id"), feed->customId().isEmpty() ? QString::number(feed->id()) : feed->customId());
q.bindValue(QSL(":id"), feed->id());
auto custom_data = feed->customDatabaseData();
QString serialized_custom_data = serializeCustomData(custom_data);
q.bindValue(QSL(":custom_data"), serialized_custom_data);
if (!q.exec()) {
throw ApplicationException(q.lastError().text());
}
}
void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot* account) { void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot* account) {
QSqlQuery q(db); QSqlQuery q(db);
@ -1731,7 +1786,7 @@ bool DatabaseQueries::deleteCategory(const QSqlDatabase& db, int id) {
return q.exec(); return q.exec();
} }
int DatabaseQueries::addStandardCategory(const QSqlDatabase& db, int parent_id, int account_id, const QString& title, int DatabaseQueries::addCategory(const QSqlDatabase& db, int parent_id, int account_id, const QString& title,
const QString& description, const QDateTime& creation_date, const QIcon& icon, const QString& description, const QDateTime& creation_date, const QIcon& icon,
bool* ok) { bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
@ -1776,7 +1831,7 @@ int DatabaseQueries::addStandardCategory(const QSqlDatabase& db, int parent_id,
} }
} }
bool DatabaseQueries::editStandardCategory(const QSqlDatabase& db, int parent_id, int category_id, bool DatabaseQueries::editCategory(const QSqlDatabase& db, int parent_id, int category_id,
const QString& title, const QString& description, const QIcon& icon) { const QString& title, const QString& description, const QIcon& icon) {
QSqlQuery q(db); QSqlQuery q(db);
@ -1792,145 +1847,6 @@ bool DatabaseQueries::editStandardCategory(const QSqlDatabase& db, int parent_id
return q.exec(); return q.exec();
} }
int DatabaseQueries::addStandardFeed(const QSqlDatabase& db, int parent_id, int account_id, const QString& title,
const QString& description, const QDateTime& creation_date, const QIcon& icon,
const QString& encoding, const QString& url, bool is_protected,
const QString& username, const QString& password,
Feed::AutoUpdateType auto_update_type, int auto_update_interval,
StandardFeed::SourceType source_type, const QString& post_process_script,
StandardFeed::Type feed_format, bool* ok) {
QSqlQuery q(db);
qDebug() << "Adding feed with title '" << title.toUtf8() << "' to DB.";
q.setForwardOnly(true);
q.prepare("INSERT INTO Feeds "
"(title, description, date_created, icon, category, encoding, url, source_type, post_process, protected, username, password, update_type, update_interval, type, account_id) "
"VALUES (:title, :description, :date_created, :icon, :category, :encoding, :url, :source_type, :post_process, :protected, :username, :password, :update_type, :update_interval, :type, :account_id);");
q.bindValue(QSL(":title"), title.toUtf8());
q.bindValue(QSL(":description"), description.toUtf8());
q.bindValue(QSL(":date_created"), creation_date.toMSecsSinceEpoch());
q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon));
q.bindValue(QSL(":category"), parent_id);
q.bindValue(QSL(":encoding"), encoding);
q.bindValue(QSL(":url"), url);
q.bindValue(QSL(":source_type"), int(source_type));
q.bindValue(QSL(":post_process"), post_process_script.simplified());
q.bindValue(QSL(":protected"), is_protected ? 1 : 0);
q.bindValue(QSL(":username"), username);
q.bindValue(QSL(":account_id"), account_id);
if (password.isEmpty()) {
q.bindValue(QSL(":password"), password);
}
else {
q.bindValue(QSL(":password"), TextFactory::encrypt(password));
}
q.bindValue(QSL(":update_type"), int(auto_update_type));
q.bindValue(QSL(":update_interval"), auto_update_interval);
q.bindValue(QSL(":type"), int(feed_format));
if (q.exec()) {
int new_id = q.lastInsertId().toInt();
// Now set custom ID in the DB.
q.prepare(QSL("UPDATE Feeds SET custom_id = :custom_id WHERE id = :id;"));
q.bindValue(QSL(":custom_id"), QString::number(new_id));
q.bindValue(QSL(":id"), new_id);
q.exec();
if (ok != nullptr) {
*ok = true;
}
return new_id;
}
else {
if (ok != nullptr) {
*ok = false;
}
qWarningNN << LOGSEC_DB
<< "Failed to add feed to database: '"
<< q.lastError().text()
<< "'.";
return 0;
}
}
bool DatabaseQueries::editStandardFeed(const QSqlDatabase& db, int parent_id, int feed_id, const QString& title,
const QString& description, const QIcon& icon,
const QString& encoding, const QString& url, bool is_protected,
const QString& username, const QString& password,
Feed::AutoUpdateType auto_update_type,
int auto_update_interval, StandardFeed::SourceType source_type,
const QString& post_process_script, StandardFeed::Type feed_format) {
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("UPDATE Feeds "
"SET title = :title, description = :description, icon = :icon, category = :category, encoding = :encoding, url = :url, source_type = :source_type, post_process = :post_process, protected = :protected, username = :username, password = :password, update_type = :update_type, update_interval = :update_interval, type = :type "
"WHERE id = :id;");
q.bindValue(QSL(":title"), title);
q.bindValue(QSL(":description"), description);
q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon));
q.bindValue(QSL(":category"), parent_id);
q.bindValue(QSL(":encoding"), encoding);
q.bindValue(QSL(":url"), url);
q.bindValue(QSL(":source_type"), int(source_type));
q.bindValue(QSL(":post_process"), post_process_script.simplified());
q.bindValue(QSL(":protected"), is_protected ? 1 : 0);
q.bindValue(QSL(":username"), username);
if (password.isEmpty()) {
q.bindValue(QSL(":password"), password);
}
else {
q.bindValue(QSL(":password"), TextFactory::encrypt(password));
}
q.bindValue(QSL(":update_type"), int(auto_update_type));
q.bindValue(QSL(":update_interval"), auto_update_interval);
q.bindValue(QSL(":type"), int(feed_format));
q.bindValue(QSL(":id"), feed_id);
bool suc = q.exec();
if (!suc) {
qWarningNN << LOGSEC_DB
<< "There was error when editing feed: '"
<< q.lastError().text()
<< "'.";
}
return suc;
}
bool DatabaseQueries::editFeed(const QSqlDatabase& db, int feed_id, Feed::AutoUpdateType auto_update_type,
int auto_update_interval, bool is_protected, const QString& username,
const QString& password) {
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("UPDATE Feeds "
"SET update_type = :update_type, update_interval = :update_interval, protected = :protected, username = :username, password = :password "
"WHERE id = :id;");
q.bindValue(QSL(":update_type"), int(auto_update_type));
q.bindValue(QSL(":update_interval"), auto_update_interval);
q.bindValue(QSL(":id"), feed_id);
q.bindValue(QSL(":protected"), is_protected ? 1 : 0);
q.bindValue(QSL(":username"), username);
if (password.isEmpty()) {
q.bindValue(QSL(":password"), password);
}
else {
q.bindValue(QSL(":password"), TextFactory::encrypt(password));
}
return q.exec();
}
MessageFilter* DatabaseQueries::addMessageFilter(const QSqlDatabase& db, const QString& title, MessageFilter* DatabaseQueries::addMessageFilter(const QSqlDatabase& db, const QString& title,
const QString& script) { const QString& script) {
if (!db.driver()->hasFeature(QSqlDriver::DriverFeature::LastInsertId)) { if (!db.driver()->hasFeature(QSqlDriver::DriverFeature::LastInsertId)) {

View File

@ -112,10 +112,6 @@ class DatabaseQueries {
static bool cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id); static bool cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id);
static bool cleanFeeds(const QSqlDatabase& db, const QStringList& ids, bool clean_read_only, int account_id); static bool cleanFeeds(const QSqlDatabase& db, const QStringList& ids, bool clean_read_only, int account_id);
static bool storeAccountTree(const QSqlDatabase& db, RootItem* tree_root, int account_id); static bool storeAccountTree(const QSqlDatabase& db, RootItem* tree_root, int account_id);
static bool editFeed(const QSqlDatabase& db, int feed_id,
Feed::AutoUpdateType auto_update_type, int auto_update_interval,
bool is_protected, const QString& username,
const QString& password);
template<typename T> template<typename T>
static Assignment getCategories(const QSqlDatabase& db, int account_id, bool* ok = nullptr); static Assignment getCategories(const QSqlDatabase& db, int account_id, bool* ok = nullptr);
@ -136,27 +132,16 @@ class DatabaseQueries {
static void updateMessageFilter(const QSqlDatabase& db, MessageFilter* filter, bool* ok = nullptr); static void updateMessageFilter(const QSqlDatabase& db, MessageFilter* filter, bool* ok = nullptr);
static void removeMessageFilterFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, int filter_id, static void removeMessageFilterFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, int filter_id,
int account_id, bool* ok = nullptr); int account_id, bool* ok = nullptr);
static void createOverwriteFeed(const QSqlDatabase& db, Feed* feed, int account_id, int parent_id);
static bool deleteFeed(const QSqlDatabase& db, int feed_custom_id, int account_id); static bool deleteFeed(const QSqlDatabase& db, int feed_custom_id, int account_id);
static bool deleteCategory(const QSqlDatabase& db, int id); static bool deleteCategory(const QSqlDatabase& db, int id);
// Standard account. // Standard account.
static int addStandardCategory(const QSqlDatabase& db, int parent_id, int account_id, const QString& title, static int addCategory(const QSqlDatabase& db, int parent_id, int account_id, const QString& title,
const QString& description, const QDateTime& creation_date, const QIcon& icon, bool* ok = nullptr);
static bool editStandardCategory(const QSqlDatabase& db, int parent_id, int category_id,
const QString& title, const QString& description, const QIcon& icon);
static int addStandardFeed(const QSqlDatabase& db, int parent_id, int account_id, const QString& title,
const QString& description, const QDateTime& creation_date, const QIcon& icon, const QString& description, const QDateTime& creation_date, const QIcon& icon,
const QString& encoding, const QString& url, bool is_protected, bool* ok = nullptr);
const QString& username, const QString& password, static bool editCategory(const QSqlDatabase& db, int parent_id, int category_id,
Feed::AutoUpdateType auto_update_type, int auto_update_interval, const QString& title, const QString& description, const QIcon& icon);
StandardFeed::SourceType source_type, const QString& post_process_script,
StandardFeed::Type feed_format, bool* ok = nullptr);
static bool editStandardFeed(const QSqlDatabase& db, int parent_id, int feed_id, const QString& title,
const QString& description, const QIcon& icon,
const QString& encoding, const QString& url, bool is_protected,
const QString& username, const QString& password, Feed::AutoUpdateType auto_update_type,
int auto_update_interval, StandardFeed::SourceType source_type,
const QString& post_process_script, StandardFeed::Type feed_format);
template<typename T> template<typename T>
static void fillFeedData(T* feed, const QSqlRecord& sql_record); static void fillFeedData(T* feed, const QSqlRecord& sql_record);

View File

@ -22,11 +22,6 @@ Feed::Feed(RootItem* parent)
: RootItem(parent), m_source(QString()), m_status(Status::Normal), m_autoUpdateType(AutoUpdateType::DefaultAutoUpdate), : RootItem(parent), m_source(QString()), m_status(Status::Normal), m_autoUpdateType(AutoUpdateType::DefaultAutoUpdate),
m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL), m_autoUpdateRemainingInterval(DEFAULT_AUTO_UPDATE_INTERVAL), m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL), m_autoUpdateRemainingInterval(DEFAULT_AUTO_UPDATE_INTERVAL),
m_messageFilters(QList<QPointer<MessageFilter>>()) { m_messageFilters(QList<QPointer<MessageFilter>>()) {
m_passwordProtected = false;
m_username = QString();
m_password = QString();
setKind(RootItem::Kind::Feed); setKind(RootItem::Kind::Feed);
} }
@ -46,16 +41,6 @@ Feed::Feed(const QSqlRecord& record) : Feed(nullptr) {
setAutoUpdateType(static_cast<Feed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); setAutoUpdateType(static_cast<Feed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool());
setUsername(record.value(FDS_DB_USERNAME_INDEX).toString());
if (record.value(FDS_DB_PASSWORD_INDEX).toString().isEmpty()) {
setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString());
}
else {
setPassword(TextFactory::decrypt(record.value(FDS_DB_PASSWORD_INDEX).toString()));
}
qDebugNN << LOGSEC_CORE qDebugNN << LOGSEC_CORE
<< "Custom ID of feed when loading from DB is" << "Custom ID of feed when loading from DB is"
<< QUOTE_W_SPACE_DOT(customId()); << QUOTE_W_SPACE_DOT(customId());
@ -72,10 +57,6 @@ Feed::Feed(const Feed& other) : RootItem(other) {
setAutoUpdateInitialInterval(other.autoUpdateInitialInterval()); setAutoUpdateInitialInterval(other.autoUpdateInitialInterval());
setAutoUpdateRemainingInterval(other.autoUpdateRemainingInterval()); setAutoUpdateRemainingInterval(other.autoUpdateRemainingInterval());
setMessageFilters(other.messageFilters()); setMessageFilters(other.messageFilters());
setPasswordProtected(other.passwordProtected());
setUsername(other.username());
setPassword(other.password());
} }
Feed::~Feed() = default; Feed::~Feed() = default;
@ -86,30 +67,6 @@ QList<Message> Feed::undeletedMessages() const {
return DatabaseQueries::getUndeletedMessagesForFeed(database, customId(), getParentServiceRoot()->accountId()); return DatabaseQueries::getUndeletedMessagesForFeed(database, customId(), getParentServiceRoot()->accountId());
} }
bool Feed::passwordProtected() const {
return m_passwordProtected;
}
void Feed::setPasswordProtected(bool passwordProtected) {
m_passwordProtected = passwordProtected;
}
QString Feed::username() const {
return m_username;
}
void Feed::setUsername(const QString& username) {
m_username = username;
}
QString Feed::password() const {
return m_password;
}
void Feed::setPassword(const QString& password) {
m_password = password;
}
QVariant Feed::data(int column, int role) const { QVariant Feed::data(int column, int role) const {
switch (role) { switch (role) {
case Qt::ForegroundRole: case Qt::ForegroundRole:
@ -171,30 +128,10 @@ bool Feed::canBeEdited() const {
bool Feed::editViaGui() { bool Feed::editViaGui() {
QScopedPointer<FormFeedDetails> form_pointer(new FormFeedDetails(getParentServiceRoot(), qApp->mainFormWidget())); QScopedPointer<FormFeedDetails> form_pointer(new FormFeedDetails(getParentServiceRoot(), qApp->mainFormWidget()));
form_pointer->editFeed(this); form_pointer->addEditFeed(this);
return false; return false;
} }
bool Feed::editItself(Feed* new_feed_data) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
if (DatabaseQueries::editFeed(database, id(), new_feed_data->autoUpdateType(),
new_feed_data->autoUpdateInitialInterval(),
new_feed_data->passwordProtected(),
new_feed_data->username(),
new_feed_data->password())) {
setPasswordProtected(new_feed_data->passwordProtected());
setUsername(new_feed_data->username());
setPassword(new_feed_data->password());
setAutoUpdateType(new_feed_data->autoUpdateType());
setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval());
return true;
}
else {
return false;
}
}
void Feed::setAutoUpdateInitialInterval(int auto_update_interval) { void Feed::setAutoUpdateInitialInterval(int auto_update_interval) {
// If new initial auto-update interval is set, then // If new initial auto-update interval is set, then
// we should reset time that remains to the next auto-update. // we should reset time that remains to the next auto-update.

View File

@ -58,8 +58,6 @@ class Feed : public RootItem {
bool canBeEdited() const; bool canBeEdited() const;
bool editViaGui(); bool editViaGui();
bool editItself(Feed* new_feed_data);
QVariant data(int column, int role) const; QVariant data(int column, int role) const;
int autoUpdateInitialInterval() const; int autoUpdateInitialInterval() const;
@ -77,15 +75,6 @@ class Feed : public RootItem {
QString source() const; QString source() const;
void setSource(const QString& source); void setSource(const QString& source);
bool passwordProtected() const;
void setPasswordProtected(bool passwordProtected);
QString username() const;
void setUsername(const QString& username);
QString password() const;
void setPassword(const QString& password);
void appendMessageFilter(MessageFilter* filter); void appendMessageFilter(MessageFilter* filter);
QList<QPointer<MessageFilter>> messageFilters() const; QList<QPointer<MessageFilter>> messageFilters() const;
void setMessageFilters(const QList<QPointer<MessageFilter>>& messageFilters); void setMessageFilters(const QList<QPointer<MessageFilter>>& messageFilters);
@ -109,9 +98,6 @@ class Feed : public RootItem {
int m_totalCount{}; int m_totalCount{};
int m_unreadCount{}; int m_unreadCount{};
QList<QPointer<MessageFilter>> m_messageFilters; QList<QPointer<MessageFilter>> m_messageFilters;
bool m_passwordProtected{};
QString m_username;
QString m_password;
}; };
Q_DECLARE_METATYPE(Feed::AutoUpdateType) Q_DECLARE_METATYPE(Feed::AutoUpdateType)

View File

@ -19,8 +19,6 @@ FormAccountDetails::FormAccountDetails(const QIcon& icon, QWidget* parent)
} }
void FormAccountDetails::apply() { void FormAccountDetails::apply() {
QSqlDatabase database = qApp->database()->connection(QSL("FormAccountDetails"));
m_account->setNetworkProxy(m_proxyDetails->proxy()); m_account->setNetworkProxy(m_proxyDetails->proxy());
} }

View File

@ -29,8 +29,8 @@ class FormAccountDetails : public QDialog {
protected slots: protected slots:
// Applies changes. // Applies changes.
// NOTE: This must be reimplemented in subclasses. Also, every // NOTE: This must be reimplemented in subclasses. Also this base
// subclass must call applyInternal() method as first statement. // implementation must be called first.
virtual void apply(); virtual void apply();
protected: protected:

View File

@ -8,6 +8,7 @@
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/systemtrayicon.h" #include "gui/systemtrayicon.h"
#include "miscellaneous/databasequeries.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
@ -23,16 +24,11 @@
#include <QTextCodec> #include <QTextCodec>
FormFeedDetails::FormFeedDetails(ServiceRoot* service_root, QWidget* parent) FormFeedDetails::FormFeedDetails(ServiceRoot* service_root, QWidget* parent)
: QDialog(parent), m_editableFeed(nullptr), m_serviceRoot(service_root) { : QDialog(parent), m_feed(nullptr), m_serviceRoot(service_root) {
initialize(); initialize();
createConnections(); createConnections();
} }
int FormFeedDetails::editFeed(Feed* input_feed) {
setEditableFeed(input_feed);
return QDialog::exec();
}
void FormFeedDetails::activateTab(int index) { void FormFeedDetails::activateTab(int index) {
m_ui->m_tabWidget->setCurrentIndex(index); m_ui->m_tabWidget->setCurrentIndex(index);
} }
@ -46,26 +42,10 @@ void FormFeedDetails::insertCustomTab(QWidget* custom_tab, const QString& title,
} }
void FormFeedDetails::apply() { void FormFeedDetails::apply() {
Feed new_feed; // Setup common data for the feed.
m_feed->setAutoUpdateType(static_cast<Feed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData(
// Setup data for new_feed.
new_feed.setAutoUpdateType(static_cast<Feed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData(
m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); m_ui->m_cmbAutoUpdateType->currentIndex()).toInt()));
new_feed.setAutoUpdateInitialInterval(int(m_ui->m_spinAutoUpdateInterval->value())); m_feed->setAutoUpdateInitialInterval(int(m_ui->m_spinAutoUpdateInterval->value()));
if (m_editableFeed != nullptr) {
// Edit the feed.
bool edited = m_editableFeed->editItself(&new_feed);
if (edited) {
accept();
}
else {
qApp->showGuiMessage(tr("Cannot edit feed"),
tr("Feed was not edited due to error."),
QSystemTrayIcon::MessageIcon::Critical, this, true);
}
}
} }
void FormFeedDetails::onAutoUpdateTypeChanged(int new_index) { void FormFeedDetails::onAutoUpdateTypeChanged(int new_index) {
@ -88,13 +68,16 @@ void FormFeedDetails::createConnections() {
&FormFeedDetails::onAutoUpdateTypeChanged); &FormFeedDetails::onAutoUpdateTypeChanged);
} }
void FormFeedDetails::setEditableFeed(Feed* editable_feed) { void FormFeedDetails::loadFeedData() {
setWindowTitle(tr("Edit '%1'").arg(editable_feed->title())); if (m_creatingNew) {
setWindowTitle(tr("Add new feed"));
}
else {
setWindowTitle(tr("Edit '%1'").arg(m_feed->title()));
}
m_editableFeed = editable_feed; m_ui->m_cmbAutoUpdateType->setCurrentIndex(m_ui->m_cmbAutoUpdateType->findData(QVariant::fromValue(int(m_feed->autoUpdateType()))));
m_ui->m_spinAutoUpdateInterval->setValue(m_feed->autoUpdateInitialInterval());
m_ui->m_cmbAutoUpdateType->setCurrentIndex(m_ui->m_cmbAutoUpdateType->findData(QVariant::fromValue((int) editable_feed->autoUpdateType())));
m_ui->m_spinAutoUpdateInterval->setValue(editable_feed->autoUpdateInitialInterval());
} }
void FormFeedDetails::initialize() { void FormFeedDetails::initialize() {

View File

@ -23,8 +23,11 @@ class FormFeedDetails : public QDialog {
explicit FormFeedDetails(ServiceRoot* service_root, QWidget* parent = nullptr); explicit FormFeedDetails(ServiceRoot* service_root, QWidget* parent = nullptr);
virtual ~FormFeedDetails() = default; virtual ~FormFeedDetails() = default;
public slots: template<class T>
int editFeed(Feed* input_feed); T* addEditFeed(T* account_to_edit = nullptr);
template<class T>
T* feed() const;
protected slots: protected slots:
void activateTab(int index); void activateTab(int index);
@ -41,7 +44,7 @@ class FormFeedDetails : public QDialog {
// Sets the feed which will be edited. // Sets the feed which will be edited.
// NOTE: This must be reimplemented in subclasses. Also this // NOTE: This must be reimplemented in subclasses. Also this
// base implementation must be called first. // base implementation must be called first.
void virtual setEditableFeed(Feed* editable_feed); virtual void loadFeedData();
private slots: private slots:
void onAutoUpdateTypeChanged(int new_index); void onAutoUpdateTypeChanged(int new_index);
@ -52,8 +55,36 @@ class FormFeedDetails : public QDialog {
protected: protected:
QScopedPointer<Ui::FormFeedDetails> m_ui; QScopedPointer<Ui::FormFeedDetails> m_ui;
Feed* m_editableFeed; Feed* m_feed;
ServiceRoot* m_serviceRoot; ServiceRoot* m_serviceRoot;
bool m_creatingNew;
}; };
template<class T>
inline T* FormFeedDetails::addEditFeed(T* feed_to_edit) {
m_creatingNew = feed_to_edit == nullptr;
if (m_creatingNew) {
m_feed = new T();
}
else {
m_feed = feed_to_edit;
}
// Load custom logic for feed data loading.
loadFeedData();
if (exec() == QDialog::DialogCode::Accepted) {
return feed<T>();
}
else {
return nullptr;
}
}
template<class T>
inline T* FormFeedDetails::feed() const {
return qobject_cast<T*>(m_feed);
}
#endif // FORMFEEDDETAILS_H #endif // FORMFEEDDETAILS_H

View File

@ -20,7 +20,8 @@ bool OwnCloudFeed::canBeDeleted() const {
} }
bool OwnCloudFeed::deleteViaGui() { bool OwnCloudFeed::deleteViaGui() {
if (serviceRoot()->network()->deleteFeed(customId(), getParentServiceRoot()->networkProxy()) && removeItself()) { if (serviceRoot()->network()->deleteFeed(customId(), getParentServiceRoot()->networkProxy()) &&
removeItself()) {
serviceRoot()->requestItemRemoval(this); serviceRoot()->requestItemRemoval(this);
return true; return true;
} }

View File

@ -3,6 +3,7 @@
#include "services/standard/gui/formstandardfeeddetails.h" #include "services/standard/gui/formstandardfeeddetails.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/databasequeries.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
#include "services/abstract/category.h" #include "services/abstract/category.h"
@ -15,9 +16,10 @@
#include <QFileDialog> #include <QFileDialog>
#include <QTextCodec> #include <QTextCodec>
FormStandardFeedDetails::FormStandardFeedDetails(ServiceRoot* service_root, QWidget* parent) FormStandardFeedDetails::FormStandardFeedDetails(ServiceRoot* service_root, RootItem* parent_to_select,
const QString& url, QWidget* parent)
: FormFeedDetails(service_root, parent), m_standardFeedDetails(new StandardFeedDetails(this)), : FormFeedDetails(service_root, parent), m_standardFeedDetails(new StandardFeedDetails(this)),
m_authDetails(new AuthenticationDetails(this)) { m_authDetails(new AuthenticationDetails(this)), m_parentToSelect(parent_to_select), m_urlToProcess(url) {
insertCustomTab(m_standardFeedDetails, tr("General"), 0); insertCustomTab(m_standardFeedDetails, tr("General"), 0);
insertCustomTab(m_authDetails, tr("Network"), 2); insertCustomTab(m_authDetails, tr("Network"), 2);
activateTab(0); activateTab(0);
@ -26,26 +28,6 @@ FormStandardFeedDetails::FormStandardFeedDetails(ServiceRoot* service_root, QWid
connect(m_standardFeedDetails->m_actionFetchIcon, &QAction::triggered, this, &FormStandardFeedDetails::guessIconOnly); connect(m_standardFeedDetails->m_actionFetchIcon, &QAction::triggered, this, &FormStandardFeedDetails::guessIconOnly);
} }
int FormStandardFeedDetails::addEditFeed(StandardFeed* input_feed, RootItem* parent_to_select, const QString& url) {
// Load categories.
m_standardFeedDetails->loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot);
if (input_feed == nullptr) {
// User is adding new feed.
setWindowTitle(tr("Add new feed"));
auto processed_url = qobject_cast<StandardServiceRoot*>(m_serviceRoot)->processFeedUrl(url);
m_standardFeedDetails->prepareForNewFeed(parent_to_select, processed_url);
}
else {
setEditableFeed(input_feed);
}
// Run the dialog.
return exec();
}
void FormStandardFeedDetails::guessFeed() { void FormStandardFeedDetails::guessFeed() {
m_standardFeedDetails->guessFeed(m_standardFeedDetails->sourceType(), m_standardFeedDetails->guessFeed(m_standardFeedDetails->sourceType(),
m_standardFeedDetails->m_ui.m_txtSource->textEdit()->toPlainText(), m_standardFeedDetails->m_ui.m_txtSource->textEdit()->toPlainText(),
@ -63,69 +45,58 @@ void FormStandardFeedDetails::guessIconOnly() {
} }
void FormStandardFeedDetails::apply() { void FormStandardFeedDetails::apply() {
FormFeedDetails::apply();
auto* std_feed = feed<StandardFeed>();
RootItem* parent = RootItem* parent =
static_cast<RootItem*>(m_standardFeedDetails->m_ui.m_cmbParentCategory->itemData( static_cast<RootItem*>(m_standardFeedDetails->m_ui.m_cmbParentCategory->itemData(
m_standardFeedDetails->m_ui.m_cmbParentCategory->currentIndex()).value<void*>()); m_standardFeedDetails->m_ui.m_cmbParentCategory->currentIndex()).value<void*>());
StandardFeed::Type type = StandardFeed::Type type =
static_cast<StandardFeed::Type>(m_standardFeedDetails->m_ui.m_cmbType->itemData(m_standardFeedDetails->m_ui.m_cmbType->currentIndex()).value<int>()); static_cast<StandardFeed::Type>(m_standardFeedDetails->m_ui.m_cmbType->itemData(m_standardFeedDetails->m_ui.m_cmbType->currentIndex()).value<int>());
auto* new_feed = new StandardFeed();
// Setup data for new_feed. // Setup data for new_feed.
new_feed->setTitle(m_standardFeedDetails->m_ui.m_txtTitle->lineEdit()->text()); std_feed->setTitle(m_standardFeedDetails->m_ui.m_txtTitle->lineEdit()->text());
new_feed->setCreationDate(QDateTime::currentDateTime()); std_feed->setCreationDate(QDateTime::currentDateTime());
new_feed->setDescription(m_standardFeedDetails->m_ui.m_txtDescription->lineEdit()->text()); std_feed->setDescription(m_standardFeedDetails->m_ui.m_txtDescription->lineEdit()->text());
new_feed->setIcon(m_standardFeedDetails->m_ui.m_btnIcon->icon()); std_feed->setIcon(m_standardFeedDetails->m_ui.m_btnIcon->icon());
new_feed->setEncoding(m_standardFeedDetails->m_ui.m_cmbEncoding->currentText());
new_feed->setType(type); std_feed->setSource(m_standardFeedDetails->m_ui.m_txtSource->textEdit()->toPlainText());
new_feed->setSourceType(m_standardFeedDetails->sourceType());
new_feed->setPostProcessScript(m_standardFeedDetails->m_ui.m_txtPostProcessScript->textEdit()->toPlainText()); std_feed->setEncoding(m_standardFeedDetails->m_ui.m_cmbEncoding->currentText());
new_feed->setSource(m_standardFeedDetails->m_ui.m_txtSource->textEdit()->toPlainText()); std_feed->setType(type);
new_feed->setPasswordProtected(m_authDetails->m_gbAuthentication->isChecked()); std_feed->setSourceType(m_standardFeedDetails->sourceType());
new_feed->setUsername(m_authDetails->m_txtUsername->lineEdit()->text()); std_feed->setPostProcessScript(m_standardFeedDetails->m_ui.m_txtPostProcessScript->textEdit()->toPlainText());
new_feed->setPassword(m_authDetails->m_txtPassword->lineEdit()->text()); std_feed->setPasswordProtected(m_authDetails->m_gbAuthentication->isChecked());
new_feed->setAutoUpdateType(static_cast<Feed::AutoUpdateType>(m_ui->m_cmbAutoUpdateType->itemData( std_feed->setUsername(m_authDetails->m_txtUsername->lineEdit()->text());
m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); std_feed->setPassword(m_authDetails->m_txtPassword->lineEdit()->text());
new_feed->setAutoUpdateInitialInterval(int(m_ui->m_spinAutoUpdateInterval->value()));
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
DatabaseQueries::createOverwriteFeed(database, std_feed, m_serviceRoot->accountId(), parent->id());
m_serviceRoot->requestItemReassignment(m_feed, parent);
if (m_editableFeed == nullptr) {
// Add the feed.
if (new_feed->addItself(parent)) {
m_serviceRoot->requestItemReassignment(new_feed, parent);
accept(); accept();
}
else {
delete new_feed;
qApp->showGuiMessage(tr("Cannot add feed"),
tr("Feed was not added due to error."),
QSystemTrayIcon::MessageIcon::Critical, this, true);
}
}
else {
new_feed->setParent(parent);
// Edit the feed.
bool edited = qobject_cast<StandardFeed*>(m_editableFeed)->editItself(new_feed);
if (edited) {
m_serviceRoot->requestItemReassignment(m_editableFeed, new_feed->parent());
accept();
}
else {
qApp->showGuiMessage(tr("Cannot edit feed"),
tr("Feed was not edited due to error."),
QSystemTrayIcon::MessageIcon::Critical, this, true);
}
delete new_feed;
}
} }
void FormStandardFeedDetails::setEditableFeed(Feed* editable_feed) { void FormStandardFeedDetails::loadFeedData() {
FormFeedDetails::setEditableFeed(editable_feed); FormFeedDetails::loadFeedData();
m_standardFeedDetails->setExistingFeed(qobject_cast<StandardFeed*>(editable_feed)); auto* std_feed = feed<StandardFeed>();
m_authDetails->m_gbAuthentication->setChecked(editable_feed->passwordProtected());
m_authDetails->m_txtUsername->lineEdit()->setText(editable_feed->username()); // Load categories.
m_authDetails->m_txtPassword->lineEdit()->setText(editable_feed->password()); m_standardFeedDetails->loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot);
m_authDetails->m_gbAuthentication->setChecked(std_feed->passwordProtected());
m_authDetails->m_txtUsername->lineEdit()->setText(std_feed->username());
m_authDetails->m_txtPassword->lineEdit()->setText(std_feed->password());
if (m_creatingNew) {
auto processed_url = qobject_cast<StandardServiceRoot*>(m_serviceRoot)->processFeedUrl(m_urlToProcess);
m_standardFeedDetails->prepareForNewFeed(m_parentToSelect, processed_url);
}
else {
m_standardFeedDetails->setExistingFeed(std_feed);
}
} }

View File

@ -13,10 +13,8 @@ class FormStandardFeedDetails : public FormFeedDetails {
Q_OBJECT Q_OBJECT
public: public:
explicit FormStandardFeedDetails(ServiceRoot* service_root, QWidget* parent = nullptr); explicit FormStandardFeedDetails(ServiceRoot* service_root, RootItem* parent_to_select = nullptr,
const QString& url = QString(), QWidget* parent = nullptr);
public slots:
int addEditFeed(StandardFeed* input_feed, RootItem* parent_to_select, const QString& url = QString());
private slots: private slots:
void guessFeed(); void guessFeed();
@ -25,11 +23,13 @@ class FormStandardFeedDetails : public FormFeedDetails {
virtual void apply(); virtual void apply();
private: private:
virtual void setEditableFeed(Feed* editable_feed); virtual void loadFeedData();
private: private:
StandardFeedDetails* m_standardFeedDetails; StandardFeedDetails* m_standardFeedDetails;
AuthenticationDetails* m_authDetails; AuthenticationDetails* m_authDetails;
RootItem* m_parentToSelect;
QString m_urlToProcess;
}; };
#endif // FORMSSFEEDDETAILS_H #endif // FORMSSFEEDDETAILS_H

View File

@ -311,6 +311,9 @@ void StandardFeedDetails::prepareForNewFeed(RootItem* parent_to_select, const QS
m_ui.m_cmbParentCategory->setCurrentIndex(target_item); m_ui.m_cmbParentCategory->setCurrentIndex(target_item);
} }
} }
else {
m_ui.m_cmbParentCategory->setCurrentIndex(0);
}
} }
if (!url.isEmpty()) { if (!url.isEmpty()) {

View File

@ -97,7 +97,7 @@ bool StandardCategory::removeItself() {
bool StandardCategory::addItself(RootItem* parent) { bool StandardCategory::addItself(RootItem* parent) {
// Now, add category to persistent storage. // Now, add category to persistent storage.
QSqlDatabase database = qApp->database()->connection(metaObject()->className()); QSqlDatabase database = qApp->database()->connection(metaObject()->className());
int new_id = DatabaseQueries::addStandardCategory(database, parent->id(), parent->getParentServiceRoot()->accountId(), int new_id = DatabaseQueries::addCategory(database, parent->id(), parent->getParentServiceRoot()->accountId(),
title(), description(), creationDate(), icon()); title(), description(), creationDate(), icon());
if (new_id <= 0) { if (new_id <= 0) {
@ -115,7 +115,7 @@ bool StandardCategory::editItself(StandardCategory* new_category_data) {
StandardCategory* original_category = this; StandardCategory* original_category = this;
RootItem* new_parent = new_category_data->parent(); RootItem* new_parent = new_category_data->parent();
if (DatabaseQueries::editStandardCategory(database, new_parent->id(), original_category->id(), if (DatabaseQueries::editCategory(database, new_parent->id(), original_category->id(),
new_category_data->title(), new_category_data->description(), new_category_data->title(), new_category_data->description(),
new_category_data->icon())) { new_category_data->icon())) {
// Setup new model data for the original item. // Setup new model data for the original item.

View File

@ -41,6 +41,10 @@ StandardFeed::StandardFeed(RootItem* parent_item)
m_type = Type::Rss0X; m_type = Type::Rss0X;
m_sourceType = SourceType::Url; m_sourceType = SourceType::Url;
m_encoding = m_postProcessScript = QString(); m_encoding = m_postProcessScript = QString();
m_passwordProtected = false;
m_username = QString();
m_password = QString();
} }
StandardFeed::StandardFeed(const StandardFeed& other) StandardFeed::StandardFeed(const StandardFeed& other)
@ -50,6 +54,9 @@ StandardFeed::StandardFeed(const StandardFeed& other)
m_postProcessScript = other.postProcessScript(); m_postProcessScript = other.postProcessScript();
m_sourceType = other.sourceType(); m_sourceType = other.sourceType();
m_encoding = other.encoding(); m_encoding = other.encoding();
m_passwordProtected = other.passwordProtected();
m_username = other.username();
m_password = other.password();
} }
StandardFeed::~StandardFeed() { StandardFeed::~StandardFeed() {
@ -68,10 +75,6 @@ QString StandardFeed::additionalTooltip() const {
StandardFeed::typeToString(type())); StandardFeed::typeToString(type()));
} }
bool StandardFeed::canBeEdited() const {
return true;
}
bool StandardFeed::canBeDeleted() const { bool StandardFeed::canBeDeleted() const {
return true; return true;
} }
@ -82,9 +85,11 @@ StandardServiceRoot* StandardFeed::serviceRoot() const {
bool StandardFeed::editViaGui() { bool StandardFeed::editViaGui() {
QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(serviceRoot(), QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(serviceRoot(),
nullptr,
{},
qApp->mainFormWidget())); qApp->mainFormWidget()));
form_pointer->addEditFeed(this, this); form_pointer->addEditFeed(this);
return false; return false;
} }
@ -98,6 +103,30 @@ bool StandardFeed::deleteViaGui() {
} }
} }
bool StandardFeed::passwordProtected() const {
return m_passwordProtected;
}
void StandardFeed::setPasswordProtected(bool passwordProtected) {
m_passwordProtected = passwordProtected;
}
QString StandardFeed::username() const {
return m_username;
}
void StandardFeed::setUsername(const QString& username) {
m_username = username;
}
QString StandardFeed::password() const {
return m_password;
}
void StandardFeed::setPassword(const QString& password) {
m_password = password;
}
QVariantHash StandardFeed::customDatabaseData() const { QVariantHash StandardFeed::customDatabaseData() const {
QVariantHash data; QVariantHash data;
@ -169,19 +198,18 @@ void StandardFeed::fetchMetadataForItself() {
getParentServiceRoot()->networkProxy()); getParentServiceRoot()->networkProxy());
if (metadata != nullptr && result) { if (metadata != nullptr && result) {
// Some properties are not updated when new metadata are fetched. // Copy metadata to our object.
metadata->setParent(parent()); setTitle(metadata->title());
metadata->setSource(source()); setDescription(metadata->description());
metadata->setPasswordProtected(passwordProtected()); setType(metadata->type());
metadata->setUsername(username()); setEncoding(metadata->encoding());
metadata->setPassword(password()); setIcon(metadata->icon());
metadata->setAutoUpdateType(autoUpdateType());
metadata->setAutoUpdateInitialInterval(autoUpdateInitialInterval());
metadata->setPostProcessScript(postProcessScript());
metadata->setSourceType(sourceType());
editItself(metadata);
delete metadata; delete metadata;
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
DatabaseQueries::createOverwriteFeed(database, this, getParentServiceRoot()->accountId(), parent()->id());
// Notify the model about fact, that it needs to reload new information about // Notify the model about fact, that it needs to reload new information about
// this item, particularly the icon. // this item, particularly the icon.
serviceRoot()->itemChanged(QList<RootItem*>() << this); serviceRoot()->itemChanged(QList<RootItem*>() << this);
@ -476,19 +504,11 @@ Qt::ItemFlags StandardFeed::additionalFlags() const {
} }
bool StandardFeed::performDragDropChange(RootItem* target_item) { bool StandardFeed::performDragDropChange(RootItem* target_item) {
auto* feed_new = new StandardFeed(*this); QSqlDatabase database = qApp->database()->connection(metaObject()->className());
feed_new->setParent(target_item); DatabaseQueries::createOverwriteFeed(database, this, getParentServiceRoot()->accountId(), target_item->id());
if (editItself(feed_new)) {
serviceRoot()->requestItemReassignment(this, target_item); serviceRoot()->requestItemReassignment(this, target_item);
delete feed_new;
return true; return true;
}
else {
delete feed_new;
return false;
}
} }
bool StandardFeed::removeItself() { bool StandardFeed::removeItself() {
@ -497,66 +517,6 @@ bool StandardFeed::removeItself() {
return DatabaseQueries::deleteFeed(database, customId().toInt(), getParentServiceRoot()->accountId()); return DatabaseQueries::deleteFeed(database, customId().toInt(), getParentServiceRoot()->accountId());
} }
bool StandardFeed::addItself(RootItem* parent) {
// Now, add feed to persistent storage.
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
bool ok;
int new_id = DatabaseQueries::addStandardFeed(database, parent->id(), parent->getParentServiceRoot()->accountId(),
title(), description(), creationDate(), icon(), encoding(), source(),
passwordProtected(), username(), password(), autoUpdateType(),
autoUpdateInitialInterval(), sourceType(), postProcessScript(),
type(), &ok);
if (!ok) {
// Query failed.
return false;
}
else {
// New feed was added, fetch is primary id from the database.
setId(new_id);
setCustomId(QString::number(new_id));
return true;
}
}
bool StandardFeed::editItself(StandardFeed* new_feed_data) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
StandardFeed* original_feed = this;
RootItem* new_parent = new_feed_data->parent();
if (!DatabaseQueries::editStandardFeed(database, new_parent->id(), original_feed->id(), new_feed_data->title(),
new_feed_data->description(), new_feed_data->icon(),
new_feed_data->encoding(), new_feed_data->source(), new_feed_data->passwordProtected(),
new_feed_data->username(), new_feed_data->password(),
new_feed_data->autoUpdateType(), new_feed_data->autoUpdateInitialInterval(),
new_feed_data->sourceType(), new_feed_data->postProcessScript(),
new_feed_data->type())) {
// Persistent storage update failed, no way to continue now.
qWarningNN << LOGSEC_CORE
<< "Self-editing of standard feed failed.";
return false;
}
// Setup new model data for the original item.
original_feed->setTitle(new_feed_data->title());
original_feed->setDescription(new_feed_data->description());
original_feed->setIcon(new_feed_data->icon());
original_feed->setEncoding(new_feed_data->encoding());
original_feed->setDescription(new_feed_data->description());
original_feed->setSource(new_feed_data->source());
original_feed->setPasswordProtected(new_feed_data->passwordProtected());
original_feed->setUsername(new_feed_data->username());
original_feed->setPassword(new_feed_data->password());
original_feed->setAutoUpdateType(new_feed_data->autoUpdateType());
original_feed->setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval());
original_feed->setType(new_feed_data->type());
original_feed->setSourceType(new_feed_data->sourceType());
original_feed->setPostProcessScript(new_feed_data->postProcessScript());
// Editing is done.
return true;
}
StandardFeed::Type StandardFeed::type() const { StandardFeed::Type StandardFeed::type() const {
return m_type; return m_type;
} }
@ -786,6 +746,16 @@ StandardFeed::StandardFeed(const QSqlRecord& record) : Feed(record) {
setSourceType(SourceType(record.value(FDS_DB_SOURCE_TYPE_INDEX).toInt())); setSourceType(SourceType(record.value(FDS_DB_SOURCE_TYPE_INDEX).toInt()));
setPostProcessScript(record.value(FDS_DB_POST_PROCESS).toString()); setPostProcessScript(record.value(FDS_DB_POST_PROCESS).toString());
setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool());
setUsername(record.value(FDS_DB_USERNAME_INDEX).toString());
if (record.value(FDS_DB_PASSWORD_INDEX).toString().isEmpty()) {
setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString());
}
else {
setPassword(TextFactory::decrypt(record.value(FDS_DB_PASSWORD_INDEX).toString()));
}
StandardFeed::Type type = static_cast<StandardFeed::Type>(record.value(FDS_DB_TYPE_INDEX).toInt()); StandardFeed::Type type = static_cast<StandardFeed::Type>(record.value(FDS_DB_TYPE_INDEX).toInt());
switch (type) { switch (type) {

View File

@ -47,11 +47,10 @@ class StandardFeed : public Feed {
QString additionalTooltip() const; QString additionalTooltip() const;
bool canBeEdited() const;
bool canBeDeleted() const; bool canBeDeleted() const;
bool deleteViaGui();
bool editViaGui(); bool editViaGui();
bool deleteViaGui();
virtual QVariantHash customDatabaseData() const; virtual QVariantHash customDatabaseData() const;
virtual void setCustomDatabaseData(const QVariantHash& data); virtual void setCustomDatabaseData(const QVariantHash& data);
@ -60,8 +59,6 @@ class StandardFeed : public Feed {
Qt::ItemFlags additionalFlags() const; Qt::ItemFlags additionalFlags() const;
bool performDragDropChange(RootItem* target_item); bool performDragDropChange(RootItem* target_item);
bool addItself(RootItem* parent);
bool editItself(StandardFeed* new_feed_data);
bool removeItself(); bool removeItself();
// Other getters/setters. // Other getters/setters.
@ -77,6 +74,15 @@ class StandardFeed : public Feed {
QString postProcessScript() const; QString postProcessScript() const;
void setPostProcessScript(const QString& post_process_script); void setPostProcessScript(const QString& post_process_script);
bool passwordProtected() const;
void setPasswordProtected(bool passwordProtected);
QString username() const;
void setUsername(const QString& username);
QString password() const;
void setPassword(const QString& password);
QNetworkReply::NetworkError networkError() const; QNetworkReply::NetworkError networkError() const;
QList<Message> obtainNewMessages(bool* error_during_obtaining); QList<Message> obtainNewMessages(bool* error_during_obtaining);
@ -113,9 +119,11 @@ class StandardFeed : public Feed {
SourceType m_sourceType; SourceType m_sourceType;
Type m_type; Type m_type;
QString m_postProcessScript; QString m_postProcessScript;
QNetworkReply::NetworkError m_networkError; QNetworkReply::NetworkError m_networkError;
QString m_encoding; QString m_encoding;
bool m_passwordProtected{};
QString m_username;
QString m_password;
}; };
Q_DECLARE_METATYPE(StandardFeed::SourceType) Q_DECLARE_METATYPE(StandardFeed::SourceType)

View File

@ -120,9 +120,11 @@ void StandardServiceRoot::addNewFeed(RootItem* selected_item, const QString& url
} }
QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(this, QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(this,
selected_item,
url,
qApp->mainFormWidget())); qApp->mainFormWidget()));
form_pointer->addEditFeed(nullptr, selected_item, url); form_pointer->addEditFeed<StandardFeed>();
qApp->feedUpdateLock()->unlock(); qApp->feedUpdateLock()->unlock();
} }
@ -239,16 +241,14 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
else if (source_item->kind() == RootItem::Kind::Feed) { else if (source_item->kind() == RootItem::Kind::Feed) {
auto* source_feed = dynamic_cast<StandardFeed*>(source_item); auto* source_feed = dynamic_cast<StandardFeed*>(source_item);
auto* new_feed = new StandardFeed(*source_feed); auto* new_feed = new StandardFeed(*source_feed);
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
// Append this feed and end this iteration. DatabaseQueries::createOverwriteFeed(database,
if (new_feed->addItself(target_parent)) { new_feed,
target_root_node->getParentServiceRoot()->accountId(),
target_parent->id());
requestItemReassignment(new_feed, target_parent); requestItemReassignment(new_feed, target_parent);
} }
else {
delete new_feed;
some_feed_category_error = true;
}
}
} }
} }

View File

@ -15,34 +15,14 @@
#include <QMimeData> #include <QMimeData>
#include <QTimer> #include <QTimer>
FormTtRssFeedDetails::FormTtRssFeedDetails(ServiceRoot* service_root, QWidget* parent) FormTtRssFeedDetails::FormTtRssFeedDetails(ServiceRoot* service_root, RootItem* parent_to_select,
const QString& url, QWidget* parent)
: FormFeedDetails(service_root, parent), m_feedDetails(new TtRssFeedDetails(this)), : FormFeedDetails(service_root, parent), m_feedDetails(new TtRssFeedDetails(this)),
m_authDetails(new AuthenticationDetails(this)) {} m_authDetails(new AuthenticationDetails(this)), m_parentToSelect(parent_to_select),
m_urlToProcess(url) {}
int FormTtRssFeedDetails::addFeed(RootItem* parent_to_select, const QString& url) {
clearTabs();
insertCustomTab(m_feedDetails, tr("General"), 0);
insertCustomTab(m_authDetails, tr("Network"), 1);
activateTab(0);
setWindowTitle(tr("Add new feed"));
m_feedDetails->loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot, parent_to_select);
if (!url.isEmpty()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(url);
}
else if (Application::clipboard()->mimeData()->hasText()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(Application::clipboard()->text());
}
m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll();
m_feedDetails->ui.m_txtUrl->setFocus();
return exec();
}
void FormTtRssFeedDetails::apply() { void FormTtRssFeedDetails::apply() {
if (m_editableFeed != nullptr) { if (!m_creatingNew) {
// NOTE: We can only edit base properties, therefore // NOTE: We can only edit base properties, therefore
// base method is fine. // base method is fine.
FormFeedDetails::apply(); FormFeedDetails::apply();
@ -78,3 +58,25 @@ void FormTtRssFeedDetails::apply() {
} }
} }
} }
void FormTtRssFeedDetails::loadFeedData() {
FormFeedDetails::loadFeedData();
if (m_creatingNew) {
insertCustomTab(m_feedDetails, tr("General"), 0);
insertCustomTab(m_authDetails, tr("Network"), 1);
activateTab(0);
m_feedDetails->loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot, m_parentToSelect);
if (!m_urlToProcess.isEmpty()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(m_urlToProcess);
}
else if (Application::clipboard()->mimeData()->hasText()) {
m_feedDetails->ui.m_txtUrl->lineEdit()->setText(Application::clipboard()->text());
}
m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll();
m_feedDetails->ui.m_txtUrl->setFocus();
}
}

View File

@ -11,17 +11,20 @@ class AuthenticationDetails;
class FormTtRssFeedDetails : public FormFeedDetails { class FormTtRssFeedDetails : public FormFeedDetails {
public: public:
explicit FormTtRssFeedDetails(ServiceRoot* service_root, QWidget* parent = nullptr); explicit FormTtRssFeedDetails(ServiceRoot* service_root, RootItem* parent_to_select = nullptr,
const QString& url = QString(), QWidget* parent = nullptr);
public slots:
int addFeed(RootItem* parent_to_select, const QString& url = QString());
protected slots: protected slots:
virtual void apply(); virtual void apply();
private:
virtual void loadFeedData();
private: private:
TtRssFeedDetails* m_feedDetails; TtRssFeedDetails* m_feedDetails;
AuthenticationDetails* m_authDetails; AuthenticationDetails* m_authDetails;
RootItem* m_parentToSelect;
QString m_urlToProcess;
}; };
#endif // FORMTTRSSFEEDDETAILS_H #endif // FORMTTRSSFEEDDETAILS_H

View File

@ -93,9 +93,9 @@ void TtRssServiceRoot::addNewFeed(RootItem* selected_item, const QString& url) {
return; return;
} }
QScopedPointer<FormTtRssFeedDetails> form_pointer(new FormTtRssFeedDetails(this, qApp->mainFormWidget())); QScopedPointer<FormTtRssFeedDetails> form_pointer(new FormTtRssFeedDetails(this, selected_item, url, qApp->mainFormWidget()));
form_pointer->addFeed(selected_item, url); form_pointer->addEditFeed<TtRssFeed>();
qApp->feedUpdateLock()->unlock(); qApp->feedUpdateLock()->unlock();
} }