initial work on supporting embedded categories/labels in feeds/entries
This commit is contained in:
parent
ff7e527399
commit
f925bf3a77
@ -65,6 +65,7 @@ QString Enclosures::encodeEnclosuresToString(const QList<Enclosure>& enclosures)
|
|||||||
Message::Message() {
|
Message::Message() {
|
||||||
m_title = m_url = m_author = m_contents = m_rawContents = m_feedId = m_customId = m_customHash = QL1S("");
|
m_title = m_url = m_author = m_contents = m_rawContents = m_feedId = m_customId = m_customHash = QL1S("");
|
||||||
m_enclosures = QList<Enclosure>();
|
m_enclosures = QList<Enclosure>();
|
||||||
|
m_categories = QList<MessageCategory>();
|
||||||
m_accountId = m_id = 0;
|
m_accountId = m_id = 0;
|
||||||
m_score = 0.0;
|
m_score = 0.0;
|
||||||
m_isRead = m_isImportant = m_isDeleted = false;
|
m_isRead = m_isImportant = m_isDeleted = false;
|
||||||
@ -209,3 +210,13 @@ uint qHash(const Message& key, uint seed) {
|
|||||||
uint qHash(const Message& key) {
|
uint qHash(const Message& key) {
|
||||||
return (uint(key.m_accountId) * 10000) + uint(key.m_id);
|
return (uint(key.m_accountId) * 10000) + uint(key.m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageCategory::MessageCategory(const QString& title) : QObject(), m_title(title) {}
|
||||||
|
|
||||||
|
MessageCategory::MessageCategory(const MessageCategory& other) {
|
||||||
|
m_title = other.m_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MessageCategory::title() const {
|
||||||
|
return m_title;
|
||||||
|
}
|
||||||
|
@ -31,6 +31,22 @@ class RSSGUARD_DLLSPEC Enclosures {
|
|||||||
|
|
||||||
class Feed;
|
class Feed;
|
||||||
|
|
||||||
|
// Represents RSS, JSON or ATOM category (or tag, label - depending on terminology of each entry.
|
||||||
|
class RSSGUARD_DLLSPEC MessageCategory : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString title READ title)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MessageCategory(const QString& title);
|
||||||
|
MessageCategory(const MessageCategory& other);
|
||||||
|
|
||||||
|
QString title() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_title;
|
||||||
|
};
|
||||||
|
|
||||||
// Represents single message.
|
// Represents single message.
|
||||||
class RSSGUARD_DLLSPEC Message {
|
class RSSGUARD_DLLSPEC Message {
|
||||||
public:
|
public:
|
||||||
@ -64,6 +80,10 @@ class RSSGUARD_DLLSPEC Message {
|
|||||||
double m_score;
|
double m_score;
|
||||||
QList<Enclosure> m_enclosures;
|
QList<Enclosure> m_enclosures;
|
||||||
|
|
||||||
|
// List of assigned labels.
|
||||||
|
// This field is only field when fetching entries of a feed.
|
||||||
|
QList<MessageCategory> m_categories;
|
||||||
|
|
||||||
// List of custom IDs of labels assigned to this message.
|
// List of custom IDs of labels assigned to this message.
|
||||||
QList<Label*> m_assignedLabels;
|
QList<Label*> m_assignedLabels;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "definitions/definitions.h"
|
#include "definitions/definitions.h"
|
||||||
#include "services/abstract/labelsnode.h"
|
#include "services/abstract/labelsnode.h"
|
||||||
|
|
||||||
|
#include <QRandomGenerator>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
#include <QSqlError>
|
#include <QSqlError>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
@ -168,7 +169,7 @@ QString MessageObject::findLabelId(const QString& label_title) const {
|
|||||||
return found_lbl != nullptr ? found_lbl->customId() : QString();
|
return found_lbl != nullptr ? found_lbl->customId() : QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MessageObject::createLabelId(const QString& title, const QString& hex_color) const {
|
QString MessageObject::createLabelId(const QString& title, const QString& hex_color) {
|
||||||
QString lbl_id = findLabelId(title);
|
QString lbl_id = findLabelId(title);
|
||||||
|
|
||||||
if (!lbl_id.isEmpty()) {
|
if (!lbl_id.isEmpty()) {
|
||||||
@ -176,13 +177,37 @@ QString MessageObject::createLabelId(const QString& title, const QString& hex_co
|
|||||||
return lbl_id;
|
return lbl_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hex_color.isEmpty()) {
|
if ((m_account->supportedLabelOperations() & ServiceRoot::LabelOperation::Adding) !=
|
||||||
// Generate color.
|
ServiceRoot::LabelOperation::Adding) {
|
||||||
return nullptr;
|
qWarningNN << LOGSEC_CORE << "This account does not support creating labels.";
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: CONTINUE
|
Label* new_lbl = nullptr;
|
||||||
return nullptr;
|
|
||||||
|
try {
|
||||||
|
auto rnd_color = QRandomGenerator::global()->bounded(0xFFFFFF);
|
||||||
|
auto rnd_color_name = QSL("#%1").arg(QString::number(rnd_color, 16));
|
||||||
|
|
||||||
|
new_lbl = new Label(title, hex_color.isEmpty() ? rnd_color_name : hex_color);
|
||||||
|
QSqlDatabase db = qApp->database()->driver()->threadSafeConnection(metaObject()->className());
|
||||||
|
|
||||||
|
DatabaseQueries::createLabel(db, new_lbl, m_account->accountId());
|
||||||
|
m_account->requestItemReassignment(new_lbl, m_account->labelsNode());
|
||||||
|
|
||||||
|
m_availableLabels.append(new_lbl);
|
||||||
|
|
||||||
|
return new_lbl->customId();
|
||||||
|
}
|
||||||
|
catch (const ApplicationException& ex) {
|
||||||
|
qCriticalNN << LOGSEC_CORE << "Cannot create label:" << QUOTE_W_SPACE_DOT(ex.message());
|
||||||
|
|
||||||
|
if (new_lbl != nullptr) {
|
||||||
|
new_lbl->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageObject::addEnclosure(const QString& url, const QString& mime_type) const {
|
void MessageObject::addEnclosure(const QString& url, const QString& mime_type) const {
|
||||||
@ -310,6 +335,10 @@ QList<Label*> MessageObject::availableLabels() const {
|
|||||||
return m_availableLabels;
|
return m_availableLabels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<MessageCategory> MessageObject::categories() const {
|
||||||
|
return m_message->m_categories;
|
||||||
|
}
|
||||||
|
|
||||||
bool MessageObject::runningFilterWhenFetching() const {
|
bool MessageObject::runningFilterWhenFetching() const {
|
||||||
return m_runningAfterFetching;
|
return m_runningAfterFetching;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
class MessageObject : public QObject {
|
class MessageObject : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QList<MessageCategory> categories READ categories)
|
||||||
Q_PROPERTY(QList<Label*> assignedLabels READ assignedLabels)
|
Q_PROPERTY(QList<Label*> assignedLabels READ assignedLabels)
|
||||||
Q_PROPERTY(QList<Label*> availableLabels READ availableLabels)
|
Q_PROPERTY(QList<Label*> availableLabels READ availableLabels)
|
||||||
Q_PROPERTY(QString feedCustomId READ feedCustomId)
|
Q_PROPERTY(QString feedCustomId READ feedCustomId)
|
||||||
@ -93,7 +94,7 @@ class MessageObject : public QObject {
|
|||||||
|
|
||||||
// Returns label custom ID given label title or creates
|
// Returns label custom ID given label title or creates
|
||||||
// the label if it does not exist.
|
// the label if it does not exist.
|
||||||
Q_INVOKABLE QString createLabelId(const QString& title, const QString& hex_color = {}) const;
|
Q_INVOKABLE QString createLabelId(const QString& title, const QString& hex_color = {});
|
||||||
|
|
||||||
// Add multimedia attachment to the message.
|
// Add multimedia attachment to the message.
|
||||||
Q_INVOKABLE void addEnclosure(const QString& url, const QString& mime_type) const;
|
Q_INVOKABLE void addEnclosure(const QString& url, const QString& mime_type) const;
|
||||||
@ -102,6 +103,8 @@ class MessageObject : public QObject {
|
|||||||
QList<Label*> assignedLabels() const;
|
QList<Label*> assignedLabels() const;
|
||||||
QList<Label*> availableLabels() const;
|
QList<Label*> availableLabels() const;
|
||||||
|
|
||||||
|
QList<MessageCategory> categories() const;
|
||||||
|
|
||||||
bool runningFilterWhenFetching() const;
|
bool runningFilterWhenFetching() const;
|
||||||
|
|
||||||
// Generic Message's properties bindings.
|
// Generic Message's properties bindings.
|
||||||
|
@ -1015,6 +1015,5 @@ QPair<int, int> ServiceRoot::updateMessages(QList<Message>& messages, Feed* feed
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Do not update model items here. We update only once when all feeds are fetched.
|
// NOTE: Do not update model items here. We update only once when all feeds are fetched.
|
||||||
|
|
||||||
return updated_messages;
|
return updated_messages;
|
||||||
}
|
}
|
||||||
|
@ -128,3 +128,18 @@ QList<Enclosure> AtomParser::xmlMessageEnclosures(const QDomElement& msg_element
|
|||||||
|
|
||||||
return enclosures;
|
return enclosures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<MessageCategory> AtomParser::xmlMessageCategories(const QDomElement& msg_element) const {
|
||||||
|
QList<MessageCategory> cats;
|
||||||
|
QDomNodeList elem_cats = msg_element.toElement().elementsByTagNameNS(m_atomNamespace, QSL("category"));
|
||||||
|
|
||||||
|
for (int i = 0; i < elem_cats.size(); i++) {
|
||||||
|
QDomElement cat = elem_cats.at(i).toElement();
|
||||||
|
QString lbl = cat.attribute(QSL("label"));
|
||||||
|
QString term = cat.attribute(QSL("term"));
|
||||||
|
|
||||||
|
cats.append(MessageCategory(lbl.isEmpty() ? term : lbl));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cats;
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ class AtomParser : public FeedParser {
|
|||||||
virtual QString xmlMessageId(const QDomElement& msg_element) const;
|
virtual QString xmlMessageId(const QDomElement& msg_element) const;
|
||||||
virtual QString xmlMessageUrl(const QDomElement& msg_element) const;
|
virtual QString xmlMessageUrl(const QDomElement& msg_element) const;
|
||||||
virtual QList<Enclosure> xmlMessageEnclosures(const QDomElement& msg_element) const;
|
virtual QList<Enclosure> xmlMessageEnclosures(const QDomElement& msg_element) const;
|
||||||
|
virtual QList<MessageCategory> xmlMessageCategories(const QDomElement& msg_element) const;
|
||||||
virtual QDomNodeList xmlMessageElements();
|
virtual QDomNodeList xmlMessageElements();
|
||||||
virtual QString xmlMessageAuthor(const QDomElement& msg_element) const;
|
virtual QString xmlMessageAuthor(const QDomElement& msg_element) const;
|
||||||
virtual QString feedAuthor() const;
|
virtual QString feedAuthor() const;
|
||||||
|
@ -76,6 +76,10 @@ QList<Enclosure> FeedParser::jsonMessageEnclosures(const QJsonObject& msg_elemen
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<MessageCategory> FeedParser::jsonMessageCategories(const QJsonObject& msg_element) const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
QString FeedParser::jsonMessageRawContents(const QJsonObject& msg_element) const {
|
QString FeedParser::jsonMessageRawContents(const QJsonObject& msg_element) const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -105,6 +109,7 @@ QList<Message> FeedParser::messages() {
|
|||||||
new_message.m_rawContents = xmlMessageRawContents(message_item);
|
new_message.m_rawContents = xmlMessageRawContents(message_item);
|
||||||
new_message.m_enclosures = xmlMessageEnclosures(message_item);
|
new_message.m_enclosures = xmlMessageEnclosures(message_item);
|
||||||
new_message.m_enclosures.append(xmlMrssGetEnclosures(message_item));
|
new_message.m_enclosures.append(xmlMrssGetEnclosures(message_item));
|
||||||
|
new_message.m_categories.append(xmlMessageCategories(message_item));
|
||||||
|
|
||||||
messages.append(new_message);
|
messages.append(new_message);
|
||||||
}
|
}
|
||||||
@ -322,3 +327,7 @@ QString FeedParser::xmlMessageId(const QDomElement& msg_element) const {
|
|||||||
QList<Enclosure> FeedParser::xmlMessageEnclosures(const QDomElement& msg_element) const {
|
QList<Enclosure> FeedParser::xmlMessageEnclosures(const QDomElement& msg_element) const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<MessageCategory> FeedParser::xmlMessageCategories(const QDomElement& msg_element) const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ class FeedParser {
|
|||||||
virtual QDateTime xmlMessageDateCreated(const QDomElement& msg_element) const;
|
virtual QDateTime xmlMessageDateCreated(const QDomElement& msg_element) const;
|
||||||
virtual QString xmlMessageId(const QDomElement& msg_element) const;
|
virtual QString xmlMessageId(const QDomElement& msg_element) const;
|
||||||
virtual QList<Enclosure> xmlMessageEnclosures(const QDomElement& msg_element) const;
|
virtual QList<Enclosure> xmlMessageEnclosures(const QDomElement& msg_element) const;
|
||||||
|
virtual QList<MessageCategory> xmlMessageCategories(const QDomElement& msg_element) const;
|
||||||
virtual QString xmlMessageRawContents(const QDomElement& msg_element) const;
|
virtual QString xmlMessageRawContents(const QDomElement& msg_element) const;
|
||||||
|
|
||||||
// JSON.
|
// JSON.
|
||||||
@ -41,13 +42,17 @@ class FeedParser {
|
|||||||
virtual QDateTime jsonMessageDateCreated(const QJsonObject& msg_element) const;
|
virtual QDateTime jsonMessageDateCreated(const QJsonObject& msg_element) const;
|
||||||
virtual QString jsonMessageId(const QJsonObject& msg_element) const;
|
virtual QString jsonMessageId(const QJsonObject& msg_element) const;
|
||||||
virtual QList<Enclosure> jsonMessageEnclosures(const QJsonObject& msg_element) const;
|
virtual QList<Enclosure> jsonMessageEnclosures(const QJsonObject& msg_element) const;
|
||||||
|
virtual QList<MessageCategory> jsonMessageCategories(const QJsonObject& msg_element) const;
|
||||||
virtual QString jsonMessageRawContents(const QJsonObject& msg_element) const;
|
virtual QString jsonMessageRawContents(const QJsonObject& msg_element) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QList<Enclosure> xmlMrssGetEnclosures(const QDomElement& msg_element) const;
|
QList<Enclosure> xmlMrssGetEnclosures(const QDomElement& msg_element) const;
|
||||||
QString xmlMrssTextFromPath(const QDomElement& msg_element, const QString& xml_path) const;
|
QString xmlMrssTextFromPath(const QDomElement& msg_element, const QString& xml_path) const;
|
||||||
QString xmlRawChild(const QDomElement& container) const;
|
QString xmlRawChild(const QDomElement& container) const;
|
||||||
QStringList xmlTextsFromPath(const QDomElement& element, const QString& namespace_uri, const QString& xml_path, bool only_first) const;
|
QStringList xmlTextsFromPath(const QDomElement& element,
|
||||||
|
const QString& namespace_uri,
|
||||||
|
const QString& xml_path,
|
||||||
|
bool only_first) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_isXml;
|
bool m_isXml;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user