Message marking starred now works. New schema DB version.

This commit is contained in:
Martin Rotter 2016-02-26 09:15:57 +01:00
parent fb1233d379
commit 3efd22491c
18 changed files with 146 additions and 43 deletions

View File

@ -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)
);

View File

@ -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)
);

View File

@ -0,0 +1,5 @@
-- !
ALTER TABLE Messages
ADD COLUMN custom_hash TEXT;
-- !
UPDATE Information SET inf_value = '6' WHERE inf_key = 'schema_version';

View 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';

View File

@ -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;

View File

@ -59,6 +59,7 @@ class Message {
int m_accountId;
int m_id;
QString m_customId;
QString m_customHash;
bool m_isRead;
bool m_isImportant;

View File

@ -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 {

View File

@ -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

View File

@ -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.");
}

View File

@ -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) {

View File

@ -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)

View File

@ -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.

View File

@ -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();

View File

@ -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;

View File

@ -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() {

View File

@ -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();

View File

@ -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

View File

@ -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;