Fix Cache logic to support labels.
This commit is contained in:
parent
9b8ad9546b
commit
3cf7d6edea
@ -12,20 +12,32 @@
|
||||
|
||||
CacheForServiceRoot::CacheForServiceRoot() : m_cacheSaveMutex(new QMutex(QMutex::NonRecursive)) {}
|
||||
|
||||
void CacheForServiceRoot::addMessageStatesToCache(const QList<Message>& ids_of_messages, Label* lbl, bool assign) {
|
||||
void CacheForServiceRoot::addLabelsAssignmentsToCache(const QList<Message>& ids_of_messages, Label* lbl, bool assign) {
|
||||
auto custom_ids = lbl->getParentServiceRoot()->customIDsOfMessages(ids_of_messages);
|
||||
|
||||
if (assign) {
|
||||
m_cachedLabelAssignments[lbl->customId()].append(custom_ids);
|
||||
m_cachedLabelAssignments[lbl->customId()].removeDuplicates();
|
||||
|
||||
// Remove the same messages from "deassign" list.
|
||||
auto deassign = m_cachedLabelDeassignments[lbl->customId()];
|
||||
auto list = boolinq::from(deassign.begin(), deassign.end()).where([custom_ids](const QString& id) {
|
||||
return !custom_ids.contains(id);
|
||||
}).toStdList();
|
||||
|
||||
m_cachedLabelDeassignments[lbl->customId()] = FROM_STD_LIST(QStringList, list);
|
||||
for (const QString& custom_id : custom_ids) {
|
||||
if (m_cachedLabelDeassignments[lbl->customId()].contains(custom_id)) {
|
||||
// We want to assign this ID but it was marked for deassignment, remove from deassignment.
|
||||
m_cachedLabelDeassignments[lbl->customId()].removeAll(custom_id);
|
||||
}
|
||||
else {
|
||||
m_cachedLabelAssignments[lbl->customId()].append(custom_id);
|
||||
m_cachedLabelAssignments[lbl->customId()].removeDuplicates();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const QString& custom_id : custom_ids) {
|
||||
if (m_cachedLabelAssignments[lbl->customId()].contains(custom_id)) {
|
||||
// We want to deassign this ID but it was marked for assignment, remove from assignment.
|
||||
m_cachedLabelAssignments[lbl->customId()].removeAll(custom_id);
|
||||
}
|
||||
else {
|
||||
m_cachedLabelDeassignments[lbl->customId()].append(custom_id);
|
||||
m_cachedLabelDeassignments[lbl->customId()].removeDuplicates();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +120,8 @@ void CacheForServiceRoot::saveCacheToFile(int acc_id) {
|
||||
void CacheForServiceRoot::clearCache() {
|
||||
m_cachedStatesRead.clear();
|
||||
m_cachedStatesImportant.clear();
|
||||
m_cachedLabelAssignments.clear();
|
||||
m_cachedLabelDeassignments.clear();
|
||||
}
|
||||
|
||||
void CacheForServiceRoot::loadCacheFromFile(int acc_id) {
|
||||
@ -132,25 +146,34 @@ void CacheForServiceRoot::loadCacheFromFile(int acc_id) {
|
||||
}
|
||||
}
|
||||
|
||||
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> CacheForServiceRoot::takeMessageCache() {
|
||||
CacheSnapshot CacheForServiceRoot::takeMessageCache() {
|
||||
QMutexLocker lck(m_cacheSaveMutex.data());
|
||||
|
||||
if (isEmpty()) {
|
||||
return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>>();
|
||||
return CacheSnapshot();
|
||||
}
|
||||
|
||||
// Make copy of changes.
|
||||
QMap<RootItem::ReadStatus, QStringList> cached_data_read = m_cachedStatesRead;
|
||||
auto cached_data_read = m_cachedStatesRead;
|
||||
auto cached_data_imp = m_cachedStatesImportant;
|
||||
auto cached_ass_lbl = m_cachedLabelAssignments;
|
||||
auto cached_deass_lbl = m_cachedLabelDeassignments;
|
||||
|
||||
cached_data_read.detach();
|
||||
|
||||
QMap<RootItem::Importance, QList<Message>> cached_data_imp = m_cachedStatesImportant;
|
||||
|
||||
cached_data_imp.detach();
|
||||
cached_ass_lbl.detach();
|
||||
cached_deass_lbl.detach();
|
||||
|
||||
clearCache();
|
||||
|
||||
return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>>(cached_data_read, cached_data_imp);
|
||||
CacheSnapshot c;
|
||||
|
||||
c.m_cachedLabelAssignments = cached_ass_lbl;
|
||||
c.m_cachedLabelDeassignments = cached_deass_lbl;
|
||||
c.m_cachedStatesImportant = cached_data_imp;
|
||||
c.m_cachedStatesRead = cached_data_read;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
bool CacheForServiceRoot::isEmpty() const {
|
||||
|
@ -11,11 +11,18 @@
|
||||
|
||||
class QMutex;
|
||||
|
||||
struct CacheSnapshot {
|
||||
QMap<QString, QStringList> m_cachedLabelAssignments;
|
||||
QMap<QString, QStringList> m_cachedLabelDeassignments;
|
||||
QMap<RootItem::ReadStatus, QStringList> m_cachedStatesRead;
|
||||
QMap<RootItem::Importance, QList<Message>> m_cachedStatesImportant;
|
||||
};
|
||||
|
||||
class CacheForServiceRoot {
|
||||
public:
|
||||
explicit CacheForServiceRoot();
|
||||
|
||||
void addMessageStatesToCache(const QList<Message>& ids_of_messages, Label* lbl, bool assign);
|
||||
void addLabelsAssignmentsToCache(const QList<Message>& ids_of_messages, Label* lbl, bool assign);
|
||||
void addMessageStatesToCache(const QList<Message>& ids_of_messages, RootItem::Importance importance);
|
||||
void addMessageStatesToCache(const QStringList& ids_of_messages, RootItem::ReadStatus read);
|
||||
|
||||
@ -27,7 +34,7 @@ class CacheForServiceRoot {
|
||||
virtual void saveAllCachedData(bool async = true) = 0;
|
||||
|
||||
protected:
|
||||
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> takeMessageCache();
|
||||
CacheSnapshot takeMessageCache();
|
||||
|
||||
QScopedPointer<QMutex> m_cacheSaveMutex;
|
||||
|
||||
|
@ -104,19 +104,21 @@ QIcon Label::generateIcon(const QColor& color) {
|
||||
void Label::assignToMessage(const Message& msg) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::assignLabelToMessage(database, this, msg);
|
||||
if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({this}, {msg}, true)) {
|
||||
DatabaseQueries::assignLabelToMessage(database, this, msg);
|
||||
|
||||
updateCounts(true);
|
||||
getParentServiceRoot()->itemChanged({ this });
|
||||
getParentServiceRoot()->onAfterLabelMessageAssignmentChanged({this}, {msg}, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Label::deassignFromMessage(const Message& msg) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::deassignLabelFromMessage(database, this, msg);
|
||||
if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({this}, {msg}, false)) {
|
||||
DatabaseQueries::deassignLabelFromMessage(database, this, msg);
|
||||
|
||||
updateCounts(true);
|
||||
getParentServiceRoot()->itemChanged({ this });
|
||||
getParentServiceRoot()->onAfterLabelMessageAssignmentChanged({this}, {msg}, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Label::setCountOfAllMessages(int totalCount) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "services/abstract/serviceroot.h"
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "core/feedsmodel.h"
|
||||
#include "core/messagesmodel.h"
|
||||
#include "miscellaneous/application.h"
|
||||
@ -616,6 +617,34 @@ bool ServiceRoot::onAfterMessagesDelete(RootItem* selected_item, const QList<Mes
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceRoot::onBeforeLabelMessageAssignmentChanged(const QList<Label*> labels, const QList<Message>& messages, bool assign) {
|
||||
auto cache = dynamic_cast<CacheForServiceRoot*>(this);
|
||||
|
||||
if (cache != nullptr) {
|
||||
boolinq::from(labels).for_each([cache, messages, assign](Label* lbl) {
|
||||
cache->addLabelsAssignmentsToCache(messages, lbl, assign);
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceRoot::onAfterLabelMessageAssignmentChanged(const QList<Label*> labels, const QList<Message>& messages, bool assign) {
|
||||
Q_UNUSED(messages)
|
||||
Q_UNUSED(assign)
|
||||
|
||||
boolinq::from(labels).for_each([](Label* lbl) {
|
||||
lbl->updateCounts(true);
|
||||
});
|
||||
|
||||
auto list = boolinq::from(labels).select([](Label* lbl) {
|
||||
return static_cast<RootItem*>(lbl);
|
||||
}).toStdList();
|
||||
|
||||
getParentServiceRoot()->itemChanged(FROM_STD_LIST(QList<RootItem*>, list));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceRoot::onBeforeMessagesRestoredFromBin(RootItem* selected_item, const QList<Message>& messages) {
|
||||
Q_UNUSED(selected_item)
|
||||
Q_UNUSED(messages)
|
||||
|
@ -123,6 +123,12 @@ class ServiceRoot : public RootItem {
|
||||
// by the user from message list.
|
||||
virtual bool onAfterMessagesDelete(RootItem* selected_item, const QList<Message>& messages);
|
||||
|
||||
// Called BEFORE some labels are assigned/deassigned from/to messages.
|
||||
virtual bool onBeforeLabelMessageAssignmentChanged(const QList<Label*> labels, const QList<Message>& messages, bool assign);
|
||||
|
||||
// Called AFTER some labels are assigned/deassigned from/to messages.
|
||||
virtual bool onAfterLabelMessageAssignmentChanged(const QList<Label*> labels, const QList<Message>& messages, bool assign);
|
||||
|
||||
// Called BEFORE the list of messages is about to be restored from recycle bin
|
||||
// by the user from message list.
|
||||
// Selected item is naturally recycle bin.
|
||||
|
@ -209,8 +209,8 @@ QString GmailServiceRoot::additionalTooltip() const {
|
||||
}
|
||||
|
||||
void GmailServiceRoot::saveAllCachedData(bool async) {
|
||||
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
|
||||
auto msg_cache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msg_cache.m_cachedStatesRead);
|
||||
|
||||
// Save the actual data read/unread.
|
||||
while (i.hasNext()) {
|
||||
@ -223,7 +223,7 @@ void GmailServiceRoot::saveAllCachedData(bool async) {
|
||||
}
|
||||
}
|
||||
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msgCache.second);
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msg_cache.m_cachedStatesImportant);
|
||||
|
||||
// Save the actual data important/not important.
|
||||
while (j.hasNext()) {
|
||||
|
@ -133,8 +133,8 @@ RootItem* InoreaderServiceRoot::obtainNewTreeForSyncIn() const {
|
||||
}
|
||||
|
||||
void InoreaderServiceRoot::saveAllCachedData(bool async) {
|
||||
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
|
||||
auto msg_cache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msg_cache.m_cachedStatesRead);
|
||||
|
||||
// Save the actual data read/unread.
|
||||
while (i.hasNext()) {
|
||||
@ -147,7 +147,7 @@ void InoreaderServiceRoot::saveAllCachedData(bool async) {
|
||||
}
|
||||
}
|
||||
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msgCache.second);
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msg_cache.m_cachedStatesImportant);
|
||||
|
||||
// Save the actual data important/not important.
|
||||
while (j.hasNext()) {
|
||||
|
@ -86,8 +86,8 @@ OwnCloudNetworkFactory* OwnCloudServiceRoot::network() const {
|
||||
}
|
||||
|
||||
void OwnCloudServiceRoot::saveAllCachedData(bool async) {
|
||||
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
|
||||
auto msg_cache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msg_cache.m_cachedStatesRead);
|
||||
|
||||
// Save the actual data read/unread.
|
||||
while (i.hasNext()) {
|
||||
@ -100,7 +100,7 @@ void OwnCloudServiceRoot::saveAllCachedData(bool async) {
|
||||
}
|
||||
}
|
||||
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msgCache.second);
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msg_cache.m_cachedStatesImportant);
|
||||
|
||||
// Save the actual data important/not important.
|
||||
while (j.hasNext()) {
|
||||
|
@ -117,8 +117,8 @@ bool TtRssServiceRoot::canBeDeleted() const {
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::saveAllCachedData(bool async) {
|
||||
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
|
||||
auto msg_cache = takeMessageCache();
|
||||
QMapIterator<RootItem::ReadStatus, QStringList> i(msg_cache.m_cachedStatesRead);
|
||||
|
||||
// Save the actual data read/unread.
|
||||
while (i.hasNext()) {
|
||||
@ -136,7 +136,7 @@ void TtRssServiceRoot::saveAllCachedData(bool async) {
|
||||
}
|
||||
}
|
||||
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msgCache.second);
|
||||
QMapIterator<RootItem::Importance, QList<Message>> j(msg_cache.m_cachedStatesImportant);
|
||||
|
||||
// Save the actual data important/not important.
|
||||
while (j.hasNext()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user