From bc06e90a07e84fec997d011e6ad1853f0e29a06f Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Tue, 23 Feb 2016 10:28:17 +0100 Subject: [PATCH] EXPERIMENTAL work on updateMessages() refactoring. Very broken right now!!!!!!!!!!!! --- src/services/abstract/feed.cpp | 190 ++++++++++++++++++++ src/services/abstract/feed.h | 14 +- src/services/owncloud/owncloudfeed.cpp | 32 +--- src/services/owncloud/owncloudfeed.h | 6 +- src/services/standard/standardfeed.cpp | 240 +++++-------------------- src/services/standard/standardfeed.h | 8 +- src/services/tt-rss/ttrssfeed.cpp | 177 +++--------------- src/services/tt-rss/ttrssfeed.h | 3 +- 8 files changed, 279 insertions(+), 391 deletions(-) diff --git a/src/services/abstract/feed.cpp b/src/services/abstract/feed.cpp index d0aaf21fa..c3ba8ee69 100755 --- a/src/services/abstract/feed.cpp +++ b/src/services/abstract/feed.cpp @@ -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 +#include 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 &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(); + 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(); + 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 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; +} diff --git a/src/services/abstract/feed.h b/src/services/abstract/feed.h index 7f8aefd1d..d20d0c13d 100755 --- a/src/services/abstract/feed.h +++ b/src/services/abstract/feed.h @@ -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 &messages); + virtual QList obtainNewMessages() = 0; + private: QString m_url; Status m_status; diff --git a/src/services/owncloud/owncloudfeed.cpp b/src/services/owncloud/owncloudfeed.cpp index dca318f6d..c3087deac 100755 --- a/src/services/owncloud/owncloudfeed.cpp +++ b/src/services/owncloud/owncloudfeed.cpp @@ -41,37 +41,21 @@ OwnCloudServiceRoot *OwnCloudFeed::serviceRoot() const { return qobject_cast(getParentServiceRoot()); } -int OwnCloudFeed::update() { +int OwnCloudFeed::messageForeignKeyId() const { + return customId(); +} + +QList OwnCloudFeed::obtainNewMessages() { OwnCloudGetMessagesResponse messages = serviceRoot()->network()->getMessages(customId()); if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) { setStatus(Feed::Error); serviceRoot()->itemChanged(QList() << this); - return 0; + return QList(); } 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(); } diff --git a/src/services/owncloud/owncloudfeed.h b/src/services/owncloud/owncloudfeed.h index e9bf218bc..74789af20 100755 --- a/src/services/owncloud/owncloudfeed.h +++ b/src/services/owncloud/owncloudfeed.h @@ -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 obtainNewMessages(); }; #endif // OWNCLOUDFEED_H diff --git a/src/services/standard/standardfeed.cpp b/src/services/standard/standardfeed.cpp index 72e94a3f8..565fc1e60 100755 --- a/src/services/standard/standardfeed.cpp +++ b/src/services/standard/standardfeed.cpp @@ -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 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 &messages) { - if (messages.isEmpty()) { - return 0; +QList 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(); + } + 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 datetime_stamps; - QList ids; - - while (query_select.next()) { - ids << query_select.value(0).toInt(); - datetime_stamps << query_select.value(2).value(); - } - - 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 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 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 { diff --git a/src/services/standard/standardfeed.h b/src/services/standard/standardfeed.h index b6e195bbe..c2e05868a 100755 --- a/src/services/standard/standardfeed.h +++ b/src/services/standard/standardfeed.h @@ -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 &messages); + QList obtainNewMessages(); private: bool m_passwordProtected; diff --git a/src/services/tt-rss/ttrssfeed.cpp b/src/services/tt-rss/ttrssfeed.cpp index 5bbef73e6..6b0000898 100755 --- a/src/services/tt-rss/ttrssfeed.cpp +++ b/src/services/tt-rss/ttrssfeed.cpp @@ -161,34 +161,6 @@ bool TtRssFeed::deleteViaGui() { } } -int TtRssFeed::update() { - QList 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() << this); - return 0; - } - else { - QList 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 TtRssFeed::obtainNewMessages() { + QList 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() << this); + return QList(); + } + else { + QList 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 &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(); - 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() << this); - } - - return updated_messages; -} diff --git a/src/services/tt-rss/ttrssfeed.h b/src/services/tt-rss/ttrssfeed.h index ad5fda308..47bfffc35 100755 --- a/src/services/tt-rss/ttrssfeed.h +++ b/src/services/tt-rss/ttrssfeed.h @@ -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 obtainNewMessages(); bool removeItself(); - int updateMessages(const QList &messages); }; #endif // TTRSSFEED_H