1
0
mirror of https://github.com/d47081/qBittorrent.git synced 2025-01-25 14:04:23 +00:00

Keep RSS articles sorted by date in memory do avoid sorting them all the time

Optimization to address issue #34.
This commit is contained in:
Christophe Dumez 2012-08-19 11:46:50 +03:00
parent aecdc57cd4
commit d1e30cacf8
8 changed files with 58 additions and 61 deletions

View File

@ -490,11 +490,9 @@ void RSSImp::refreshArticleList(QTreeWidgetItem* item) {
qDebug("Getting the list of news"); qDebug("Getting the list of news");
RssArticleList news; RssArticleList news;
if (rss_item == m_rssManager) if (rss_item == m_rssManager)
news = rss_item->unreadArticleList(); news = rss_item->unreadArticleListByDateDesc();
else if (rss_item) else if (rss_item)
news = rss_item->articleList(); news = rss_item->articleListByDateDesc();
// Sort
RssManager::sortArticleListByDateDesc(news);
// Clear the list first // Clear the list first
textBrowser->clear(); textBrowser->clear();
m_currentArticle = 0; m_currentArticle = 0;

View File

@ -41,6 +41,11 @@
#include "downloadthread.h" #include "downloadthread.h"
#include "fs_utils.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): RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString &url):
m_manager(manager), m_parent(parent), m_icon(":/Icons/oxygen/application-rss+xml.png"), 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) { 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) { foreach (const QVariant &var_it, old_items) {
QHash<QString, QVariant> item = var_it.toHash(); QHash<QString, QVariant> item = var_it.toHash();
RssArticlePtr rss_item = hashToRssArticle(this, item); RssArticlePtr rss_item = hashToRssArticle(this, item);
if (rss_item) { if (rss_item)
m_articles.insert(rss_item->guid(), rss_item); addArticle(rss_item);
if (!rss_item->isRead()) }
++m_unreadCount; }
}
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; return m_unreadCount;
} }
RssArticleList RssFeed::articleList() const { RssArticleList RssFeed::articleListByDateDesc() const {
return m_articles.values(); return m_articlesByDate;
} }
RssArticleList RssFeed::unreadArticleList() const { RssArticleList RssFeed::unreadArticleListByDateDesc() const {
RssArticleList unread_news; RssArticleList unread_news;
RssArticleHash::ConstIterator it = m_articles.begin(); RssArticleList::ConstIterator it = m_articlesByDate.begin();
RssArticleHash::ConstIterator itend = m_articles.end(); RssArticleList::ConstIterator itend = m_articlesByDate.end();
for ( ; it != itend; ++it) { for ( ; it != itend; ++it) {
if (!it.value()->isRead()) if (!(*it)->isRead())
unread_news << it.value(); unread_news << *it;
} }
return unread_news; return unread_news;
} }
@ -223,22 +247,6 @@ QString RssFeed::iconUrl() const {
return QString("http://")+QUrl(m_url).host()+QString("/favicon.ico"); 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; i<nb_articles; ++i) {
RssArticlePtr article = m_articles.take(listItems.at(i)->guid());
// Update unreadCount
if (!article->isRead())
--m_unreadCount;
}
}
}
// read and store the downloaded rss' informations // read and store the downloaded rss' informations
void RssFeed::handleFinishedDownload(const QString& url, const QString &file_path) { void RssFeed::handleFinishedDownload(const QString& url, const QString &file_path) {
if (url == m_url) { if (url == m_url) {
@ -290,7 +298,7 @@ void RssFeed::handleNewArticle(const QString& feedUrl, const QVariantHash& artic
RssArticlePtr article = hashToRssArticle(this, articleData); RssArticlePtr article = hashToRssArticle(this, articleData);
Q_ASSERT(article); Q_ASSERT(article);
m_articles[guid] = article; addArticle(article);
// Download torrent if necessary. // Download torrent if necessary.
if (RssSettings().isRssDownloadingEnabled()) { 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()); 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); m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount);
// FIXME: We should forward the information here but this would seriously decrease // 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; qWarning() << "Reason:" << error;
} }
// Make sure we limit the number of articles
removeOldArticles();
m_loading = false; m_loading = false;
m_inErrorState = !error.isEmpty(); m_inErrorState = !error.isEmpty();

View File

@ -45,6 +45,8 @@ typedef QHash<QString, RssArticlePtr> RssArticleHash;
typedef QSharedPointer<RssFeed> RssFeedPtr; typedef QSharedPointer<RssFeed> RssFeedPtr;
typedef QList<RssFeedPtr> RssFeedList; typedef QList<RssFeedPtr> RssFeedList;
bool rssArticleDateRecentThan(const RssArticlePtr& left, const RssArticlePtr& right);
class RssFeed: public QObject, public RssFile { class RssFeed: public QObject, public RssFile {
Q_OBJECT Q_OBJECT
@ -70,9 +72,9 @@ public:
uint count() const; uint count() const;
virtual void markAsRead(); virtual void markAsRead();
virtual uint unreadCount() const; virtual uint unreadCount() const;
virtual RssArticleList articleList() const; virtual RssArticleList articleListByDateDesc() const;
const RssArticleHash& articleHash() const { return m_articles; } const RssArticleHash& articleHash() const { return m_articles; }
virtual RssArticleList unreadArticleList() const; virtual RssArticleList unreadArticleListByDateDesc() const;
void decrementUnreadCount(); void decrementUnreadCount();
private slots: private slots:
@ -83,14 +85,15 @@ private slots:
void handleFeedParsingFinished(const QString& feedUrl, const QString& error); void handleFeedParsingFinished(const QString& feedUrl, const QString& error);
private: private:
void removeOldArticles();
QString iconUrl() const; QString iconUrl() const;
void loadItemsFromDisk(); void loadItemsFromDisk();
void addArticle(const RssArticlePtr& article);
private: private:
RssManager* m_manager; RssManager* m_manager;
RssArticleHash m_articles; RssArticleHash m_articles;
RssFolder *m_parent; RssArticleList m_articlesByDate; // Articles sorted by date (more recent first)
RssFolder* m_parent;
QString m_title; QString m_title;
QString m_url; QString m_url;
QString m_alias; QString m_alias;

View File

@ -59,8 +59,8 @@ public:
virtual RssFolder* parent() const = 0; virtual RssFolder* parent() const = 0;
virtual void setParent(RssFolder* parent) = 0; virtual void setParent(RssFolder* parent) = 0;
virtual void refresh() = 0; virtual void refresh() = 0;
virtual RssArticleList articleList() const = 0; virtual RssArticleList articleListByDateDesc() const = 0;
virtual RssArticleList unreadArticleList() const = 0; virtual RssArticleList unreadArticleListByDateDesc() const = 0;
virtual void removeAllSettings() = 0; virtual void removeAllSettings() = 0;
virtual void saveItemsToDisk() = 0; virtual void saveItemsToDisk() = 0;
QStringList pathHierarchy() const; QStringList pathHierarchy() const;

View File

@ -91,24 +91,28 @@ void RssFolder::refresh() {
} }
} }
RssArticleList RssFolder::articleList() const { RssArticleList RssFolder::articleListByDateDesc() const {
RssArticleList news; RssArticleList news;
RssFileHash::ConstIterator it = m_children.begin(); RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end(); RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) { 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; return news;
} }
RssArticleList RssFolder::unreadArticleList() const { RssArticleList RssFolder::unreadArticleListByDateDesc() const {
RssArticleList unread_news; RssArticleList unread_news;
RssFileHash::ConstIterator it = m_children.begin(); RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end(); RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) { 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; return unread_news;
} }

View File

@ -62,8 +62,8 @@ public:
virtual QString displayName() const; virtual QString displayName() const;
virtual QString id() const; virtual QString id() const;
bool hasChild(const QString &childId); bool hasChild(const QString &childId);
virtual RssArticleList articleList() const; virtual RssArticleList articleListByDateDesc() const;
virtual RssArticleList unreadArticleList() const; virtual RssArticleList unreadArticleListByDateDesc() const;
virtual void removeAllSettings(); virtual void removeAllSettings();
virtual void saveItemsToDisk(); virtual void saveItemsToDisk();
void removeAllItems(); void removeAllItems();

View File

@ -151,15 +151,6 @@ void RssManager::saveStreamList() const {
settings.setRssFeedsAliases(aliases); 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 RssDownloadRuleList *RssManager::downloadRules() const
{ {
Q_ASSERT(m_downloadRules); Q_ASSERT(m_downloadRules);

View File

@ -52,7 +52,6 @@ public:
DownloadThread* rssDownloader() const; DownloadThread* rssDownloader() const;
RssParser* rssParser() const; RssParser* rssParser() const;
static void sortArticleListByDateDesc(RssArticleList& news_list);
RssDownloadRuleList* downloadRules() const; RssDownloadRuleList* downloadRules() const;