Browse Source

Fix coding style (Issue #2192).

adaptive-webui-19844
Vladimir Golovnev (Glassez) 9 years ago committed by Vladimir Golovnev (qlassez)
parent
commit
67758cb092
  1. 49
      src/base/rss/rssarticle.cpp
  2. 15
      src/base/rss/rssarticle.h
  3. 165
      src/base/rss/rssdownloadrule.cpp
  4. 57
      src/base/rss/rssdownloadrule.h
  5. 51
      src/base/rss/rssdownloadrulelist.cpp
  6. 13
      src/base/rss/rssdownloadrulelist.h
  7. 178
      src/base/rss/rssfeed.cpp
  8. 42
      src/base/rss/rssfeed.h
  9. 10
      src/base/rss/rssfile.cpp
  10. 13
      src/base/rss/rssfile.h
  11. 137
      src/base/rss/rssfolder.cpp
  12. 43
      src/base/rss/rssfolder.h
  13. 53
      src/base/rss/rssmanager.cpp
  14. 12
      src/base/rss/rssmanager.h
  15. 120
      src/base/rss/rssparser.cpp
  16. 5
      src/base/rss/rssparser.h
  17. 4
      src/gui/rss/feedlistwidget.cpp

49
src/base/rss/rssarticle.cpp

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -36,14 +37,20 @@ @@ -36,14 +37,20 @@
#include "rssarticle.h"
// public constructor
RssArticle::RssArticle(RssFeed* parent, const QString& guid):
m_parent(parent), m_guid(guid), m_read(false) {}
RssArticle::RssArticle(RssFeed *parent, const QString &guid)
: m_parent(parent)
, m_guid(guid)
, m_read(false)
{
}
bool RssArticle::hasAttachment() const {
bool RssArticle::hasAttachment() const
{
return !m_torrentUrl.isEmpty();
}
QVariantHash RssArticle::toHash() const {
QVariantHash RssArticle::toHash() const
{
QVariantHash item;
item["title"] = m_title;
item["id"] = m_guid;
@ -56,7 +63,8 @@ QVariantHash RssArticle::toHash() const { @@ -56,7 +63,8 @@ QVariantHash RssArticle::toHash() const {
return item;
}
RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& h) {
RssArticlePtr RssArticle::fromHash(RssFeed *parent, const QVariantHash &h)
{
const QString guid = h.value("id").toString();
if (guid.isEmpty())
return RssArticlePtr();
@ -73,19 +81,23 @@ RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& h) { @@ -73,19 +81,23 @@ RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& h) {
return art;
}
RssFeed* RssArticle::parent() const {
RssFeed *RssArticle::parent() const
{
return m_parent;
}
const QString& RssArticle::author() const {
const QString &RssArticle::author() const
{
return m_author;
}
const QString& RssArticle::torrentUrl() const {
const QString &RssArticle::torrentUrl() const
{
return m_torrentUrl;
}
const QString& RssArticle::link() const {
const QString &RssArticle::link() const
{
return m_link;
}
@ -94,17 +106,19 @@ QString RssArticle::description() const @@ -94,17 +106,19 @@ QString RssArticle::description() const
return m_description.isNull() ? "" : m_description;
}
const QDateTime& RssArticle::date() const {
const QDateTime &RssArticle::date() const
{
return m_date;
}
bool RssArticle::isRead() const {
bool RssArticle::isRead() const
{
return m_read;
}
void RssArticle::markAsRead() {
if (m_read)
return;
void RssArticle::markAsRead()
{
if (m_read) return;
m_read = true;
m_parent->decrementUnreadCount();
@ -122,7 +136,8 @@ const QString& RssArticle::title() const @@ -122,7 +136,8 @@ const QString& RssArticle::title() const
return m_title;
}
void RssArticle::handleTorrentDownloadSuccess(const QString &url) {
void RssArticle::handleTorrentDownloadSuccess(const QString &url)
{
if (url == m_torrentUrl)
markAsRead();
}

15
src/base/rss/rssarticle.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -42,11 +43,13 @@ class RssArticle; @@ -42,11 +43,13 @@ class RssArticle;
typedef QSharedPointer<RssArticle> RssArticlePtr;
// Item of a rss stream, single information
class RssArticle : public QObject {
class RssArticle: public QObject
{
Q_OBJECT
public:
RssArticle(RssFeed *parent, const QString &guid);
// Accessors
bool hasAttachment() const;
const QString &guid() const;
@ -60,8 +63,10 @@ public: @@ -60,8 +63,10 @@ public:
bool isRead() const;
// Setters
void markAsRead();
// Serialization
QVariantHash toHash() const;
static RssArticlePtr fromHash(RssFeed *parent, const QVariantHash &hash);
signals:
void articleWasRead();
@ -69,8 +74,6 @@ signals: @@ -69,8 +74,6 @@ signals:
public slots:
void handleTorrentDownloadSuccess(const QString &url);
friend RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& hash);
private:
RssFeed *m_parent;
QString m_guid;
@ -83,6 +86,4 @@ private: @@ -83,6 +86,4 @@ private:
bool m_read;
};
RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& hash);
#endif // RSSARTICLE_H

165
src/base/rss/rssdownloadrule.cpp

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@ -38,16 +38,19 @@ @@ -38,16 +38,19 @@
#include "rssarticle.h"
#include "rssdownloadrule.h"
RssDownloadRule::RssDownloadRule(): m_enabled(false), m_useRegex(false), m_apstate(USE_GLOBAL)
RssDownloadRule::RssDownloadRule()
: m_enabled(false)
, m_useRegex(false)
, m_apstate(USE_GLOBAL)
{
}
bool RssDownloadRule::matches(const QString &article_title) const
bool RssDownloadRule::matches(const QString &articleTitle) const
{
foreach (const QString &token, m_mustContain) {
if (!token.isEmpty()) {
QRegExp reg(token, Qt::CaseInsensitive, m_useRegex ? QRegExp::RegExp : QRegExp::Wildcard);
if (reg.indexIn(article_title) < 0)
if (reg.indexIn(articleTitle) < 0)
return false;
}
}
@ -56,7 +59,7 @@ bool RssDownloadRule::matches(const QString &article_title) const @@ -56,7 +59,7 @@ bool RssDownloadRule::matches(const QString &article_title) const
foreach (const QString &token, m_mustNotContain) {
if (!token.isEmpty()) {
QRegExp reg(token, Qt::CaseInsensitive, m_useRegex ? QRegExp::RegExp : QRegExp::Wildcard);
if (reg.indexIn(article_title) > -1)
if (reg.indexIn(articleTitle) > -1)
return false;
}
}
@ -84,7 +87,7 @@ bool RssDownloadRule::matches(const QString &article_title) const @@ -84,7 +87,7 @@ bool RssDownloadRule::matches(const QString &article_title) const
int epOurs = ep.left(ep.size() - 1).toInt();
// Extract partial match from article and compare as digits
pos = reg.indexIn(article_title);
pos = reg.indexIn(articleTitle);
if (pos != -1) {
int epTheirs = reg.cap(1).toInt();
if (epTheirs >= epOurs)
@ -101,7 +104,7 @@ bool RssDownloadRule::matches(const QString &article_title) const @@ -101,7 +104,7 @@ bool RssDownloadRule::matches(const QString &article_title) const
int epOursLast = range.last().toInt();
// Extract partial match from article and compare as digits
pos = reg.indexIn(article_title);
pos = reg.indexIn(articleTitle);
if (pos != -1) {
int epTheirs = reg.cap(1).toInt();
if (epOursFirst <= epTheirs && epOursLast >= epTheirs)
@ -111,7 +114,7 @@ bool RssDownloadRule::matches(const QString &article_title) const @@ -111,7 +114,7 @@ bool RssDownloadRule::matches(const QString &article_title) const
}
else { // Single number
QRegExp reg(expStr + ep + "\\D", Qt::CaseInsensitive);
if (reg.indexIn(article_title) != -1)
if (reg.indexIn(articleTitle) != -1)
return true;
}
}
@ -136,21 +139,46 @@ void RssDownloadRule::setMustNotContain(const QString &tokens) @@ -136,21 +139,46 @@ void RssDownloadRule::setMustNotContain(const QString &tokens)
m_mustNotContain = tokens.split("|");
}
RssDownloadRulePtr RssDownloadRule::fromVariantHash(const QVariantHash &rule_hash)
QStringList RssDownloadRule::rssFeeds() const
{
return m_rssFeeds;
}
void RssDownloadRule::setRssFeeds(const QStringList &rssFeeds)
{
m_rssFeeds = rssFeeds;
}
QString RssDownloadRule::name() const
{
return m_name;
}
void RssDownloadRule::setName(const QString &name)
{
m_name = name;
}
QString RssDownloadRule::savePath() const
{
return m_savePath;
}
RssDownloadRulePtr RssDownloadRule::fromVariantHash(const QVariantHash &ruleHash)
{
RssDownloadRulePtr rule(new RssDownloadRule);
rule->setName(rule_hash.value("name").toString());
rule->setUseRegex(rule_hash.value("use_regex", false).toBool());
rule->setMustContain(rule_hash.value("must_contain").toString());
rule->setMustNotContain(rule_hash.value("must_not_contain").toString());
rule->setEpisodeFilter(rule_hash.value("episode_filter").toString());
rule->setRssFeeds(rule_hash.value("affected_feeds").toStringList());
rule->setEnabled(rule_hash.value("enabled", false).toBool());
rule->setSavePath(rule_hash.value("save_path").toString());
rule->setLabel(rule_hash.value("label_assigned").toString());
rule->setAddPaused(AddPausedState(rule_hash.value("add_paused").toUInt()));
rule->setLastMatch(rule_hash.value("last_match").toDateTime());
rule->setIgnoreDays(rule_hash.value("ignore_days").toInt());
rule->setName(ruleHash.value("name").toString());
rule->setUseRegex(ruleHash.value("use_regex", false).toBool());
rule->setMustContain(ruleHash.value("must_contain").toString());
rule->setMustNotContain(ruleHash.value("must_not_contain").toString());
rule->setEpisodeFilter(ruleHash.value("episode_filter").toString());
rule->setRssFeeds(ruleHash.value("affected_feeds").toStringList());
rule->setEnabled(ruleHash.value("enabled", false).toBool());
rule->setSavePath(ruleHash.value("save_path").toString());
rule->setLabel(ruleHash.value("label_assigned").toString());
rule->setAddPaused(AddPausedState(ruleHash.value("add_paused").toUInt()));
rule->setLastMatch(ruleHash.value("last_match").toDateTime());
rule->setIgnoreDays(ruleHash.value("ignore_days").toInt());
return rule;
}
@ -172,25 +200,106 @@ QVariantHash RssDownloadRule::toVariantHash() const @@ -172,25 +200,106 @@ QVariantHash RssDownloadRule::toVariantHash() const
return hash;
}
bool RssDownloadRule::operator==(const RssDownloadRule &other) const {
bool RssDownloadRule::operator==(const RssDownloadRule &other) const
{
return m_name == other.name();
}
void RssDownloadRule::setSavePath(const QString &save_path)
void RssDownloadRule::setSavePath(const QString &savePath)
{
if (!save_path.isEmpty() && QDir(save_path) != QDir(Preferences::instance()->getSavePath()))
m_savePath = Utils::Fs::fromNativePath(save_path);
if (!savePath.isEmpty() && (QDir(savePath) != QDir(Preferences::instance()->getSavePath())))
m_savePath = Utils::Fs::fromNativePath(savePath);
else
m_savePath = QString();
}
RssDownloadRule::AddPausedState RssDownloadRule::addPaused() const
{
return m_apstate;
}
void RssDownloadRule::setAddPaused(const RssDownloadRule::AddPausedState &aps)
{
m_apstate = aps;
}
QString RssDownloadRule::label() const
{
return m_label;
}
void RssDownloadRule::setLabel(const QString &label)
{
m_label = label;
}
bool RssDownloadRule::isEnabled() const
{
return m_enabled;
}
void RssDownloadRule::setEnabled(bool enable)
{
m_enabled = enable;
}
void RssDownloadRule::setLastMatch(const QDateTime &d)
{
m_lastMatch = d;
}
QDateTime RssDownloadRule::lastMatch() const
{
return m_lastMatch;
}
void RssDownloadRule::setIgnoreDays(int d)
{
m_ignoreDays = d;
}
int RssDownloadRule::ignoreDays() const
{
return m_ignoreDays;
}
QString RssDownloadRule::mustContain() const
{
return m_mustContain.join(" ");
}
QString RssDownloadRule::mustNotContain() const
{
return m_mustNotContain.join("|");
}
bool RssDownloadRule::useRegex() const
{
return m_useRegex;
}
void RssDownloadRule::setUseRegex(bool enabled)
{
m_useRegex = enabled;
}
QString RssDownloadRule::episodeFilter() const
{
return m_episodeFilter;
}
void RssDownloadRule::setEpisodeFilter(const QString &e)
{
m_episodeFilter = e;
}
QStringList RssDownloadRule::findMatchingArticles(const RssFeedPtr &feed) const
{
QStringList ret;
const RssArticleHash& feed_articles = feed->articleHash();
const RssArticleHash &feedArticles = feed->articleHash();
RssArticleHash::ConstIterator artIt = feed_articles.begin();
RssArticleHash::ConstIterator artItend = feed_articles.end();
RssArticleHash::ConstIterator artIt = feedArticles.begin();
RssArticleHash::ConstIterator artItend = feedArticles.end();
for ( ; artIt != artItend ; ++artIt) {
const QString title = artIt.value()->title();
if (matches(title))

57
src/base/rss/rssdownloadrule.h

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@ -44,42 +44,43 @@ typedef QSharedPointer<RssDownloadRule> RssDownloadRulePtr; @@ -44,42 +44,43 @@ typedef QSharedPointer<RssDownloadRule> RssDownloadRulePtr;
class RssDownloadRule
{
public:
enum AddPausedState {
enum AddPausedState
{
USE_GLOBAL = 0,
ALWAYS_PAUSED,
NEVER_PAUSED
};
explicit RssDownloadRule();
static RssDownloadRulePtr fromVariantHash(const QVariantHash &rule_hash);
RssDownloadRule();
static RssDownloadRulePtr fromVariantHash(const QVariantHash &ruleHash);
QVariantHash toVariantHash() const;
bool matches(const QString &article_title) const;
bool matches(const QString &articleTitle) const;
void setMustContain(const QString &tokens);
void setMustNotContain(const QString &tokens);
inline QStringList rssFeeds() const { return m_rssFeeds; }
inline void setRssFeeds(const QStringList& rss_feeds) { m_rssFeeds = rss_feeds; }
inline QString name() const { return m_name; }
inline void setName(const QString &name) { m_name = name; }
inline QString savePath() const { return m_savePath; }
void setSavePath(const QString &save_path);
inline AddPausedState addPaused() const { return m_apstate; }
inline void setAddPaused(const AddPausedState &aps) { m_apstate = aps; }
inline QString label() const { return m_label; }
inline void setLabel(const QString &_label) { m_label = _label; }
inline bool isEnabled() const { return m_enabled; }
inline void setEnabled(bool enable) { m_enabled = enable; }
inline void setLastMatch(const QDateTime& d) { m_lastMatch = d; }
inline QDateTime lastMatch() const { return m_lastMatch; }
inline void setIgnoreDays(int d) { m_ignoreDays = d; }
inline int ignoreDays() const { return m_ignoreDays; }
inline QString mustContain() const { return m_mustContain.join(" "); }
inline QString mustNotContain() const { return m_mustNotContain.join("|"); }
inline bool useRegex() const { return m_useRegex; }
inline void setUseRegex(bool enabled) { m_useRegex = enabled; }
inline QString episodeFilter() const { return m_episodeFilter; }
inline void setEpisodeFilter(const QString& e) { m_episodeFilter = e; }
QStringList rssFeeds() const;
void setRssFeeds(const QStringList &rssFeeds);
QString name() const;
void setName(const QString &name);
QString savePath() const;
void setSavePath(const QString &savePath);
AddPausedState addPaused() const;
void setAddPaused(const AddPausedState &aps);
QString label() const;
void setLabel(const QString &label);
bool isEnabled() const;
void setEnabled(bool enable);
void setLastMatch(const QDateTime &d);
QDateTime lastMatch() const;
void setIgnoreDays(int d);
int ignoreDays() const;
QString mustContain() const;
QString mustNotContain() const;
bool useRegex() const;
void setUseRegex(bool enabled);
QString episodeFilter() const;
void setEpisodeFilter(const QString &e);
QStringList findMatchingArticles(const RssFeedPtr &feed) const;
// Operators
bool operator==(const RssDownloadRule &other) const;

51
src/base/rss/rssdownloadrulelist.cpp

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@ -41,18 +41,19 @@ RssDownloadRuleList::RssDownloadRuleList() @@ -41,18 +41,19 @@ RssDownloadRuleList::RssDownloadRuleList()
loadRulesFromStorage();
}
RssDownloadRulePtr RssDownloadRuleList::findMatchingRule(const QString &feed_url, const QString &article_title) const
RssDownloadRulePtr RssDownloadRuleList::findMatchingRule(const QString &feedUrl, const QString &articleTitle) const
{
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
QStringList rule_names = m_feedRules.value(feed_url);
foreach (const QString &rule_name, rule_names) {
QStringList ruleNames = m_feedRules.value(feedUrl);
foreach (const QString &rule_name, ruleNames) {
RssDownloadRulePtr rule = m_rules[rule_name];
if (rule->isEnabled() && rule->matches(article_title)) return rule;
if (rule->isEnabled() && rule->matches(articleTitle)) return rule;
}
return RssDownloadRulePtr();
}
void RssDownloadRuleList::replace(RssDownloadRuleList *other) {
void RssDownloadRuleList::replace(RssDownloadRuleList *other)
{
m_rules.clear();
m_feedRules.clear();
foreach (const QString &name, other->ruleNames()) {
@ -102,8 +103,8 @@ void RssDownloadRuleList::saveRule(const RssDownloadRulePtr &rule) @@ -102,8 +103,8 @@ void RssDownloadRuleList::saveRule(const RssDownloadRulePtr &rule)
}
m_rules.insert(rule->name(), rule);
// Update feedRules hashtable
foreach (const QString &feed_url, rule->rssFeeds()) {
m_feedRules[feed_url].append(rule->name());
foreach (const QString &feedUrl, rule->rssFeeds()) {
m_feedRules[feedUrl].append(rule->name());
}
qDebug() << Q_FUNC_INFO << "EXIT";
}
@ -114,20 +115,21 @@ void RssDownloadRuleList::removeRule(const QString &name) @@ -114,20 +115,21 @@ void RssDownloadRuleList::removeRule(const QString &name)
if (!m_rules.contains(name)) return;
RssDownloadRulePtr rule = m_rules.take(name);
// Update feedRules hashtable
foreach (const QString &feed_url, rule->rssFeeds()) {
m_feedRules[feed_url].removeOne(rule->name());
foreach (const QString &feedUrl, rule->rssFeeds()) {
m_feedRules[feedUrl].removeOne(rule->name());
}
}
void RssDownloadRuleList::renameRule(const QString &old_name, const QString &new_name)
void RssDownloadRuleList::renameRule(const QString &oldName, const QString &newName)
{
if (!m_rules.contains(old_name)) return;
RssDownloadRulePtr rule = m_rules.take(old_name);
rule->setName(new_name);
m_rules.insert(new_name, rule);
if (!m_rules.contains(oldName)) return;
RssDownloadRulePtr rule = m_rules.take(oldName);
rule->setName(newName);
m_rules.insert(newName, rule);
// Update feedRules hashtable
foreach (const QString &feed_url, rule->rssFeeds()) {
m_feedRules[feed_url].replace(m_feedRules[feed_url].indexOf(old_name), new_name);
foreach (const QString &feedUrl, rule->rssFeeds()) {
m_feedRules[feedUrl].replace(m_feedRules[feedUrl].indexOf(oldName), newName);
}
}
@ -136,6 +138,16 @@ RssDownloadRulePtr RssDownloadRuleList::getRule(const QString &name) const @@ -136,6 +138,16 @@ RssDownloadRulePtr RssDownloadRuleList::getRule(const QString &name) const
return m_rules.value(name);
}
QStringList RssDownloadRuleList::ruleNames() const
{
return m_rules.keys();
}
bool RssDownloadRuleList::isEmpty() const
{
return m_rules.isEmpty();
}
bool RssDownloadRuleList::serialize(const QString &path)
{
QFile f(path);
@ -145,9 +157,9 @@ bool RssDownloadRuleList::serialize(const QString& path) @@ -145,9 +157,9 @@ bool RssDownloadRuleList::serialize(const QString& path)
out << toVariantHash();
f.close();
return true;
} else {
return false;
}
return false;
}
bool RssDownloadRuleList::unserialize(const QString &path)
@ -169,4 +181,3 @@ bool RssDownloadRuleList::unserialize(const QString &path) @@ -169,4 +181,3 @@ bool RssDownloadRuleList::unserialize(const QString &path)
return false;
}
}

13
src/base/rss/rssdownloadrulelist.h

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
#include <QList>
#include <QHash>
#include <QVariantHash>
#include "rssdownloadrule.h"
class RssDownloadRuleList
@ -42,14 +43,15 @@ class RssDownloadRuleList @@ -42,14 +43,15 @@ class RssDownloadRuleList
public:
RssDownloadRuleList();
RssDownloadRulePtr findMatchingRule(const QString &feed_url, const QString &article_title) const;
RssDownloadRulePtr findMatchingRule(const QString &feedUrl, const QString &articleTitle) const;
// Operators
void saveRule(const RssDownloadRulePtr &rule);
void removeRule(const QString &name);
void renameRule(const QString &old_name, const QString &new_name);
void renameRule(const QString &oldName, const QString &newName);
RssDownloadRulePtr getRule(const QString &name) const;
inline QStringList ruleNames() const { return m_rules.keys(); }
inline bool isEmpty() const { return m_rules.isEmpty(); }
QStringList ruleNames() const;
bool isEmpty() const;
void saveRulesToStorage();
bool serialize(const QString &path);
bool unserialize(const QString &path);
@ -63,7 +65,6 @@ private: @@ -63,7 +65,6 @@ private:
private:
QHash<QString, RssDownloadRulePtr> m_rules;
QHash<QString, QStringList> m_feedRules;
};
#endif // RSSDOWNLOADFILTERLIST_H

178
src/base/rss/rssfeed.cpp

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -30,15 +31,15 @@ @@ -30,15 +31,15 @@
#include <QDebug>
#include "base/bittorrent/session.h"
#include "base/bittorrent/magneturi.h"
#include "base/preferences.h"
#include "base/qinisettings.h"
#include "base/logger.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/magneturi.h"
#include "base/utils/misc.h"
#include "base/utils/fs.h"
#include "base/net/downloadmanager.h"
#include "base/net/downloadhandler.h"
#include "base/utils/fs.h"
#include "base/logger.h"
#include "rssdownloadrulelist.h"
#include "rssarticle.h"
#include "rssparser.h"
@ -51,15 +52,15 @@ bool rssArticleDateRecentThan(const RssArticlePtr& left, const RssArticlePtr& ri @@ -51,15 +52,15 @@ bool rssArticleDateRecentThan(const RssArticlePtr& left, const RssArticlePtr& ri
return left->date() > right->date();
}
RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString& url):
m_manager(manager),
m_parent(parent),
m_url (QUrl::fromEncoded(url.toUtf8()).toString()),
m_icon(":/icons/oxygen/application-rss+xml.png"),
m_unreadCount(0),
m_dirty(false),
m_inErrorState(false),
m_loading(false)
RssFeed::RssFeed(RssManager *manager, RssFolder *parent, const QString &url)
: m_manager(manager)
, m_parent(parent)
, m_url (QUrl::fromEncoded(url.toUtf8()).toString())
, m_icon(":/icons/oxygen/application-rss+xml.png")
, m_unreadCount(0)
, m_dirty(false)
, m_inErrorState(false)
, m_loading(false)
{
qDebug() << Q_FUNC_INFO << m_url;
// Listen for new RSS downloads
@ -83,44 +84,55 @@ RssFeed::~RssFeed() @@ -83,44 +84,55 @@ RssFeed::~RssFeed()
Utils::Fs::forceRemove(m_icon);
}
RssFolder *RssFeed::parent() const
{
return m_parent;
}
void RssFeed::setParent(RssFolder *parent)
{
m_parent = parent;
}
void RssFeed::saveItemsToDisk()
{
qDebug() << Q_FUNC_INFO << m_url;
if (!m_dirty)
return;
if (!m_dirty) return;
markAsDirty(false);
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QVariantList old_items;
QVariantList oldItems;
RssArticleHash::ConstIterator it = m_articles.begin();
RssArticleHash::ConstIterator itend = m_articles.end();
for ( ; it != itend; ++it) {
old_items << it.value()->toHash();
oldItems << it.value()->toHash();
}
qDebug("Saving %d old items for feed %s", old_items.size(), qPrintable(displayName()));
QHash<QString, QVariant> all_old_items = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
all_old_items[m_url] = old_items;
qBTRSS.setValue("old_items", all_old_items);
qDebug("Saving %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
QHash<QString, QVariant> allOldItems = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
allOldItems[m_url] = oldItems;
qBTRSS.setValue("old_items", allOldItems);
}
void RssFeed::loadItemsFromDisk()
{
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> all_old_items = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
const QVariantList old_items = all_old_items.value(m_url, QVariantList()).toList();
qDebug("Loading %d old items for feed %s", old_items.size(), qPrintable(displayName()));
QHash<QString, QVariant> allOldItems = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
const QVariantList oldItems = allOldItems.value(m_url, QVariantList()).toList();
qDebug("Loading %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
foreach (const QVariant& var_it, old_items) {
foreach (const QVariant &var_it, oldItems) {
QVariantHash item = var_it.toHash();
RssArticlePtr rss_item = hashToRssArticle(this, item);
if (rss_item)
addArticle(rss_item);
RssArticlePtr rssItem = RssArticle::fromHash(this, item);
if (rssItem)
addArticle(rssItem);
}
}
void RssFeed::addArticle(const RssArticlePtr& article) {
int max_articles = Preferences::instance()->getRSSMaxArticlesPerFeed();
void RssFeed::addArticle(const RssArticlePtr &article)
{
int maxArticles = Preferences::instance()->getRSSMaxArticlesPerFeed();
if (!m_articles.contains(article->guid())) {
markAsDirty();
@ -134,7 +146,7 @@ void RssFeed::addArticle(const RssArticlePtr& article) { @@ -134,7 +146,7 @@ void RssFeed::addArticle(const RssArticlePtr& article) {
RssArticleList::Iterator lowerBound = qLowerBound(m_articlesByDate.begin(), m_articlesByDate.end(), article, rssArticleDateRecentThan);
m_articlesByDate.insert(lowerBound, article);
int lbIndex = m_articlesByDate.indexOf(article);
if (m_articlesByDate.size() > max_articles) {
if (m_articlesByDate.size() > maxArticles) {
RssArticlePtr oldestArticle = m_articlesByDate.takeLast();
m_articles.remove(oldestArticle->guid());
// Update unreadCount
@ -144,7 +156,7 @@ void RssFeed::addArticle(const RssArticlePtr& article) { @@ -144,7 +156,7 @@ void RssFeed::addArticle(const RssArticlePtr& article) {
// Check if article was inserted at the end of the list and will break max_articles limit
if (Preferences::instance()->isRssDownloadingEnabled()) {
if (lbIndex < max_articles && !article->isRead())
if ((lbIndex < maxArticles) && !article->isRead())
downloadArticleTorrentIfMatching(m_manager->downloadRules(), article);
}
}
@ -176,24 +188,29 @@ bool RssFeed::refresh() @@ -176,24 +188,29 @@ bool RssFeed::refresh()
return true;
}
QString RssFeed::id() const
{
return m_url;
}
void RssFeed::removeAllSettings()
{
qDebug() << "Removing all settings / history for feed: " << m_url;
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QVariantHash feeds_w_downloader = qBTRSS.value("downloader_on", QVariantHash()).toHash();
if (feeds_w_downloader.contains(m_url)) {
feeds_w_downloader.remove(m_url);
qBTRSS.setValue("downloader_on", feeds_w_downloader);
QVariantHash feedsWDownloader = qBTRSS.value("downloader_on", QVariantHash()).toHash();
if (feedsWDownloader.contains(m_url)) {
feedsWDownloader.remove(m_url);
qBTRSS.setValue("downloader_on", feedsWDownloader);
}
QVariantHash all_feeds_filters = qBTRSS.value("feed_filters", QVariantHash()).toHash();
if (all_feeds_filters.contains(m_url)) {
all_feeds_filters.remove(m_url);
qBTRSS.setValue("feed_filters", all_feeds_filters);
QVariantHash allFeedsFilters = qBTRSS.value("feed_filters", QVariantHash()).toHash();
if (allFeedsFilters.contains(m_url)) {
allFeedsFilters.remove(m_url);
qBTRSS.setValue("feed_filters", allFeedsFilters);
}
QVariantHash all_old_items = qBTRSS.value("old_items", QVariantHash()).toHash();
if (all_old_items.contains(m_url)) {
all_old_items.remove(m_url);
qBTRSS.setValue("old_items", all_old_items);
QVariantHash allOldItems = qBTRSS.value("old_items", QVariantHash()).toHash();
if (allOldItems.contains(m_url)) {
allOldItems.remove(m_url);
qBTRSS.setValue("old_items", allOldItems);
}
}
@ -207,10 +224,10 @@ QString RssFeed::title() const @@ -207,10 +224,10 @@ QString RssFeed::title() const
return m_title;
}
void RssFeed::rename(const QString &new_name)
void RssFeed::rename(const QString &newName)
{
qDebug() << "Renaming stream to" << new_name;
m_alias = new_name;
qDebug() << "Renaming stream to" << newName;
m_alias = newName;
}
// Return the alias if the stream has one, the url if it has no alias
@ -243,9 +260,7 @@ bool RssFeed::hasCustomIcon() const @@ -243,9 +260,7 @@ bool RssFeed::hasCustomIcon() const
void RssFeed::setIconPath(const QString &path)
{
if (path.isEmpty() || !QFile::exists(path))
return;
if (!path.isEmpty() && QFile::exists(path))
m_icon = path;
}
@ -285,17 +300,22 @@ RssArticleList RssFeed::articleListByDateDesc() const @@ -285,17 +300,22 @@ RssArticleList RssFeed::articleListByDateDesc() const
return m_articlesByDate;
}
const RssArticleHash &RssFeed::articleHash() const
{
return m_articles;
}
RssArticleList RssFeed::unreadArticleListByDateDesc() const
{
RssArticleList unread_news;
RssArticleList unreadNews;
RssArticleList::ConstIterator it = m_articlesByDate.begin();
RssArticleList::ConstIterator itend = m_articlesByDate.end();
for ( ; it != itend; ++it) {
if (!(*it)->isRead())
unread_news << *it;
unreadNews << *it;
}
return unread_news;
return unreadNews;
}
// download the icon from the address
@ -312,7 +332,8 @@ void RssFeed::handleFinishedDownload(const QString &url, const QString &filePath @@ -312,7 +332,8 @@ void RssFeed::handleFinishedDownload(const QString &url, const QString &filePath
qDebug() << Q_FUNC_INFO << "Successfully downloaded RSS feed at" << url;
// Parse the download RSS
m_manager->rssParser()->parseRssFile(m_url, filePath);
} else if (url == m_iconUrl) {
}
else if (url == m_iconUrl) {
m_icon = filePath;
qDebug() << Q_FUNC_INFO << "icon path:" << m_icon;
m_manager->forwardFeedIconChanged(m_url, m_icon);
@ -332,11 +353,8 @@ void RssFeed::handleDownloadFailure(const QString &url, const QString &error) @@ -332,11 +353,8 @@ void RssFeed::handleDownloadFailure(const QString &url, const QString &error)
void RssFeed::handleFeedTitle(const QString &feedUrl, const QString &title)
{
if (feedUrl != m_url)
return;
if (m_title == title)
return;
if (feedUrl != m_url) return;
if (m_title == title) return;
m_title = title;
@ -348,45 +366,45 @@ void RssFeed::handleFeedTitle(const QString& feedUrl, const QString& title) @@ -348,45 +366,45 @@ void RssFeed::handleFeedTitle(const QString& feedUrl, const QString& title)
void RssFeed::downloadArticleTorrentIfMatching(RssDownloadRuleList *rules, const RssArticlePtr &article)
{
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
RssDownloadRulePtr matching_rule = rules->findMatchingRule(m_url, article->title());
if (!matching_rule)
return;
RssDownloadRulePtr matchingRule = rules->findMatchingRule(m_url, article->title());
if (!matchingRule) return;
if (matching_rule->ignoreDays() > 0) {
QDateTime lastMatch = matching_rule->lastMatch();
if (matchingRule->ignoreDays() > 0) {
QDateTime lastMatch = matchingRule->lastMatch();
if (lastMatch.isValid()) {
if (QDateTime::currentDateTime() < lastMatch.addDays(matching_rule->ignoreDays())) {
if (QDateTime::currentDateTime() < lastMatch.addDays(matchingRule->ignoreDays())) {
connect(article.data(), SIGNAL(articleWasRead()), SLOT(handleArticleStateChanged()), Qt::UniqueConnection);
article->markAsRead();
return;
}
}
}
matching_rule->setLastMatch(QDateTime::currentDateTime());
matchingRule->setLastMatch(QDateTime::currentDateTime());
rules->saveRulesToStorage();
// Download the torrent
const QString& torrent_url = article->torrentUrl();
if (torrent_url.isEmpty()) {
const QString &torrentUrl = article->torrentUrl();
if (torrentUrl.isEmpty()) {
Logger::instance()->addMessage(tr("Automatic download of '%1' from '%2' RSS feed failed because it doesn't contain a torrent or a magnet link...").arg(article->title()).arg(displayName()), Log::WARNING);
article->markAsRead();
return;
}
Logger::instance()->addMessage(tr("Automatically downloading '%1' torrent from '%2' RSS feed...").arg(article->title()).arg(displayName()));
connect(article.data(), SIGNAL(articleWasRead()), SLOT(handleArticleStateChanged()), Qt::UniqueConnection);
connect(BitTorrent::Session::instance(), SIGNAL(downloadFromUrlFinished(QString)), article.data(), SLOT(handleTorrentDownloadSuccess(const QString &)), Qt::UniqueConnection);
if (BitTorrent::MagnetUri(torrent_url).isValid())
article->markAsRead();
else
connect(BitTorrent::Session::instance(), SIGNAL(downloadFromUrlFinished(QString)), article.data(), SLOT(handleTorrentDownloadSuccess(const QString&)), Qt::UniqueConnection);
BitTorrent::AddTorrentParams params;
params.savePath = matching_rule->savePath();
params.label = matching_rule->label();
if (matching_rule->addPaused() == RssDownloadRule::ALWAYS_PAUSED)
params.savePath = matchingRule->savePath();
params.label = matchingRule->label();
if (matchingRule->addPaused() == RssDownloadRule::ALWAYS_PAUSED)
params.addPaused = TriStateBool::True;
else if (matching_rule->addPaused() == RssDownloadRule::NEVER_PAUSED)
else if (matchingRule->addPaused() == RssDownloadRule::NEVER_PAUSED)
params.addPaused = TriStateBool::False;
BitTorrent::Session::instance()->addTorrent(torrent_url, params);
BitTorrent::Session::instance()->addTorrent(torrentUrl, params);
}
void RssFeed::recheckRssItemsForDownload()
@ -401,10 +419,9 @@ void RssFeed::recheckRssItemsForDownload() @@ -401,10 +419,9 @@ void RssFeed::recheckRssItemsForDownload()
void RssFeed::handleNewArticle(const QString &feedUrl, const QVariantHash &articleData)
{
if (feedUrl != m_url)
return;
if (feedUrl != m_url) return;
RssArticlePtr article = hashToRssArticle(this, articleData);
RssArticlePtr article = RssArticle::fromHash(this, articleData);
if (article.isNull()) {
qDebug() << "Article hash corrupted or guid is uncomputable; feed url: " << feedUrl;
return;
@ -420,8 +437,7 @@ void RssFeed::handleNewArticle(const QString& feedUrl, const QVariantHash& artic @@ -420,8 +437,7 @@ void RssFeed::handleNewArticle(const QString& feedUrl, const QVariantHash& artic
void RssFeed::handleFeedParsingFinished(const QString &feedUrl, const QString &error)
{
if (feedUrl != m_url)
return;
if (feedUrl != m_url) return;
if (!error.isEmpty()) {
qWarning() << "Failed to parse RSS feed at" << feedUrl;

42
src/base/rss/rssfeed.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -39,6 +40,7 @@ @@ -39,6 +40,7 @@
#include "rssfile.h"
class RssFolder;
class RssFeed;
class RssManager;
class RssDownloadRuleList;
@ -49,34 +51,36 @@ typedef QList<RssFeedPtr> RssFeedList; @@ -49,34 +51,36 @@ 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
public:
RssFeed(RssManager* manager, RssFolder* m_parent, const QString& url);
virtual ~RssFeed();
virtual RssFolder* parent() const { return m_parent; }
virtual void setParent(RssFolder* parent) { m_parent = parent; }
RssFeed(RssManager *manager, RssFolder *parent, const QString &url);
~RssFeed();
RssFolder *parent() const;
void setParent(RssFolder *parent);
bool refresh();
virtual QString id() const { return m_url; }
virtual void removeAllSettings();
virtual void saveItemsToDisk();
QString id() const;
void removeAllSettings();
void saveItemsToDisk();
bool isLoading() const;
QString title() const;
virtual void rename(const QString &alias);
virtual QString displayName() const;
void rename(const QString &newName);
QString displayName() const;
QString url() const;
virtual QString iconPath() const;
QString iconPath() const;
bool hasCustomIcon() const;
void setIconPath(const QString &pathHierarchy);
RssArticlePtr getItem(const QString &guid) const;
uint count() const;
virtual void markAsRead();
void markAsRead();
void markAsDirty(bool dirty = true);
virtual uint unreadCount() const;
virtual RssArticleList articleListByDateDesc() const;
const RssArticleHash& articleHash() const { return m_articles; }
virtual RssArticleList unreadArticleListByDateDesc() const;
uint unreadCount() const;
RssArticleList articleListByDateDesc() const;
const RssArticleHash &articleHash() const;
RssArticleList unreadArticleListByDateDesc() const;
void decrementUnreadCount();
void recheckRssItemsForDownload();
@ -108,8 +112,6 @@ private: @@ -108,8 +112,6 @@ private:
bool m_dirty;
bool m_inErrorState;
bool m_loading;
};
#endif // RSSFEED_H

10
src/base/rss/rssfile.cpp

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -31,7 +32,10 @@ @@ -31,7 +32,10 @@
#include "rssfolder.h"
#include "rssfile.h"
QStringList RssFile::pathHierarchy() const {
RssFile::~RssFile() {}
QStringList RssFile::pathHierarchy() const
{
QStringList path;
if (parent())
path << parent()->pathHierarchy();

13
src/base/rss/rssfile.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -47,15 +48,16 @@ typedef QList<RssFilePtr> RssFileList; @@ -47,15 +48,16 @@ typedef QList<RssFilePtr> RssFileList;
/**
* Parent interface for RssFolder and RssFeed.
*/
class RssFile {
class RssFile
{
public:
virtual ~RssFile() {}
virtual ~RssFile();
virtual uint unreadCount() const = 0;
virtual QString displayName() const = 0;
virtual QString id() const = 0;
virtual QString iconPath() const = 0;
virtual void rename(const QString &new_name) = 0;
virtual void rename(const QString &newName) = 0;
virtual void markAsRead() = 0;
virtual RssFolder *parent() const = 0;
virtual void setParent(RssFolder *parent) = 0;
@ -65,6 +67,7 @@ public: @@ -65,6 +67,7 @@ public:
virtual void removeAllSettings() = 0;
virtual void saveItemsToDisk() = 0;
virtual void recheckRssItemsForDownload() = 0;
QStringList pathHierarchy() const;
protected:

137
src/base/rss/rssfolder.cpp

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -37,42 +38,59 @@ @@ -37,42 +38,59 @@
#include "rssarticle.h"
#include "rssfolder.h"
RssFolder::RssFolder(RssFolder *parent, const QString &name): m_parent(parent), m_name(name) {
RssFolder::RssFolder(RssFolder *parent, const QString &name)
: m_parent(parent)
, m_name(name)
{
}
RssFolder::~RssFolder() {}
RssFolder *RssFolder::parent() const
{
return m_parent;
}
RssFolder::~RssFolder() {
void RssFolder::setParent(RssFolder *parent)
{
m_parent = parent;
}
unsigned int RssFolder::unreadCount() const {
uint nb_unread = 0;
uint RssFolder::unreadCount() const
{
uint nbUnread = 0;
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) {
nb_unread += it.value()->unreadCount();
}
return nb_unread;
for ( ; it != itend; ++it)
nbUnread += it.value()->unreadCount();
return nbUnread;
}
void RssFolder::removeChild(const QString &childId) {
void RssFolder::removeChild(const QString &childId)
{
if (m_children.contains(childId)) {
RssFilePtr child = m_children.take(childId);
child->removeAllSettings();
}
}
RssFolderPtr RssFolder::addFolder(const QString &name) {
RssFolderPtr RssFolder::addFolder(const QString &name)
{
RssFolderPtr subfolder;
if (!m_children.contains(name)) {
subfolder = RssFolderPtr(new RssFolder(this, name));
m_children[name] = subfolder;
} else {
}
else {
subfolder = qSharedPointerDynamicCast<RssFolder>(m_children.value(name));
}
return subfolder;
}
RssFeedPtr RssFolder::addStream(RssManager* manager, const QString &url) {
RssFeedPtr RssFolder::addStream(RssManager *manager, const QString &url)
{
qDebug() << Q_FUNC_INFO << manager << url;
RssFeedPtr stream(new RssFeed(manager, this, url));
Q_ASSERT(stream);
@ -84,7 +102,8 @@ RssFeedPtr RssFolder::addStream(RssManager* manager, const QString &url) { @@ -84,7 +102,8 @@ RssFeedPtr RssFolder::addStream(RssManager* manager, const QString &url) {
}
// Refresh All Children
bool RssFolder::refresh() {
bool RssFolder::refresh()
{
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
bool refreshed = false;
@ -95,7 +114,8 @@ bool RssFolder::refresh() { @@ -95,7 +114,8 @@ bool RssFolder::refresh() {
return refreshed;
}
RssArticleList RssFolder::articleListByDateDesc() const {
RssArticleList RssFolder::articleListByDateDesc() const
{
RssArticleList news;
RssFileHash::ConstIterator it = m_children.begin();
@ -108,24 +128,27 @@ RssArticleList RssFolder::articleListByDateDesc() const { @@ -108,24 +128,27 @@ RssArticleList RssFolder::articleListByDateDesc() const {
return news;
}
RssArticleList RssFolder::unreadArticleListByDateDesc() const {
RssArticleList unread_news;
RssArticleList RssFolder::unreadArticleListByDateDesc() const
{
RssArticleList unreadNews;
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) {
int n = unread_news.size();
unread_news << it.value()->unreadArticleListByDateDesc();
std::inplace_merge(unread_news.begin(), unread_news.begin() + n, unread_news.end(), rssArticleDateRecentThan);
int n = unreadNews.size();
unreadNews << it.value()->unreadArticleListByDateDesc();
std::inplace_merge(unreadNews.begin(), unreadNews.begin() + n, unreadNews.end(), rssArticleDateRecentThan);
}
return unread_news;
return unreadNews;
}
RssFileList RssFolder::getContent() const {
RssFileList RssFolder::getContent() const
{
return m_children.values();
}
unsigned int RssFolder::getNbFeeds() const {
uint RssFolder::getNbFeeds() const
{
uint nbFeeds = 0;
RssFileHash::ConstIterator it = m_children.begin();
@ -139,22 +162,26 @@ unsigned int RssFolder::getNbFeeds() const { @@ -139,22 +162,26 @@ unsigned int RssFolder::getNbFeeds() const {
return nbFeeds;
}
QString RssFolder::displayName() const {
QString RssFolder::displayName() const
{
return m_name;
}
void RssFolder::rename(const QString &new_name) {
if (m_name == new_name) return;
Q_ASSERT(!m_parent->hasChild(new_name));
if (!m_parent->hasChild(new_name)) {
void RssFolder::rename(const QString &newName)
{
if (m_name == newName) return;
Q_ASSERT(!m_parent->hasChild(newName));
if (!m_parent->hasChild(newName)) {
// Update parent
m_parent->renameChildFolder(m_name, new_name);
m_parent->renameChildFolder(m_name, newName);
// Actually rename
m_name = new_name;
m_name = newName;
}
}
void RssFolder::markAsRead() {
void RssFolder::markAsRead()
{
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) {
@ -162,22 +189,23 @@ void RssFolder::markAsRead() { @@ -162,22 +189,23 @@ void RssFolder::markAsRead() {
}
}
RssFeedList RssFolder::getAllFeeds() const {
RssFeedList RssFolder::getAllFeeds() const
{
RssFeedList streams;
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) {
if (RssFeedPtr feed = qSharedPointerDynamicCast<RssFeed>(it.value())) {
if (RssFeedPtr feed = qSharedPointerDynamicCast<RssFeed>(it.value()))
streams << feed;
} else if (RssFolderPtr folder = qSharedPointerDynamicCast<RssFolder>(it.value())) {
else if (RssFolderPtr folder = qSharedPointerDynamicCast<RssFolder>(it.value()))
streams << folder->getAllFeeds();
}
}
return streams;
}
QHash<QString, RssFeedPtr> RssFolder::getAllFeedsAsHash() const {
QHash<QString, RssFeedPtr> RssFolder::getAllFeedsAsHash() const
{
QHash<QString, RssFeedPtr> ret;
RssFileHash::ConstIterator it = m_children.begin();
@ -186,19 +214,22 @@ QHash<QString, RssFeedPtr> RssFolder::getAllFeedsAsHash() const { @@ -186,19 +214,22 @@ QHash<QString, RssFeedPtr> RssFolder::getAllFeedsAsHash() const {
if (RssFeedPtr feed = qSharedPointerDynamicCast<RssFeed>(it.value())) {
qDebug() << Q_FUNC_INFO << feed->url();
ret[feed->url()] = feed;
} else if (RssFolderPtr folder = qSharedPointerDynamicCast<RssFolder>(it.value())) {
}
else if (RssFolderPtr folder = qSharedPointerDynamicCast<RssFolder>(it.value())) {
ret.unite(folder->getAllFeedsAsHash());
}
}
return ret;
}
void RssFolder::addFile(const RssFilePtr& item) {
void RssFolder::addFile(const RssFilePtr &item)
{
if (RssFeedPtr feed = qSharedPointerDynamicCast<RssFeed>(item)) {
Q_ASSERT(!m_children.contains(feed->url()));
m_children[feed->url()] = item;
qDebug("Added feed %s to folder ./%s", qPrintable(feed->url()), qPrintable(m_name));
} else if (RssFolderPtr folder = qSharedPointerDynamicCast<RssFolder>(item)) {
}
else if (RssFolderPtr folder = qSharedPointerDynamicCast<RssFolder>(item)) {
Q_ASSERT(!m_children.contains(folder->displayName()));
m_children[folder->displayName()] = item;
qDebug("Added folder %s to folder ./%s", qPrintable(folder->displayName()), qPrintable(m_name));
@ -207,24 +238,24 @@ void RssFolder::addFile(const RssFilePtr& item) { @@ -207,24 +238,24 @@ void RssFolder::addFile(const RssFilePtr& item) {
item->setParent(this);
}
void RssFolder::removeAllItems() {
void RssFolder::removeAllItems()
{
m_children.clear();
}
void RssFolder::removeAllSettings() {
void RssFolder::removeAllSettings()
{
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) {
for ( ; it != itend; ++it)
it.value()->removeAllSettings();
}
}
void RssFolder::saveItemsToDisk()
{
foreach (const RssFilePtr& child, m_children.values()) {
foreach (const RssFilePtr &child, m_children.values())
child->saveItemsToDisk();
}
}
QString RssFolder::id() const
{
@ -236,15 +267,16 @@ QString RssFolder::iconPath() const @@ -236,15 +267,16 @@ QString RssFolder::iconPath() const
return IconProvider::instance()->getIconPath("inode-directory");
}
bool RssFolder::hasChild(const QString &childId) {
bool RssFolder::hasChild(const QString &childId)
{
return m_children.contains(childId);
}
void RssFolder::renameChildFolder(const QString &old_name, const QString &new_name)
void RssFolder::renameChildFolder(const QString &oldName, const QString &newName)
{
Q_ASSERT(m_children.contains(old_name));
RssFilePtr folder = m_children.take(old_name);
m_children[new_name] = folder;
Q_ASSERT(m_children.contains(oldName));
RssFilePtr folder = m_children.take(oldName);
m_children[newName] = folder;
}
RssFilePtr RssFolder::takeChild(const QString &childId)
@ -256,7 +288,6 @@ void RssFolder::recheckRssItemsForDownload() @@ -256,7 +288,6 @@ void RssFolder::recheckRssItemsForDownload()
{
RssFileHash::ConstIterator it = m_children.begin();
RssFileHash::ConstIterator itend = m_children.end();
for ( ; it != itend; ++it) {
for ( ; it != itend; ++it)
it.value()->recheckRssItemsForDownload();
}
}

43
src/base/rss/rssfolder.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -45,40 +46,42 @@ typedef QSharedPointer<RssFeed> RssFeedPtr; @@ -45,40 +46,42 @@ typedef QSharedPointer<RssFeed> RssFeedPtr;
typedef QSharedPointer<RssFolder> RssFolderPtr;
typedef QList<RssFeedPtr> RssFeedList;
class RssFolder: public QObject, public RssFile {
class RssFolder: public QObject, public RssFile
{
Q_OBJECT
public:
RssFolder(RssFolder *parent = 0, const QString &name = QString());
virtual ~RssFolder();
virtual RssFolder* parent() const { return m_parent; }
virtual void setParent(RssFolder* parent) { m_parent = parent; }
virtual unsigned int unreadCount() const;
explicit RssFolder(RssFolder *parent = 0, const QString &name = QString());
~RssFolder();
RssFolder *parent() const;
void setParent(RssFolder *parent);
uint unreadCount() const;
RssFeedPtr addStream(RssManager *manager, const QString &url);
RssFolderPtr addFolder(const QString &name);
unsigned int getNbFeeds() const;
uint getNbFeeds() const;
RssFileList getContent() const;
RssFeedList getAllFeeds() const;
QHash<QString, RssFeedPtr> getAllFeedsAsHash() const;
virtual QString displayName() const;
virtual QString id() const;
virtual QString iconPath() const;
QString displayName() const;
QString id() const;
QString iconPath() const;
bool hasChild(const QString &childId);
virtual RssArticleList articleListByDateDesc() const;
virtual RssArticleList unreadArticleListByDateDesc() const;
virtual void removeAllSettings();
virtual void saveItemsToDisk();
RssArticleList articleListByDateDesc() const;
RssArticleList unreadArticleListByDateDesc() const;
void removeAllSettings();
void saveItemsToDisk();
void removeAllItems();
void renameChildFolder(const QString &old_name, const QString &new_name);
void renameChildFolder(const QString &oldName, const QString &newName);
RssFilePtr takeChild(const QString &childId);
void recheckRssItemsForDownload();
public slots:
virtual bool refresh();
bool refresh();
void addFile(const RssFilePtr &item);
void removeChild(const QString &childId);
virtual void rename(const QString &new_name);
virtual void markAsRead();
void rename(const QString &newName);
void markAsRead();
private:
RssFolder *m_parent;

53
src/base/rss/rssmanager.cpp

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -30,8 +31,8 @@ @@ -30,8 +31,8 @@
#include <QDebug>
#include "base/logger.h"
#include "base/preferences.h"
#include "base/bittorrent/session.h"
#include "rssfeed.h"
#include "rssarticle.h"
#include "rssdownloadrulelist.h"
@ -40,9 +41,9 @@ @@ -40,9 +41,9 @@
static const int MSECS_PER_MIN = 60000;
RssManager::RssManager():
m_downloadRules(new RssDownloadRuleList),
m_rssParser(new RssParser(this))
RssManager::RssManager()
: m_downloadRules(new RssDownloadRuleList)
, m_rssParser(new RssParser(this))
{
connect(&m_refreshTimer, SIGNAL(timeout()), SLOT(refresh()));
m_refreshInterval = Preferences::instance()->getRSSRefreshInterval();
@ -79,29 +80,30 @@ void RssManager::loadStreamList() @@ -79,29 +80,30 @@ void RssManager::loadStreamList()
const QStringList streamsUrl = pref->getRssFeedsUrls();
const QStringList aliases = pref->getRssFeedsAliases();
if (streamsUrl.size() != aliases.size()) {
std::cerr << "Corrupted Rss list, not loading it\n";
Logger::instance()->addMessage("Corrupted RSS list, not loading it.", Log::WARNING);
return;
}
uint i = 0;
qDebug() << Q_FUNC_INFO << streamsUrl;
foreach (QString s, streamsUrl) {
QStringList path = s.split("\\", QString::SkipEmptyParts);
if (path.empty()) continue;
const QString feed_url = path.takeLast();
qDebug() << "Feed URL:" << feed_url;
const QString feedUrl = path.takeLast();
qDebug() << "Feed URL:" << feedUrl;
// Create feed path (if it does not exists)
RssFolder* feed_parent = this;
foreach (const QString &folder_name, path) {
qDebug() << "Adding parent folder:" << folder_name;
feed_parent = feed_parent->addFolder(folder_name).data();
RssFolder *feedParent = this;
foreach (const QString &folderName, path) {
qDebug() << "Adding parent folder:" << folderName;
feedParent = feedParent->addFolder(folderName).data();
}
// Create feed
qDebug() << "Adding feed to parent folder";
RssFeedPtr stream = feed_parent->addStream(this, feed_url);
RssFeedPtr stream = feedParent->addStream(this, feedUrl);
const QString &alias = aliases[i];
if (!alias.isEmpty()) {
if (!alias.isEmpty())
stream->rename(alias);
}
++i;
}
qDebug("NB RSS streams loaded: %d", streamsUrl.size());
@ -124,13 +126,14 @@ void RssManager::forwardFeedIconChanged(const QString& url, const QString& iconP @@ -124,13 +126,14 @@ void RssManager::forwardFeedIconChanged(const QString& url, const QString& iconP
void RssManager::moveFile(const RssFilePtr &file, const RssFolderPtr &destinationFolder)
{
RssFolder* src_folder = file->parent();
if (destinationFolder != src_folder) {
RssFolder *srcFolder = file->parent();
if (destinationFolder != srcFolder) {
// Remove reference in old folder
src_folder->takeChild(file->id());
srcFolder->takeChild(file->id());
// add to new Folder
destinationFolder->addFile(file);
} else {
}
else {
qDebug("Nothing to move, same destination folder");
}
}
@ -142,11 +145,11 @@ void RssManager::saveStreamList() const @@ -142,11 +145,11 @@ void RssManager::saveStreamList() const
RssFeedList streams = getAllFeeds();
foreach (const RssFeedPtr &stream, streams) {
// This backslash has nothing to do with path handling
QString stream_path = stream->pathHierarchy().join("\\");
if (stream_path.isNull())
stream_path = "";
qDebug("Saving stream path: %s", qPrintable(stream_path));
streamsUrl << stream_path;
QString streamPath = stream->pathHierarchy().join("\\");
if (streamPath.isNull())
streamPath = "";
qDebug("Saving stream path: %s", qPrintable(streamPath));
streamsUrl << streamPath;
aliases << stream->displayName();
}
Preferences *const pref = Preferences::instance();

12
src/base/rss/rssmanager.h

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -38,16 +39,17 @@ @@ -38,16 +39,17 @@
class RssDownloadRuleList;
class RssParser;
class RssManager;
typedef QSharedPointer<RssManager> RssManagerPtr;
class RssManager: public RssFolder {
class RssManager: public RssFolder
{
Q_OBJECT
public:
RssManager();
virtual ~RssManager();
~RssManager();
RssParser *rssParser() const;
RssDownloadRuleList *downloadRules() const;

120
src/base/rss/rssparser.cpp

@ -37,7 +37,8 @@ @@ -37,7 +37,8 @@
#include "base/utils/fs.h"
#include "rssparser.h"
struct ParsingJob {
struct ParsingJob
{
QString feedUrl;
QString filePath;
};
@ -47,19 +48,22 @@ static const char shortDay[][4] = { @@ -47,19 +48,22 @@ static const char shortDay[][4] = {
"Thu", "Fri", "Sat",
"Sun"
};
static const char longDay[][10] = {
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
"Sunday"
};
static const char shortMonth[][4] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
// Ported to Qt4 from KDElibs4
QDateTime RssParser::parseDate(const QString &string) {
// Ported to Qt from KDElibs4
QDateTime RssParser::parseDate(const QString &string)
{
const QString str = string.trimmed();
if (str.isEmpty())
return QDateTime::currentDateTime();
@ -81,7 +85,8 @@ QDateTime RssParser::parseDate(const QString &string) { @@ -81,7 +85,8 @@ QDateTime RssParser::parseDate(const QString &string) {
bool h2 = (parts[5] == QLatin1String("-"));
if (h1 != h2)
return QDateTime::currentDateTime();
} else {
}
else {
// Check for the obsolete form "Wdy Mon DD HH:MM:SS YYYY"
rx = QRegExp("^([A-Z][a-z]+)\\s+(\\S+)\\s+(\\d\\d)\\s+(\\d\\d):(\\d\\d):(\\d\\d)\\s+(\\d\\d\\d\\d)$");
if (str.indexOf(rx))
@ -95,6 +100,7 @@ QDateTime RssParser::parseDate(const QString &string) { @@ -95,6 +100,7 @@ QDateTime RssParser::parseDate(const QString &string) {
nsec = 6;
parts = rx.capturedTexts();
}
bool ok[4];
const int day = parts[nday].toInt(&ok[0]);
int year = parts[nyear].toInt(&ok[1]);
@ -102,24 +108,27 @@ QDateTime RssParser::parseDate(const QString &string) { @@ -102,24 +108,27 @@ QDateTime RssParser::parseDate(const QString &string) {
const int minute = parts[nmin].toInt(&ok[3]);
if (!ok[0] || !ok[1] || !ok[2] || !ok[3])
return QDateTime::currentDateTime();
int second = 0;
if (!parts[nsec].isEmpty()) {
second = parts[nsec].toInt(&ok[0]);
if (!ok[0])
return QDateTime::currentDateTime();
}
bool leapSecond = (second == 60);
if (leapSecond)
second = 59; // apparently a leap second - validate below, once time zone is known
int month = 0;
for ( ; month < 12 && parts[nmonth] != shortMonth[month]; ++month) ;
for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month);
int dayOfWeek = -1;
if (!parts[nwday].isEmpty()) {
// Look up the weekday name
while (++dayOfWeek < 7 && shortDay[dayOfWeek] != parts[nwday]) ;
while (++dayOfWeek < 7 && (shortDay[dayOfWeek] != parts[nwday]));
if (dayOfWeek >= 7)
for (dayOfWeek = 0; dayOfWeek < 7 && longDay[dayOfWeek] != parts[nwday]; ++dayOfWeek) ;
for (dayOfWeek = 0; dayOfWeek < 7 && (longDay[dayOfWeek] != parts[nwday]); ++dayOfWeek);
}
// if (month >= 12 || dayOfWeek >= 7
// || (dayOfWeek < 0 && format == RFCDateDay))
// return QDateTime;
@ -145,22 +154,29 @@ QDateTime RssParser::parseDate(const QString &string) { @@ -145,22 +154,29 @@ QDateTime RssParser::parseDate(const QString &string) {
negOffset = (parts[1] == QLatin1String("-"));
if (negOffset)
offset = -offset;
} else {
}
else {
// Check for an obsolete time zone name
QByteArray zone = parts[10].toLatin1();
if (zone.length() == 1 && isalpha(zone[0]) && toupper(zone[0]) != 'J')
if (zone.length() == 1 && isalpha(zone[0]) && toupper(zone[0]) != 'J') {
negOffset = true; // military zone: RFC 2822 treats as '-0000'
}
else if (zone != "UT" && zone != "GMT") { // treated as '+0000'
offset = (zone == "EDT") ? -4*3600
: (zone == "EST" || zone == "CDT") ? -5*3600
: (zone == "CST" || zone == "MDT") ? -6*3600
: (zone == "MST" || zone == "PDT") ? -7*3600
: (zone == "PST") ? -8*3600
offset = (zone == "EDT")
? -4 * 3600
: ((zone == "EST") || (zone == "CDT"))
? -5 * 3600
: ((zone == "CST") || (zone == "MDT"))
? -6 * 3600
: (zone == "MST" || zone == "PDT")
? -7 * 3600
: (zone == "PST")
? -8 * 3600
: 0;
if (!offset) {
// Check for any other alphabetic time zone
bool nonalpha = false;
for (int i = 0, end = zone.size(); i < end && !nonalpha; ++i)
for (int i = 0, end = zone.size(); (i < end) && !nonalpha; ++i)
nonalpha = !isalpha(zone[i]);
if (nonalpha)
return QDateTime();
@ -170,11 +186,12 @@ QDateTime RssParser::parseDate(const QString &string) { @@ -170,11 +186,12 @@ QDateTime RssParser::parseDate(const QString &string) {
}
}
}
QDate qdate(year, month + 1, day); // convert date, and check for out-of-range
if (!qdate.isValid())
return QDateTime::currentDateTime();
QTime qTime(hour, minute, second);
QTime qTime(hour, minute, second);
QDateTime result(qdate, qTime, Qt::UTC);
if (offset)
result = result.addSecs(-offset);
@ -187,11 +204,13 @@ QDateTime RssParser::parseDate(const QString &string) { @@ -187,11 +204,13 @@ QDateTime RssParser::parseDate(const QString &string) {
if ((hour*3600 + minute*60 + 60 - offset + 86400*5) % 86400) // (max abs(offset) is 100 hours)
return QDateTime::currentDateTime(); // the time isn't the last second of the day
}
return result;
}
RssParser::RssParser(QObject *parent) :
QThread(parent), m_running(true)
RssParser::RssParser(QObject *parent)
: QThread(parent)
, m_running(true)
{
start();
}
@ -232,7 +251,8 @@ void RssParser::run() @@ -232,7 +251,8 @@ void RssParser::run()
ParsingJob job = m_queue.dequeue();
m_mutex.unlock();
parseFeed(job);
} else {
}
else {
qDebug() << Q_FUNC_INFO << "Thread is waiting.";
m_waitCondition.wait(&m_mutex);
qDebug() << Q_FUNC_INFO << "Thread woke up.";
@ -252,8 +272,9 @@ void RssParser::parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl) @@ -252,8 +272,9 @@ void RssParser::parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl)
break;
if (xml.isStartElement()) {
if (xml.name() == "title")
if (xml.name() == "title") {
article["title"] = xml.readElementText().trimmed();
}
else if (xml.name() == "enclosure") {
if (xml.attributes().value("type") == "application/x-bittorrent")
article["torrent_url"] = xml.attributes().value("url").toString();
@ -265,16 +286,20 @@ void RssParser::parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl) @@ -265,16 +286,20 @@ void RssParser::parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl)
else
article["news_link"] = link;
}
else if (xml.name() == "description")
else if (xml.name() == "description") {
article["description"] = xml.readElementText().trimmed();
else if (xml.name() == "pubDate")
}
else if (xml.name() == "pubDate") {
article["date"] = parseDate(xml.readElementText().trimmed());
else if (xml.name() == "author")
}
else if (xml.name() == "author") {
article["author"] = xml.readElementText().trimmed();
else if (xml.name() == "guid")
}
else if (xml.name() == "guid") {
article["id"] = xml.readElementText().trimmed();
}
}
}
if (!article.contains("torrent_url") && article.contains("news_link"))
article["torrent_url"] = article["news_link"];
@ -282,12 +307,14 @@ void RssParser::parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl) @@ -282,12 +307,14 @@ void RssParser::parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl)
if (!article.contains("id")) {
// Item does not have a guid, fall back to some other identifier
const QString link = article.value("news_link").toString();
if (!link.isEmpty())
if (!link.isEmpty()) {
article["id"] = link;
}
else {
const QString title = article.value("title").toString();
if (!title.isEmpty())
if (!title.isEmpty()) {
article["id"] = title;
}
else {
qWarning() << "Item has no guid, link or title, ignoring it...";
return;
@ -332,12 +359,12 @@ void RssParser::parseRSSChannel(QXmlStreamReader& xml, const QString& feedUrl) @@ -332,12 +359,12 @@ void RssParser::parseRSSChannel(QXmlStreamReader& xml, const QString& feedUrl)
void RssParser::parseAtomArticle(QXmlStreamReader &xml, const QString &feedUrl, const QString &baseUrl)
{
QVariantHash article;
bool double_content = false;
bool doubleContent = false;
while(!xml.atEnd()) {
xml.readNext();
if(xml.isEndElement() && xml.name() == "entry")
if(xml.isEndElement() && (xml.name() == "entry"))
break;
if (xml.isStartElement()) {
@ -358,11 +385,11 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl, @@ -358,11 +385,11 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl,
article["news_link"] = ( baseUrl.isEmpty() ? link : baseUrl + link );
}
else if (xml.name() == "summary" || xml.name() == "content"){
if(double_content) { // Duplicate content -> ignore
else if ((xml.name() == "summary") || (xml.name() == "content")){
if (doubleContent) { // Duplicate content -> ignore
xml.readNext();
while(xml.name() != "summary" && xml.name() != "content")
while ((xml.name() != "summary") && (xml.name() != "content"))
xml.readNext();
continue;
@ -374,14 +401,12 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl, @@ -374,14 +401,12 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl,
if (!feedText.isEmpty())
article["description"] = feedText.trimmed();
double_content = true;
doubleContent = true;
}
else if (xml.name() == "updated") {
// ATOM uses standard compliant date, don't do fancy stuff
QDateTime articleDate = QDateTime::fromString(xml.readElementText().trimmed(), Qt::ISODate);
article["date"] = ( articleDate.isValid() ?
articleDate :
QDateTime::currentDateTime() );
article["date"] = (articleDate.isValid() ? articleDate : QDateTime::currentDateTime());
}
else if (xml.name() == "author") {
xml.readNext();
@ -391,10 +416,11 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl, @@ -391,10 +416,11 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl,
xml.readNext();
}
}
else if (xml.name() == "id")
else if (xml.name() == "id") {
article["id"] = xml.readElementText().trimmed();
}
}
}
if (!article.contains("torrent_url") && article.contains("news_link"))
article["torrent_url"] = article["news_link"];
@ -402,12 +428,14 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl, @@ -402,12 +428,14 @@ void RssParser::parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl,
if (!article.contains("id")) {
// Item does not have a guid, fall back to some other identifier
const QString link = article.value("news_link").toString();
if (!link.isEmpty())
if (!link.isEmpty()) {
article["id"] = link;
}
else {
const QString title = article.value("title").toString();
if (!title.isEmpty())
if (!title.isEmpty()) {
article["id"] = title;
}
else {
qWarning() << "Item has no guid, link or title, ignoring it...";
return;
@ -460,18 +488,19 @@ void RssParser::parseFeed(const ParsingJob& job) @@ -460,18 +488,19 @@ void RssParser::parseFeed(const ParsingJob& job)
reportFailure(job, tr("Failed to open downloaded RSS file."));
return;
}
QXmlStreamReader xml(&fileRss);
bool found_channel = false;
QXmlStreamReader xml(&fileRss);
bool foundChannel = false;
while (xml.readNextStartElement()) {
if (xml.name() == "rss") {
// Find channels
while (xml.readNextStartElement()) {
if (xml.name() == "channel") {
parseRSSChannel(xml, job.feedUrl);
found_channel = true;
foundChannel = true;
break;
} else {
}
else {
qDebug() << "Skip rss item: " << xml.name();
xml.skipCurrentElement();
}
@ -480,9 +509,10 @@ void RssParser::parseFeed(const ParsingJob& job) @@ -480,9 +509,10 @@ void RssParser::parseFeed(const ParsingJob& job)
}
else if (xml.name() == "feed") { // Atom feed
parseAtomChannel(xml, job.feedUrl);
found_channel = true;
foundChannel = true;
break;
} else {
}
else {
qDebug() << "Skip root item: " << xml.name();
xml.skipCurrentElement();
}
@ -493,7 +523,7 @@ void RssParser::parseFeed(const ParsingJob& job) @@ -493,7 +523,7 @@ void RssParser::parseFeed(const ParsingJob& job)
return;
}
if (!found_channel) {
if (!foundChannel) {
reportFailure(job, tr("Invalid RSS feed at '%1'.").arg(job.feedUrl));
return;
}

5
src/base/rss/rssparser.h

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2012 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@ -59,6 +59,8 @@ public slots: @@ -59,6 +59,8 @@ public slots:
protected:
virtual void run();
private:
static QDateTime parseDate(const QString &string);
void parseRssArticle(QXmlStreamReader &xml, const QString &feedUrl);
void parseRSSChannel(QXmlStreamReader &xml, const QString &feedUrl);
@ -67,7 +69,6 @@ protected: @@ -67,7 +69,6 @@ protected:
void parseFeed(const ParsingJob &job);
void reportFailure(const ParsingJob &job, const QString &error);
private:
bool m_running;
QMutex m_mutex;
QQueue<ParsingJob> m_queue;

4
src/gui/rss/feedlistwidget.cpp

@ -28,8 +28,8 @@ @@ -28,8 +28,8 @@
* Contact: chris@qbittorrent.org, arnaud@qbittorrent.org
*/
#include "core/rss/rssmanager.h"
#include "core/rss/rssfeed.h"
#include "base/rss/rssmanager.h"
#include "base/rss/rssfeed.h"
#include "guiiconprovider.h"
#include "feedlistwidget.h"

Loading…
Cancel
Save