mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-01-29 16:49:34 +01:00
Message marking starred now works. New schema DB version.
This commit is contained in:
parent
fb1233d379
commit
3efd22491c
@ -96,6 +96,7 @@ CREATE TABLE IF NOT EXISTS Messages (
|
||||
enclosures TEXT,
|
||||
account_id INTEGER NOT NULL,
|
||||
custom_id TEXT,
|
||||
custom_hash TEXT,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
@ -91,6 +91,7 @@ CREATE TABLE IF NOT EXISTS Messages (
|
||||
enclosures TEXT,
|
||||
account_id INTEGER NOT NULL,
|
||||
custom_id TEXT,
|
||||
custom_hash TEXT,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
5
resources/misc/db_update_mysql_5_6.sql
Executable file
5
resources/misc/db_update_mysql_5_6.sql
Executable file
@ -0,0 +1,5 @@
|
||||
-- !
|
||||
ALTER TABLE Messages
|
||||
ADD COLUMN custom_hash TEXT;
|
||||
-- !
|
||||
UPDATE Information SET inf_value = '6' WHERE inf_key = 'schema_version';
|
30
resources/misc/db_update_sqlite_5_6.sql
Executable file
30
resources/misc/db_update_sqlite_5_6.sql
Executable file
@ -0,0 +1,30 @@
|
||||
CREATE TABLE backup_Messages AS SELECT * FROM Messages;
|
||||
-- !
|
||||
DROP TABLE Messages;
|
||||
-- !
|
||||
CREATE TABLE Messages (
|
||||
id INTEGER PRIMARY KEY,
|
||||
is_read INTEGER(1) NOT NULL CHECK (is_read >= 0 AND is_read <= 1) DEFAULT 0,
|
||||
is_deleted INTEGER(1) NOT NULL CHECK (is_deleted >= 0 AND is_deleted <= 1) DEFAULT 0,
|
||||
is_important INTEGER(1) NOT NULL CHECK (is_important >= 0 AND is_important <= 1) DEFAULT 0,
|
||||
feed TEXT NOT NULL,
|
||||
title TEXT NOT NULL CHECK (title != ''),
|
||||
url TEXT,
|
||||
author TEXT,
|
||||
date_created INTEGER NOT NULL CHECK (date_created != 0),
|
||||
contents TEXT,
|
||||
is_pdeleted INTEGER(1) NOT NULL CHECK (is_pdeleted >= 0 AND is_pdeleted <= 1) DEFAULT 0,
|
||||
enclosures TEXT,
|
||||
account_id INTEGER NOT NULL,
|
||||
custom_id TEXT,
|
||||
custom_hash TEXT,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
INSERT INTO Messages (id, is_read, is_deleted, is_important, feed, title, url, author, date_created, contents, is_pdeleted, enclosures, account_id, custom_id)
|
||||
SELECT id, is_read, is_deleted, is_important, feed, title, url, author, date_created, contents, is_pdeleted, enclosures, account_id, custom_id FROM backup_Messages;
|
||||
-- !
|
||||
DROP TABLE backup_Messages;
|
||||
-- !
|
||||
UPDATE Information SET inf_value = '6' WHERE inf_key = 'schema_version';
|
@ -65,14 +65,14 @@ QString Enclosures::encodeEnclosuresToString(const QList<Enclosure> &enclosures)
|
||||
}
|
||||
|
||||
Message::Message() {
|
||||
m_title = m_url = m_author = m_contents = m_feedId = m_customId = "";
|
||||
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = "";
|
||||
m_enclosures = QList<Enclosure>();
|
||||
m_accountId = m_id = 0;
|
||||
m_isRead = m_isImportant = false;
|
||||
}
|
||||
|
||||
Message Message::fromSqlRecord(const QSqlRecord &record, bool *result) {
|
||||
if (record.count() != MSG_DB_CUSTOM_ID_INDEX + 1) {
|
||||
if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) {
|
||||
if (result != NULL) {
|
||||
*result = false;
|
||||
return Message();
|
||||
@ -93,6 +93,7 @@ Message Message::fromSqlRecord(const QSqlRecord &record, bool *result) {
|
||||
message.m_enclosures = Enclosures::decodeEnclosuresFromString(record.value(MSG_DB_ENCLOSURES_INDEX).toString());
|
||||
message.m_accountId = record.value(MSG_DB_ACCOUNT_ID_INDEX).toInt();
|
||||
message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString();
|
||||
message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString();
|
||||
|
||||
if (result != NULL) {
|
||||
*result = true;
|
||||
|
@ -59,6 +59,7 @@ class Message {
|
||||
int m_accountId;
|
||||
int m_id;
|
||||
QString m_customId;
|
||||
QString m_customHash;
|
||||
|
||||
bool m_isRead;
|
||||
bool m_isImportant;
|
||||
|
@ -146,7 +146,8 @@ void MessagesModel::setupHeaderData() {
|
||||
/*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") <<
|
||||
/*: Tooltip for attachments of message.*/ tr("Attachments") <<
|
||||
/*: Tooltip for account ID of message.*/ tr("Account ID") <<
|
||||
/*: Tooltip for custom ID of message.*/ tr("Custom ID");
|
||||
/*: Tooltip for custom ID of message.*/ tr("Custom ID") <<
|
||||
/*: Tooltip for custom hash string of message.*/ tr("Custom hash");
|
||||
|
||||
m_tooltipData << tr("Id of the message.") << tr("Is message read?") <<
|
||||
tr("Is message deleted?") << tr("Is message important?") <<
|
||||
@ -154,7 +155,8 @@ void MessagesModel::setupHeaderData() {
|
||||
tr("Title of the message.") << tr("Url of the message.") <<
|
||||
tr("Author of the message.") << tr("Creation date of the message.") <<
|
||||
tr("Contents of the message.") << tr("Is message permanently deleted from recycle bin?") <<
|
||||
tr("List of attachments.") << tr("Account ID of the message.") << tr("Custom ID of the message");
|
||||
tr("List of attachments.") << tr("Account ID of the message.") << tr("Custom ID of the message") <<
|
||||
tr("Custom hash of the message.");
|
||||
}
|
||||
|
||||
Qt::ItemFlags MessagesModel::flags(const QModelIndex &index) const {
|
||||
|
@ -176,20 +176,21 @@
|
||||
#endif
|
||||
|
||||
// Indexes of columns as they are DEFINED IN THE TABLE for MESSAGES.
|
||||
#define MSG_DB_ID_INDEX 0
|
||||
#define MSG_DB_READ_INDEX 1
|
||||
#define MSG_DB_DELETED_INDEX 2
|
||||
#define MSG_DB_IMPORTANT_INDEX 3
|
||||
#define MSG_DB_FEED_INDEX 4
|
||||
#define MSG_DB_TITLE_INDEX 5
|
||||
#define MSG_DB_URL_INDEX 6
|
||||
#define MSG_DB_AUTHOR_INDEX 7
|
||||
#define MSG_DB_DCREATED_INDEX 8
|
||||
#define MSG_DB_CONTENTS_INDEX 9
|
||||
#define MSG_DB_PDELETED_INDEX 10
|
||||
#define MSG_DB_ENCLOSURES_INDEX 11
|
||||
#define MSG_DB_ACCOUNT_ID_INDEX 12
|
||||
#define MSG_DB_CUSTOM_ID_INDEX 13
|
||||
#define MSG_DB_ID_INDEX 0
|
||||
#define MSG_DB_READ_INDEX 1
|
||||
#define MSG_DB_DELETED_INDEX 2
|
||||
#define MSG_DB_IMPORTANT_INDEX 3
|
||||
#define MSG_DB_FEED_INDEX 4
|
||||
#define MSG_DB_TITLE_INDEX 5
|
||||
#define MSG_DB_URL_INDEX 6
|
||||
#define MSG_DB_AUTHOR_INDEX 7
|
||||
#define MSG_DB_DCREATED_INDEX 8
|
||||
#define MSG_DB_CONTENTS_INDEX 9
|
||||
#define MSG_DB_PDELETED_INDEX 10
|
||||
#define MSG_DB_ENCLOSURES_INDEX 11
|
||||
#define MSG_DB_ACCOUNT_ID_INDEX 12
|
||||
#define MSG_DB_CUSTOM_ID_INDEX 13
|
||||
#define MSG_DB_CUSTOM_HASH_INDEX 14
|
||||
|
||||
// Indexes of columns as they are DEFINED IN THE TABLE for CATEGORIES.
|
||||
#define CAT_DB_ID_INDEX 0
|
||||
|
@ -564,6 +564,7 @@ void MessagesView::adjustColumns() {
|
||||
hideColumn(MSG_DB_ENCLOSURES_INDEX);
|
||||
hideColumn(MSG_DB_ACCOUNT_ID_INDEX);
|
||||
hideColumn(MSG_DB_CUSTOM_ID_INDEX);
|
||||
hideColumn(MSG_DB_CUSTOM_HASH_INDEX);
|
||||
|
||||
qDebug("Adjusting column resize modes for MessagesView.");
|
||||
}
|
||||
|
@ -203,8 +203,8 @@ int Feed::updateMessages(const QList<Message> &messages) {
|
||||
// Used to insert new messages.
|
||||
query_insert.setForwardOnly(true);
|
||||
query_insert.prepare("INSERT INTO Messages "
|
||||
"(feed, title, is_read, is_important, url, author, date_created, contents, enclosures, custom_id, account_id) "
|
||||
"VALUES (:feed, :title, :is_read, :is_important, :url, :author, :date_created, :contents, :enclosures, :custom_id, :account_id);");
|
||||
"(feed, title, is_read, is_important, url, author, date_created, contents, enclosures, custom_id, custom_hash, account_id) "
|
||||
"VALUES (:feed, :title, :is_read, :is_important, :url, :author, :date_created, :contents, :enclosures, :custom_id, :custom_hash, :account_id);");
|
||||
|
||||
// Used to update existing messages.
|
||||
query_update.setForwardOnly(true);
|
||||
@ -313,6 +313,7 @@ int Feed::updateMessages(const QList<Message> &messages) {
|
||||
query_insert.bindValue(QSL(":contents"), message.m_contents);
|
||||
query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
|
||||
query_insert.bindValue(QSL(":custom_id"), message.m_customId);
|
||||
query_insert.bindValue(QSL(":custom_hash"), message.m_customHash);
|
||||
query_insert.bindValue(QSL(":account_id"), account_id);
|
||||
|
||||
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
|
||||
|
@ -299,7 +299,7 @@ QStringList ServiceRoot::textualFeedIds(const QList<Feed*> &feeds) const {
|
||||
return stringy_ids;
|
||||
}
|
||||
|
||||
QStringList ServiceRoot::customIDsOfMessages(const QList<QPair<Message,RootItem::Importance> > &changes) {
|
||||
QStringList ServiceRoot::customIDsOfMessages(const QList<ImportanceChange> &changes) {
|
||||
QStringList list;
|
||||
|
||||
for (int i = 0; i < changes.size(); i++) {
|
||||
@ -360,14 +360,14 @@ bool ServiceRoot::onAfterSetMessagesRead(RootItem *selected_item, const QList<Me
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message, RootItem::Importance> > &changes) {
|
||||
bool ServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes) {
|
||||
Q_UNUSED(selected_item)
|
||||
Q_UNUSED(changes)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceRoot::onAfterSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message, RootItem::Importance> > &changes) {
|
||||
bool ServiceRoot::onAfterSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes) {
|
||||
Q_UNUSED(selected_item)
|
||||
Q_UNUSED(changes)
|
||||
|
||||
|
@ -33,6 +33,7 @@ class QSqlTableModel;
|
||||
// Car here represents ID of the item.
|
||||
typedef QList<QPair<int,RootItem*> > Assignment;
|
||||
typedef QPair<int,RootItem*> AssignmentItem;
|
||||
typedef QPair<Message,RootItem::Importance> ImportanceChange;
|
||||
|
||||
// THIS IS the root node of the service.
|
||||
// NOTE: The root usually contains some core functionality of the
|
||||
@ -120,7 +121,7 @@ class ServiceRoot : public RootItem {
|
||||
// some ONLINE service or something.
|
||||
//
|
||||
// "changes" - list of pairs - <message (integer id), new status>
|
||||
virtual bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message,RootItem::Importance> > &changes);
|
||||
virtual bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes);
|
||||
|
||||
// Called AFTER this importance switch update is stored in DB,
|
||||
// when false is returned, change is aborted.
|
||||
@ -128,7 +129,7 @@ class ServiceRoot : public RootItem {
|
||||
// which items are actually changed.
|
||||
//
|
||||
// "changes" - list of pairs - <message (integer id), new status>
|
||||
virtual bool onAfterSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message,RootItem::Importance> > &changes);
|
||||
virtual bool onAfterSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes);
|
||||
|
||||
// Called BEFORE the list of messages is about to be deleted
|
||||
// by the user from message list.
|
||||
@ -176,7 +177,7 @@ class ServiceRoot : public RootItem {
|
||||
|
||||
QStringList textualFeedIds(const QList<Feed*> &feeds) const;
|
||||
|
||||
QStringList customIDsOfMessages(const QList<QPair<Message,Importance> > &changes);
|
||||
QStringList customIDsOfMessages(const QList<ImportanceChange> &changes);
|
||||
QStringList customIDsOfMessages(const QList<Message> &messages);
|
||||
|
||||
// Takes lists of feeds/categories and assembles them into the tree structure.
|
||||
|
@ -221,8 +221,47 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesRead(RootItem::R
|
||||
return (m_lastError = network_reply.first);
|
||||
}
|
||||
|
||||
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance, const QStringList &custom_ids) {
|
||||
return QNetworkReply::NoError;
|
||||
QNetworkReply::NetworkError OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance,
|
||||
const QStringList &feed_ids,
|
||||
const QStringList &guid_hashes) {
|
||||
QtJson::JsonObject json;
|
||||
QtJson::JsonArray ids;
|
||||
QByteArray raw_output;
|
||||
|
||||
QString final_url;
|
||||
|
||||
if (importance == RootItem::Important) {
|
||||
final_url = m_fixedUrl + API_PATH + "items/star/multiple";
|
||||
}
|
||||
else {
|
||||
final_url = m_fixedUrl + API_PATH + "items/unstar/multiple";
|
||||
}
|
||||
|
||||
for (int i = 0; i < feed_ids.size(); i++) {
|
||||
QVariantMap item;
|
||||
item.insert(QSL("feedId"), feed_ids.at(i));
|
||||
item.insert(QSL("guidHash"), guid_hashes.at(i));
|
||||
|
||||
ids.append(item);
|
||||
}
|
||||
|
||||
json["items"] = ids;
|
||||
|
||||
NetworkResult network_reply = NetworkFactory::uploadData(final_url,
|
||||
qApp->settings()->value(GROUP(Feeds),
|
||||
SETTING(Feeds::UpdateTimeout)).toInt(),
|
||||
QtJson::serialize(json),
|
||||
"application/json",
|
||||
raw_output,
|
||||
QNetworkAccessManager::PutOperation,
|
||||
true, m_authUsername, m_authPassword,
|
||||
true);
|
||||
|
||||
if (network_reply.first != QNetworkReply::NoError) {
|
||||
qWarning("ownCloud: Marking messages as (un)starred failed with error %d.", network_reply.first);
|
||||
}
|
||||
|
||||
return (m_lastError = network_reply.first);
|
||||
}
|
||||
|
||||
QString OwnCloudNetworkFactory::userId() const {
|
||||
@ -398,6 +437,7 @@ QList<Message> OwnCloudGetMessagesResponse::messages() const {
|
||||
msg.m_created = TextFactory::parseDateTime(message_map["pubDate"].value<qint64>() * 1000);
|
||||
msg.m_createdFromFeed = true;
|
||||
msg.m_customId = message_map["id"].toString();
|
||||
msg.m_customHash = message_map["guidHash"].toString();
|
||||
|
||||
QString enclosure_link = message_map["enclosureLink"].toString();
|
||||
|
||||
|
@ -123,7 +123,8 @@ class OwnCloudNetworkFactory {
|
||||
OwnCloudGetMessagesResponse getMessages(int feed_id);
|
||||
|
||||
QNetworkReply::NetworkError markMessagesRead(RootItem::ReadStatus status, const QStringList &custom_ids);
|
||||
QNetworkReply::NetworkError markMessagesStarred(RootItem::Importance importance, const QStringList &custom_ids);
|
||||
QNetworkReply::NetworkError markMessagesStarred(RootItem::Importance importance, const QStringList &feed_ids,
|
||||
const QStringList &guid_hashes);
|
||||
|
||||
private:
|
||||
QString m_url;
|
||||
|
@ -121,24 +121,41 @@ bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item, const
|
||||
}
|
||||
|
||||
bool OwnCloudServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item,
|
||||
const QList<QPair<Message,RootItem::Importance> > &changes) {
|
||||
const QList<ImportanceChange> &changes) {
|
||||
Q_UNUSED(selected_item)
|
||||
|
||||
QNetworkReply::NetworkError reply;
|
||||
// Now, we need to separate the changes because of ownCloud API limitations.
|
||||
QStringList mark_starred_feed_ids, mark_starred_guid_hashes;
|
||||
QStringList mark_unstarred_feed_ids, mark_unstarred_guid_hashes;
|
||||
|
||||
/*if (read == RootItem::Read) {
|
||||
//reply = network()->markMessagesRead();
|
||||
foreach (const ImportanceChange &pair, changes) {
|
||||
if (pair.second == RootItem::Important) {
|
||||
mark_starred_feed_ids.append(pair.first.m_feedId);
|
||||
mark_starred_guid_hashes.append(pair.first.m_customHash);
|
||||
}
|
||||
else {
|
||||
mark_unstarred_feed_ids.append(pair.first.m_feedId);
|
||||
mark_unstarred_guid_hashes.append(pair.first.m_customHash);
|
||||
}
|
||||
}
|
||||
else {
|
||||
reply = network()->markMessagesUnread();
|
||||
}*/
|
||||
|
||||
if (reply == QNetworkReply::NoError) {
|
||||
return true;
|
||||
// OK, now perform the online update itself.
|
||||
|
||||
if (!mark_starred_feed_ids.isEmpty()) {
|
||||
if (network()->markMessagesStarred(RootItem::Important, mark_starred_feed_ids, mark_starred_guid_hashes) !=
|
||||
QNetworkReply::NoError) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
||||
if (!mark_unstarred_feed_ids.isEmpty()) {
|
||||
if (network()->markMessagesStarred(RootItem::NotImportant, mark_unstarred_feed_ids, mark_unstarred_guid_hashes) !=
|
||||
QNetworkReply::NoError) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OwnCloudServiceRoot::updateTitle() {
|
||||
|
@ -46,7 +46,7 @@ class OwnCloudServiceRoot : public ServiceRoot {
|
||||
OwnCloudNetworkFactory *network() const;
|
||||
|
||||
bool onBeforeSetMessagesRead(RootItem *selected_item, const QList<Message> &messages, ReadStatus read);
|
||||
bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message,RootItem::Importance> > &changes);
|
||||
bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes);
|
||||
|
||||
void updateTitle();
|
||||
void saveAccountDataToDatabase();
|
||||
|
@ -200,7 +200,7 @@ bool TtRssServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item, const QL
|
||||
}
|
||||
}
|
||||
|
||||
bool TtRssServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message,Importance> > &changes) {
|
||||
bool TtRssServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes) {
|
||||
Q_UNUSED(selected_item)
|
||||
|
||||
// NOTE: We just toggle it here, because we know, that there is only
|
||||
|
@ -50,7 +50,7 @@ class TtRssServiceRoot : public ServiceRoot {
|
||||
RecycleBin *recycleBin() const;
|
||||
|
||||
bool onBeforeSetMessagesRead(RootItem *selected_item, const QList<Message> &messages, ReadStatus read);
|
||||
bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<QPair<Message,RootItem::Importance> > &changes);
|
||||
bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList<ImportanceChange> &changes);
|
||||
|
||||
// Access to network.
|
||||
TtRssNetworkFactory *network() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user