mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-22 17:26:21 +03:00
RSS code rewrite in progress
This commit is contained in:
parent
2b1e4912f2
commit
2d5612435c
14 changed files with 331 additions and 434 deletions
|
@ -468,20 +468,20 @@ void AutomatedRssDownloader::addFeedArticlesToTree(const RssFeed *feed, const QS
|
|||
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()) {
|
||||
if(item->data(0, Qt::UserRole).toString() == feed->url()) {
|
||||
treeFeedItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If there is none, create it
|
||||
if(!treeFeedItem) {
|
||||
treeFeedItem = new QTreeWidgetItem(QStringList() << feed->getName());
|
||||
treeFeedItem->setToolTip(0, feed->getName());
|
||||
treeFeedItem = new QTreeWidgetItem(QStringList() << feed->displayName());
|
||||
treeFeedItem->setToolTip(0, feed->displayName());
|
||||
QFont f = treeFeedItem->font(0);
|
||||
f.setBold(true);
|
||||
treeFeedItem->setFont(0, f);
|
||||
treeFeedItem->setData(0, Qt::DecorationRole, IconProvider::instance()->getIcon("inode-directory"));
|
||||
treeFeedItem->setData(0, Qt::UserRole, feed->getUrl());
|
||||
treeFeedItem->setData(0, Qt::UserRole, feed->url());
|
||||
ui->treeMatchingArticles->addTopLevelItem(treeFeedItem);
|
||||
}
|
||||
// Insert the articles
|
||||
|
|
|
@ -40,7 +40,7 @@ FeedListWidget::FeedListWidget(QWidget *parent, RssManager *rssmanager): QTreeWi
|
|||
setColumnCount(1);
|
||||
headerItem()->setText(0, tr("RSS feeds"));
|
||||
unread_item = new QTreeWidgetItem(this);
|
||||
unread_item->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->getNbUnRead(), 10)+ QString(")"));
|
||||
unread_item->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->unreadCount(), 10)+ QString(")"));
|
||||
unread_item->setData(0,Qt::DecorationRole, IconProvider::instance()->getIcon("mail-folder-inbox"));
|
||||
itemAdded(unread_item, rssmanager);
|
||||
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
||||
|
@ -54,19 +54,19 @@ FeedListWidget::~FeedListWidget() {
|
|||
|
||||
void FeedListWidget::itemAdded(QTreeWidgetItem *item, RssFile* file) {
|
||||
mapping[item] = file;
|
||||
if(file->getType() == RssFile::FEED) {
|
||||
feeds_items[file->getID()] = item;
|
||||
if(file->type() == RssFile::FEED) {
|
||||
feeds_items[file->id()] = item;
|
||||
}
|
||||
}
|
||||
|
||||
void FeedListWidget::itemAboutToBeRemoved(QTreeWidgetItem *item) {
|
||||
RssFile* file = mapping.take(item);
|
||||
if(file->getType() == RssFile::FEED) {
|
||||
feeds_items.remove(file->getID());
|
||||
if(file->type() == RssFile::FEED) {
|
||||
feeds_items.remove(file->id());
|
||||
} else {
|
||||
QList<RssFeed*> feeds = ((RssFolder*)file)->getAllFeeds();
|
||||
foreach(RssFeed* feed, feeds) {
|
||||
feeds_items.remove(feed->getID());
|
||||
feeds_items.remove(feed->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ QStringList FeedListWidget::getItemPath(QTreeWidgetItem* item) const {
|
|||
if(item) {
|
||||
if(item->parent())
|
||||
path << getItemPath(item->parent());
|
||||
path.append(getRSSItem(item)->getID());
|
||||
path.append(getRSSItem(item)->id());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
@ -137,11 +137,11 @@ RssFile* FeedListWidget::getRSSItem(QTreeWidgetItem *item) const {
|
|||
}
|
||||
|
||||
RssFile::FileType FeedListWidget::getItemType(QTreeWidgetItem *item) const {
|
||||
return mapping.value(item)->getType();
|
||||
return mapping.value(item)->type();
|
||||
}
|
||||
|
||||
QString FeedListWidget::getItemID(QTreeWidgetItem *item) const {
|
||||
return mapping.value(item)->getID();
|
||||
return mapping.value(item)->id();
|
||||
}
|
||||
|
||||
QTreeWidgetItem* FeedListWidget::getTreeItemFromUrl(QString url) const{
|
||||
|
@ -199,8 +199,8 @@ void FeedListWidget::dropEvent(QDropEvent *event) {
|
|||
// Check if there is not going to overwrite another file
|
||||
foreach(QTreeWidgetItem *src_item, src_items) {
|
||||
RssFile *file = getRSSItem(src_item);
|
||||
if(dest_folder->hasChild(file->getID())) {
|
||||
emit overwriteAttempt(file->getID());
|
||||
if(dest_folder->hasChild(file->id())) {
|
||||
emit overwriteAttempt(file->id());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ void RSSImp::askNewFolder() {
|
|||
if(listStreams->selectedItems().size() > 0) {
|
||||
parent_item = listStreams->selectedItems().at(0);
|
||||
rss_parent = (RssFolder*)listStreams->getRSSItem(parent_item);
|
||||
Q_ASSERT(rss_parent->getType() == RssFile::FOLDER);
|
||||
Q_ASSERT(rss_parent->type() == RssFile::FOLDER);
|
||||
} else {
|
||||
rss_parent = rssmanager;
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ void RSSImp::askNewFolder() {
|
|||
// Notify TreeWidget
|
||||
listStreams->itemAdded(folder_item, new_folder);
|
||||
// Set Text
|
||||
folder_item->setText(0, new_folder->getName() + QString::fromUtf8(" (0)"));
|
||||
folder_item->setText(0, new_folder->displayName() + QString::fromUtf8(" (0)"));
|
||||
folder_item->setData(0,Qt::DecorationRole, QVariant(IconProvider::instance()->getIcon("inode-directory")));
|
||||
// Expand parent folder to display new folder
|
||||
if(parent_item)
|
||||
|
@ -211,7 +211,7 @@ void RSSImp::on_newFeedButton_clicked() {
|
|||
// Notify TreeWidget
|
||||
listStreams->itemAdded(item, stream);
|
||||
// Set text
|
||||
item->setText(0, stream->getName() + QString::fromUtf8(" (0)"));
|
||||
item->setText(0, stream->displayName() + QString::fromUtf8(" (0)"));
|
||||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png")));
|
||||
stream->refresh();
|
||||
rssmanager->saveStreamList();
|
||||
|
@ -243,7 +243,7 @@ void RSSImp::deleteSelectedItems() {
|
|||
// Notify TreeWidget
|
||||
listStreams->itemAboutToBeRemoved(item);
|
||||
// Actually delete the item
|
||||
rss_item->getParent()->removeFile(rss_item->getID());
|
||||
rss_item->parent()->removeFile(rss_item->id());
|
||||
delete item;
|
||||
}
|
||||
rssmanager->saveStreamList();
|
||||
|
@ -272,7 +272,7 @@ void RSSImp::loadFoldersOpenState() {
|
|||
child = parent->child(i);
|
||||
else
|
||||
child = listStreams->topLevelItem(i);
|
||||
if(listStreams->getRSSItem(child)->getID() == name) {
|
||||
if(listStreams->getRSSItem(child)->id() == name) {
|
||||
parent = child;
|
||||
parent->setExpanded(true);
|
||||
qDebug("expanding folder %s", qPrintable(name));
|
||||
|
@ -302,7 +302,7 @@ void RSSImp::on_updateAllButton_clicked() {
|
|||
foreach(QTreeWidgetItem *item, listStreams->getAllFeedItems()) {
|
||||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png")));
|
||||
}
|
||||
rssmanager->refreshAll();
|
||||
rssmanager->refresh();
|
||||
}
|
||||
|
||||
void RSSImp::downloadTorrent() {
|
||||
|
@ -337,10 +337,10 @@ void RSSImp::renameFiles() {
|
|||
bool ok;
|
||||
QString newName;
|
||||
do {
|
||||
newName = QInputDialog::getText(this, tr("Please choose a new name for this RSS feed"), tr("New feed name:"), QLineEdit::Normal, listStreams->getRSSItem(item)->getName(), &ok);
|
||||
newName = QInputDialog::getText(this, tr("Please choose a new name for this RSS feed"), tr("New feed name:"), QLineEdit::Normal, listStreams->getRSSItem(item)->displayName(), &ok);
|
||||
// Check if name is already taken
|
||||
if(ok) {
|
||||
if(rss_item->getParent()->contains(newName)) {
|
||||
if(rss_item->parent()->contains(newName)) {
|
||||
QMessageBox::warning(0, tr("Name already in use"), tr("This name is already used by another item, please choose another one."));
|
||||
ok = false;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ void RSSImp::renameFiles() {
|
|||
}
|
||||
}while(!ok);
|
||||
// Rename item
|
||||
rss_item->rename(newName);
|
||||
rss_item->setAlias(newName);
|
||||
// Update TreeWidget
|
||||
updateItemInfos(item);
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ void RSSImp::refreshSelectedItems() {
|
|||
file->refresh();
|
||||
break;
|
||||
} else {
|
||||
if(file->getType() == RssFile::FEED) {
|
||||
if(file->type() == RssFile::FEED) {
|
||||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png")));
|
||||
} else {
|
||||
// Update feeds in the folder
|
||||
|
@ -397,7 +397,7 @@ void RSSImp::on_markReadButton_clicked() {
|
|||
QTreeWidgetItem* item;
|
||||
foreach(item, selectedItems){
|
||||
RssFile *rss_item = listStreams->getRSSItem(item);
|
||||
rss_item->markAllAsRead();
|
||||
rss_item->markAsRead();
|
||||
updateItemInfos(item);
|
||||
}
|
||||
if(selectedItems.size())
|
||||
|
@ -417,11 +417,11 @@ void RSSImp::fillFeedsList(QTreeWidgetItem *parent, RssFolder *rss_parent) {
|
|||
item = new QTreeWidgetItem(listStreams);
|
||||
else
|
||||
item = new QTreeWidgetItem(parent);
|
||||
item->setData(0, Qt::DisplayRole, QVariant(rss_child->getName()+ QString::fromUtf8(" (")+QString::number(rss_child->getNbUnRead(), 10)+QString(")")));
|
||||
item->setData(0, Qt::DisplayRole, QVariant(rss_child->displayName()+ QString::fromUtf8(" (")+QString::number(rss_child->unreadCount(), 10)+QString(")")));
|
||||
// Notify TreeWidget of item addition
|
||||
listStreams->itemAdded(item, rss_child);
|
||||
// Set Icon
|
||||
if(rss_child->getType() == RssFile::FEED) {
|
||||
if(rss_child->type() == RssFile::FEED) {
|
||||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(QString::fromUtf8(":/Icons/loading.png"))));
|
||||
} else {
|
||||
item->setData(0,Qt::DecorationRole, QVariant(IconProvider::instance()->getIcon("inode-directory")));
|
||||
|
@ -444,9 +444,9 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
|
|||
qDebug("Getting the list of news");
|
||||
QList<RssArticle> news;
|
||||
if(rss_item == rssmanager)
|
||||
news = RssManager::sortNewsList(rss_item->getUnreadNewsList());
|
||||
news = RssManager::sortNewsList(rss_item->unreadArticleList());
|
||||
else if(rss_item)
|
||||
news = RssManager::sortNewsList(rss_item->getNewsList());
|
||||
news = RssManager::sortNewsList(rss_item->articleList());
|
||||
// Clear the list first
|
||||
textBrowser->clear();
|
||||
previous_news = 0;
|
||||
|
@ -455,7 +455,7 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
|
|||
foreach(const RssArticle &article, news){
|
||||
QTreeWidgetItem* it = new QTreeWidgetItem(listNews);
|
||||
it->setText(NEWS_TITLE_COL, article.title());
|
||||
it->setText(NEWS_URL_COL, article.parent()->getUrl());
|
||||
it->setText(NEWS_URL_COL, article.parent()->url());
|
||||
it->setText(NEWS_ID, article.guid());
|
||||
if(article.isRead()){
|
||||
it->setData(NEWS_TITLE_COL, Qt::ForegroundRole, QVariant(QColor("grey")));
|
||||
|
@ -542,8 +542,8 @@ void RSSImp::updateItemInfos(QTreeWidgetItem *item) {
|
|||
if(rss_item == rssmanager)
|
||||
name = tr("Unread");
|
||||
else
|
||||
name = rss_item->getName();
|
||||
item->setText(0, name + QString::fromUtf8(" (") + QString::number(rss_item->getNbUnRead(), 10)+ QString(")"));
|
||||
name = rss_item->displayName();
|
||||
item->setText(0, name + QString::fromUtf8(" (") + QString::number(rss_item->unreadCount(), 10)+ QString(")"));
|
||||
// If item has a parent, update it too
|
||||
if(item->parent())
|
||||
updateItemInfos(item->parent());
|
||||
|
@ -554,12 +554,13 @@ void RSSImp::updateFeedIcon(QString url, QString icon_path){
|
|||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(icon_path)));
|
||||
}
|
||||
|
||||
void RSSImp::updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread){
|
||||
void RSSImp::updateFeedInfos(QString url, QString display_name, unsigned int nbUnread){
|
||||
qDebug() << Q_FUNC_INFO << display_name;
|
||||
QTreeWidgetItem *item = listStreams->getTreeItemFromUrl(url);
|
||||
RssFeed *stream = (RssFeed*)listStreams->getRSSItem(item);
|
||||
item->setText(0, aliasOrUrl + QString::fromUtf8(" (") + QString::number(nbUnread, 10)+ QString(")"));
|
||||
item->setText(0, display_name + QString::fromUtf8(" (") + QString::number(nbUnread, 10)+ QString(")"));
|
||||
if(!stream->isLoading())
|
||||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(stream->getIconPath())));
|
||||
item->setData(0,Qt::DecorationRole, QVariant(QIcon(stream->icon())));
|
||||
// Update parent
|
||||
if(item->parent())
|
||||
updateItemInfos(item->parent());
|
||||
|
@ -609,6 +610,7 @@ RSSImp::RSSImp(QWidget *parent) : QWidget(parent) {
|
|||
listNews->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
listNews->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
rssmanager->loadStreamList();
|
||||
fillFeedsList();
|
||||
refreshNewsList(listStreams->currentItem());
|
||||
|
||||
|
@ -640,7 +642,7 @@ RSSImp::RSSImp(QWidget *parent) : QWidget(parent) {
|
|||
connect(listNews, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(downloadTorrent()));
|
||||
|
||||
// Refresh all feeds
|
||||
rssmanager->refreshAll();
|
||||
rssmanager->refresh();
|
||||
// Restore sliders position
|
||||
restoreSlidersPosition();
|
||||
// Bind saveSliders slots
|
||||
|
|
|
@ -64,7 +64,7 @@ protected slots:
|
|||
void refreshNewsList(QTreeWidgetItem* item);
|
||||
void refreshTextBrowser();
|
||||
void updateFeedIcon(QString url, QString icon_path);
|
||||
void updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread);
|
||||
void updateFeedInfos(QString url, QString display_name, unsigned int nbUnread);
|
||||
void updateItemsInfos(QList<QTreeWidgetItem*> items);
|
||||
void updateItemInfos(QTreeWidgetItem *item);
|
||||
void openNewsUrl();
|
||||
|
|
|
@ -60,7 +60,7 @@ static const char longMonth[][10] = {
|
|||
|
||||
// Ported to Qt4 from KDElibs4
|
||||
QDateTime RssArticle::parseDate(const QString &string) {
|
||||
QString str = string.trimmed();
|
||||
const QString str = string.trimmed();
|
||||
if (str.isEmpty())
|
||||
return QDateTime::currentDateTime();
|
||||
|
||||
|
@ -228,7 +228,7 @@ RssArticle::RssArticle(RssFeed* parent, QXmlStreamReader& xml): m_parent(parent)
|
|||
}
|
||||
|
||||
RssArticle::RssArticle(RssFeed* parent, const QString &guid):
|
||||
m_parent(parent), m_guid(guid) {
|
||||
m_parent(parent), m_guid(guid), m_read(false) {
|
||||
}
|
||||
|
||||
RssArticle::~RssArticle(){
|
||||
|
|
|
@ -62,8 +62,8 @@ public:
|
|||
QVariantHash toHash() const;
|
||||
friend RssArticle hashToRssArticle(RssFeed* parent, const QVariantHash &hash);
|
||||
|
||||
protected:
|
||||
QDateTime parseDate(const QString &string);
|
||||
private:
|
||||
static QDateTime parseDate(const QString &string);
|
||||
|
||||
private:
|
||||
RssFeed* m_parent;
|
||||
|
|
|
@ -129,7 +129,7 @@ void RssDownloadRule::setSavePath(const QString &save_path)
|
|||
QStringList RssDownloadRule::findMatchingArticles(const RssFeed *feed) const
|
||||
{
|
||||
QStringList ret;
|
||||
foreach(const RssArticle &art, feed->values()) {
|
||||
foreach(const RssArticle &art, feed->articleList()) {
|
||||
if(matches(art.title()))
|
||||
ret << art.title();
|
||||
}
|
||||
|
|
|
@ -36,166 +36,159 @@
|
|||
#include "rssarticle.h"
|
||||
#include "misc.h"
|
||||
#include "rssdownloadrulelist.h"
|
||||
#include "downloadthread.h"
|
||||
|
||||
RssFeed::RssFeed(RssFolder* parent, QString _url): parent(parent), alias(""), iconPath(":/Icons/oxygen/application-rss+xml.png"), refreshed(false), downloadFailure(false), currently_loading(false) {
|
||||
qDebug("RSSStream constructed");
|
||||
RssFeed::RssFeed(RssFolder* parent, const QString &url): m_parent(parent), m_icon(":/Icons/oxygen/application-rss+xml.png"),
|
||||
m_refreshed(false), m_downloadFailure(false), m_loading(false) {
|
||||
qDebug() << Q_FUNC_INFO << url;
|
||||
m_url = QUrl(url).toString();
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
url = QUrl(_url).toString();
|
||||
QHash<QString, QVariant> all_old_items = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
|
||||
const QVariantList old_items = all_old_items.value(url, QVariantList()).toList();
|
||||
qDebug("Loading %d old items for feed %s", old_items.size(), getName().toLocal8Bit().data());
|
||||
const QVariantList old_items = all_old_items.value(m_url, QVariantList()).toList();
|
||||
qDebug("Loading %d old items for feed %s", old_items.size(), displayName().toLocal8Bit().data());
|
||||
foreach(const QVariant &var_it, old_items) {
|
||||
QHash<QString, QVariant> item = var_it.toHash();
|
||||
const RssArticle rss_item = hashToRssArticle(this, item);
|
||||
if(rss_item.isValid()) {
|
||||
insert(rss_item.guid(), rss_item);
|
||||
m_articles.insert(rss_item.guid(), rss_item);
|
||||
}
|
||||
}
|
||||
// Listen for new RSS downloads
|
||||
connect(RssManager::instance()->rssDownloader(), SIGNAL(downloadFinished(QString,QString)), SLOT(handleFinishedDownload(QString,QString)));
|
||||
connect(RssManager::instance()->rssDownloader(), SIGNAL(downloadFailure(QString,QString)), SLOT(handleDownloadFailure(QString,QString)));
|
||||
// Download the RSS Feed icon
|
||||
m_iconUrl = iconUrl();
|
||||
RssManager::instance()->rssDownloader()->downloadUrl(m_iconUrl);
|
||||
}
|
||||
|
||||
RssFeed::~RssFeed(){
|
||||
qDebug("Deleting a RSS stream: %s", getName().toLocal8Bit().data());
|
||||
if(refreshed) {
|
||||
// Saving current articles to hard disk
|
||||
if(m_refreshed) {
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QVariantList old_items;
|
||||
foreach(const RssArticle &item, this->values()) {
|
||||
foreach(const RssArticle &item, m_articles.values()) {
|
||||
old_items << item.toHash();
|
||||
}
|
||||
qDebug("Saving %d old items for feed %s", old_items.size(), getName().toLocal8Bit().data());
|
||||
qDebug("Saving %d old items for feed %s", old_items.size(), displayName().toLocal8Bit().data());
|
||||
QHash<QString, QVariant> all_old_items = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
|
||||
all_old_items[url] = old_items;
|
||||
all_old_items[m_url] = old_items;
|
||||
qBTRSS.setValue("old_items", all_old_items);
|
||||
}
|
||||
qDebug("All items were removed");
|
||||
if(QFile::exists(filePath))
|
||||
misc::safeRemove(filePath);
|
||||
if(QFile::exists(iconPath) && !iconPath.startsWith(":/"))
|
||||
misc::safeRemove(iconPath);
|
||||
if(!m_icon.startsWith(":/") && QFile::exists(m_icon))
|
||||
misc::safeRemove(m_icon);
|
||||
}
|
||||
|
||||
RssFile::FileType RssFeed::getType() const {
|
||||
RssFile::FileType RssFeed::type() const {
|
||||
return RssFile::FEED;
|
||||
}
|
||||
|
||||
void RssFeed::refresh() {
|
||||
parent->refreshStream(url);
|
||||
if(m_loading) return;
|
||||
m_loading = true;
|
||||
// Download the RSS again
|
||||
RssManager::instance()->rssDownloader()->downloadUrl(m_url);
|
||||
}
|
||||
|
||||
void RssFeed::removeAllSettings() {
|
||||
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
if(feeds_w_downloader.contains(url)) {
|
||||
feeds_w_downloader.remove(url);
|
||||
if(feeds_w_downloader.contains(m_url)) {
|
||||
feeds_w_downloader.remove(m_url);
|
||||
qBTRSS.setValue("downloader_on", feeds_w_downloader);
|
||||
}
|
||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||
if(all_feeds_filters.contains(url)) {
|
||||
all_feeds_filters.remove(url);
|
||||
if(all_feeds_filters.contains(m_url)) {
|
||||
all_feeds_filters.remove(m_url);
|
||||
qBTRSS.setValue("feed_filters", all_feeds_filters);
|
||||
}
|
||||
}
|
||||
|
||||
bool RssFeed::itemAlreadyExists(QString name) {
|
||||
return this->contains(name);
|
||||
bool RssFeed::itemAlreadyExists(const QString &hash) const {
|
||||
return m_articles.contains(hash);
|
||||
}
|
||||
|
||||
void RssFeed::setLoading(bool val) {
|
||||
currently_loading = val;
|
||||
m_loading = val;
|
||||
}
|
||||
|
||||
bool RssFeed::isLoading() {
|
||||
return currently_loading;
|
||||
bool RssFeed::isLoading() const {
|
||||
return m_loading;
|
||||
}
|
||||
|
||||
QString RssFeed::getTitle() const{
|
||||
return title;
|
||||
QString RssFeed::title() const{
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void RssFeed::rename(QString new_name){
|
||||
qDebug("Renaming stream to %s", new_name.toLocal8Bit().data());
|
||||
alias = new_name;
|
||||
void RssFeed::setAlias(const QString &new_name){
|
||||
qDebug() << "Renaming stream to" << new_name;
|
||||
m_alias = new_name;
|
||||
}
|
||||
|
||||
// Return the alias if the stream has one, the url if it has no alias
|
||||
QString RssFeed::getName() const{
|
||||
if(!alias.isEmpty()) {
|
||||
QString RssFeed::displayName() const {
|
||||
if(!m_alias.isEmpty()) {
|
||||
//qDebug("getName() returned alias: %s", (const char*)alias.toLocal8Bit());
|
||||
return alias;
|
||||
return m_alias;
|
||||
}
|
||||
if(!title.isEmpty()) {
|
||||
if(!m_title.isEmpty()) {
|
||||
//qDebug("getName() returned title: %s", (const char*)title.toLocal8Bit());
|
||||
return title;
|
||||
return m_title;
|
||||
}
|
||||
//qDebug("getName() returned url: %s", (const char*)url.toLocal8Bit());
|
||||
return url;
|
||||
return m_url;
|
||||
}
|
||||
|
||||
QString RssFeed::getLink() const{
|
||||
return link;
|
||||
QString RssFeed::url() const{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
QString RssFeed::getUrl() const{
|
||||
return url;
|
||||
}
|
||||
|
||||
QString RssFeed::getDescription() const{
|
||||
return description;
|
||||
}
|
||||
|
||||
QString RssFeed::getImage() const{
|
||||
return image;
|
||||
}
|
||||
|
||||
QString RssFeed::getFilePath() const{
|
||||
return filePath;
|
||||
}
|
||||
|
||||
QString RssFeed::getIconPath() const{
|
||||
if(downloadFailure)
|
||||
QString RssFeed::icon() const{
|
||||
if(m_downloadFailure)
|
||||
return ":/Icons/oxygen/unavailable.png";
|
||||
return iconPath;
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
bool RssFeed::hasCustomIcon() const{
|
||||
return !iconPath.startsWith(":/");
|
||||
return !m_icon.startsWith(":/");
|
||||
}
|
||||
|
||||
void RssFeed::setIconPath(QString path) {
|
||||
iconPath = path;
|
||||
void RssFeed::setIconPath(const QString &path) {
|
||||
if(path.isEmpty() || !QFile::exists(path)) return;
|
||||
m_icon = path;
|
||||
}
|
||||
|
||||
RssArticle& RssFeed::getItem(QString id) {
|
||||
return (*this)[id];
|
||||
RssArticle& RssFeed::getItem(const QString &id) {
|
||||
return m_articles[id];
|
||||
}
|
||||
|
||||
unsigned int RssFeed::getNbNews() const{
|
||||
return this->size();
|
||||
return m_articles.size();
|
||||
}
|
||||
|
||||
void RssFeed::markAllAsRead() {
|
||||
void RssFeed::markAsRead() {
|
||||
QHash<QString, RssArticle>::iterator it;
|
||||
for(it = this->begin(); it != this->end(); it++) {
|
||||
for(it = m_articles.begin(); it != m_articles.end(); it++) {
|
||||
it.value().markAsRead();
|
||||
}
|
||||
RssManager::instance()->forwardFeedInfosChanged(url, getName(), 0);
|
||||
RssManager::instance()->forwardFeedInfosChanged(m_url, displayName(), 0);
|
||||
}
|
||||
|
||||
unsigned int RssFeed::getNbUnRead() const{
|
||||
unsigned int nbUnread=0;
|
||||
foreach(const RssArticle &item, this->values()) {
|
||||
unsigned int RssFeed::unreadCount() const{
|
||||
uint nbUnread=0;
|
||||
foreach(const RssArticle &item, m_articles.values()) {
|
||||
if(!item.isRead())
|
||||
++nbUnread;
|
||||
}
|
||||
return nbUnread;
|
||||
}
|
||||
|
||||
QList<RssArticle> RssFeed::getNewsList() const{
|
||||
return this->values();
|
||||
QList<RssArticle> RssFeed::articleList() const{
|
||||
return m_articles.values();
|
||||
}
|
||||
|
||||
QList<RssArticle> RssFeed::getUnreadNewsList() const {
|
||||
QList<RssArticle> RssFeed::unreadArticleList() const {
|
||||
QList<RssArticle> unread_news;
|
||||
foreach(const RssArticle &item, this->values()) {
|
||||
foreach(const RssArticle &item, m_articles.values()) {
|
||||
if(!item.isRead())
|
||||
unread_news << item;
|
||||
}
|
||||
|
@ -203,26 +196,27 @@ QList<RssArticle> RssFeed::getUnreadNewsList() const {
|
|||
}
|
||||
|
||||
// download the icon from the adress
|
||||
QString RssFeed::getIconUrl() {
|
||||
QUrl siteUrl(url);
|
||||
return QString::fromUtf8("http://")+siteUrl.host()+QString::fromUtf8("/favicon.ico");
|
||||
QString RssFeed::iconUrl() const {
|
||||
const QUrl siteUrl(m_url);
|
||||
// XXX: This works for most sites but it is not perfect
|
||||
return QString("http://")+siteUrl.host()+QString("/favicon.ico");
|
||||
}
|
||||
|
||||
// read and create items from a rss document
|
||||
short RssFeed::readDoc(QIODevice* device) {
|
||||
bool RssFeed::parseRSS(QIODevice* device) {
|
||||
qDebug("Parsing RSS file...");
|
||||
QXmlStreamReader xml(device);
|
||||
// is it a rss file ?
|
||||
if (xml.atEnd()) {
|
||||
qDebug("ERROR: Could not parse RSS file");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
while (!xml.atEnd()) {
|
||||
xml.readNext();
|
||||
if(xml.isStartElement()) {
|
||||
if(xml.name() != "rss") {
|
||||
qDebug("ERROR: this is not a rss file, root tag is <%s>", qPrintable(xml.name().toString()));
|
||||
return -1;
|
||||
return false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -232,121 +226,131 @@ short RssFeed::readDoc(QIODevice* device) {
|
|||
while(!xml.atEnd()) {
|
||||
xml.readNext();
|
||||
|
||||
if(xml.isEndElement())
|
||||
break;
|
||||
if(!xml.isStartElement())
|
||||
continue;
|
||||
|
||||
if(xml.isStartElement()) {
|
||||
//qDebug("xml.name() == %s", qPrintable(xml.name().toString()));
|
||||
if(xml.name() == "channel") {
|
||||
qDebug("in channel");
|
||||
if(xml.name() != "channel")
|
||||
continue;
|
||||
|
||||
// Parse channel content
|
||||
while(!xml.atEnd()) {
|
||||
xml.readNext();
|
||||
// Parse channel content
|
||||
while(!xml.atEnd()) {
|
||||
xml.readNext();
|
||||
|
||||
if(xml.isEndElement() && xml.name() == "channel") {
|
||||
break;
|
||||
}
|
||||
if(xml.isEndElement() && xml.name() == "channel")
|
||||
break; // End of this channel, parse the next one
|
||||
|
||||
if(xml.isStartElement()) {
|
||||
//qDebug("xml.name() == %s", qPrintable(xml.name().toString()));
|
||||
if(xml.name() == "title") {
|
||||
title = xml.readElementText();
|
||||
if(alias == getUrl())
|
||||
rename(title);
|
||||
}
|
||||
else if(xml.name() == "link") {
|
||||
link = xml.readElementText();
|
||||
}
|
||||
else if(xml.name() == "description") {
|
||||
description = xml.readElementText();
|
||||
}
|
||||
else if(xml.name() == "image") {
|
||||
image = xml.attributes().value("url").toString();
|
||||
}
|
||||
else if(xml.name() == "item") {
|
||||
RssArticle item(this, xml);
|
||||
if(item.isValid() && !itemAlreadyExists(item.guid())) {
|
||||
this->insert(item.guid(), item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!xml.isStartElement())
|
||||
continue;
|
||||
|
||||
if(xml.name() == "title") {
|
||||
m_title = xml.readElementText();
|
||||
if(m_alias == url())
|
||||
setAlias(m_title);
|
||||
}
|
||||
else if(xml.name() == "image") {
|
||||
QString icon_path = xml.attributes().value("url").toString();
|
||||
if(!icon_path.isEmpty()) {
|
||||
m_iconUrl = icon_path;
|
||||
RssManager::instance()->rssDownloader()->downloadUrl(m_iconUrl);
|
||||
}
|
||||
}
|
||||
else if(xml.name() == "item") {
|
||||
RssArticle item(this, xml);
|
||||
if(item.isValid() && !itemAlreadyExists(item.guid())) {
|
||||
m_articles.insert(item.guid(), item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RSS Feed Downloader
|
||||
if(RssSettings().isRssDownloadingEnabled())
|
||||
downloadMatchingArticleTorrents();
|
||||
|
||||
// Make sure we limit the number of articles
|
||||
resizeList();
|
||||
|
||||
// RSS Feed Downloader
|
||||
if(RssSettings().isRssDownloadingEnabled()) {
|
||||
QHash<QString, RssArticle>::iterator it;
|
||||
for(it = this->begin(); it != this->end(); it++) {
|
||||
RssArticle &item = it.value();
|
||||
if(item.isRead()) continue;
|
||||
QString torrent_url;
|
||||
if(item.hasAttachment())
|
||||
torrent_url = item.torrentUrl();
|
||||
else
|
||||
torrent_url = item.link();
|
||||
// Check if the item should be automatically downloaded
|
||||
const RssDownloadRule matching_rule = RssDownloadRuleList::instance()->findMatchingRule(url, item.title());
|
||||
if(matching_rule.isValid()) {
|
||||
// Download the torrent
|
||||
QBtSession::instance()->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item.title()).arg(getName()));
|
||||
QBtSession::instance()->downloadUrlAndSkipDialog(torrent_url, matching_rule.savePath(), matching_rule.label());
|
||||
// Item was downloaded, consider it as Read
|
||||
item.markAsRead();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RssFeed::downloadMatchingArticleTorrents() {
|
||||
Q_ASSERT(RssSettings().isRssDownloadingEnabled());
|
||||
QHash<QString, RssArticle>::iterator it;
|
||||
for(it = m_articles.begin(); it != m_articles.end(); it++) {
|
||||
RssArticle &item = it.value();
|
||||
if(item.isRead()) continue;
|
||||
QString torrent_url;
|
||||
if(item.hasAttachment())
|
||||
torrent_url = item.torrentUrl();
|
||||
else
|
||||
torrent_url = item.link();
|
||||
// Check if the item should be automatically downloaded
|
||||
const RssDownloadRule matching_rule = RssDownloadRuleList::instance()->findMatchingRule(m_url, item.title());
|
||||
if(matching_rule.isValid()) {
|
||||
// Download the torrent
|
||||
QBtSession::instance()->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item.title()).arg(displayName()));
|
||||
QBtSession::instance()->downloadUrlAndSkipDialog(torrent_url, matching_rule.savePath(), matching_rule.label());
|
||||
// Item was downloaded, consider it as Read
|
||||
item.markAsRead();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RssFeed::resizeList() {
|
||||
const unsigned int max_articles = RssSettings().getRSSMaxArticlesPerFeed();
|
||||
const unsigned int nb_articles = this->size();
|
||||
const uint max_articles = RssSettings().getRSSMaxArticlesPerFeed();
|
||||
const uint nb_articles = m_articles.size();
|
||||
if(nb_articles > max_articles) {
|
||||
const QList<RssArticle> listItem = RssManager::sortNewsList(this->values());
|
||||
const QList<RssArticle> listItem = RssManager::sortNewsList(m_articles.values());
|
||||
const int excess = nb_articles - max_articles;
|
||||
for(uint i=nb_articles-excess; i<nb_articles; ++i){
|
||||
this->remove(listItem.at(i).guid());
|
||||
m_articles.remove(listItem.at(i).guid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// existing and opening test after download
|
||||
short RssFeed::openRss(){
|
||||
bool RssFeed::parseXmlFile(const QString &file_path){
|
||||
qDebug("openRss() called");
|
||||
QFile fileRss(filePath);
|
||||
QFile fileRss(file_path);
|
||||
if(!fileRss.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qDebug("openRss error: open failed, no file or locked, %s", (const char*)filePath.toLocal8Bit());
|
||||
if(QFile::exists(filePath)) {
|
||||
qDebug("openRss error: open failed, no file or locked, %s", qPrintable(file_path));
|
||||
if(QFile::exists(file_path)) {
|
||||
fileRss.remove();
|
||||
}
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// start reading the xml
|
||||
short return_lecture = readDoc(&fileRss);
|
||||
bool ret = parseRSS(&fileRss);
|
||||
fileRss.close();
|
||||
if(QFile::exists(filePath)) {
|
||||
if(QFile::exists(file_path))
|
||||
fileRss.remove();
|
||||
}
|
||||
return return_lecture;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// read and store the downloaded rss' informations
|
||||
void RssFeed::processDownloadedFile(QString file_path) {
|
||||
filePath = file_path;
|
||||
downloadFailure = false;
|
||||
if(openRss() >= 0) {
|
||||
refreshed = true;
|
||||
} else {
|
||||
qDebug("OpenRss: Feed update Failed");
|
||||
void RssFeed::handleFinishedDownload(const QString& url, const QString &file_path) {
|
||||
if(url == m_url) {
|
||||
m_downloadFailure = false;
|
||||
m_loading = false;
|
||||
// Parse the download RSS
|
||||
if(parseXmlFile(file_path)) {
|
||||
m_refreshed = true;
|
||||
RssManager::instance()->forwardFeedInfosChanged(m_url, displayName(), unreadCount()); // XXX: Ugly
|
||||
}
|
||||
}
|
||||
else if(url == m_iconUrl) {
|
||||
m_icon = file_path;
|
||||
qDebug() << "icon path:" << m_icon;
|
||||
RssManager::instance()->forwardFeedIconChanged(m_url, m_icon); // XXX: Ugly
|
||||
emit iconUpdated(m_icon);
|
||||
}
|
||||
}
|
||||
|
||||
void RssFeed::setDownloadFailed(){
|
||||
downloadFailure = true;
|
||||
void RssFeed::handleDownloadFailure(const QString &url, const QString& error) {
|
||||
Q_UNUSED(error);
|
||||
if(url != m_url) return;
|
||||
m_downloadFailure = true;
|
||||
m_loading = false;
|
||||
RssManager::instance()->forwardFeedInfosChanged(m_url, displayName(), unreadCount()); // XXX: Ugly
|
||||
}
|
||||
|
|
|
@ -37,63 +37,61 @@
|
|||
|
||||
class RssManager;
|
||||
|
||||
class RssFeed: public RssFile, public QHash<QString, RssArticle> {
|
||||
class RssFeed: public RssFile {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RssFeed(RssFolder* parent, QString _url);
|
||||
RssFeed(RssFolder* m_parent, const QString &url);
|
||||
~RssFeed();
|
||||
RssFolder* getParent() const { return parent; }
|
||||
void setParent(RssFolder* _parent) { parent = _parent; }
|
||||
FileType getType() const;
|
||||
inline RssFolder* parent() const { return m_parent; }
|
||||
void setParent(RssFolder* parent) { m_parent = parent; }
|
||||
FileType type() const;
|
||||
void refresh();
|
||||
QString getID() const { return url; }
|
||||
QString id() const { return m_url; }
|
||||
void removeAllSettings();
|
||||
bool itemAlreadyExists(QString hash);
|
||||
bool itemAlreadyExists(const QString &hash) const;
|
||||
void setLoading(bool val);
|
||||
bool isLoading();
|
||||
QString getTitle() const;
|
||||
void rename(QString _alias);
|
||||
QString getName() const;
|
||||
QString getLink() const;
|
||||
QString getUrl() const;
|
||||
QString getDescription() const;
|
||||
QString getImage() const;
|
||||
QString getFilePath() const;
|
||||
QString getIconPath() const;
|
||||
bool isLoading() const;
|
||||
QString title() const;
|
||||
void setAlias(const QString &alias);
|
||||
QString displayName() const;
|
||||
QString url() const;
|
||||
QString icon() const;
|
||||
bool hasCustomIcon() const;
|
||||
void setIconPath(QString path);
|
||||
RssArticle& getItem(QString name);
|
||||
void setIconPath(const QString &pathHierarchy);
|
||||
RssArticle& getItem(const QString &name);
|
||||
unsigned int getNbNews() const;
|
||||
void markAllAsRead();
|
||||
unsigned int getNbUnRead() const;
|
||||
QList<RssArticle> getNewsList() const;
|
||||
QList<RssArticle> getUnreadNewsList() const;
|
||||
QString getIconUrl();
|
||||
void markAsRead();
|
||||
unsigned int unreadCount() const;
|
||||
QList<RssArticle> articleList() const;
|
||||
QList<RssArticle> unreadArticleList() const;
|
||||
|
||||
public slots:
|
||||
void processDownloadedFile(QString file_path);
|
||||
void setDownloadFailed();
|
||||
signals:
|
||||
void iconUpdated(const QString &icon);
|
||||
|
||||
private slots:
|
||||
void handleFinishedDownload(const QString& url, const QString &file_path);
|
||||
void handleDownloadFailure(const QString &url, const QString& error);
|
||||
|
||||
private:
|
||||
short readDoc(QIODevice* device);
|
||||
bool parseRSS(QIODevice* device);
|
||||
void resizeList();
|
||||
short openRss();
|
||||
bool parseXmlFile(const QString &file_path);
|
||||
void downloadMatchingArticleTorrents();
|
||||
QString iconUrl() const;
|
||||
|
||||
private:
|
||||
RssFolder *parent;
|
||||
QString title;
|
||||
QString link;
|
||||
QString description;
|
||||
QString image;
|
||||
QString url;
|
||||
QString alias;
|
||||
QString filePath;
|
||||
QString iconPath;
|
||||
bool read;
|
||||
bool refreshed;
|
||||
bool downloadFailure;
|
||||
bool currently_loading;
|
||||
QHash<QString, RssArticle> m_articles;
|
||||
RssFolder *m_parent;
|
||||
QString m_title;
|
||||
QString m_url;
|
||||
QString m_alias;
|
||||
QString m_icon;
|
||||
QString m_iconUrl;
|
||||
bool m_read;
|
||||
bool m_refreshed;
|
||||
bool m_downloadFailure;
|
||||
bool m_loading;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -46,24 +46,23 @@ public:
|
|||
RssFile(): QObject() {}
|
||||
virtual ~RssFile() {}
|
||||
|
||||
virtual unsigned int getNbUnRead() const = 0;
|
||||
virtual FileType getType() const = 0;
|
||||
virtual QString getName() const = 0;
|
||||
virtual QString getID() const = 0;
|
||||
virtual void rename(QString new_name) = 0;
|
||||
virtual void markAllAsRead() = 0;
|
||||
virtual RssFolder* getParent() const = 0;
|
||||
virtual void setParent(RssFolder*) = 0;
|
||||
virtual unsigned int unreadCount() const = 0;
|
||||
virtual FileType type() const = 0;
|
||||
virtual QString displayName() const = 0;
|
||||
virtual QString id() const = 0;
|
||||
virtual void setAlias(const QString &new_name) = 0;
|
||||
virtual void markAsRead() = 0;
|
||||
virtual RssFolder* parent() const = 0;
|
||||
virtual void setParent(RssFolder* parent) = 0;
|
||||
virtual void refresh() = 0;
|
||||
virtual void removeAllSettings() = 0;
|
||||
virtual QList<RssArticle> getNewsList() const = 0;
|
||||
virtual QList<RssArticle> getUnreadNewsList() const = 0;
|
||||
QStringList getPath() const {
|
||||
virtual QList<RssArticle> articleList() const = 0;
|
||||
virtual QList<RssArticle> unreadArticleList() const = 0;
|
||||
QStringList pathHierarchy() const {
|
||||
QStringList path;
|
||||
if(getParent()) {
|
||||
path = ((RssFile*)getParent())->getPath();
|
||||
path.append(getID());
|
||||
}
|
||||
if(parent())
|
||||
path << ((RssFile*)parent())->pathHierarchy();
|
||||
path << id();
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,54 +37,26 @@
|
|||
#include "rssmanager.h"
|
||||
#include "rssfeed.h"
|
||||
|
||||
RssFolder::RssFolder(RssFolder *parent, QString name): parent(parent), name(name) {
|
||||
downloader = new DownloadThread(this);
|
||||
connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processFinishedDownload(QString, QString)));
|
||||
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
RssFolder::RssFolder(RssFolder *parent, QString name): m_parent(parent), m_name(name) {
|
||||
}
|
||||
|
||||
RssFolder::~RssFolder() {
|
||||
qDebug("Deleting a RSS folder, removing elements");
|
||||
qDeleteAll(this->values());
|
||||
qDebug("Deleting downloader thread");
|
||||
delete downloader;
|
||||
qDebug("Downloader thread removed");
|
||||
}
|
||||
|
||||
unsigned int RssFolder::getNbUnRead() const {
|
||||
unsigned int RssFolder::unreadCount() const {
|
||||
unsigned int nb_unread = 0;
|
||||
foreach(RssFile *file, this->values()) {
|
||||
nb_unread += file->getNbUnRead();
|
||||
nb_unread += file->unreadCount();
|
||||
}
|
||||
return nb_unread;
|
||||
}
|
||||
|
||||
RssFile::FileType RssFolder::getType() const {
|
||||
RssFile::FileType RssFolder::type() const {
|
||||
return RssFile::FOLDER;
|
||||
}
|
||||
|
||||
void RssFolder::refreshAll(){
|
||||
qDebug("Refreshing all rss feeds");
|
||||
const QList<RssFile*> items = this->values();
|
||||
for(int i=0; i<items.size(); ++i) {
|
||||
//foreach(RssFile *item, *this){
|
||||
RssFile *item = items.at(i);
|
||||
if(item->getType() == RssFile::FEED) {
|
||||
RssFeed* stream = (RssFeed*) item;
|
||||
QString url = stream->getUrl();
|
||||
if(stream->isLoading()) return;
|
||||
stream->setLoading(true);
|
||||
downloader->downloadUrl(url);
|
||||
if(!stream->hasCustomIcon()){
|
||||
downloader->downloadUrl(stream->getIconUrl());
|
||||
}
|
||||
} else {
|
||||
RssFolder *folder = (RssFolder*)item;
|
||||
folder->refreshAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RssFolder::removeFile(QString ID) {
|
||||
if(this->contains(ID)) {
|
||||
RssFile* child = this->take(ID);
|
||||
|
@ -106,57 +78,35 @@ RssFolder* RssFolder::addFolder(QString name) {
|
|||
|
||||
RssFeed* RssFolder::addStream(QString url) {
|
||||
RssFeed* stream = new RssFeed(this, url);
|
||||
Q_ASSERT(!this->contains(stream->getUrl()));
|
||||
(*this)[stream->getUrl()] = stream;
|
||||
refreshStream(stream->getUrl());
|
||||
Q_ASSERT(!this->contains(stream->url()));
|
||||
(*this)[stream->url()] = stream;
|
||||
stream->refresh();
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Refresh All Children
|
||||
void RssFolder::refresh() {
|
||||
foreach(RssFile *child, this->values()) {
|
||||
// Little optimization child->refresh() would work too
|
||||
if(child->getType() == RssFile::FEED)
|
||||
refreshStream(child->getID());
|
||||
else
|
||||
child->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
QList<RssArticle> RssFolder::getNewsList() const {
|
||||
QList<RssArticle> RssFolder::articleList() const {
|
||||
QList<RssArticle> news;
|
||||
foreach(const RssFile *child, this->values()) {
|
||||
news << child->getNewsList();
|
||||
news << child->articleList();
|
||||
}
|
||||
return news;
|
||||
}
|
||||
|
||||
QList<RssArticle> RssFolder::getUnreadNewsList() const {
|
||||
QList<RssArticle> RssFolder::unreadArticleList() const {
|
||||
QList<RssArticle> unread_news;
|
||||
foreach(const RssFile *child, this->values()) {
|
||||
unread_news << child->getUnreadNewsList();
|
||||
unread_news << child->unreadArticleList();
|
||||
}
|
||||
return unread_news;
|
||||
}
|
||||
|
||||
void RssFolder::refreshStream(QString url) {
|
||||
qDebug("Refreshing feed: %s", url.toLocal8Bit().data());
|
||||
Q_ASSERT(this->contains(url));
|
||||
RssFeed *stream = (RssFeed*)this->value(url);
|
||||
if(stream->isLoading()) {
|
||||
qDebug("Stream %s is already being loaded...", stream->getUrl().toLocal8Bit().data());
|
||||
return;
|
||||
}
|
||||
stream->setLoading(true);
|
||||
qDebug("stream %s : loaded=true", stream->getUrl().toLocal8Bit().data());
|
||||
downloader->downloadUrl(url);
|
||||
if(!stream->hasCustomIcon()){
|
||||
downloader->downloadUrl(stream->getIconUrl());
|
||||
}else{
|
||||
qDebug("No need to download this feed's icon, it was already downloaded");
|
||||
}
|
||||
}
|
||||
|
||||
QList<RssFile*> RssFolder::getContent() const {
|
||||
return this->values();
|
||||
}
|
||||
|
@ -164,7 +114,7 @@ QList<RssFile*> RssFolder::getContent() const {
|
|||
unsigned int RssFolder::getNbFeeds() const {
|
||||
unsigned int nbFeeds = 0;
|
||||
foreach(RssFile* item, this->values()) {
|
||||
if(item->getType() == RssFile::FOLDER)
|
||||
if(item->type() == RssFile::FOLDER)
|
||||
nbFeeds += ((RssFolder*)item)->getNbFeeds();
|
||||
else
|
||||
nbFeeds += 1;
|
||||
|
@ -172,90 +122,30 @@ unsigned int RssFolder::getNbFeeds() const {
|
|||
return nbFeeds;
|
||||
}
|
||||
|
||||
void RssFolder::processFinishedDownload(QString url, QString path) {
|
||||
if(url.endsWith("favicon.ico")){
|
||||
// Icon downloaded
|
||||
QImage fileIcon;
|
||||
if(fileIcon.load(path)) {
|
||||
QList<RssFeed*> res = findFeedsWithIcon(url);
|
||||
foreach(RssFeed* stream, res){
|
||||
stream->setIconPath(path);
|
||||
if(!stream->isLoading())
|
||||
RssManager::instance()->forwardFeedIconChanged(stream->getUrl(), stream->getIconPath());
|
||||
}
|
||||
}else{
|
||||
qDebug("Unsupported icon format at %s", (const char*)url.toLocal8Bit());
|
||||
}
|
||||
return;
|
||||
}
|
||||
RssFeed *stream = static_cast<RssFeed*>(this->value(url, 0));
|
||||
if(!stream){
|
||||
qDebug("This rss stream was deleted in the meantime, nothing to update");
|
||||
return;
|
||||
}
|
||||
stream->processDownloadedFile(path);
|
||||
stream->setLoading(false);
|
||||
qDebug("stream %s : loaded=false", stream->getUrl().toLocal8Bit().data());
|
||||
// If the feed has no alias, then we use the title as Alias
|
||||
// this is more user friendly
|
||||
if(stream->getName().isEmpty()){
|
||||
if(!stream->getTitle().isEmpty())
|
||||
stream->rename(stream->getTitle());
|
||||
}
|
||||
RssManager::instance()->forwardFeedInfosChanged(url, stream->getName(), stream->getNbUnRead());
|
||||
QString RssFolder::displayName() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void RssFolder::handleDownloadFailure(QString url, QString reason) {
|
||||
if(url.endsWith("favicon.ico")){
|
||||
// Icon download failure
|
||||
qDebug("Could not download icon at %s, reason: %s", (const char*)url.toLocal8Bit(), (const char*)reason.toLocal8Bit());
|
||||
return;
|
||||
}
|
||||
RssFeed *stream = static_cast<RssFeed*>(this->value(url, 0));
|
||||
if(!stream){
|
||||
qDebug("This rss stream was deleted in the meantime, nothing to update");
|
||||
return;
|
||||
}
|
||||
stream->setLoading(false);
|
||||
qDebug("Could not download Rss at %s, reason: %s", (const char*)url.toLocal8Bit(), (const char*)reason.toLocal8Bit());
|
||||
stream->setDownloadFailed();
|
||||
RssManager::instance()->forwardFeedInfosChanged(url, stream->getName(), stream->getNbUnRead());
|
||||
}
|
||||
|
||||
QList<RssFeed*> RssFolder::findFeedsWithIcon(QString icon_url) const {
|
||||
QList<RssFeed*> res;
|
||||
RssFile* item;
|
||||
foreach(item, this->values()){
|
||||
if(item->getType() == RssFile::FEED && ((RssFeed*)item)->getIconUrl() == icon_url)
|
||||
res << (RssFeed*)item;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QString RssFolder::getName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void RssFolder::rename(QString new_name) {
|
||||
Q_ASSERT(!parent->contains(new_name));
|
||||
if(!parent->contains(new_name)) {
|
||||
void RssFolder::setAlias(const QString &new_name) {
|
||||
Q_ASSERT(!m_parent->contains(new_name));
|
||||
if(!m_parent->contains(new_name)) {
|
||||
// Update parent
|
||||
(*parent)[new_name] = parent->take(name);
|
||||
(*m_parent)[new_name] = m_parent->take(m_name);
|
||||
// Actually rename
|
||||
name = new_name;
|
||||
m_name = new_name;
|
||||
}
|
||||
}
|
||||
|
||||
void RssFolder::markAllAsRead() {
|
||||
void RssFolder::markAsRead() {
|
||||
foreach(RssFile *item, this->values()) {
|
||||
item->markAllAsRead();
|
||||
item->markAsRead();
|
||||
}
|
||||
}
|
||||
|
||||
QList<RssFeed*> RssFolder::getAllFeeds() const {
|
||||
QList<RssFeed*> streams;
|
||||
foreach(RssFile *item, this->values()) {
|
||||
if(item->getType() == RssFile::FEED) {
|
||||
if(item->type() == RssFile::FEED) {
|
||||
streams << static_cast<RssFeed*>(item);
|
||||
} else {
|
||||
streams << static_cast<RssFolder*>(item)->getAllFeeds();
|
||||
|
@ -267,11 +157,11 @@ QList<RssFeed*> RssFolder::getAllFeeds() const {
|
|||
QHash<QString, RssFeed*> RssFolder::getAllFeedsAsHash() const {
|
||||
QHash<QString, RssFeed*> ret;
|
||||
foreach(RssFile *item, this->values()) {
|
||||
if(item->getType() == RssFile::FEED) {
|
||||
if(item->type() == RssFile::FEED) {
|
||||
RssFeed* feed = dynamic_cast<RssFeed*>(item);
|
||||
Q_ASSERT(feed);
|
||||
qDebug() << Q_FUNC_INFO << feed->getUrl();
|
||||
ret[feed->getUrl()] = feed;
|
||||
qDebug() << Q_FUNC_INFO << feed->url();
|
||||
ret[feed->url()] = feed;
|
||||
} else {
|
||||
ret.unite(static_cast<RssFolder*>(item)->getAllFeedsAsHash());
|
||||
}
|
||||
|
@ -280,14 +170,14 @@ QHash<QString, RssFeed*> RssFolder::getAllFeedsAsHash() const {
|
|||
}
|
||||
|
||||
void RssFolder::addFile(RssFile * item) {
|
||||
if(item->getType() == RssFile::FEED) {
|
||||
Q_ASSERT(!this->contains(((RssFeed*)item)->getUrl()));
|
||||
(*this)[((RssFeed*)item)->getUrl()] = item;
|
||||
qDebug("Added feed %s to folder ./%s", ((RssFeed*)item)->getUrl().toLocal8Bit().data(), name.toLocal8Bit().data());
|
||||
if(item->type() == RssFile::FEED) {
|
||||
Q_ASSERT(!this->contains(((RssFeed*)item)->url()));
|
||||
(*this)[((RssFeed*)item)->url()] = item;
|
||||
qDebug("Added feed %s to folder ./%s", ((RssFeed*)item)->url().toLocal8Bit().data(), m_name.toLocal8Bit().data());
|
||||
} else {
|
||||
Q_ASSERT(!this->contains(((RssFolder*)item)->getName()));
|
||||
(*this)[((RssFolder*)item)->getName()] = item;
|
||||
qDebug("Added folder %s to folder ./%s", ((RssFolder*)item)->getName().toLocal8Bit().data(), name.toLocal8Bit().data());
|
||||
Q_ASSERT(!this->contains(((RssFolder*)item)->displayName()));
|
||||
(*this)[((RssFolder*)item)->displayName()] = item;
|
||||
qDebug("Added folder %s to folder ./%s", ((RssFolder*)item)->displayName().toLocal8Bit().data(), m_name.toLocal8Bit().data());
|
||||
}
|
||||
// Update parent
|
||||
item->setParent(this);
|
||||
|
@ -304,8 +194,8 @@ void RssFolder::removeAllSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
QString RssFolder::getID() const {
|
||||
return name;
|
||||
QString RssFolder::id() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool RssFolder::hasChild(QString ID) {
|
||||
|
|
|
@ -45,40 +45,34 @@ class RssFolder: public RssFile, public QHash<QString, RssFile*> {
|
|||
public:
|
||||
RssFolder(RssFolder *parent = 0, QString name = QString());
|
||||
~RssFolder();
|
||||
RssFolder* getParent() const { return parent; }
|
||||
void setParent(RssFolder* _parent) { parent = _parent; }
|
||||
unsigned int getNbUnRead() const;
|
||||
FileType getType() const;
|
||||
RssFolder* parent() const { return m_parent; }
|
||||
void setParent(RssFolder* parent) { m_parent = parent; }
|
||||
unsigned int unreadCount() const;
|
||||
FileType type() const;
|
||||
RssFeed* addStream(QString url);
|
||||
RssFolder* addFolder(QString name);
|
||||
QList<RssFeed*> findFeedsWithIcon(QString icon_url) const;
|
||||
unsigned int getNbFeeds() const;
|
||||
QList<RssFile*> getContent() const;
|
||||
QList<RssFeed*> getAllFeeds() const;
|
||||
QHash<QString, RssFeed*> getAllFeedsAsHash() const;
|
||||
QString getName() const;
|
||||
QString getID() const;
|
||||
QString displayName() const;
|
||||
QString id() const;
|
||||
bool hasChild(QString ID);
|
||||
QList<RssArticle> getNewsList() const;
|
||||
QList<RssArticle> getUnreadNewsList() const;
|
||||
QList<RssArticle> articleList() const;
|
||||
QList<RssArticle> unreadArticleList() const;
|
||||
void removeAllSettings();
|
||||
void removeAllItems();
|
||||
|
||||
public slots:
|
||||
void refreshAll();
|
||||
void refresh();
|
||||
void addFile(RssFile * item);
|
||||
void removeFile(QString ID);
|
||||
void refresh();
|
||||
void refreshStream(QString url);
|
||||
void processFinishedDownload(QString url, QString path);
|
||||
void handleDownloadFailure(QString url, QString reason);
|
||||
void rename(QString new_name);
|
||||
void markAllAsRead();
|
||||
void setAlias(const QString &new_name);
|
||||
void markAsRead();
|
||||
|
||||
private:
|
||||
RssFolder *parent;
|
||||
DownloadThread *downloader;
|
||||
QString name;
|
||||
RssFolder *m_parent;
|
||||
QString m_name;
|
||||
};
|
||||
|
||||
#endif // RSSFOLDER_H
|
||||
|
|
|
@ -34,18 +34,20 @@
|
|||
#include "rssfeed.h"
|
||||
#include "rssarticle.h"
|
||||
#include "rssdownloadrulelist.h"
|
||||
#include "downloadthread.h"
|
||||
|
||||
RssManager* RssManager::m_instance = 0;
|
||||
|
||||
RssManager::RssManager(): RssFolder() {
|
||||
loadStreamList();
|
||||
connect(&newsRefresher, SIGNAL(timeout()), this, SLOT(refreshAll()));
|
||||
m_rssDownloader = new DownloadThread(this);
|
||||
connect(&newsRefresher, SIGNAL(timeout()), this, SLOT(refresh()));
|
||||
refreshInterval = RssSettings().getRSSRefreshInterval();
|
||||
newsRefresher.start(refreshInterval*60000);
|
||||
}
|
||||
|
||||
RssManager::~RssManager(){
|
||||
qDebug("Deleting RSSManager");
|
||||
delete m_rssDownloader;
|
||||
RssDownloadRuleList::drop();
|
||||
saveStreamList();
|
||||
qDebug("RSSManager deleted");
|
||||
|
@ -67,21 +69,25 @@ void RssManager::loadStreamList() {
|
|||
std::cerr << "Corrupted Rss list, not loading it\n";
|
||||
return;
|
||||
}
|
||||
unsigned int i = 0;
|
||||
uint i = 0;
|
||||
qDebug() << Q_FUNC_INFO << streamsUrl;
|
||||
foreach(QString s, streamsUrl){
|
||||
QStringList path = s.split("\\");
|
||||
QStringList path = s.split("\\", QString::SkipEmptyParts);
|
||||
if(path.empty()) continue;
|
||||
QString feed_url = path.takeLast();
|
||||
const QString feed_url = path.takeLast();
|
||||
qDebug() << "Feed URL:" << feed_url;
|
||||
// Create feed path (if it does not exists)
|
||||
RssFolder * feed_parent = this;
|
||||
foreach(QString folder_name, path) {
|
||||
foreach(const QString &folder_name, path) {
|
||||
qDebug() << "Adding parent folder:" << folder_name;
|
||||
feed_parent = feed_parent->addFolder(folder_name);
|
||||
}
|
||||
// Create feed
|
||||
qDebug() << "Adding feed to parent folder";
|
||||
RssFeed *stream = feed_parent->addStream(feed_url);
|
||||
QString alias = aliases.at(i);
|
||||
const QString alias = aliases.at(i);
|
||||
if(!alias.isEmpty()) {
|
||||
stream->rename(alias);
|
||||
stream->setAlias(alias);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
@ -97,12 +103,12 @@ void RssManager::forwardFeedIconChanged(QString url, QString icon_path) {
|
|||
}
|
||||
|
||||
void RssManager::moveFile(RssFile* file, RssFolder* dest_folder) {
|
||||
RssFolder* src_folder = file->getParent();
|
||||
RssFolder* src_folder = file->parent();
|
||||
if(dest_folder != src_folder) {
|
||||
// Copy to new Folder
|
||||
dest_folder->addFile(file);
|
||||
// Remove reference in old folder
|
||||
src_folder->remove(file->getID());
|
||||
src_folder->remove(file->id());
|
||||
} else {
|
||||
qDebug("Nothing to move, same destination folder");
|
||||
}
|
||||
|
@ -113,13 +119,13 @@ void RssManager::saveStreamList(){
|
|||
QStringList aliases;
|
||||
const QList<RssFeed*> streams = getAllFeeds();
|
||||
foreach(const RssFeed *stream, streams) {
|
||||
QString stream_path = stream->getPath().join("\\");
|
||||
QString stream_path = stream->pathHierarchy().join("\\");
|
||||
if(stream_path.isNull()) {
|
||||
stream_path = "";
|
||||
}
|
||||
qDebug("Saving stream path: %s", qPrintable(stream_path));
|
||||
streamsUrl << stream_path;
|
||||
aliases << stream->getName();
|
||||
aliases << stream->displayName();
|
||||
}
|
||||
RssSettings settings;
|
||||
settings.setRssFeedsUrls(streamsUrl);
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include "rssfolder.h"
|
||||
|
||||
class DownloadThread;
|
||||
|
||||
class RssManager: public RssFolder {
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
@ -45,6 +47,7 @@ public:
|
|||
static RssManager* instance();
|
||||
static void drop();
|
||||
~RssManager();
|
||||
inline DownloadThread* rssDownloader() const { return m_rssDownloader; }
|
||||
static void insertSortElem(QList<RssArticle> &list, const RssArticle &item);
|
||||
static QList<RssArticle> sortNewsList(const QList<RssArticle>& news_list);
|
||||
|
||||
|
@ -63,6 +66,7 @@ signals:
|
|||
private:
|
||||
QTimer newsRefresher;
|
||||
unsigned int refreshInterval;
|
||||
DownloadThread *m_rssDownloader;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue