Browse Source

Fix possible rule saving issue

Matching articles are now previewable in the rss downloader dialog
Make sure Rss downloading is enabled before checking for matching rules
adaptive-webui-19844
Christophe Dumez 14 years ago
parent
commit
c387c15eb0
  1. 9
      src/GUI.cpp
  2. 4
      src/headlessloader.h
  3. 16
      src/qtlibtorrent/qbtsession.cpp
  4. 8
      src/qtlibtorrent/qbtsession.h
  5. 63
      src/rss/automatedrssdownloader.cpp
  6. 2
      src/rss/automatedrssdownloader.h
  7. 11
      src/rss/automatedrssdownloader.ui
  8. 4
      src/rss/rss_imp.cpp
  9. 8
      src/rss/rssarticle.cpp
  10. 4
      src/rss/rssarticle.h
  11. 12
      src/rss/rssdownloadrule.cpp
  12. 3
      src/rss/rssdownloadrule.h
  13. 3
      src/rss/rssdownloadrulelist.cpp
  14. 32
      src/rss/rssfeed.cpp
  15. 19
      src/rss/rssfolder.cpp
  16. 1
      src/rss/rssfolder.h
  17. 17
      src/rss/rssmanager.cpp
  18. 6
      src/rss/rssmanager.h

9
src/GUI.cpp

@ -131,7 +131,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for @@ -131,7 +131,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), for
// Fix Tool bar layout
toolBar->layout()->setSpacing(7);
// Creating Bittorrent session
BTSession = new QBtSession();
BTSession = QBtSession::instance();
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&, QString)), this, SLOT(fullDiskError(QTorrentHandle&, QString)));
connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&)));
connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&)));
@ -277,11 +277,6 @@ GUI::~GUI() { @@ -277,11 +277,6 @@ GUI::~GUI() {
// Workaround to avoid bug http://bugreports.qt.nokia.com/browse/QTBUG-7305
setUnifiedTitleAndToolBarOnMac(false);
#endif
// Async deletion of Bittorrent session as early as possible
// in order to speed up exit
session_proxy sp;
if(BTSession)
sp = BTSession->asyncDeletion();
// Some saving
properties->saveSettings();
disconnect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tab_changed(int)));
@ -328,7 +323,7 @@ GUI::~GUI() { @@ -328,7 +323,7 @@ GUI::~GUI() {
delete switchRSSShortcut;
// Delete BTSession objects
qDebug("Deleting BTSession");
delete BTSession;
QBtSession::drop();
// May freeze for a few seconds after the next line
// because the Bittorrent session proxy will
// actually be deleted now and destruction

4
src/headlessloader.h

@ -44,7 +44,7 @@ public: @@ -44,7 +44,7 @@ public:
// Enable Web UI
Preferences::setWebUiEnabled(true);
// Instanciate Bittorrent Object
BTSession = new QBtSession();
BTSession = QBtSession::instance();
connect(BTSession, SIGNAL(newConsoleMessage(QString)), this, SLOT(displayConsoleMessage(QString)));
// Resume unfinished torrents
BTSession->startUpTorrents();
@ -61,7 +61,7 @@ public: @@ -61,7 +61,7 @@ public:
}
~HeadlessLoader() {
delete BTSession;
QBtSession::drop();
}
public slots:

16
src/qtlibtorrent/qbtsession.cpp

@ -68,6 +68,8 @@ @@ -68,6 +68,8 @@
#include <boost/filesystem/exception.hpp>
#include <queue>
QBtSession* QBtSession::m_instance = 0;
const int MAX_TRACKER_ERRORS = 2;
const float MAX_RATIO = 100.;
enum VersionType { NORMAL,ALPHA,BETA,RELEASE_CANDIDATE,DEVEL };
@ -2628,3 +2630,17 @@ void QBtSession::startUpTorrents() { @@ -2628,3 +2630,17 @@ void QBtSession::startUpTorrents() {
settings.setValue("ported_to_new_savepath_system", true);
qDebug("Unfinished torrents resumed");
}
QBtSession * QBtSession::instance()
{
if(!m_instance) {
m_instance = new QBtSession;
}
return m_instance;
}
void QBtSession::drop()
{
if(m_instance)
delete m_instance;
}

8
src/qtlibtorrent/qbtsession.h

@ -66,9 +66,13 @@ class QBtSession : public QObject { @@ -66,9 +66,13 @@ class QBtSession : public QObject {
Q_OBJECT
Q_DISABLE_COPY(QBtSession)
private:
explicit QBtSession();
static QBtSession* m_instance;
public:
// Constructor / Destructor
QBtSession();
static QBtSession* instance();
static void drop();
~QBtSession();
QTorrentHandle getTorrentHandle(QString hash) const;
std::vector<torrent_handle> getTorrents() const;

63
src/rss/automatedrssdownloader.cpp

@ -41,6 +41,8 @@ @@ -41,6 +41,8 @@
#include "rssdownloadrulelist.h"
#include "preferences.h"
#include "qinisettings.h"
#include "rssmanager.h"
#include "rssfeed.h"
AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent) :
QDialog(parent),
@ -49,6 +51,8 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent) : @@ -49,6 +51,8 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent) :
ui->setupUi(this);
ui->listRules->setSortingEnabled(true);
ui->listRules->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->treeMatchingArticles->setSortingEnabled(true);
connect(ui->listRules, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayRulesListMenu(const QPoint&)));
m_ruleList = RssDownloadRuleList::instance();
initLabelCombobox();
@ -58,6 +62,9 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent) : @@ -58,6 +62,9 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent) :
connect(ui->listRules, SIGNAL(itemSelectionChanged()), SLOT(updateRuleDefinitionBox()));
connect(ui->listRules, SIGNAL(itemSelectionChanged()), SLOT(updateFeedList()));
connect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(handleFeedCheckStateChange(QListWidgetItem*)));
// Update matching articles when necessary
connect(ui->lineContains, SIGNAL(textEdited(QString)), SLOT(updateMatchingArticles()));
connect(ui->lineNotContains, SIGNAL(textEdited(QString)), SLOT(updateMatchingArticles()));
updateRuleDefinitionBox();
updateFeedList();
}
@ -149,6 +156,7 @@ void AutomatedRssDownloader::updateFeedList() @@ -149,6 +156,7 @@ void AutomatedRssDownloader::updateFeedList()
}
ui->listFeeds->setEnabled(!ui->listRules->selectedItems().isEmpty());
connect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(handleFeedCheckStateChange(QListWidgetItem*)));
updateMatchingArticles();
}
bool AutomatedRssDownloader::isRssDownloaderEnabled() const
@ -224,7 +232,11 @@ void AutomatedRssDownloader::saveCurrentRule(QListWidgetItem * item) @@ -224,7 +232,11 @@ void AutomatedRssDownloader::saveCurrentRule(QListWidgetItem * item)
{
qDebug() << Q_FUNC_INFO << item;
if(!item) return;
if(!ui->listRules->findItems(item->text(), Qt::MatchExactly).isEmpty()) return;
if(ui->listRules->findItems(item->text(), Qt::MatchExactly).isEmpty()) {
qDebug() << "Could not find rule" << item->text() << "in the UI list";
qDebug() << "Probably removed the item, no need to save it";
return;
}
RssDownloadRule rule = m_ruleList->getRule(item->text());
if(!rule.isValid()) {
rule.setName(item->text());
@ -263,6 +275,7 @@ void AutomatedRssDownloader::on_addRuleBtn_clicked() @@ -263,6 +275,7 @@ void AutomatedRssDownloader::on_addRuleBtn_clicked()
QListWidgetItem * item = new QListWidgetItem(rule, ui->listRules);
item->setFlags(item->flags()|Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked); // Enable as a default
ui->listRules->clearSelection();
ui->listRules->setCurrentItem(item);
}
@ -402,6 +415,54 @@ void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feed_it @@ -402,6 +415,54 @@ void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feed_it
m_ruleList->saveRule(rule);
}
}
// Update Matching articles
updateMatchingArticles();
}
void AutomatedRssDownloader::updateMatchingArticles()
{
ui->treeMatchingArticles->clear();
if(ui->ruleDefBox->isEnabled()) {
saveCurrentRule(ui->listRules->currentItem());
}
const QHash<QString, RssFeed*> all_feeds = RssManager::instance()->getAllFeedsAsHash();
foreach(const QListWidgetItem *rule_item, ui->listRules->selectedItems()) {
RssDownloadRule rule = m_ruleList->getRule(rule_item->text());
if(!rule.isValid()) continue;
foreach(const QString &feed_url, rule.rssFeeds()) {
Q_ASSERT(all_feeds.contains(feed_url));
const RssFeed *feed = all_feeds.value(feed_url);
const QStringList matching_articles = rule.findMatchingArticles(feed);
if(!matching_articles.isEmpty())
addFeedArticlesToTree(feed, matching_articles);
}
}
}
void AutomatedRssDownloader::addFeedArticlesToTree(const RssFeed *feed, const QStringList &articles)
{
// Check if this feed is already in the tree
QTreeWidgetItem *treeFeedItem = 0;
for(int i=0; i<ui->treeMatchingArticles->topLevelItemCount(); ++i) {
QTreeWidgetItem *item = ui->treeMatchingArticles->topLevelItem(i);
if(item->data(0, Qt::UserRole).toString() == feed->getUrl()) {
treeFeedItem = item;
break;
}
}
// If there is none, create it
if(!treeFeedItem) {
treeFeedItem = new QTreeWidgetItem(QStringList() << feed->getName());
treeFeedItem->setData(0, Qt::UserRole, feed->getUrl());
ui->treeMatchingArticles->addTopLevelItem(treeFeedItem);
}
// Insert the articles
foreach(const QString &art, articles) {
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << art);
treeFeedItem->addChild(item);
}
ui->treeMatchingArticles->expandItem(treeFeedItem);
}

2
src/rss/automatedrssdownloader.h

@ -70,10 +70,12 @@ private slots: @@ -70,10 +70,12 @@ private slots:
void on_exportBtn_clicked();
void on_importBtn_clicked();
void renameSelectedRule();
void updateMatchingArticles();
private:
RssDownloadRule getCurrentRule() const;
void initLabelCombobox();
void addFeedArticlesToTree(const RssFeed *feed, const QStringList& articles);
private:
Ui::AutomatedRssDownloader *ui;

11
src/rss/automatedrssdownloader.ui

@ -266,10 +266,15 @@ @@ -266,10 +266,15 @@
</widget>
</item>
<item>
<widget class="QListWidget" name="listMatchingArticles">
<property name="enabled">
<widget class="QTreeWidget" name="treeMatchingArticles">
<attribute name="headerVisible">
<bool>false</bool>
</property>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>

4
src/rss/rss_imp.cpp

@ -580,7 +580,7 @@ void RSSImp::updateRefreshInterval(unsigned int val) { @@ -580,7 +580,7 @@ void RSSImp::updateRefreshInterval(unsigned int val) {
RSSImp::RSSImp(QBtSession *BTSession) : QWidget(), BTSession(BTSession){
setupUi(this);
rssmanager = new RssManager(BTSession);
rssmanager = RssManager::instance();
listStreams = new FeedListWidget(splitter_h, rssmanager);
splitter_h->insertWidget(0, listStreams);
@ -634,7 +634,7 @@ RSSImp::~RSSImp(){ @@ -634,7 +634,7 @@ RSSImp::~RSSImp(){
qDebug("Deleting RSSImp...");
saveFoldersOpenState();
delete listStreams;
delete rssmanager;
RssManager::drop();
qDebug("RSSImp deleted");
}

8
src/rss/rssarticle.cpp

@ -252,10 +252,6 @@ bool RssArticle::has_attachment() const { @@ -252,10 +252,6 @@ bool RssArticle::has_attachment() const {
return !torrent_url.isEmpty();
}
QString RssArticle::getId() const {
return id;
}
QHash<QString, QVariant> RssArticle::toHash() const {
QHash<QString, QVariant> item;
item["title"] = title;
@ -282,10 +278,6 @@ bool RssArticle::isValid() const { @@ -282,10 +278,6 @@ bool RssArticle::isValid() const {
return is_valid;
}
QString RssArticle::getTitle() const{
return title;
}
QString RssArticle::getAuthor() const {
return author;
}

4
src/rss/rssarticle.h

@ -48,12 +48,12 @@ public: @@ -48,12 +48,12 @@ public:
QDateTime _date, QString _author, bool _read);
~RssArticle();
bool has_attachment() const;
QString getId() const;
inline QString getId() const { return id; }
QHash<QString, QVariant> toHash() const;
static RssArticle* fromHash(RssFeed* parent, const QHash<QString, QVariant> &h);
RssFeed* getParent() const;
bool isValid() const;
QString getTitle() const;
inline QString getTitle() const { return title; }
QString getAuthor() const;
QString getTorrentUrl() const;
QString getLink() const;

12
src/rss/rssdownloadrule.cpp

@ -34,6 +34,8 @@ @@ -34,6 +34,8 @@
#include "rssdownloadrule.h"
#include "preferences.h"
#include "qinisettings.h"
#include "rssfeed.h"
#include "rssarticle.h"
RssDownloadRule::RssDownloadRule()
{
@ -123,3 +125,13 @@ void RssDownloadRule::setSavePath(const QString &save_path) @@ -123,3 +125,13 @@ void RssDownloadRule::setSavePath(const QString &save_path)
else
m_savePath = QString();
}
QStringList RssDownloadRule::findMatchingArticles(const RssFeed *feed) const
{
QStringList ret;
foreach(const RssArticle *art, feed->values()) {
if(matches(art->getTitle()))
ret << art->getTitle();
}
return ret;
}

3
src/rss/rssdownloadrule.h

@ -34,6 +34,8 @@ @@ -34,6 +34,8 @@
#include <QStringList>
#include <QVariantHash>
class RssFeed;
class RssDownloadRule
{
@ -58,6 +60,7 @@ public: @@ -58,6 +60,7 @@ public:
inline bool isValid() const { return !m_name.isEmpty(); }
inline QString mustContain() const { return m_mustContain.join(" "); }
inline QString mustNotContain() const { return m_mustNotContain.join(" "); }
QStringList findMatchingArticles(const RssFeed* feed) const;
// Operators
bool operator==(const RssDownloadRule &other);

3
src/rss/rssdownloadrulelist.cpp

@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
#include <QDebug>
#include "rssdownloadrulelist.h"
#include "rsssettings.h"
#include "qinisettings.h"
RssDownloadRuleList* RssDownloadRuleList::m_instance = 0;
@ -56,6 +57,7 @@ void RssDownloadRuleList::drop() @@ -56,6 +57,7 @@ void RssDownloadRuleList::drop()
RssDownloadRule RssDownloadRuleList::findMatchingRule(const QString &feed_url, const QString &article_title) const
{
Q_ASSERT(RssSettings::isRssDownloadingEnabled());
QStringList rule_names = feedRules(feed_url);
foreach(const QString &rule_name, rule_names) {
RssDownloadRule rule = m_rules[rule_name];
@ -127,6 +129,7 @@ void RssDownloadRuleList::loadRulesFromVariantHash(const QVariantHash &h) @@ -127,6 +129,7 @@ void RssDownloadRuleList::loadRulesFromVariantHash(const QVariantHash &h)
void RssDownloadRuleList::saveRule(const RssDownloadRule &rule)
{
qDebug() << Q_FUNC_INFO << rule.name();
Q_ASSERT(rule.isValid());
if(m_rules.contains(rule.name())) {
removeRule(rule.name());

32
src/rss/rssfeed.cpp

@ -290,21 +290,23 @@ short RssFeed::readDoc(QIODevice* device) { @@ -290,21 +290,23 @@ short RssFeed::readDoc(QIODevice* device) {
resizeList();
// RSS Feed Downloader
foreach(RssArticle* item, values()) {
if(item->isRead()) continue;
QString torrent_url;
if(item->has_attachment())
torrent_url = item->getTorrentUrl();
else
torrent_url = item->getLink();
// Check if the item should be automatically downloaded
const RssDownloadRule matching_rule = RssDownloadRuleList::instance()->findMatchingRule(url, item->getTitle());
if(matching_rule.isValid()) {
// Download the torrent
BTSession->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item->getTitle()).arg(getName()));
BTSession->downloadUrlAndSkipDialog(torrent_url, matching_rule.savePath(), matching_rule.label());
// Item was downloaded, consider it as Read
item->setRead();
if(RssSettings::isRssDownloadingEnabled()) {
foreach(RssArticle* item, values()) {
if(item->isRead()) continue;
QString torrent_url;
if(item->has_attachment())
torrent_url = item->getTorrentUrl();
else
torrent_url = item->getLink();
// Check if the item should be automatically downloaded
const RssDownloadRule matching_rule = RssDownloadRuleList::instance()->findMatchingRule(url, item->getTitle());
if(matching_rule.isValid()) {
// Download the torrent
BTSession->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item->getTitle()).arg(getName()));
BTSession->downloadUrlAndSkipDialog(torrent_url, matching_rule.savePath(), matching_rule.label());
// Item was downloaded, consider it as Read
item->setRead();
}
}
}
return 0;

19
src/rss/rssfolder.cpp

@ -256,16 +256,27 @@ QList<RssFeed*> RssFolder::getAllFeeds() const { @@ -256,16 +256,27 @@ QList<RssFeed*> RssFolder::getAllFeeds() const {
QList<RssFeed*> streams;
foreach(RssFile *item, this->values()) {
if(item->getType() == RssFile::FEED) {
streams << ((RssFeed*)item);
streams << static_cast<RssFeed*>(item);
} else {
foreach(RssFeed* stream, ((RssFolder*)item)->getAllFeeds()) {
streams << stream;
}
streams << static_cast<RssFolder*>(item)->getAllFeeds();
}
}
return streams;
}
QHash<QString, RssFeed*> RssFolder::getAllFeedsAsHash() const {
QHash<QString, RssFeed*> ret;
foreach(RssFile *item, this->values()) {
if(item->getType() == RssFile::FEED) {
RssFeed* feed = static_cast<RssFeed*>(item);
ret[feed->getUrl()] = feed;
} else {
ret.unite(static_cast<RssFolder*>(item)->getAllFeedsAsHash());
}
}
return ret;
}
void RssFolder::addFile(RssFile * item) {
if(item->getType() == RssFile::FEED) {
Q_ASSERT(!this->contains(((RssFeed*)item)->getUrl()));

1
src/rss/rssfolder.h

@ -57,6 +57,7 @@ public: @@ -57,6 +57,7 @@ public:
unsigned int getNbFeeds() const;
QList<RssFile*> getContent() const;
QList<RssFeed*> getAllFeeds() const;
QHash<QString, RssFeed*> getAllFeedsAsHash() const;
QString getName() const;
QString getID() const;
bool hasChild(QString ID);

17
src/rss/rssmanager.cpp

@ -35,7 +35,9 @@ @@ -35,7 +35,9 @@
#include "rssarticle.h"
#include "rssdownloadrulelist.h"
RssManager::RssManager(QBtSession *BTSession): RssFolder(0, this, BTSession, QString::null) {
RssManager* RssManager::m_instance = 0;
RssManager::RssManager(): RssFolder(0, this, QBtSession::instance(), QString::null) {
loadStreamList();
connect(&newsRefresher, SIGNAL(timeout()), this, SLOT(refreshAll()));
refreshInterval = RssSettings::getRSSRefreshInterval();
@ -137,3 +139,16 @@ QList<RssArticle*> RssManager::sortNewsList(const QList<RssArticle*>& news_list) @@ -137,3 +139,16 @@ QList<RssArticle*> RssManager::sortNewsList(const QList<RssArticle*>& news_list)
}
return new_list;
}
RssManager * RssManager::instance()
{
if(!m_instance)
m_instance = new RssManager;
return m_instance;
}
void RssManager::drop()
{
if(m_instance)
delete m_instance;
}

6
src/rss/rssmanager.h

@ -37,9 +37,13 @@ @@ -37,9 +37,13 @@
class RssManager: public RssFolder {
Q_OBJECT
private:
explicit RssManager();
static RssManager* m_instance;
public:
RssManager(QBtSession *BTSession);
static RssManager* instance();
static void drop();
~RssManager();
static void insertSortElem(QList<RssArticle*> &list, RssArticle *item);
static QList<RssArticle*> sortNewsList(const QList<RssArticle*>& news_list);

Loading…
Cancel
Save