diff --git a/src/rss/rss_imp.cpp b/src/rss/rss_imp.cpp index d769cce9f..59d219a3d 100644 --- a/src/rss/rss_imp.cpp +++ b/src/rss/rss_imp.cpp @@ -490,11 +490,9 @@ void RSSImp::refreshArticleList(QTreeWidgetItem* item) { qDebug("Getting the list of news"); RssArticleList news; if (rss_item == m_rssManager) - news = rss_item->unreadArticleList(); + news = rss_item->unreadArticleListByDateDesc(); else if (rss_item) - news = rss_item->articleList(); - // Sort - RssManager::sortArticleListByDateDesc(news); + news = rss_item->articleListByDateDesc(); // Clear the list first textBrowser->clear(); m_currentArticle = 0; diff --git a/src/rss/rssfeed.cpp b/src/rss/rssfeed.cpp index 360292502..e6915af73 100644 --- a/src/rss/rssfeed.cpp +++ b/src/rss/rssfeed.cpp @@ -41,6 +41,11 @@ #include "downloadthread.h" #include "fs_utils.h" +bool rssArticleDateRecentThan(const RssArticlePtr& left, const RssArticlePtr& right) +{ + return left->date() > right->date(); +} + RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString &url): m_manager(manager), m_parent(parent), m_icon(":/Icons/oxygen/application-rss+xml.png"), m_unreadCount(0), m_dirty(false), m_inErrorState(false), m_loading(false) { @@ -95,11 +100,30 @@ void RssFeed::loadItemsFromDisk() { foreach (const QVariant &var_it, old_items) { QHash item = var_it.toHash(); RssArticlePtr rss_item = hashToRssArticle(this, item); - if (rss_item) { - m_articles.insert(rss_item->guid(), rss_item); - if (!rss_item->isRead()) - ++m_unreadCount; - } + if (rss_item) + addArticle(rss_item); + } +} + +void RssFeed::addArticle(const RssArticlePtr& article) +{ + Q_ASSERT(!m_articles.contains(article->guid())); + // Update unreadCount + if (!article->isRead()) + ++m_unreadCount; + // Insert in hash table + m_articles[article->guid()] = article; + // Insertion sort + RssArticleList::Iterator lowerBound = qLowerBound(m_articlesByDate.begin(), m_articlesByDate.end(), article, rssArticleDateRecentThan); + m_articlesByDate.insert(lowerBound, article); + // Restrict size + const int max_articles = RssSettings().getRSSMaxArticlesPerFeed(); + if (m_articlesByDate.size() > max_articles) { + RssArticlePtr oldestArticle = m_articlesByDate.takeLast(); + m_articles.remove(oldestArticle->guid()); + // Update unreadCount + if (!oldestArticle->isRead()) + --m_unreadCount; } } @@ -201,18 +225,18 @@ uint RssFeed::unreadCount() const return m_unreadCount; } -RssArticleList RssFeed::articleList() const { - return m_articles.values(); +RssArticleList RssFeed::articleListByDateDesc() const { + return m_articlesByDate; } -RssArticleList RssFeed::unreadArticleList() const { +RssArticleList RssFeed::unreadArticleListByDateDesc() const { RssArticleList unread_news; - RssArticleHash::ConstIterator it = m_articles.begin(); - RssArticleHash::ConstIterator itend = m_articles.end(); + RssArticleList::ConstIterator it = m_articlesByDate.begin(); + RssArticleList::ConstIterator itend = m_articlesByDate.end(); for ( ; it != itend; ++it) { - if (!it.value()->isRead()) - unread_news << it.value(); + if (!(*it)->isRead()) + unread_news << *it; } return unread_news; } @@ -223,22 +247,6 @@ QString RssFeed::iconUrl() const { return QString("http://")+QUrl(m_url).host()+QString("/favicon.ico"); } -void RssFeed::removeOldArticles() { - const uint max_articles = RssSettings().getRSSMaxArticlesPerFeed(); - const uint nb_articles = m_articles.size(); - if (nb_articles > max_articles) { - RssArticleList listItems = m_articles.values(); - RssManager::sortArticleListByDateDesc(listItems); - const int excess = nb_articles - max_articles; - for (uint i=nb_articles-excess; iguid()); - // Update unreadCount - if (!article->isRead()) - --m_unreadCount; - } - } -} - // read and store the downloaded rss' informations void RssFeed::handleFinishedDownload(const QString& url, const QString &file_path) { if (url == m_url) { @@ -290,7 +298,7 @@ void RssFeed::handleNewArticle(const QString& feedUrl, const QVariantHash& artic RssArticlePtr article = hashToRssArticle(this, articleData); Q_ASSERT(article); - m_articles[guid] = article; + addArticle(article); // Download torrent if necessary. if (RssSettings().isRssDownloadingEnabled()) { @@ -307,9 +315,6 @@ void RssFeed::handleNewArticle(const QString& feedUrl, const QVariantHash& artic QBtSession::instance()->downloadUrlAndSkipDialog(torrent_url, matching_rule->savePath(), matching_rule->label()); } } - // Update unreadCount if necessary - if (!article->isRead()) - ++m_unreadCount; m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount); // FIXME: We should forward the information here but this would seriously decrease @@ -327,9 +332,6 @@ void RssFeed::handleFeedParsingFinished(const QString& feedUrl, const QString& e qWarning() << "Reason:" << error; } - // Make sure we limit the number of articles - removeOldArticles(); - m_loading = false; m_inErrorState = !error.isEmpty(); diff --git a/src/rss/rssfeed.h b/src/rss/rssfeed.h index db71f8e7a..5c430e202 100644 --- a/src/rss/rssfeed.h +++ b/src/rss/rssfeed.h @@ -45,6 +45,8 @@ typedef QHash RssArticleHash; typedef QSharedPointer RssFeedPtr; typedef QList RssFeedList; +bool rssArticleDateRecentThan(const RssArticlePtr& left, const RssArticlePtr& right); + class RssFeed: public QObject, public RssFile { Q_OBJECT @@ -70,9 +72,9 @@ public: uint count() const; virtual void markAsRead(); virtual uint unreadCount() const; - virtual RssArticleList articleList() const; + virtual RssArticleList articleListByDateDesc() const; const RssArticleHash& articleHash() const { return m_articles; } - virtual RssArticleList unreadArticleList() const; + virtual RssArticleList unreadArticleListByDateDesc() const; void decrementUnreadCount(); private slots: @@ -83,14 +85,15 @@ private slots: void handleFeedParsingFinished(const QString& feedUrl, const QString& error); private: - void removeOldArticles(); QString iconUrl() const; void loadItemsFromDisk(); + void addArticle(const RssArticlePtr& article); private: RssManager* m_manager; RssArticleHash m_articles; - RssFolder *m_parent; + RssArticleList m_articlesByDate; // Articles sorted by date (more recent first) + RssFolder* m_parent; QString m_title; QString m_url; QString m_alias; diff --git a/src/rss/rssfile.h b/src/rss/rssfile.h index 8d9684531..4b9590c3c 100644 --- a/src/rss/rssfile.h +++ b/src/rss/rssfile.h @@ -59,8 +59,8 @@ public: virtual RssFolder* parent() const = 0; virtual void setParent(RssFolder* parent) = 0; virtual void refresh() = 0; - virtual RssArticleList articleList() const = 0; - virtual RssArticleList unreadArticleList() const = 0; + virtual RssArticleList articleListByDateDesc() const = 0; + virtual RssArticleList unreadArticleListByDateDesc() const = 0; virtual void removeAllSettings() = 0; virtual void saveItemsToDisk() = 0; QStringList pathHierarchy() const; diff --git a/src/rss/rssfolder.cpp b/src/rss/rssfolder.cpp index b0bd6253d..afb625127 100644 --- a/src/rss/rssfolder.cpp +++ b/src/rss/rssfolder.cpp @@ -91,24 +91,28 @@ void RssFolder::refresh() { } } -RssArticleList RssFolder::articleList() const { +RssArticleList RssFolder::articleListByDateDesc() const { RssArticleList news; RssFileHash::ConstIterator it = m_children.begin(); RssFileHash::ConstIterator itend = m_children.end(); for ( ; it != itend; ++it) { - news << it.value()->articleList(); + int n = news.size(); + news << it.value()->articleListByDateDesc(); + std::inplace_merge(news.begin(), news.begin() + n, news.end(), rssArticleDateRecentThan); } return news; } -RssArticleList RssFolder::unreadArticleList() const { +RssArticleList RssFolder::unreadArticleListByDateDesc() const { RssArticleList unread_news; RssFileHash::ConstIterator it = m_children.begin(); RssFileHash::ConstIterator itend = m_children.end(); for ( ; it != itend; ++it) { - unread_news << it.value()->unreadArticleList(); + int n = unread_news.size(); + unread_news << it.value()->unreadArticleListByDateDesc(); + std::inplace_merge(unread_news.begin(), unread_news.begin() + n, unread_news.end(), rssArticleDateRecentThan); } return unread_news; } diff --git a/src/rss/rssfolder.h b/src/rss/rssfolder.h index 8d2e58ff1..fad154fd3 100644 --- a/src/rss/rssfolder.h +++ b/src/rss/rssfolder.h @@ -62,8 +62,8 @@ public: virtual QString displayName() const; virtual QString id() const; bool hasChild(const QString &childId); - virtual RssArticleList articleList() const; - virtual RssArticleList unreadArticleList() const; + virtual RssArticleList articleListByDateDesc() const; + virtual RssArticleList unreadArticleListByDateDesc() const; virtual void removeAllSettings(); virtual void saveItemsToDisk(); void removeAllItems(); diff --git a/src/rss/rssmanager.cpp b/src/rss/rssmanager.cpp index f8a62c8c8..5e07ccb49 100644 --- a/src/rss/rssmanager.cpp +++ b/src/rss/rssmanager.cpp @@ -151,15 +151,6 @@ void RssManager::saveStreamList() const { settings.setRssFeedsAliases(aliases); } -static bool laterItemDate(const RssArticlePtr& a, const RssArticlePtr& b) -{ - return (a->date() > b->date()); -} - -void RssManager::sortArticleListByDateDesc(RssArticleList& news_list) { - qSort(news_list.begin(), news_list.end(), laterItemDate); -} - RssDownloadRuleList *RssManager::downloadRules() const { Q_ASSERT(m_downloadRules); diff --git a/src/rss/rssmanager.h b/src/rss/rssmanager.h index 545e293fa..28418b4e3 100644 --- a/src/rss/rssmanager.h +++ b/src/rss/rssmanager.h @@ -52,7 +52,6 @@ public: DownloadThread* rssDownloader() const; RssParser* rssParser() const; - static void sortArticleListByDateDesc(RssArticleList& news_list); RssDownloadRuleList* downloadRules() const;