Label assignments are now correctly download for TT-RSS, storage works for all plugins.
This commit is contained in:
parent
ed56e7581b
commit
6ed79f5133
@ -3,6 +3,7 @@
|
|||||||
#include "core/message.h"
|
#include "core/message.h"
|
||||||
|
|
||||||
#include "miscellaneous/textfactory.h"
|
#include "miscellaneous/textfactory.h"
|
||||||
|
#include "services/abstract/label.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
@ -61,6 +62,7 @@ Message::Message() {
|
|||||||
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 = false;
|
||||||
|
m_assignedLabels = QList<Label*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
|
Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
|
||||||
|
@ -28,6 +28,8 @@ class Enclosures {
|
|||||||
static QString encodeEnclosuresToString(const QList<Enclosure>& enclosures);
|
static QString encodeEnclosuresToString(const QList<Enclosure>& enclosures);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Label;
|
||||||
|
|
||||||
// Represents single message.
|
// Represents single message.
|
||||||
class Message {
|
class Message {
|
||||||
public:
|
public:
|
||||||
@ -52,6 +54,9 @@ class Message {
|
|||||||
bool m_isImportant;
|
bool m_isImportant;
|
||||||
QList<Enclosure> m_enclosures;
|
QList<Enclosure> m_enclosures;
|
||||||
|
|
||||||
|
// List of custom IDs of labels assigned to this message.
|
||||||
|
QList<Label*> m_assignedLabels;
|
||||||
|
|
||||||
// Is true if "created" date was obtained directly
|
// Is true if "created" date was obtained directly
|
||||||
// from the feed, otherwise is false
|
// from the feed, otherwise is false
|
||||||
bool m_createdFromFeed = false;
|
bool m_createdFromFeed = false;
|
||||||
|
@ -80,6 +80,35 @@ bool DatabaseQueries::assignLabelToMessage(const QSqlDatabase& db, Label* label,
|
|||||||
return succ;
|
return succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DatabaseQueries::setLabelsForMessage(const QSqlDatabase& db, const QList<Label*>& labels, const Message& msg) {
|
||||||
|
QSqlQuery q(db);
|
||||||
|
|
||||||
|
q.setForwardOnly(true);
|
||||||
|
q.prepare(QSL("DELETE FROM LabelsInMessages WHERE message = :message AND account_id = :account_id"));
|
||||||
|
q.bindValue(QSL(":account_id"), msg.m_accountId);
|
||||||
|
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
|
||||||
|
|
||||||
|
auto succ = q.exec();
|
||||||
|
|
||||||
|
if (!succ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.prepare(QSL("INSERT INTO LabelsInMessages (message, label, account_id) VALUES (:message, :label, :account_id);"));
|
||||||
|
|
||||||
|
for (const Label* label : labels) {
|
||||||
|
q.bindValue(QSL(":account_id"), msg.m_accountId);
|
||||||
|
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
|
||||||
|
q.bindValue(QSL(":label"), label->customId());
|
||||||
|
|
||||||
|
if (!q.exec()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
QList<Label*> DatabaseQueries::getLabels(const QSqlDatabase& db, int account_id) {
|
QList<Label*> DatabaseQueries::getLabels(const QSqlDatabase& db, int account_id) {
|
||||||
QList<Label*> labels;
|
QList<Label*> labels;
|
||||||
QSqlQuery q(db);
|
QSqlQuery q(db);
|
||||||
@ -912,6 +941,10 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
|||||||
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
|
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
|
||||||
updated_messages++;
|
updated_messages++;
|
||||||
|
|
||||||
|
if (query_insert.lastInsertId().isValid()) {
|
||||||
|
id_existing_message = query_insert.lastInsertId().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
qDebugNN << LOGSEC_DB
|
qDebugNN << LOGSEC_DB
|
||||||
<< "Adding new message with title '"
|
<< "Adding new message with title '"
|
||||||
<< message.m_title
|
<< message.m_title
|
||||||
@ -930,6 +963,25 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
|||||||
|
|
||||||
query_insert.finish();
|
query_insert.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update labels assigned to message.
|
||||||
|
if (!message.m_assignedLabels.isEmpty()) {
|
||||||
|
// NOTE: This message provides list of its labels from remote
|
||||||
|
// source, which means they must replace local labels.
|
||||||
|
if (!message.m_customId.isEmpty()) {
|
||||||
|
setLabelsForMessage(db, message.m_assignedLabels, message);
|
||||||
|
}
|
||||||
|
else if (id_existing_message >= 0) {
|
||||||
|
message.m_id = id_existing_message;
|
||||||
|
setLabelsForMessage(db, message.m_assignedLabels, message);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarningNN << LOGSEC_DB
|
||||||
|
<< "Cannot set labels for message"
|
||||||
|
<< QUOTE_W_SPACE(message.m_title)
|
||||||
|
<< "because we don't have ID or custom ID.";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, fixup custom IDS for messages which initially did not have them,
|
// Now, fixup custom IDS for messages which initially did not have them,
|
||||||
|
@ -22,6 +22,7 @@ class DatabaseQueries {
|
|||||||
static bool isLabelAssignedToMessage(const QSqlDatabase& db, Label* label, const Message& msg);
|
static bool isLabelAssignedToMessage(const QSqlDatabase& db, Label* label, const Message& msg);
|
||||||
static bool deassignLabelFromMessage(const QSqlDatabase& db, Label* label, const Message& msg);
|
static bool deassignLabelFromMessage(const QSqlDatabase& db, Label* label, const Message& msg);
|
||||||
static bool assignLabelToMessage(const QSqlDatabase& db, Label* label, const Message& msg);
|
static bool assignLabelToMessage(const QSqlDatabase& db, Label* label, const Message& msg);
|
||||||
|
static bool setLabelsForMessage(const QSqlDatabase& db, const QList<Label*>& labels, const Message& msg);
|
||||||
static QList<Label*> getLabels(const QSqlDatabase& db, int account_id);
|
static QList<Label*> getLabels(const QSqlDatabase& db, int account_id);
|
||||||
static bool updateLabel(const QSqlDatabase& db, Label* label);
|
static bool updateLabel(const QSqlDatabase& db, Label* label);
|
||||||
static bool deleteLabel(const QSqlDatabase& db, Label* label);
|
static bool deleteLabel(const QSqlDatabase& db, Label* label);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "miscellaneous/textfactory.h"
|
#include "miscellaneous/textfactory.h"
|
||||||
#include "services/abstract/cacheforserviceroot.h"
|
#include "services/abstract/cacheforserviceroot.h"
|
||||||
#include "services/abstract/importantnode.h"
|
#include "services/abstract/importantnode.h"
|
||||||
|
#include "services/abstract/labelsnode.h"
|
||||||
#include "services/abstract/recyclebin.h"
|
#include "services/abstract/recyclebin.h"
|
||||||
#include "services/abstract/serviceroot.h"
|
#include "services/abstract/serviceroot.h"
|
||||||
|
|
||||||
@ -227,6 +228,11 @@ int Feed::updateMessages(const QList<Message>& messages, bool error_during_obtai
|
|||||||
getParentServiceRoot()->importantNode()->updateCounts(true);
|
getParentServiceRoot()->importantNode()->updateCounts(true);
|
||||||
items_to_update.append(getParentServiceRoot()->importantNode());
|
items_to_update.append(getParentServiceRoot()->importantNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getParentServiceRoot()->labelsNode() != nullptr) {
|
||||||
|
getParentServiceRoot()->labelsNode()->updateCounts(true);
|
||||||
|
items_to_update.append(getParentServiceRoot()->labelsNode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
Label::Label(const QString& name, const QColor& color, RootItem* parent_item) : Label(parent_item) {
|
Label::Label(const QString& name, const QColor& color, RootItem* parent_item) : Label(parent_item) {
|
||||||
setColor(color);
|
setColor(color);
|
||||||
@ -71,7 +72,10 @@ bool Label::deleteViaGui() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Label::updateCounts(bool including_total_count) {
|
void Label::updateCounts(bool including_total_count) {
|
||||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||||
|
QSqlDatabase database = is_main_thread ?
|
||||||
|
qApp->database()->connection(metaObject()->className()) :
|
||||||
|
qApp->database()->connection(QSL("feed_upd"));
|
||||||
int account_id = getParentServiceRoot()->accountId();
|
int account_id = getParentServiceRoot()->accountId();
|
||||||
|
|
||||||
if (including_total_count) {
|
if (including_total_count) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "services/tt-rss/network/ttrssnetworkfactory.h"
|
#include "services/tt-rss/network/ttrssnetworkfactory.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"
|
||||||
@ -9,7 +10,9 @@
|
|||||||
#include "network-web/networkfactory.h"
|
#include "network-web/networkfactory.h"
|
||||||
#include "services/abstract/category.h"
|
#include "services/abstract/category.h"
|
||||||
#include "services/abstract/label.h"
|
#include "services/abstract/label.h"
|
||||||
|
#include "services/abstract/labelsnode.h"
|
||||||
#include "services/abstract/rootitem.h"
|
#include "services/abstract/rootitem.h"
|
||||||
|
#include "services/abstract/serviceroot.h"
|
||||||
#include "services/tt-rss/definitions.h"
|
#include "services/tt-rss/definitions.h"
|
||||||
#include "services/tt-rss/ttrssfeed.h"
|
#include "services/tt-rss/ttrssfeed.h"
|
||||||
|
|
||||||
@ -626,7 +629,7 @@ TtRssGetHeadlinesResponse::TtRssGetHeadlinesResponse(const QString& raw_content)
|
|||||||
|
|
||||||
TtRssGetHeadlinesResponse::~TtRssGetHeadlinesResponse() = default;
|
TtRssGetHeadlinesResponse::~TtRssGetHeadlinesResponse() = default;
|
||||||
|
|
||||||
QList<Message> TtRssGetHeadlinesResponse::messages() const {
|
QList<Message> TtRssGetHeadlinesResponse::messages(ServiceRoot* root) const {
|
||||||
QList<Message> messages;
|
QList<Message> messages;
|
||||||
|
|
||||||
for (const QJsonValue& item : m_rawContent["content"].toArray()) {
|
for (const QJsonValue& item : m_rawContent["content"].toArray()) {
|
||||||
@ -638,6 +641,23 @@ QList<Message> TtRssGetHeadlinesResponse::messages() const {
|
|||||||
message.m_isImportant = mapped["marked"].toBool();
|
message.m_isImportant = mapped["marked"].toBool();
|
||||||
message.m_contents = mapped["content"].toString();
|
message.m_contents = mapped["content"].toString();
|
||||||
|
|
||||||
|
auto active_labels = root->labelsNode() != nullptr ? root->labelsNode()->labels() : QList<Label*>();
|
||||||
|
|
||||||
|
for (const QJsonValue& lbl_val : mapped["labels"].toArray()) {
|
||||||
|
QString lbl_custom_id = QString::number(lbl_val.toArray().at(0).toInt());
|
||||||
|
Label* label = boolinq::from(active_labels.begin(), active_labels.end()).firstOrDefault([lbl_custom_id](Label* lbl) {
|
||||||
|
return lbl->customId() == lbl_custom_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (label != nullptr) {
|
||||||
|
message.m_assignedLabels.append(label);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qWarningNN << LOGSEC_TTRSS << "Label with custom ID" << QUOTE_W_SPACE(lbl_custom_id)
|
||||||
|
<< "was not found. Maybe you need to perform sync-in to download it from server.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Multiply by 1000 because Tiny Tiny RSS API does not include miliseconds in Unix
|
// Multiply by 1000 because Tiny Tiny RSS API does not include miliseconds in Unix
|
||||||
// date/time number.
|
// date/time number.
|
||||||
const qint64 t = static_cast<qint64>(mapped["updated"].toDouble()) * 1000;
|
const qint64 t = static_cast<qint64>(mapped["updated"].toDouble()) * 1000;
|
||||||
|
@ -59,12 +59,14 @@ class TtRssGetFeedsCategoriesResponse : public TtRssResponse {
|
|||||||
RootItem* feedsCategories(bool obtain_icons, QString base_address = QString()) const;
|
RootItem* feedsCategories(bool obtain_icons, QString base_address = QString()) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ServiceRoot;
|
||||||
|
|
||||||
class TtRssGetHeadlinesResponse : public TtRssResponse {
|
class TtRssGetHeadlinesResponse : public TtRssResponse {
|
||||||
public:
|
public:
|
||||||
explicit TtRssGetHeadlinesResponse(const QString& raw_content = QString());
|
explicit TtRssGetHeadlinesResponse(const QString& raw_content = QString());
|
||||||
virtual ~TtRssGetHeadlinesResponse();
|
virtual ~TtRssGetHeadlinesResponse();
|
||||||
|
|
||||||
QList<Message> messages() const;
|
QList<Message> messages(ServiceRoot* root) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TtRssUpdateArticleResponse : public TtRssResponse {
|
class TtRssUpdateArticleResponse : public TtRssResponse {
|
||||||
|
@ -87,7 +87,7 @@ QList<Message> TtRssFeed::obtainNewMessages(bool* error_during_obtaining) {
|
|||||||
return QList<Message>();
|
return QList<Message>();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QList<Message> new_messages = headlines.messages();
|
QList<Message> new_messages = headlines.messages(getParentServiceRoot());
|
||||||
|
|
||||||
messages.append(new_messages);
|
messages.append(new_messages);
|
||||||
newly_added_messages = new_messages.size();
|
newly_added_messages = new_messages.size();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user