From d0b19b73616520b8822a179fd9fa2efa92d877d7 Mon Sep 17 00:00:00 2001 From: martinrotter Date: Fri, 28 Apr 2017 08:41:38 +0200 Subject: [PATCH] Experimental async starred msg marking. - #71 --- src/core/message.cpp | 9 ++++ src/core/message.h | 11 +++++ src/gui/messagepreviewer.cpp | 10 ++-- src/gui/webbrowser.cpp | 10 ++-- src/services/abstract/cacheforserviceroot.cpp | 31 ++++++++++-- src/services/abstract/cacheforserviceroot.h | 5 +- src/services/owncloud/owncloudserviceroot.cpp | 48 +++++++++++-------- src/services/tt-rss/ttrssserviceroot.cpp | 2 +- 8 files changed, 89 insertions(+), 37 deletions(-) diff --git a/src/core/message.cpp b/src/core/message.cpp index 4bba43d99..6459bd700 100755 --- a/src/core/message.cpp +++ b/src/core/message.cpp @@ -101,3 +101,12 @@ Message Message::fromSqlRecord(const QSqlRecord &record, bool *result) { return message; } + +uint qHash(Message key, uint seed) { + Q_UNUSED(seed) + return (key.m_accountId * 10000) + key.m_id; +} + +uint qHash(const Message &key) { + return (key.m_accountId * 10000) + key.m_id; +} diff --git a/src/core/message.h b/src/core/message.h index b2340715a..1a917ca5b 100755 --- a/src/core/message.h +++ b/src/core/message.h @@ -69,6 +69,17 @@ class Message { // Is true if "created" date was obtained directly // from the feed, otherwise is false bool m_createdFromFeed; + + friend inline bool operator==(const Message &lhs, const Message &rhs) { + return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id; + } + + friend inline bool operator!=(const Message &lhs, const Message &rhs) { + return !(lhs == rhs); + } }; +uint qHash(Message key, uint seed); +uint qHash(const Message &key); + #endif // MESSAGE_H diff --git a/src/gui/messagepreviewer.cpp b/src/gui/messagepreviewer.cpp index aa2a1ffb3..739585b66 100755 --- a/src/gui/messagepreviewer.cpp +++ b/src/gui/messagepreviewer.cpp @@ -189,11 +189,11 @@ void MessagePreviewer::switchMessageImportance(bool checked) { DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), QStringList() << QString::number(m_message.m_id)); - m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(m_message, - m_message.m_isImportant ? - RootItem::NotImportant : - RootItem::Important)); + m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(), + QList() << ImportanceChange(m_message, + m_message.m_isImportant ? + RootItem::NotImportant : + RootItem::Important)); emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant); m_message.m_isImportant = checked; diff --git a/src/gui/webbrowser.cpp b/src/gui/webbrowser.cpp index f46970882..9c847b655 100755 --- a/src/gui/webbrowser.cpp +++ b/src/gui/webbrowser.cpp @@ -290,11 +290,11 @@ void WebBrowser::switchMessageImportance(int id, bool checked) { DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), QStringList() << QString::number(msg->m_id)); - m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(*msg, - msg->m_isImportant ? - RootItem::NotImportant : - RootItem::Important)); + m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(), + QList() << ImportanceChange(*msg, + msg->m_isImportant ? + RootItem::NotImportant : + RootItem::Important)); emit markMessageImportant(msg->m_id, msg->m_isImportant ? RootItem::NotImportant : RootItem::Important); msg->m_isImportant = checked; diff --git a/src/services/abstract/cacheforserviceroot.cpp b/src/services/abstract/cacheforserviceroot.cpp index eb812c4d1..a54c456ab 100755 --- a/src/services/abstract/cacheforserviceroot.cpp +++ b/src/services/abstract/cacheforserviceroot.cpp @@ -24,13 +24,34 @@ CacheForServiceRoot::CacheForServiceRoot() : m_cacheSaveMutex(new Mutex(QMutex::NonRecursive, nullptr)), m_cachedStatesRead(QMap()), - m_cachedStatesImportant(QMap()) { + m_cachedStatesImportant(QMap>()) { } CacheForServiceRoot::~CacheForServiceRoot() { m_cacheSaveMutex->deleteLater(); } +void CacheForServiceRoot::addMessageStatesToCache(const QList &ids_of_messages, RootItem::Importance importance) { + m_cacheSaveMutex->lock(); + + QList &list_act = m_cachedStatesImportant[importance]; + QList &list_other = m_cachedStatesImportant[importance == RootItem::Important ? RootItem::NotImportant : RootItem::Important]; + + // Store changes, they will be sent to server later. + list_act.append(ids_of_messages); + + QSet set_act = list_act.toSet(); + QSet set_other = list_other.toSet(); + + // Now, we want to remove all IDS from list_other, which are contained in list. + set_other -= set_act; + + list_act.clear(); list_act.append(set_act.toList()); + list_other.clear(); list_other.append(set_other.toList()); + + m_cacheSaveMutex->unlock(); +} + void CacheForServiceRoot::addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read) { m_cacheSaveMutex->lock(); @@ -52,20 +73,20 @@ void CacheForServiceRoot::addMessageStatesToCache(const QStringList &ids_of_mess m_cacheSaveMutex->unlock(); } -QPair, QMap > CacheForServiceRoot::takeMessageCache() { +QPair, QMap> > CacheForServiceRoot::takeMessageCache() { m_cacheSaveMutex->lock(); if (m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty()) { // No cached changes. m_cacheSaveMutex->unlock(); - return QPair, QMap >(); + return QPair, QMap> >(); } // Make copy of changes. QMap cached_data_read = m_cachedStatesRead; cached_data_read.detach(); - QMap cached_data_imp = m_cachedStatesImportant; + QMap> cached_data_imp = m_cachedStatesImportant; cached_data_imp.detach(); m_cachedStatesRead.clear(); @@ -73,5 +94,5 @@ QPair, QMapunlock(); - return QPair, QMap >(cached_data_read, cached_data_imp); + return QPair, QMap> >(cached_data_read, cached_data_imp); } diff --git a/src/services/abstract/cacheforserviceroot.h b/src/services/abstract/cacheforserviceroot.h index 67829fd54..a62a73d27 100755 --- a/src/services/abstract/cacheforserviceroot.h +++ b/src/services/abstract/cacheforserviceroot.h @@ -32,14 +32,15 @@ class CacheForServiceRoot { explicit CacheForServiceRoot(); virtual ~CacheForServiceRoot(); + void addMessageStatesToCache(const QList &ids_of_messages, RootItem::Importance importance); void addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read); protected: - QPair, QMap> takeMessageCache(); + QPair, QMap > > takeMessageCache(); Mutex *m_cacheSaveMutex; QMap m_cachedStatesRead; - QMap m_cachedStatesImportant; + QMap> m_cachedStatesImportant; }; #endif // CACHEFORSERVICEROOT_H diff --git a/src/services/owncloud/owncloudserviceroot.cpp b/src/services/owncloud/owncloudserviceroot.cpp index fdedbd621..1a35b09d3 100755 --- a/src/services/owncloud/owncloudserviceroot.cpp +++ b/src/services/owncloud/owncloudserviceroot.cpp @@ -118,7 +118,7 @@ OwnCloudNetworkFactory *OwnCloudServiceRoot::network() const { } void OwnCloudServiceRoot::saveAllCachedData() { - QPair, QMap> msgCache = takeMessageCache(); + QPair, QMap>> msgCache = takeMessageCache(); QMapIterator i(msgCache.first); // Save the actual data read/unread. @@ -131,6 +131,26 @@ void OwnCloudServiceRoot::saveAllCachedData() { network()->markMessagesRead(key, ids); } } + + QMapIterator> j(msgCache.second); + + // Save the actual data important/not important. + while (j.hasNext()) { + j.next(); + auto key = j.key(); + QList messages = j.value(); + + if (!messages.isEmpty()) { + QStringList feed_ids, guid_hashes; + + foreach (const Message &msg, messages) { + feed_ids.append(msg.m_feedId); + guid_hashes.append(msg.m_customHash); + } + + network()->markMessagesStarred(key, feed_ids, guid_hashes); + } + } } bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item, @@ -147,34 +167,24 @@ bool OwnCloudServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_ite Q_UNUSED(selected_item) // 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; + QList mark_starred_msgs; + QList mark_unstarred_msgs; 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); + mark_starred_msgs.append(pair.first); } else { - mark_unstarred_feed_ids.append(pair.first.m_feedId); - mark_unstarred_guid_hashes.append(pair.first.m_customHash); + mark_unstarred_msgs.append(pair.first); } } - // 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; - } + if (!mark_starred_msgs.isEmpty()) { + addMessageStatesToCache(mark_starred_msgs, RootItem::Important); } - if (!mark_unstarred_feed_ids.isEmpty()) { - if (network()->markMessagesStarred(RootItem::NotImportant, mark_unstarred_feed_ids, mark_unstarred_guid_hashes) != - QNetworkReply::NoError) { - return false; - } + if (!mark_unstarred_msgs.isEmpty()) { + addMessageStatesToCache(mark_unstarred_msgs, RootItem::NotImportant); } return true; diff --git a/src/services/tt-rss/ttrssserviceroot.cpp b/src/services/tt-rss/ttrssserviceroot.cpp index 800417e79..c8ca6c662 100755 --- a/src/services/tt-rss/ttrssserviceroot.cpp +++ b/src/services/tt-rss/ttrssserviceroot.cpp @@ -170,7 +170,7 @@ void TtRssServiceRoot::saveAllCachedData() { return false; }*/ - QPair, QMap> msgCache = takeMessageCache(); + QPair, QMap>> msgCache = takeMessageCache(); QMapIterator i(msgCache.first); // Save the actual data read/unread.