From 027b1b8abd48b8b663dc1ac33729b625df74ce33 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Fri, 11 Dec 2020 13:29:00 +0100 Subject: [PATCH] Save. --- src/librssguard/core/messageobject.h | 2 +- .../core/messagesforfiltersmodel.cpp | 4 + .../gui/dialogs/formmessagefiltersmanager.cpp | 98 +++++++++++++++++-- .../services/abstract/accountcheckmodel.cpp | 7 +- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/librssguard/core/messageobject.h b/src/librssguard/core/messageobject.h index ac3e041d8..1aaea4dab 100755 --- a/src/librssguard/core/messageobject.h +++ b/src/librssguard/core/messageobject.h @@ -29,7 +29,7 @@ class MessageObject : public QObject { // Message is normally accepted and stored in DB or updated. Accept = 1, - // Message is ignored and will not be stored in DB but is not purge if it already exists. + // Message is ignored and will not be stored in DB but is not purged if it already exists. Ignore = 2, // Message is purged from DB if it already exists. diff --git a/src/librssguard/core/messagesforfiltersmodel.cpp b/src/librssguard/core/messagesforfiltersmodel.cpp index 7ebb1762a..959e8af13 100755 --- a/src/librssguard/core/messagesforfiltersmodel.cpp +++ b/src/librssguard/core/messagesforfiltersmodel.cpp @@ -42,7 +42,11 @@ QVariant MessagesForFiltersModel::data(const QModelIndex& index, int role) const return qApp->skins()->currentSkin().m_colorPalette[Skin::PaletteColors::Allright]; case MessageObject::FilteringAction::Ignore: + case MessageObject::FilteringAction::Purge: return qApp->skins()->currentSkin().m_colorPalette[Skin::PaletteColors::Error]; + + default: + break; } } diff --git a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp index d26fb0dd8..e5f9b6a6f 100644 --- a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp +++ b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp @@ -6,12 +6,14 @@ #include "gui/dialogs/formmessagefiltersmanager.h" +#include "3rd-party/boolinq/boolinq.h" #include "core/messagefilter.h" #include "core/messagesforfiltersmodel.h" #include "exceptions/filteringexception.h" #include "gui/guiutilities.h" #include "gui/messagebox.h" #include "miscellaneous/application.h" +#include "miscellaneous/databasequeries.h" #include "miscellaneous/feedreader.h" #include "miscellaneous/iconfactory.h" #include "network-web/webfactory.h" @@ -248,33 +250,113 @@ void FormMessageFiltersManager::processCheckedFeeds() { auto* fltr = selectedFilter(); QSqlDatabase database = qApp->database()->connection(metaObject()->className()); - for (const RootItem* it : checked) { + for (RootItem* it : checked) { if (it->kind() == RootItem::Kind::Feed) { QJSEngine filter_engine; MessageObject msg_obj(&database, - QString(), - selectedAccount() != nullptr ? selectedAccount()->accountId() : NO_PARENT_CATEGORY, + it->customId(), + selectedAccount()->accountId(), it->getParentServiceRoot()->labelsNode()->labels()); MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj); // We process messages of the feed. QList msgs = it->undeletedMessages(); + QList read_msgs, important_msgs; for (int i = 0; i < msgs.size(); i++) { - Message& msg = msgs[i]; + auto labels_in_message = DatabaseQueries::getLabelsForMessage(database, msgs[i], msg_obj.availableLabels()); - // TODO: create backup of msg and forward changes to - // caching mechanisms if needed. + // Create backup of message. + Message* msg = &msgs[i]; msg->m_assignedLabels = labels_in_message; + Message msg_backup(*msg); + + msg_obj.setMessage(msg); MessageObject::FilteringAction result = fltr->filterMessage(&filter_engine); + bool remove_from_list = false; if (result == MessageObject::FilteringAction::Purge) { + remove_from_list = true; + // TODO: Purge the message completely. - msgs.removeAt(i--); + // DatabaseQueries::purgeMessage(msg_id); + } + else if (result == MessageObject::FilteringAction::Ignore) { + remove_from_list = true; } - // Message will be processed/update via SQL layer. + if (!msg_backup.m_isRead && msg->m_isRead) { + qDebugNN << LOGSEC_FEEDDOWNLOADER << "Message with custom ID: '" << msg_backup.m_customId << "' was marked as read by message scripts."; + + read_msgs << *msg; + } + + if (!msg_backup.m_isImportant && msg->m_isImportant) { + qDebugNN << LOGSEC_FEEDDOWNLOADER << "Message with custom ID: '" << msg_backup.m_customId << "' was marked as important by message scripts."; + + important_msgs << *msg; + } + + // Process changed labels. + for (Label* lbl : msg_backup.m_assignedLabels) { + if (!msg->m_assignedLabels.contains(lbl)) { + // Label is not there anymore, it was deassigned. + lbl->deassignFromMessage(*msg); + + qDebugNN << LOGSEC_FEEDDOWNLOADER + << "It was detected that label" << QUOTE_W_SPACE(lbl->customId()) + << "was DEASSIGNED from message" << QUOTE_W_SPACE(msg->m_customId) + << "by message filter(s)."; + } + } + + for (Label* lbl : msg->m_assignedLabels) { + if (!msg_backup.m_assignedLabels.contains(lbl)) { + // Label is in new message, but is not in old message, it + // was newly assigned. + lbl->assignToMessage(*msg); + + qDebugNN << LOGSEC_FEEDDOWNLOADER + << "It was detected that label" << QUOTE_W_SPACE(lbl->customId()) + << "was ASSIGNED to message" << QUOTE_W_SPACE(msg->m_customId) + << "by message filter(s)."; + } + } + + if (remove_from_list) { + // Do not update message. + msgs.removeAt(i--); + } + } + + if (!read_msgs.isEmpty()) { + // Now we push new read states to the service. + if (it->getParentServiceRoot()->onBeforeSetMessagesRead(it, read_msgs, RootItem::ReadStatus::Read)) { + qDebugNN << LOGSEC_FEEDDOWNLOADER + << "Notified services about messages marked as read by message filters."; + } + else { + qCriticalNN << LOGSEC_FEEDDOWNLOADER + << "Notification of services about messages marked as read by message filters FAILED."; + } + } + + if (!important_msgs.isEmpty()) { + // Now we push new read states to the service. + auto list = boolinq::from(important_msgs).select([](const Message& msg) { + return ImportanceChange(msg, RootItem::Importance::Important); + }).toStdList(); + QList chngs = FROM_STD_LIST(QList, list); + + if (it->getParentServiceRoot()->onBeforeSwitchMessageImportance(it, chngs)) { + qDebugNN << LOGSEC_FEEDDOWNLOADER + << "Notified services about messages marked as important by message filters."; + } + else { + qCriticalNN << LOGSEC_FEEDDOWNLOADER + << "Notification of services about messages marked as important by message filters FAILED."; + } } int updated_in_db = it->toFeed()->updateMessages(msgs, false); diff --git a/src/librssguard/services/abstract/accountcheckmodel.cpp b/src/librssguard/services/abstract/accountcheckmodel.cpp index c403870aa..2f855dafb 100644 --- a/src/librssguard/services/abstract/accountcheckmodel.cpp +++ b/src/librssguard/services/abstract/accountcheckmodel.cpp @@ -276,10 +276,11 @@ Qt::ItemFlags AccountCheckModel::flags(const QModelIndex& index) const { QList AccountCheckModel::checkedItems() const { auto keys = m_checkStates.keys(); - - return FROM_STD_LIST(QList, boolinq::from(keys).where([&](const auto& key) { + auto res = boolinq::from(keys).where([&](const auto& key) { return m_checkStates.value(key) == Qt::CheckState::Checked; - }).toStdList()); + }).toStdList(); + + return FROM_STD_LIST(QList, res); } bool AccountCheckModel::isItemChecked(RootItem* item) const {