This commit is contained in:
Martin Rotter 2020-12-10 20:53:31 +01:00
parent b077c7f846
commit c8b1b900df
8 changed files with 105 additions and 25 deletions

View File

@ -66,7 +66,7 @@ Message::Message() {
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = ""; m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = "";
m_enclosures = QList<Enclosure>(); m_enclosures = QList<Enclosure>();
m_accountId = m_id = 0; m_accountId = m_id = 0;
m_isRead = m_isImportant = false; m_isRead = m_isImportant = m_isDeleted = false;
m_assignedLabels = QList<Label*>(); m_assignedLabels = QList<Label*>();
} }
@ -98,6 +98,7 @@ Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
message.m_id = record.value(MSG_DB_ID_INDEX).toInt(); message.m_id = record.value(MSG_DB_ID_INDEX).toInt();
message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool(); message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool();
message.m_isImportant = record.value(MSG_DB_IMPORTANT_INDEX).toBool(); message.m_isImportant = record.value(MSG_DB_IMPORTANT_INDEX).toBool();
message.m_isDeleted = record.value(MSG_DB_DELETED_INDEX).toBool();
message.m_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString(); message.m_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString();
message.m_title = record.value(MSG_DB_TITLE_INDEX).toString(); message.m_title = record.value(MSG_DB_TITLE_INDEX).toString();
message.m_url = record.value(MSG_DB_URL_INDEX).toString(); message.m_url = record.value(MSG_DB_URL_INDEX).toString();
@ -116,19 +117,20 @@ Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
return message; return message;
} }
QDataStream& operator<<(QDataStream& out, const Message& myObj) { QDataStream& operator<<(QDataStream& out, const Message& my_obj) {
out << myObj.m_accountId out << my_obj.m_accountId
<< myObj.m_customHash << my_obj.m_customHash
<< myObj.m_customId << my_obj.m_customId
<< myObj.m_feedId << my_obj.m_feedId
<< myObj.m_id << my_obj.m_id
<< myObj.m_isImportant << my_obj.m_isImportant
<< myObj.m_isRead; << my_obj.m_isRead
<< my_obj.m_isDeleted;
return out; return out;
} }
QDataStream& operator>>(QDataStream& in, Message& myObj) { QDataStream& operator>>(QDataStream& in, Message& my_obj) {
int accountId; int accountId;
QString customHash; QString customHash;
QString customId; QString customId;
@ -136,16 +138,18 @@ QDataStream& operator>>(QDataStream& in, Message& myObj) {
int id; int id;
bool isImportant; bool isImportant;
bool isRead; bool isRead;
bool isDeleted;
in >> accountId >> customHash >> customId >> feedId >> id >> isImportant >> isRead; in >> accountId >> customHash >> customId >> feedId >> id >> isImportant >> isRead >> isDeleted;
myObj.m_accountId = accountId; my_obj.m_accountId = accountId;
myObj.m_customHash = customHash; my_obj.m_customHash = customHash;
myObj.m_customId = customId; my_obj.m_customId = customId;
myObj.m_feedId = feedId; my_obj.m_feedId = feedId;
myObj.m_id = id; my_obj.m_id = id;
myObj.m_isImportant = isImportant; my_obj.m_isImportant = isImportant;
myObj.m_isRead = isRead; my_obj.m_isRead = isRead;
my_obj.m_isDeleted = isDeleted;
return in; return in;
} }

View File

@ -53,6 +53,7 @@ class RSSGUARD_DLLSPEC Message {
QString m_customHash; QString m_customHash;
bool m_isRead; bool m_isRead;
bool m_isImportant; bool m_isImportant;
bool m_isDeleted;
QList<Enclosure> m_enclosures; QList<Enclosure> m_enclosures;
// List of custom IDs of labels assigned to this message. // List of custom IDs of labels assigned to this message.
@ -75,8 +76,8 @@ inline bool operator!=(const Message& lhs, const Message& rhs) {
// Serialize message state. // Serialize message state.
// NOTE: This is used for persistent caching of message state changes. // NOTE: This is used for persistent caching of message state changes.
RSSGUARD_DLLSPEC QDataStream& operator<<(QDataStream& out, const Message& myObj); RSSGUARD_DLLSPEC QDataStream& operator<<(QDataStream& out, const Message& my_obj);
RSSGUARD_DLLSPEC QDataStream& operator>>(QDataStream& in, Message& myObj); RSSGUARD_DLLSPEC QDataStream& operator>>(QDataStream& in, Message& my_obj);
uint qHash(const Message& key, uint seed); uint qHash(const Message& key, uint seed);
uint qHash(const Message& key); uint qHash(const Message& key);

View File

@ -175,6 +175,14 @@ void MessageObject::setIsImportant(bool is_important) {
m_message->m_isImportant = is_important; m_message->m_isImportant = is_important;
} }
bool MessageObject::isDeleted() const {
return m_message->m_isDeleted;
}
void MessageObject::setIsDeleted(bool is_deleted) {
m_message->m_isDeleted = is_deleted;
}
QString MessageObject::feedCustomId() const { QString MessageObject::feedCustomId() const {
return m_feedCustomId; return m_feedCustomId;
} }

View File

@ -21,6 +21,7 @@ class MessageObject : public QObject {
Q_PROPERTY(QDateTime created READ created WRITE setCreated) Q_PROPERTY(QDateTime created READ created WRITE setCreated)
Q_PROPERTY(bool isRead READ isRead WRITE setIsRead) Q_PROPERTY(bool isRead READ isRead WRITE setIsRead)
Q_PROPERTY(bool isImportant READ isImportant WRITE setIsImportant) Q_PROPERTY(bool isImportant READ isImportant WRITE setIsImportant)
Q_PROPERTY(bool isDeleted READ isDeleted WRITE setIsDeleted)
Q_PROPERTY(bool alreadyStored READ alreadyStored) Q_PROPERTY(bool alreadyStored READ alreadyStored)
public: public:
@ -108,6 +109,9 @@ class MessageObject : public QObject {
bool isImportant() const; bool isImportant() const;
void setIsImportant(bool is_important); void setIsImportant(bool is_important);
bool isDeleted() const;
void setIsDeleted(bool is_deleted);
private: private:
QSqlDatabase* m_db; QSqlDatabase* m_db;
QString m_feedCustomId; QString m_feedCustomId;

View File

@ -17,6 +17,7 @@
#include "network-web/webfactory.h" #include "network-web/webfactory.h"
#include "services/abstract/accountcheckmodel.h" #include "services/abstract/accountcheckmodel.h"
#include "services/abstract/feed.h" #include "services/abstract/feed.h"
#include "services/abstract/labelsnode.h"
FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const QList<ServiceRoot*>& accounts, QWidget* parent) FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const QList<ServiceRoot*>& accounts, QWidget* parent)
: QDialog(parent), m_feedsModel(new AccountCheckSortedModel(this)), m_rootItem(new RootItem()), : QDialog(parent), m_feedsModel(new AccountCheckSortedModel(this)), m_rootItem(new RootItem()),
@ -72,6 +73,8 @@ FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const Q
this, &FormMessageFiltersManager::onFeedChecked); this, &FormMessageFiltersManager::onFeedChecked);
connect(m_ui.m_treeFeeds->selectionModel(), &QItemSelectionModel::selectionChanged, connect(m_ui.m_treeFeeds->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &FormMessageFiltersManager::displayMessagesOfFeed); this, &FormMessageFiltersManager::displayMessagesOfFeed);
connect(m_ui.m_btnRunOnMessages, &QPushButton::clicked,
this, &FormMessageFiltersManager::processCheckedFeeds);
initializeTestingMessage(); initializeTestingMessage();
loadFilters(); loadFilters();
@ -165,14 +168,17 @@ void FormMessageFiltersManager::testFilter() {
m_ui.m_txtErrors->clear(); m_ui.m_txtErrors->clear();
// Perform per-message filtering. // Perform per-message filtering.
auto* selected_fd_cat = selectedCategoryFeed();
QJSEngine filter_engine; QJSEngine filter_engine;
QSqlDatabase database = qApp->database()->connection(metaObject()->className()); QSqlDatabase database = qApp->database()->connection(metaObject()->className());
MessageObject msg_obj(&database, MessageObject msg_obj(&database,
QString::number(NO_PARENT_CATEGORY), selected_fd_cat->kind() == RootItem::Kind::Feed
? selected_fd_cat->customId()
: QString::number(NO_PARENT_CATEGORY),
selectedAccount() != nullptr selectedAccount() != nullptr
? selectedAccount()->accountId() ? selectedAccount()->accountId()
: NO_PARENT_CATEGORY, : NO_PARENT_CATEGORY,
{}); selected_fd_cat->getParentServiceRoot()->labelsNode()->labels());
auto* fltr = selectedFilter(); auto* fltr = selectedFilter();
MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj); MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj);
@ -227,7 +233,7 @@ void FormMessageFiltersManager::testFilter() {
} }
void FormMessageFiltersManager::displayMessagesOfFeed() { void FormMessageFiltersManager::displayMessagesOfFeed() {
auto* item = m_feedsModel->sourceModel()->itemForIndex(m_feedsModel->mapToSource(m_ui.m_treeFeeds->currentIndex())); auto* item = selectedCategoryFeed();
if (item != nullptr) { if (item != nullptr) {
m_msgModel->setMessages(item->undeletedMessages()); m_msgModel->setMessages(item->undeletedMessages());
@ -237,6 +243,45 @@ void FormMessageFiltersManager::displayMessagesOfFeed() {
} }
} }
void FormMessageFiltersManager::processCheckedFeeds() {
QList<RootItem*> checked = m_feedsModel->sourceModel()->checkedItems();
auto* fltr = selectedFilter();
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
for (const 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->getParentServiceRoot()->labelsNode()->labels());
MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj);
// We process messages of the feed.
QList<Message> msgs = it->undeletedMessages();
for (int i = 0; i < msgs.size(); i++) {
Message& msg = msgs[i];
// TODO: create backup of msg and forward changes to
// caching mechanisms if needed.
MessageObject::FilteringAction result = fltr->filterMessage(&filter_engine);
if (result == MessageObject::FilteringAction::Purge) {
// TODO: Purge the message completely.
msgs.removeAt(i--);
}
// Message will be processed/update via SQL layer.
}
int updated_in_db = it->toFeed()->updateMessages(msgs, false);
}
}
}
void FormMessageFiltersManager::loadAccount(ServiceRoot* account) { void FormMessageFiltersManager::loadAccount(ServiceRoot* account) {
m_feedsModel->setRootItem(account, false, true); m_feedsModel->setRootItem(account, false, true);
@ -395,6 +440,10 @@ void FormMessageFiltersManager::initializeTestingMessage() {
m_ui.m_txtSampleCreatedOn->setText(QString::number(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch())); m_ui.m_txtSampleCreatedOn->setText(QString::number(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()));
} }
RootItem* FormMessageFiltersManager::selectedCategoryFeed() const {
return m_feedsModel->sourceModel()->itemForIndex(m_feedsModel->mapToSource(m_ui.m_treeFeeds->currentIndex()));
}
Message FormMessageFiltersManager::testingMessage() const { Message FormMessageFiltersManager::testingMessage() const {
Message msg; Message msg;

View File

@ -32,6 +32,7 @@ class FormMessageFiltersManager : public QDialog {
void loadFilters(); void loadFilters();
void testFilter(); void testFilter();
void displayMessagesOfFeed(); void displayMessagesOfFeed();
void processCheckedFeeds();
// Load feeds/categories tree. // Load feeds/categories tree.
void loadAccount(ServiceRoot* account); void loadAccount(ServiceRoot* account);
@ -49,6 +50,8 @@ class FormMessageFiltersManager : public QDialog {
void loadAccounts(); void loadAccounts();
void beautifyScript(); void beautifyScript();
void initializeTestingMessage(); void initializeTestingMessage();
RootItem* selectedCategoryFeed() const;
Message testingMessage() const; Message testingMessage() const;
private: private:

View File

@ -2,6 +2,7 @@
#include "services/abstract/accountcheckmodel.h" #include "services/abstract/accountcheckmodel.h"
#include "3rd-party/boolinq/boolinq.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
@ -273,7 +274,15 @@ Qt::ItemFlags AccountCheckModel::flags(const QModelIndex& index) const {
return flags; return flags;
} }
bool AccountCheckModel::isItemChecked(RootItem* item) { QList<RootItem*> AccountCheckModel::checkedItems() const {
auto keys = m_checkStates.keys();
return FROM_STD_LIST(QList<RootItem*>, boolinq::from(keys).where([&](const auto& key) {
return m_checkStates.value(key) == Qt::CheckState::Checked;
}).toStdList());
}
bool AccountCheckModel::isItemChecked(RootItem* item) const {
return m_checkStates.value(item, Qt::CheckState::Unchecked) == Qt::CheckState::Checked; return m_checkStates.value(item, Qt::CheckState::Unchecked) == Qt::CheckState::Checked;
} }

View File

@ -25,7 +25,9 @@ class AccountCheckModel : public QAbstractItemModel {
bool setData(const QModelIndex& index, const QVariant& value, int role); bool setData(const QModelIndex& index, const QVariant& value, int role);
Qt::ItemFlags flags(const QModelIndex& index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
bool isItemChecked(RootItem* item); QList<RootItem*> checkedItems() const;
bool isItemChecked(RootItem* item) const;
bool setItemChecked(RootItem* item, Qt::CheckState check); bool setItemChecked(RootItem* item, Qt::CheckState check);
// Returns feed/category which lies at the specified index or // Returns feed/category which lies at the specified index or