EXPERIMENTAL work on updateMessages() refactoring. Very broken right now!!!!!!!!!!!!

This commit is contained in:
Martin Rotter 2016-02-23 10:28:17 +01:00
parent 127e43b952
commit bc06e90a07
8 changed files with 279 additions and 391 deletions

View File

@ -20,9 +20,11 @@
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasefactory.h"
#include "services/abstract/recyclebin.h"
#include "services/abstract/serviceroot.h"
#include <QSqlQuery>
#include <QSqlError>
Feed::Feed(RootItem *parent)
@ -102,6 +104,10 @@ void Feed::setCountOfUnreadMessages(int count_unread_messages) {
m_unreadCount = count_unread_messages;
}
int Feed::update() {
return updateMessages(obtainNewMessages());
}
void Feed::setAutoUpdateInitialInterval(int auto_update_interval) {
// If new initial auto-update interval is set, then
// we should reset time that remains to the next auto-update.
@ -124,3 +130,187 @@ int Feed::autoUpdateRemainingInterval() const {
void Feed::setAutoUpdateRemainingInterval(int auto_update_remaining_interval) {
m_autoUpdateRemainingInterval = auto_update_remaining_interval;
}
int Feed::updateMessages(const QList<Message> &messages) {
if (messages.isEmpty()) {
return 0;
}
// Does not make any difference, since each feed now has
// its own "custom ID" (standard feeds have their custom ID equal to primary key ID).
int custom_id = customId();
int account_id = getParentServiceRoot()->accountId();
int updated_messages = 0;
bool anything_duplicated = false;
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
// Prepare queries.
QSqlQuery query_select(database);
QSqlQuery query_select_with_id(database);
QSqlQuery query_update(database);
QSqlQuery query_insert(database);
// Here we have query which will check for existence of the "same" message in given feed.
// The two message are the "same" if:
// 1) they belong to the same feed AND,
// 2) they have same URL AND,
// 3) they have same AUTHOR.
query_select.setForwardOnly(true);
query_select.prepare("SELECT id, date_created, is_read, is_important FROM Messages "
"WHERE feed = :feed AND url = :url AND author = :author AND account_id = :account_id;");
query_select_with_id.setForwardOnly(true);
query_select_with_id.prepare("SELECT id, date_created, is_read, is_important FROM Messages "
"WHERE custom_id = :custom_id AND account_id = :account_id;");
// Used to insert new messages.
query_insert.setForwardOnly(true);
query_insert.prepare("INSERT INTO Messages "
"(feed, title, is_read, is_important, url, author, date_created, contents, enclosures, custom_id, account_id) "
"VALUES (:feed, :title, :is_read, :is_important, :url, :author, :date_created, :contents, :enclosures, :custom_id, :account_id);");
// Used to update existing messages.
query_update.setForwardOnly(true);
query_update.prepare("UPDATE Messages "
"SET title = :title, is_read = :is_read, is_important = :is_important, url = :url, author = :author, date_created = :date_created, contents = :contents, enclosures = :enclosures "
"WHERE id = :id;");
if (!database.transaction()) {
database.rollback();
qDebug("Transaction start for message downloader failed: '%s'.", qPrintable(database.lastError().text()));
return updated_messages;
}
foreach (Message message, messages) {
// Check if messages contain relative URLs and if they do, then replace them.
if (message.m_url.startsWith(QL1S("/"))) {
QString new_message_url = QUrl(url()).toString(QUrl::RemoveUserInfo |
QUrl::RemovePath |
QUrl::RemoveQuery |
#if QT_VERSION >= 0x050000
QUrl::RemoveFilename |
#endif
QUrl::StripTrailingSlash);
new_message_url += message.m_url;
message.m_url = new_message_url;
}
int id_existing_message = -1;
qint64 date_existing_message;
bool is_read_existing_message;
bool is_important_existing_message;
if (message.m_customId.isEmpty()) {
// We need to recognize existing messages according URL & AUTHOR.
query_select.bindValue(QSL(":feed"), custom_id);
query_select.bindValue(QSL(":url"), message.m_url);
query_select.bindValue(QSL(":author"), message.m_author);
query_select.bindValue(QSL(":account_id"), account_id);
query_select.exec();
if (query_select.next()) {
id_existing_message = query_select.value(0).toInt();
date_existing_message = query_select.value(1).value<qint64>();
is_read_existing_message = query_select.value(2).toBool();
is_important_existing_message = query_select.value(3).toBool();
}
query_select.finish();
}
else {
// We can recognize existing messages via their custom ID.
query_select_with_id.bindValue(QSL(":account_id"), account_id);
query_select_with_id.bindValue(QSL(":custom_id"), message.m_customId);
query_select_with_id.exec();
if (query_select_with_id.next()) {
id_existing_message = query_select_with_id.value(0).toInt();
date_existing_message = query_select_with_id.value(1).value<qint64>();
is_read_existing_message = query_select_with_id.value(2).toBool();
is_important_existing_message = query_select_with_id.value(3).toBool();
}
query_select_with_id.finish();
}
// Now, check if this message is already in the DB.
if (id_existing_message >= 0) {
// Message is already in the DB.
// Now, we update at least one of next conditions is true:
// 1) Message has custom ID AND (its date OR read status OR starred status are changed).
// 2) Message has its date fetched from feed AND its date is different from date in DB.
if (message.m_created.toMSecsSinceEpoch() != date_existing_message ||
message.m_isRead != is_read_existing_message ||
message.m_isImportant != is_important_existing_message) {
// Message exists, it is changed, update it.
query_update.bindValue(QSL(":title"), message.m_title);
query_update.bindValue(QSL(":is_read"), (int) message.m_isRead);
query_update.bindValue(QSL(":is_important"), (int) message.m_isImportant);
query_update.bindValue(QSL(":url"), message.m_url);
query_update.bindValue(QSL(":author"), message.m_author);
query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_update.bindValue(QSL(":contents"), message.m_contents);
query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_update.bindValue(QSL(":id"), id_existing_message);
if (query_update.exec()) {
updated_messages++;
}
query_update.finish();
qDebug("Updating message '%s' in DB.", qPrintable(message.m_title));
}
}
else {
// Message with this URL is not fetched in this feed yet.
query_insert.bindValue(QSL(":feed"), custom_id);
query_insert.bindValue(QSL(":title"), message.m_title);
query_insert.bindValue(QSL(":is_read"), (int) message.m_isRead);
query_insert.bindValue(QSL(":is_important"), (int) message.m_isImportant);
query_insert.bindValue(QSL(":url"), message.m_url);
query_insert.bindValue(QSL(":author"), message.m_author);
query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_insert.bindValue(QSL(":contents"), message.m_contents);
query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_insert.bindValue(QSL(":custom_id"), message.m_customId);
query_insert.bindValue(QSL(":account_id"), account_id);
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
updated_messages++;
}
query_insert.finish();
qDebug("Adding new message '%s' to DB.", qPrintable(message.m_title));
}
}
if (!database.commit()) {
database.rollback();
qDebug("Transaction commit for message downloader failed.");
}
else {
if (updated_messages > 0) {
setStatus(NewMessages);
}
else {
setStatus(Normal);
}
QList<RootItem*> items_to_update;
updateCounts(true);
items_to_update.append(this);
if (getParentServiceRoot()->recycleBin() != NULL && anything_duplicated) {
getParentServiceRoot()->recycleBin()->updateCounts(true);
items_to_update.append(getParentServiceRoot()->recycleBin());
}
getParentServiceRoot()->itemChanged(items_to_update);
}
return updated_messages;
}

View File

@ -60,23 +60,15 @@ class Feed : public RootItem {
void setCountOfAllMessages(int count_all_messages);
void setCountOfUnreadMessages(int count_unread_messages);
/////////////////////////////////////////
// /* Members to override.
/////////////////////////////////////////
// Performs synchronous update and returns number of newly updated messages.
// NOTE: This is called from worker thread, not from main UI thread.
// NOTE: This should COMPLETELY download ALL messages from online source
// into locale "Messages" table, INCLUDING contents (or excerpts) of those
// messages.
virtual int update() = 0;
int update();
QVariant data(int column, int role) const;
/////////////////////////////////////////
// Members to override. */
/////////////////////////////////////////
int autoUpdateInitialInterval() const;
void setAutoUpdateInitialInterval(int auto_update_interval);
@ -104,6 +96,10 @@ class Feed : public RootItem {
virtual int messageForeignKeyId() const = 0;
private:
int updateMessages(const QList<Message> &messages);
virtual QList<Message> obtainNewMessages() = 0;
private:
QString m_url;
Status m_status;

View File

@ -41,37 +41,21 @@ OwnCloudServiceRoot *OwnCloudFeed::serviceRoot() const {
return qobject_cast<OwnCloudServiceRoot*>(getParentServiceRoot());
}
int OwnCloudFeed::update() {
int OwnCloudFeed::messageForeignKeyId() const {
return customId();
}
QList<Message> OwnCloudFeed::obtainNewMessages() {
OwnCloudGetMessagesResponse messages = serviceRoot()->network()->getMessages(customId());
if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) {
setStatus(Feed::Error);
serviceRoot()->itemChanged(QList<RootItem*>() << this);
return 0;
return QList<Message>();
}
else {
return 0;
// TODO: TADY POKRACOVAT
// Udělat změnu tuto v tabulkách které mají sloupec custom_id
// Udělat to tak, že custom_id se bude vyplňovat pro všechny
// položky v Feeds, Categories a Messages
// taky tu property budou mít všechny příslušné objekty
// u standardních Feeds, Categories a Message se custom_id == id
//
// toto pak umožní přesunout všechny metody, které budou s custom ID a ID
// pracovat, do třídy předka a ušetřit kód.
// - toto sql provede překopirovani hodnot z atributu id do custom_id, pokud
// je custom_id prazdne, což plati pro standardní učet
// bude potřeba překopirovat u zprav, kategorii a feedů
/*
*UPDATE Categories
SET custom_id = (SELECT id FROM Categories t WHERE t.id = Categories.id)
WHERE Categories.custom_id IS NULL;
*
* //return updateMessages(headlines.messages());*/
return messages.messages();
}
}
int OwnCloudFeed::messageForeignKeyId() const {
return customId();
return QList<Message>();
}

View File

@ -24,14 +24,18 @@
class OwnCloudServiceRoot;
class OwnCloudFeed : public Feed {
Q_OBJECT
public:
explicit OwnCloudFeed(RootItem *parent = NULL);
explicit OwnCloudFeed(const QSqlRecord &record);
virtual ~OwnCloudFeed();
OwnCloudServiceRoot *serviceRoot() const;
int update();
int messageForeignKeyId() const;
private:
QList<Message> obtainNewMessages();
};
#endif // OWNCLOUDFEED_H

View File

@ -406,58 +406,6 @@ bool StandardFeed::performDragDropChange(RootItem *target_item) {
}
}
int StandardFeed::update() {
QByteArray feed_contents;
int download_timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
m_networkError = NetworkFactory::downloadFeedFile(url(), download_timeout, feed_contents,
passwordProtected(), username(), password()).first;
if (m_networkError != QNetworkReply::NoError) {
qWarning("Error during fetching of new messages for feed '%s' (id %d).", qPrintable(url()), id());
setStatus(Error);
return 0;
}
else if (status() != NewMessages) {
setStatus(Normal);
}
// Encode downloaded data for further parsing.
QTextCodec *codec = QTextCodec::codecForName(encoding().toLocal8Bit());
QString formatted_feed_contents;
if (codec == NULL) {
// No suitable codec for this encoding was found.
// Use non-converted data.
formatted_feed_contents = feed_contents;
}
else {
formatted_feed_contents = codec->toUnicode(feed_contents);
}
// Feed data are downloaded and encoded.
// Parse data and obtain messages.
QList<Message> messages;
switch (type()) {
case StandardFeed::Rss0X:
case StandardFeed::Rss2X:
messages = ParsingFactory::parseAsRSS20(formatted_feed_contents);
break;
case StandardFeed::Rdf:
messages = ParsingFactory::parseAsRDF(formatted_feed_contents);
break;
case StandardFeed::Atom10:
messages = ParsingFactory::parseAsATOM10(formatted_feed_contents);
default:
break;
}
return updateMessages(messages);
}
bool StandardFeed::removeItself() {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query_remove(database);
@ -588,158 +536,56 @@ int StandardFeed::messageForeignKeyId() const {
return id();
}
int StandardFeed::updateMessages(const QList<Message> &messages) {
if (messages.isEmpty()) {
return 0;
QList<Message> StandardFeed::obtainNewMessages() {
QByteArray feed_contents;
int download_timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
m_networkError = NetworkFactory::downloadFeedFile(url(), download_timeout, feed_contents,
passwordProtected(), username(), password()).first;
if (m_networkError != QNetworkReply::NoError) {
qWarning("Error during fetching of new messages for feed '%s' (id %d).", qPrintable(url()), id());
setStatus(Error);
return QList<Message>();
}
else if (status() != NewMessages) {
setStatus(Normal);
}
int feed_id = messageForeignKeyId();
int updated_messages = 0;
bool anything_duplicated = false;
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
bool remove_duplicates = qApp->settings()->value(GROUP(Messages), SETTING(Messages::RemoveDuplicates)).toBool();
int account_id = serviceRoot()->accountId();
// Encode downloaded data for further parsing.
QTextCodec *codec = QTextCodec::codecForName(encoding().toLocal8Bit());
QString formatted_feed_contents;
// Prepare queries.
QSqlQuery query_select(database);
QSqlQuery query_update(database);
QSqlQuery query_insert(database);
// Used to check if given feed contains any message with given title, url and date_created.
// WARNING: One feed CANNOT contain two (or more) messages with same AUTHOR AND TITLE AND URL AND DATE_CREATED.
query_select.setForwardOnly(true);
query_select.prepare("SELECT id, feed, date_created FROM Messages "
"WHERE feed = :feed AND url = :url AND author = :author AND account_id = :account_id;");
// Used to insert new messages.
query_insert.setForwardOnly(true);
query_insert.prepare("INSERT INTO Messages "
"(feed, title, url, author, date_created, contents, enclosures, account_id) "
"VALUES (:feed, :title, :url, :author, :date_created, :contents, :enclosures, :account_id);");
if (remove_duplicates) {
query_update.setForwardOnly(true);
query_update.prepare("UPDATE Messages SET is_read = 0, is_deleted = 0, is_pdeleted = 0, "
"contents = :contents, enclosures = :enclosures, date_created = :date_created "
"WHERE id = :id;");
}
if (!database.transaction()) {
database.rollback();
qDebug("Transaction start for message downloader failed: '%s'.", qPrintable(database.lastError().text()));
return updated_messages;
}
foreach (Message message, messages) {
// Check if messages contain relative URLs and if they do, then replace them.
if (message.m_url.startsWith(QL1S("/"))) {
QString new_message_url = QUrl(url()).toString(QUrl::RemoveUserInfo |
QUrl::RemovePath |
QUrl::RemoveQuery |
#if QT_VERSION >= 0x050000
QUrl::RemoveFilename |
#endif
QUrl::StripTrailingSlash);
new_message_url += message.m_url;
message.m_url = new_message_url;
}
query_select.bindValue(QSL(":feed"), feed_id);
query_select.bindValue(QSL(":url"), message.m_url);
query_select.bindValue(QSL(":author"), message.m_author);
query_select.bindValue(QSL(":account_id"), account_id);
query_select.exec();
QList<qint64> datetime_stamps;
QList<int> ids;
while (query_select.next()) {
ids << query_select.value(0).toInt();
datetime_stamps << query_select.value(2).value<qint64>();
}
query_select.finish();
if (datetime_stamps.isEmpty()) {
// Message is not fetched in this feed yet.
query_insert.bindValue(QSL(":feed"), feed_id);
query_insert.bindValue(QSL(":title"), message.m_title);
query_insert.bindValue(QSL(":url"), message.m_url);
query_insert.bindValue(QSL(":author"), message.m_author);
query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_insert.bindValue(QSL(":contents"), message.m_contents);
query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_insert.bindValue(QSL(":account_id"), account_id);
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
updated_messages++;
}
query_insert.finish();
qDebug("Adding new message '%s' to DB.", qPrintable(message.m_title));
}
else if (message.m_createdFromFeed && !datetime_stamps.contains(message.m_created.toMSecsSinceEpoch())) {
if (remove_duplicates && datetime_stamps.size() == 1) {
// Message is already in feed and new message has new unique time but user wishes to update existing
// messages and there is exactly ONE existing duplicate.
query_update.bindValue(QSL(":id"), ids.at(0));
query_update.bindValue(QSL(":contents"), message.m_contents);
query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_update.exec();
query_update.finish();
QString sss = query_update.lastError().text();
anything_duplicated = true;
qDebug("Updating contents of duplicate message '%s'.", qPrintable(message.m_title));
}
else {
// Message with same title, author and url exists, but new message has new unique time and
// user does not wish to update duplicates.
query_insert.bindValue(QSL(":feed"), feed_id);
query_insert.bindValue(QSL(":title"), message.m_title);
query_insert.bindValue(QSL(":url"), message.m_url);
query_insert.bindValue(QSL(":author"), message.m_author);
query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_insert.bindValue(QSL(":contents"), message.m_contents);
query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
updated_messages++;
}
query_insert.finish();
qDebug("Adding new duplicate (with potentially updated contents) message '%s' to DB.", qPrintable(message.m_title));
}
}
}
if (updated_messages > 0) {
setStatus(NewMessages);
}
if (!database.commit()) {
database.rollback();
qDebug("Transaction commit for message downloader failed.");
if (codec == NULL) {
// No suitable codec for this encoding was found.
// Use non-converted data.
formatted_feed_contents = feed_contents;
}
else {
QList<RootItem*> items_to_update;
updateCounts(true);
items_to_update.append(this);
if (anything_duplicated) {
serviceRoot()->recycleBin()->updateCounts(true);
items_to_update.append(serviceRoot()->recycleBin());
}
serviceRoot()->itemChanged(items_to_update);
formatted_feed_contents = codec->toUnicode(feed_contents);
}
return updated_messages;
// Feed data are downloaded and encoded.
// Parse data and obtain messages.
QList<Message> messages;
switch (type()) {
case StandardFeed::Rss0X:
case StandardFeed::Rss2X:
messages = ParsingFactory::parseAsRSS20(formatted_feed_contents);
break;
case StandardFeed::Rdf:
messages = ParsingFactory::parseAsRDF(formatted_feed_contents);
break;
case StandardFeed::Atom10:
messages = ParsingFactory::parseAsATOM10(formatted_feed_contents);
default:
break;
}
return messages;
}
QNetworkReply::NetworkError StandardFeed::networkError() const {

View File

@ -76,9 +76,6 @@ class StandardFeed : public Feed {
Qt::ItemFlags additionalFlags() const;
bool performDragDropChange(RootItem *target_item);
// Perform fetching of new messages. Returns number of newly updated messages.
int update();
// Updates counts of all/unread messages for this feed.
void updateCounts(bool including_total_count);
@ -150,10 +147,7 @@ class StandardFeed : public Feed {
void fetchMetadataForItself();
private:
// Persistently stores given messages into the database
// and updates existing messages if newer version is
// available.
int updateMessages(const QList<Message> &messages);
QList<Message> obtainNewMessages();
private:
bool m_passwordProtected;

View File

@ -161,34 +161,6 @@ bool TtRssFeed::deleteViaGui() {
}
}
int TtRssFeed::update() {
QList<Message> messages;
int newly_added_messages = 0;
int limit = MAX_MESSAGES;
int skip = 0;
do {
TtRssGetHeadlinesResponse headlines = serviceRoot()->network()->getHeadlines(customId(), limit, skip,
true, true, false);
if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) {
setStatus(Feed::Error);
serviceRoot()->itemChanged(QList<RootItem*>() << this);
return 0;
}
else {
QList<Message> new_messages = headlines.messages();
messages.append(new_messages);
newly_added_messages = new_messages.size();
skip += newly_added_messages;
}
}
while (newly_added_messages > 0);
return updateMessages(messages);
}
bool TtRssFeed::markAsReadUnread(RootItem::ReadStatus status) {
QStringList ids = serviceRoot()->customIDSOfMessagesForItem(this);
TtRssUpdateArticleResponse response = serviceRoot()->network()->updateArticles(ids, UpdateArticle::Unread,
@ -232,6 +204,32 @@ bool TtRssFeed::editItself(TtRssFeed *new_feed_data) {
}
}
QList<Message> TtRssFeed::obtainNewMessages() {
QList<Message> messages;
int newly_added_messages = 0;
int limit = MAX_MESSAGES;
int skip = 0;
do {
TtRssGetHeadlinesResponse headlines = serviceRoot()->network()->getHeadlines(customId(), limit, skip,
true, true, false);
if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) {
setStatus(Feed::Error);
serviceRoot()->itemChanged(QList<RootItem*>() << this);
return QList<Message>();
}
else {
QList<Message> new_messages = headlines.messages();
messages.append(new_messages);
newly_added_messages = new_messages.size();
skip += newly_added_messages;
}
}
while (newly_added_messages > 0);
}
bool TtRssFeed::removeItself() {
TtRssUnsubscribeFeedResponse response = serviceRoot()->network()->unsubscribeFeed(customId());
@ -262,126 +260,3 @@ bool TtRssFeed::removeItself() {
return false;
}
}
int TtRssFeed::updateMessages(const QList<Message> &messages) {
if (messages.isEmpty()) {
return 0;
}
int feed_id = messageForeignKeyId();
int updated_messages = 0;
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
int account_id = serviceRoot()->accountId();
// Prepare queries.
QSqlQuery query_insert(database);
QSqlQuery query_select(database);
QSqlQuery query_update(database);
query_update.setForwardOnly(true);
query_update.prepare("UPDATE Messages "
"SET title = :title, is_read = :is_read, is_important = :is_important, url = :url, author = :author, date_created = :date_created, contents = :contents, enclosures = :enclosures "
"WHERE id = :id;");
query_select.setForwardOnly(true);
query_select.prepare("SELECT id, date_created, is_read, is_important FROM Messages "
"WHERE account_id = :account_id AND custom_id = :custom_id;");
// Used to insert new messages.
query_insert.setForwardOnly(true);
query_insert.prepare("INSERT INTO Messages "
"(feed, title, is_read, is_important, url, author, date_created, contents, enclosures, custom_id, account_id) "
"VALUES (:feed, :title, :is_read, :is_important, :url, :author, :date_created, :contents, :enclosures, :custom_id, :account_id);");
if (!database.transaction()) {
database.rollback();
qDebug("Transaction start for message downloader failed.");
return updated_messages;
}
foreach (Message message, messages) {
query_select.bindValue(QSL(":account_id"), account_id);
query_select.bindValue(QSL(":custom_id"), message.m_customId);
query_select.exec();
int id_existing_message = -1;
qint64 date_existing_message;
bool is_read_existing_message;
bool is_important_existing_message;
if (query_select.next()) {
id_existing_message = query_select.value(0).toInt();
date_existing_message = query_select.value(1).value<qint64>();
is_read_existing_message = query_select.value(2).toBool();
is_important_existing_message = query_select.value(3).toBool();
}
query_select.finish();
// Now, check if this message is already in the DB.
if (id_existing_message >= 0) {
// Message is already in the DB.
if (message.m_created.toMSecsSinceEpoch() != date_existing_message ||
message.m_isRead != is_read_existing_message ||
message.m_isImportant != is_important_existing_message) {
// Message exists, it is changed, update it.
query_update.bindValue(QSL(":title"), message.m_title);
query_update.bindValue(QSL(":is_read"), (int) message.m_isRead);
query_update.bindValue(QSL(":is_important"), (int) message.m_isImportant);
query_update.bindValue(QSL(":url"), message.m_url);
query_update.bindValue(QSL(":author"), message.m_author);
query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_update.bindValue(QSL(":contents"), message.m_contents);
query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_update.bindValue(QSL(":id"), id_existing_message);
if (query_update.exec()) {
updated_messages++;
}
query_update.finish();
qDebug("Updating message '%s' in DB.", qPrintable(message.m_title));
}
}
else {
// Message with this URL is not fetched in this feed yet.
query_insert.bindValue(QSL(":feed"), feed_id);
query_insert.bindValue(QSL(":title"), message.m_title);
query_insert.bindValue(QSL(":is_read"), (int) message.m_isRead);
query_insert.bindValue(QSL(":is_important"), (int) message.m_isImportant);
query_insert.bindValue(QSL(":url"), message.m_url);
query_insert.bindValue(QSL(":author"), message.m_author);
query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_insert.bindValue(QSL(":contents"), message.m_contents);
query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_insert.bindValue(QSL(":custom_id"), message.m_customId);
query_insert.bindValue(QSL(":account_id"), account_id);
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
updated_messages++;
}
query_insert.finish();
qDebug("Adding new message '%s' to DB.", qPrintable(message.m_title));
}
}
if (!database.commit()) {
database.rollback();
qDebug("Transaction commit for message downloader failed.");
}
else {
if (updated_messages > 0) {
setStatus(NewMessages);
}
else {
setStatus(Normal);
}
updateCounts(true);
serviceRoot()->itemChanged(QList<RootItem*>() << this);
}
return updated_messages;
}

View File

@ -42,14 +42,13 @@ class TtRssFeed : public Feed {
bool canBeDeleted() const;
bool deleteViaGui();
int update();
bool markAsReadUnread(ReadStatus status);
bool cleanMessages(bool clear_only_read);
bool editItself(TtRssFeed *new_feed_data);
private:
QList<Message> obtainNewMessages();
bool removeItself();
int updateMessages(const QList<Message> &messages);
};
#endif // TTRSSFEED_H