mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-01-31 09:34:52 +01:00
EXPERIMENTAL work on updateMessages() refactoring. Very broken right now!!!!!!!!!!!!
This commit is contained in:
parent
127e43b952
commit
bc06e90a07
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user