diff --git a/src/librssguard/core/feeddownloader.h b/src/librssguard/core/feeddownloader.h index 3cbb8f31e..ab61fe7d0 100644 --- a/src/librssguard/core/feeddownloader.h +++ b/src/librssguard/core/feeddownloader.h @@ -8,8 +8,8 @@ #include #include "core/message.h" +#include "services/abstract/feed.h" -class Feed; class MessageFilter; class QMutex; diff --git a/src/librssguard/core/message.cpp b/src/librssguard/core/message.cpp index 0d3573b2c..9058af5c7 100644 --- a/src/librssguard/core/message.cpp +++ b/src/librssguard/core/message.cpp @@ -158,186 +158,3 @@ uint qHash(const Message& key, uint seed) { uint qHash(const Message& key) { return (uint(key.m_accountId) * 10000) + uint(key.m_id); } - -MessageObject::MessageObject(QSqlDatabase* db, const QString& feed_custom_id, - int account_id, QList available_labels, - QObject* parent) - : QObject(parent), m_db(db), m_feedCustomId(feed_custom_id), m_accountId(account_id), m_message(nullptr), - m_availableLabels(available_labels) {} - -void MessageObject::setMessage(Message* message) { - m_message = message; -} - -bool MessageObject::isDuplicateWithAttribute(MessageObject::DuplicationAttributeCheck attribute_check) const { - // Check database according to duplication attribute_check. - QSqlQuery q(*m_db); - QStringList where_clauses; - QList> bind_values; - - // Now we construct the query according to parameter. - if ((attribute_check& DuplicationAttributeCheck::SameTitle) == DuplicationAttributeCheck::SameTitle) { - where_clauses.append(QSL("title = :title")); - bind_values.append({ ":title", title() }); - } - - if ((attribute_check& DuplicationAttributeCheck::SameUrl) == DuplicationAttributeCheck::SameUrl) { - where_clauses.append(QSL("url = :url")); - bind_values.append({ ":url", url() }); - } - - if ((attribute_check& DuplicationAttributeCheck::SameAuthor) == DuplicationAttributeCheck::SameAuthor) { - where_clauses.append(QSL("author = :author")); - bind_values.append({ ":author", author() }); - } - - if ((attribute_check& DuplicationAttributeCheck::SameDateCreated) == DuplicationAttributeCheck::SameDateCreated) { - where_clauses.append(QSL("date_created = :date_created")); - bind_values.append({ ":date_created", created().toMSecsSinceEpoch() }); - } - - where_clauses.append(QSL("account_id = :account_id")); - bind_values.append({ ":account_id", accountId() }); - - if ((attribute_check& DuplicationAttributeCheck::AllFeedsSameAccount) != DuplicationAttributeCheck::AllFeedsSameAccount) { - // Limit to current feed. - where_clauses.append(QSL("feed = :feed")); - bind_values.append({ ":feed", feedCustomId() }); - } - - QString full_query = QSL("SELECT COUNT(*) FROM Messages WHERE ") + where_clauses.join(QSL(" AND ")) + QSL(";"); - - qDebugNN << LOGSEC_MESSAGEMODEL - << "Query for MSG duplicate identification is: '" - << full_query - << "'."; - - q.setForwardOnly(true); - q.prepare(full_query); - - for (const auto& bind : bind_values) { - q.bindValue(bind.first, bind.second); - } - - if (q.exec() && q.next()) { - if (q.record().value(0).toInt() > 0) { - // Whoops, we have the "same" message in database. - qDebugNN << LOGSEC_MESSAGEMODEL - << "Message '" - << title() - << "' was identified as duplicate by filter script."; - return true; - } - } - else if (q.lastError().isValid()) { - qWarningNN << LOGSEC_MESSAGEMODEL - << "Error when checking for duplicate messages via filtering system, error: '" - << q.lastError().text() - << "'."; - } - - return false; -} - -bool MessageObject::assignLabel(QString label_custom_id) const { - Label* lbl = boolinq::from(m_availableLabels).firstOrDefault([label_custom_id](Label* lbl) { - return lbl->customId() == label_custom_id; - }); - - if (lbl != nullptr) { - if (!m_message->m_assignedLabels.contains(lbl)) { - m_message->m_assignedLabels.append(lbl); - } - - return true; - } - else { - return false; - } -} - -bool MessageObject::deassignLabel(QString label_custom_id) const { - Label* lbl = boolinq::from(m_message->m_assignedLabels).firstOrDefault([label_custom_id](Label* lbl) { - return lbl->customId() == label_custom_id; - }); - - if (lbl != nullptr) { - m_message->m_assignedLabels.removeAll(lbl); - return true; - } - else { - return false; - } -} - -QString MessageObject::title() const { - return m_message->m_title; -} - -void MessageObject::setTitle(const QString& title) { - m_message->m_title = title; -} - -QString MessageObject::url() const { - return m_message->m_url; -} - -void MessageObject::setUrl(const QString& url) { - m_message->m_url = url; -} - -QString MessageObject::author() const { - return m_message->m_author; -} - -void MessageObject::setAuthor(const QString& author) { - m_message->m_author = author; -} - -QString MessageObject::contents() const { - return m_message->m_contents; -} - -void MessageObject::setContents(const QString& contents) { - m_message->m_contents = contents; -} - -QDateTime MessageObject::created() const { - return m_message->m_created; -} - -void MessageObject::setCreated(const QDateTime& created) { - m_message->m_created = created; -} - -bool MessageObject::isRead() const { - return m_message->m_isRead; -} - -void MessageObject::setIsRead(bool is_read) { - m_message->m_isRead = is_read; -} - -bool MessageObject::isImportant() const { - return m_message->m_isImportant; -} - -void MessageObject::setIsImportant(bool is_important) { - m_message->m_isImportant = is_important; -} - -QString MessageObject::feedCustomId() const { - return m_feedCustomId; -} - -int MessageObject::accountId() const { - return m_accountId; -} - -QList MessageObject::assignedLabels() const { - return m_message->m_assignedLabels; -} - -QList MessageObject::availableLabels() const { - return m_availableLabels; -} diff --git a/src/librssguard/core/message.h b/src/librssguard/core/message.h index b99b16ce4..c25fd44bb 100644 --- a/src/librssguard/core/message.h +++ b/src/librssguard/core/message.h @@ -11,9 +11,10 @@ #include class QSqlDatabase; +class Label; // Represents single enclosure. -struct Enclosure { +struct RSSGUARD_DLLSPEC Enclosure { public: explicit Enclosure(QString url = QString(), QString mime = QString()); @@ -22,16 +23,14 @@ struct Enclosure { }; // Represents single enclosure. -class Enclosures { +class RSSGUARD_DLLSPEC Enclosures { public: static QList decodeEnclosuresFromString(const QString& enclosures_data); static QString encodeEnclosuresToString(const QList& enclosures); }; -class Label; - // Represents single message. -class Message { +class RSSGUARD_DLLSPEC Message { public: explicit Message(); @@ -76,123 +75,10 @@ inline bool operator!=(const Message& lhs, const Message& rhs) { // Serialize message state. // NOTE: This is used for persistent caching of message state changes. -QDataStream& operator<<(QDataStream& out, const Message& myObj); -QDataStream& operator>>(QDataStream& in, Message& myObj); +RSSGUARD_DLLSPEC QDataStream& operator<<(QDataStream& out, const Message& myObj); +RSSGUARD_DLLSPEC QDataStream& operator>>(QDataStream& in, Message& myObj); uint qHash(const Message& key, uint seed); uint qHash(const Message& key); -class MessageObject : public QObject { - Q_OBJECT - - Q_PROPERTY(QList assignedLabels READ assignedLabels) - Q_PROPERTY(QList availableLabels READ availableLabels) - Q_PROPERTY(QString feedCustomId READ feedCustomId) - Q_PROPERTY(int accountId READ accountId) - Q_PROPERTY(QString title READ title WRITE setTitle) - Q_PROPERTY(QString url READ url WRITE setUrl) - Q_PROPERTY(QString author READ author WRITE setAuthor) - Q_PROPERTY(QString contents READ contents WRITE setContents) - Q_PROPERTY(QDateTime created READ created WRITE setCreated) - Q_PROPERTY(bool isRead READ isRead WRITE setIsRead) - Q_PROPERTY(bool isImportant READ isImportant WRITE setIsImportant) - - public: - enum class FilteringAction { - // Message is normally accepted and stored in DB. - Accept = 1, - - // Message is ignored and now stored in DB. - Ignore = 2 - }; - - Q_ENUM(FilteringAction) - - enum class DuplicationAttributeCheck { - // Message with same title in DB. - SameTitle = 1, - - // Message with same URL in DB. - SameUrl = 2, - - // Message with same author in DB. - SameAuthor = 4, - - // Messages with same creation date in DB. - SameDateCreated = 8, - - // Compare with all messages from the account not only with messages from same feed. - // Note that this value must be used via bitwise OR with other values, - // for example 2 | 4 | 16. - AllFeedsSameAccount = 16 - }; - - Q_ENUM(DuplicationAttributeCheck) - - explicit MessageObject(QSqlDatabase* db, const QString& feed_custom_id, - int account_id, QList available_labels, - QObject* parent = nullptr); - - void setMessage(Message* message); - - // Check if message is duplicate with another messages in DB. - // Parameter "attribute_check" is DuplicationAttributeCheck enum - // value casted to int. - Q_INVOKABLE bool isDuplicateWithAttribute(DuplicationAttributeCheck attribute_check) const; - - // Adds given label to list of assigned labels to this message. - // Returns true if label was assigned now or if the message already has it assigned. - Q_INVOKABLE bool assignLabel(QString label_custom_id) const; - - // Removes given label from list of assigned labels of this message. - // Returns true if label was now removed or if it is not assigned to the message at all. - Q_INVOKABLE bool deassignLabel(QString label_custom_id) const; - - // Returns list of assigned and available messages. - QList assignedLabels() const; - QList availableLabels() const; - - // Generic Message's properties bindings. - QString feedCustomId() const; - int accountId() const; - - QString title() const; - void setTitle(const QString& title); - - QString url() const; - void setUrl(const QString& url); - - QString author() const; - void setAuthor(const QString& author); - - QString contents() const; - void setContents(const QString& contents); - - QDateTime created() const; - void setCreated(const QDateTime& created); - - bool isRead() const; - void setIsRead(bool is_read); - - bool isImportant() const; - void setIsImportant(bool is_important); - - private: - QSqlDatabase* m_db; - QString m_feedCustomId; - int m_accountId; - Message* m_message; - QList m_availableLabels; -}; - -inline MessageObject::DuplicationAttributeCheck operator|(MessageObject::DuplicationAttributeCheck lhs, - MessageObject::DuplicationAttributeCheck rhs) { - return static_cast(int(lhs) | int(rhs)); -} - -inline MessageObject::DuplicationAttributeCheck operator&(MessageObject::DuplicationAttributeCheck lhs, - MessageObject::DuplicationAttributeCheck rhs) { - return static_cast(int(lhs) & int(rhs)); -} - #endif // MESSAGE_H diff --git a/src/librssguard/core/messagefilter.h b/src/librssguard/core/messagefilter.h index d561792fa..775a3b893 100755 --- a/src/librssguard/core/messagefilter.h +++ b/src/librssguard/core/messagefilter.h @@ -6,6 +6,7 @@ #include #include "core/message.h" +#include "core/messageobject.h" #include diff --git a/src/librssguard/core/messageobject.cpp b/src/librssguard/core/messageobject.cpp new file mode 100755 index 000000000..0b1765f70 --- /dev/null +++ b/src/librssguard/core/messageobject.cpp @@ -0,0 +1,192 @@ +// For license of this file, see /LICENSE.md. + +#include "core/messageobject.h" + +#include "3rd-party/boolinq/boolinq.h" + +#include +#include +#include + +MessageObject::MessageObject(QSqlDatabase* db, const QString& feed_custom_id, + int account_id, QList available_labels, + QObject* parent) + : QObject(parent), m_db(db), m_feedCustomId(feed_custom_id), m_accountId(account_id), m_message(nullptr), + m_availableLabels(available_labels) {} + +void MessageObject::setMessage(Message* message) { + m_message = message; +} + +bool MessageObject::isDuplicateWithAttribute(MessageObject::DuplicationAttributeCheck attribute_check) const { + // Check database according to duplication attribute_check. + QSqlQuery q(*m_db); + QStringList where_clauses; + QList> bind_values; + + // Now we construct the query according to parameter. + if ((attribute_check& DuplicationAttributeCheck::SameTitle) == DuplicationAttributeCheck::SameTitle) { + where_clauses.append(QSL("title = :title")); + bind_values.append({ ":title", title() }); + } + + if ((attribute_check& DuplicationAttributeCheck::SameUrl) == DuplicationAttributeCheck::SameUrl) { + where_clauses.append(QSL("url = :url")); + bind_values.append({ ":url", url() }); + } + + if ((attribute_check& DuplicationAttributeCheck::SameAuthor) == DuplicationAttributeCheck::SameAuthor) { + where_clauses.append(QSL("author = :author")); + bind_values.append({ ":author", author() }); + } + + if ((attribute_check& DuplicationAttributeCheck::SameDateCreated) == DuplicationAttributeCheck::SameDateCreated) { + where_clauses.append(QSL("date_created = :date_created")); + bind_values.append({ ":date_created", created().toMSecsSinceEpoch() }); + } + + where_clauses.append(QSL("account_id = :account_id")); + bind_values.append({ ":account_id", accountId() }); + + if ((attribute_check& DuplicationAttributeCheck::AllFeedsSameAccount) != DuplicationAttributeCheck::AllFeedsSameAccount) { + // Limit to current feed. + where_clauses.append(QSL("feed = :feed")); + bind_values.append({ ":feed", feedCustomId() }); + } + + QString full_query = QSL("SELECT COUNT(*) FROM Messages WHERE ") + where_clauses.join(QSL(" AND ")) + QSL(";"); + + qDebugNN << LOGSEC_MESSAGEMODEL + << "Query for MSG duplicate identification is: '" + << full_query + << "'."; + + q.setForwardOnly(true); + q.prepare(full_query); + + for (const auto& bind : bind_values) { + q.bindValue(bind.first, bind.second); + } + + if (q.exec() && q.next()) { + if (q.record().value(0).toInt() > 0) { + // Whoops, we have the "same" message in database. + qDebugNN << LOGSEC_MESSAGEMODEL + << "Message '" + << title() + << "' was identified as duplicate by filter script."; + return true; + } + } + else if (q.lastError().isValid()) { + qWarningNN << LOGSEC_MESSAGEMODEL + << "Error when checking for duplicate messages via filtering system, error: '" + << q.lastError().text() + << "'."; + } + + return false; +} + +bool MessageObject::assignLabel(QString label_custom_id) const { + Label* lbl = boolinq::from(m_availableLabels).firstOrDefault([label_custom_id](Label* lbl) { + return lbl->customId() == label_custom_id; + }); + + if (lbl != nullptr) { + if (!m_message->m_assignedLabels.contains(lbl)) { + m_message->m_assignedLabels.append(lbl); + } + + return true; + } + else { + return false; + } +} + +bool MessageObject::deassignLabel(QString label_custom_id) const { + Label* lbl = boolinq::from(m_message->m_assignedLabels).firstOrDefault([label_custom_id](Label* lbl) { + return lbl->customId() == label_custom_id; + }); + + if (lbl != nullptr) { + m_message->m_assignedLabels.removeAll(lbl); + return true; + } + else { + return false; + } +} + +QString MessageObject::title() const { + return m_message->m_title; +} + +void MessageObject::setTitle(const QString& title) { + m_message->m_title = title; +} + +QString MessageObject::url() const { + return m_message->m_url; +} + +void MessageObject::setUrl(const QString& url) { + m_message->m_url = url; +} + +QString MessageObject::author() const { + return m_message->m_author; +} + +void MessageObject::setAuthor(const QString& author) { + m_message->m_author = author; +} + +QString MessageObject::contents() const { + return m_message->m_contents; +} + +void MessageObject::setContents(const QString& contents) { + m_message->m_contents = contents; +} + +QDateTime MessageObject::created() const { + return m_message->m_created; +} + +void MessageObject::setCreated(const QDateTime& created) { + m_message->m_created = created; +} + +bool MessageObject::isRead() const { + return m_message->m_isRead; +} + +void MessageObject::setIsRead(bool is_read) { + m_message->m_isRead = is_read; +} + +bool MessageObject::isImportant() const { + return m_message->m_isImportant; +} + +void MessageObject::setIsImportant(bool is_important) { + m_message->m_isImportant = is_important; +} + +QString MessageObject::feedCustomId() const { + return m_feedCustomId; +} + +int MessageObject::accountId() const { + return m_accountId; +} + +QList MessageObject::assignedLabels() const { + return m_message->m_assignedLabels; +} + +QList MessageObject::availableLabels() const { + return m_availableLabels; +} diff --git a/src/librssguard/core/messageobject.h b/src/librssguard/core/messageobject.h new file mode 100755 index 000000000..417846cc9 --- /dev/null +++ b/src/librssguard/core/messageobject.h @@ -0,0 +1,123 @@ +// For license of this file, see /LICENSE.md. + +#ifndef MESSAGEOBJECT_H +#define MESSAGEOBJECT_H + +#include + +#include "services/abstract/label.h" + +class MessageObject : public QObject { + Q_OBJECT + + Q_PROPERTY(QList assignedLabels READ assignedLabels) + Q_PROPERTY(QList availableLabels READ availableLabels) + Q_PROPERTY(QString feedCustomId READ feedCustomId) + Q_PROPERTY(int accountId READ accountId) + Q_PROPERTY(QString title READ title WRITE setTitle) + Q_PROPERTY(QString url READ url WRITE setUrl) + Q_PROPERTY(QString author READ author WRITE setAuthor) + Q_PROPERTY(QString contents READ contents WRITE setContents) + Q_PROPERTY(QDateTime created READ created WRITE setCreated) + Q_PROPERTY(bool isRead READ isRead WRITE setIsRead) + Q_PROPERTY(bool isImportant READ isImportant WRITE setIsImportant) + + public: + enum class FilteringAction { + // Message is normally accepted and stored in DB. + Accept = 1, + + // Message is ignored and now stored in DB. + Ignore = 2 + }; + + Q_ENUM(FilteringAction) + + enum class DuplicationAttributeCheck { + // Message with same title in DB. + SameTitle = 1, + + // Message with same URL in DB. + SameUrl = 2, + + // Message with same author in DB. + SameAuthor = 4, + + // Messages with same creation date in DB. + SameDateCreated = 8, + + // Compare with all messages from the account not only with messages from same feed. + // Note that this value must be used via bitwise OR with other values, + // for example 2 | 4 | 16. + AllFeedsSameAccount = 16 + }; + + Q_ENUM(DuplicationAttributeCheck) + + explicit MessageObject(QSqlDatabase* db, const QString& feed_custom_id, + int account_id, QList available_labels, + QObject* parent = nullptr); + + void setMessage(Message* message); + + // Check if message is duplicate with another messages in DB. + // Parameter "attribute_check" is DuplicationAttributeCheck enum + // value casted to int. + Q_INVOKABLE bool isDuplicateWithAttribute(DuplicationAttributeCheck attribute_check) const; + + // Adds given label to list of assigned labels to this message. + // Returns true if label was assigned now or if the message already has it assigned. + Q_INVOKABLE bool assignLabel(QString label_custom_id) const; + + // Removes given label from list of assigned labels of this message. + // Returns true if label was now removed or if it is not assigned to the message at all. + Q_INVOKABLE bool deassignLabel(QString label_custom_id) const; + + // Returns list of assigned and available messages. + QList assignedLabels() const; + QList availableLabels() const; + + // Generic Message's properties bindings. + QString feedCustomId() const; + int accountId() const; + + QString title() const; + void setTitle(const QString& title); + + QString url() const; + void setUrl(const QString& url); + + QString author() const; + void setAuthor(const QString& author); + + QString contents() const; + void setContents(const QString& contents); + + QDateTime created() const; + void setCreated(const QDateTime& created); + + bool isRead() const; + void setIsRead(bool is_read); + + bool isImportant() const; + void setIsImportant(bool is_important); + + private: + QSqlDatabase* m_db; + QString m_feedCustomId; + int m_accountId; + Message* m_message; + QList m_availableLabels; +}; + +inline MessageObject::DuplicationAttributeCheck operator|(MessageObject::DuplicationAttributeCheck lhs, + MessageObject::DuplicationAttributeCheck rhs) { + return static_cast(int(lhs) | int(rhs)); +} + +inline MessageObject::DuplicationAttributeCheck operator&(MessageObject::DuplicationAttributeCheck lhs, + MessageObject::DuplicationAttributeCheck rhs) { + return static_cast(int(lhs) & int(rhs)); +} + +#endif // MESSAGEOBJECT_H diff --git a/src/librssguard/librssguard.pro b/src/librssguard/librssguard.pro index 839d6d970..549cfd8c1 100644 --- a/src/librssguard/librssguard.pro +++ b/src/librssguard/librssguard.pro @@ -37,6 +37,7 @@ HEADERS += core/feeddownloader.h \ core/feedsproxymodel.h \ core/message.h \ core/messagefilter.h \ + core/messageobject.h \ core/messagesmodel.h \ core/messagesmodelcache.h \ core/messagesmodelsqllayer.h \ @@ -191,6 +192,7 @@ SOURCES += core/feeddownloader.cpp \ core/feedsproxymodel.cpp \ core/message.cpp \ core/messagefilter.cpp \ + core/messageobject.cpp \ core/messagesmodel.cpp \ core/messagesmodelcache.cpp \ core/messagesmodelsqllayer.cpp \ diff --git a/src/rssguard/main.cpp b/src/rssguard/main.cpp index 0274d95e5..b323f52f0 100755 --- a/src/rssguard/main.cpp +++ b/src/rssguard/main.cpp @@ -16,8 +16,10 @@ extern void disableWindowTabbing(); int main(int argc, char* argv[]) { qSetMessagePattern(QSL("time=\"%{time process}\" type=\"%{type}\" -> %{message}")); - QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#if QT_VERSION_MAJOR <= 5 + QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseHighDpiPixmaps); + QApplication::setAttribute(Qt::ApplicationAttribute::AA_EnableHighDpiScaling); +#endif #if defined (Q_OS_LINUX) QApplication::setDesktopFileName(APP_DESKTOP_ENTRY_FILE);