mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-24 10:16:00 +03:00
- Display "Unread" item in RSS Feed list which displays all unread items
This commit is contained in:
parent
a0923741a4
commit
480d00d747
8 changed files with 170 additions and 115 deletions
BIN
src/Icons/oxygen/mail-folder-inbox.png
Normal file
BIN
src/Icons/oxygen/mail-folder-inbox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 739 B |
|
@ -18,6 +18,7 @@ private:
|
||||||
QHash<QTreeWidgetItem*, RssFile*> mapping;
|
QHash<QTreeWidgetItem*, RssFile*> mapping;
|
||||||
QHash<QString, QTreeWidgetItem*> feeds_items;
|
QHash<QString, QTreeWidgetItem*> feeds_items;
|
||||||
QTreeWidgetItem* current_feed;
|
QTreeWidgetItem* current_feed;
|
||||||
|
QTreeWidgetItem *unread_item;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FeedList(QWidget *parent, RssManager *rssmanager): QTreeWidget(parent), rssmanager(rssmanager) {
|
FeedList(QWidget *parent, RssManager *rssmanager): QTreeWidget(parent), rssmanager(rssmanager) {
|
||||||
|
@ -28,14 +29,17 @@ public:
|
||||||
QTreeWidgetItem *___qtreewidgetitem = headerItem();
|
QTreeWidgetItem *___qtreewidgetitem = headerItem();
|
||||||
___qtreewidgetitem->setText(0, QApplication::translate("RSS", "RSS feeds", 0, QApplication::UnicodeUTF8));
|
___qtreewidgetitem->setText(0, QApplication::translate("RSS", "RSS feeds", 0, QApplication::UnicodeUTF8));
|
||||||
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
|
||||||
}
|
unread_item = new QTreeWidgetItem(this);
|
||||||
|
unread_item->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->getNbUnRead(), 10)+ QString(")"));
|
||||||
|
unread_item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/mail-folder-inbox.png")));
|
||||||
|
itemAdded(unread_item, rssmanager);
|
||||||
|
setCurrentItem(unread_item);
|
||||||
|
}
|
||||||
|
|
||||||
void itemAdded(QTreeWidgetItem *item, RssFile* file) {
|
void itemAdded(QTreeWidgetItem *item, RssFile* file) {
|
||||||
mapping[item] = file;
|
mapping[item] = file;
|
||||||
if(file->getType() == RssFile::STREAM) {
|
if(file->getType() == RssFile::STREAM) {
|
||||||
feeds_items[file->getID()] = item;
|
feeds_items[file->getID()] = item;
|
||||||
if(topLevelItemCount() == 1)
|
|
||||||
setCurrentItem(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,15 +49,19 @@ public:
|
||||||
feeds_items.remove(file->getID());
|
feeds_items.remove(file->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasFeed(QString url) {
|
bool hasFeed(QString url) const {
|
||||||
return feeds_items.contains(QUrl(url).toString());
|
return feeds_items.contains(QUrl(url).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> getAllFeedItems() {
|
QList<QTreeWidgetItem*> getAllFeedItems() const {
|
||||||
return feeds_items.values();
|
return feeds_items.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList getItemPath(QTreeWidgetItem* item) {
|
QTreeWidgetItem* getUnreadItem() const {
|
||||||
|
return unread_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList getItemPath(QTreeWidgetItem* item) const {
|
||||||
QStringList path;
|
QStringList path;
|
||||||
if(item) {
|
if(item) {
|
||||||
if(item->parent())
|
if(item->parent())
|
||||||
|
@ -63,7 +71,7 @@ public:
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> getAllOpenFolders(QTreeWidgetItem *parent=0) {
|
QList<QTreeWidgetItem*> getAllOpenFolders(QTreeWidgetItem *parent=0) const {
|
||||||
QList<QTreeWidgetItem*> open_folders;
|
QList<QTreeWidgetItem*> open_folders;
|
||||||
int nbChildren;
|
int nbChildren;
|
||||||
if(parent)
|
if(parent)
|
||||||
|
@ -102,19 +110,15 @@ public:
|
||||||
return feeds;
|
return feeds;
|
||||||
}
|
}
|
||||||
|
|
||||||
RssFile* getRSSItem(QTreeWidgetItem *item) {
|
RssFile* getRSSItem(QTreeWidgetItem *item) const {
|
||||||
return mapping[item];
|
return mapping[item];
|
||||||
}
|
}
|
||||||
|
|
||||||
RssFile* getCurrentRSSItem() {
|
RssFile::FileType getItemType(QTreeWidgetItem *item) const {
|
||||||
return mapping[current_feed];
|
|
||||||
}
|
|
||||||
|
|
||||||
RssFile::FileType getItemType(QTreeWidgetItem *item) {
|
|
||||||
return mapping[item]->getType();
|
return mapping[item]->getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getItemID(QTreeWidgetItem *item) {
|
QString getItemID(QTreeWidgetItem *item) const {
|
||||||
return mapping[item]->getID();
|
return mapping[item]->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +126,10 @@ public:
|
||||||
return feeds_items[url];
|
return feeds_items[url];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RssStream* getRSSItemFromUrl(QString url) const {
|
||||||
|
return (RssStream*)getRSSItem(getTreeItemFromUrl(url));
|
||||||
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* currentItem() const {
|
QTreeWidgetItem* currentItem() const {
|
||||||
return current_feed;
|
return current_feed;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +144,7 @@ signals:
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void updateCurrentFeed(QTreeWidgetItem* new_item) {
|
void updateCurrentFeed(QTreeWidgetItem* new_item) {
|
||||||
if(new_item && getItemType(new_item) == RssFile::STREAM)
|
if((new_item && getItemType(new_item) == RssFile::STREAM) || new_item == unread_item)
|
||||||
current_feed = new_item;
|
current_feed = new_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +154,11 @@ protected:
|
||||||
if(item && getItemType(item) != RssFile::FOLDER)
|
if(item && getItemType(item) != RssFile::FOLDER)
|
||||||
event->ignore();
|
event->ignore();
|
||||||
else {
|
else {
|
||||||
QTreeWidget::dragMoveEvent(event);
|
if(selectedItems().contains(unread_item)) {
|
||||||
|
event->ignore();
|
||||||
|
} else {
|
||||||
|
QTreeWidget::dragMoveEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
<file>Icons/flags/japan.png</file>
|
<file>Icons/flags/japan.png</file>
|
||||||
<file>Icons/oxygen/view-refresh.png</file>
|
<file>Icons/oxygen/view-refresh.png</file>
|
||||||
<file>Icons/oxygen/file.png</file>
|
<file>Icons/oxygen/file.png</file>
|
||||||
|
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||||
<file>Icons/oxygen/time.png</file>
|
<file>Icons/oxygen/time.png</file>
|
||||||
<file>Icons/oxygen/folder-new.png</file>
|
<file>Icons/oxygen/folder-new.png</file>
|
||||||
<file>Icons/oxygen/edit-paste.png</file>
|
<file>Icons/oxygen/edit-paste.png</file>
|
||||||
|
|
96
src/rss.cpp
96
src/rss.cpp
|
@ -117,6 +117,22 @@ void RssFolder::refresh() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<RssItem*> RssFolder::getNewsList() const {
|
||||||
|
QList<RssItem*> news;
|
||||||
|
foreach(RssFile *child, this->values()) {
|
||||||
|
news.append(child->getNewsList());
|
||||||
|
}
|
||||||
|
return news;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<RssItem*> RssFolder::getUnreadNewsList() const {
|
||||||
|
QList<RssItem*> unread_news;
|
||||||
|
foreach(RssFile *child, this->values()) {
|
||||||
|
unread_news.append(child->getUnreadNewsList());
|
||||||
|
}
|
||||||
|
return unread_news;
|
||||||
|
}
|
||||||
|
|
||||||
void RssFolder::refreshStream(QString url) {
|
void RssFolder::refreshStream(QString url) {
|
||||||
qDebug("Refreshing feed: %s", url.toLocal8Bit().data());
|
qDebug("Refreshing feed: %s", url.toLocal8Bit().data());
|
||||||
Q_ASSERT(this->contains(url));
|
Q_ASSERT(this->contains(url));
|
||||||
|
@ -349,9 +365,9 @@ RssStream::RssStream(RssFolder* parent, RssManager *rssmanager, bittorrent *BTSe
|
||||||
qDebug("Loading %d old items for feed %s", old_items.size(), getName().toLocal8Bit().data());
|
qDebug("Loading %d old items for feed %s", old_items.size(), getName().toLocal8Bit().data());
|
||||||
foreach(const QVariant &var_it, old_items) {
|
foreach(const QVariant &var_it, old_items) {
|
||||||
QHash<QString, QVariant> item = var_it.toHash();
|
QHash<QString, QVariant> item = var_it.toHash();
|
||||||
RssItem *rss_item = RssItem::fromHash(item);
|
RssItem *rss_item = RssItem::fromHash(this, item);
|
||||||
if(rss_item->isValid())
|
if(rss_item->isValid())
|
||||||
listItem << rss_item;
|
(*this)[rss_item->getTitle()] = rss_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +376,7 @@ RssStream::~RssStream(){
|
||||||
if(refreshed) {
|
if(refreshed) {
|
||||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||||
QVariantList old_items;
|
QVariantList old_items;
|
||||||
foreach(RssItem *item, listItem) {
|
foreach(RssItem *item, this->values()) {
|
||||||
old_items << item->toHash();
|
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(), getName().toLocal8Bit().data());
|
||||||
|
@ -387,16 +403,12 @@ void RssStream::refresh() {
|
||||||
|
|
||||||
// delete all the items saved
|
// delete all the items saved
|
||||||
void RssStream::removeAllItems() {
|
void RssStream::removeAllItems() {
|
||||||
qDeleteAll(listItem);
|
qDeleteAll(this->values());
|
||||||
listItem.clear();
|
this->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RssStream::itemAlreadyExists(QString hash) {
|
bool RssStream::itemAlreadyExists(QString name) {
|
||||||
RssItem * item;
|
return this->contains(name);
|
||||||
foreach(item, listItem) {
|
|
||||||
if(item->getHash() == hash) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RssStream::setLoading(bool val) {
|
void RssStream::setLoading(bool val) {
|
||||||
|
@ -464,27 +476,24 @@ void RssStream::setIconPath(QString path) {
|
||||||
iconPath = path;
|
iconPath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
RssItem* RssStream::getItem(unsigned int index) const{
|
RssItem* RssStream::getItem(QString name) const{
|
||||||
return listItem.at(index);
|
return this->value(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int RssStream::getNbNews() const{
|
unsigned int RssStream::getNbNews() const{
|
||||||
return listItem.size();
|
return this->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RssStream::markAllAsRead() {
|
void RssStream::markAllAsRead() {
|
||||||
RssItem *item;
|
foreach(RssItem *item, this->values()){
|
||||||
foreach(item, listItem){
|
item->setRead();
|
||||||
if(!item->isRead())
|
|
||||||
item->setRead();
|
|
||||||
}
|
}
|
||||||
rssmanager->forwardFeedInfosChanged(url, getName(), 0);
|
rssmanager->forwardFeedInfosChanged(url, getName(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int RssStream::getNbUnRead() const{
|
unsigned int RssStream::getNbUnRead() const{
|
||||||
unsigned int nbUnread=0;
|
unsigned int nbUnread=0;
|
||||||
RssItem *item;
|
foreach(RssItem *item, this->values()) {
|
||||||
foreach(item, listItem){
|
|
||||||
if(!item->isRead())
|
if(!item->isRead())
|
||||||
++nbUnread;
|
++nbUnread;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +501,16 @@ unsigned int RssStream::getNbUnRead() const{
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<RssItem*> RssStream::getNewsList() const{
|
QList<RssItem*> RssStream::getNewsList() const{
|
||||||
return listItem;
|
return this->values();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<RssItem*> RssStream::getUnreadNewsList() const {
|
||||||
|
QList<RssItem*> unread_news;
|
||||||
|
foreach(RssItem *item, this->values()) {
|
||||||
|
if(!item->isRead())
|
||||||
|
unread_news << item;
|
||||||
|
}
|
||||||
|
return unread_news;
|
||||||
}
|
}
|
||||||
|
|
||||||
// download the icon from the adress
|
// download the icon from the adress
|
||||||
|
@ -533,9 +551,9 @@ short RssStream::readDoc(const QDomDocument& doc) {
|
||||||
else if (property.tagName() == "image")
|
else if (property.tagName() == "image")
|
||||||
image = property.text();
|
image = property.text();
|
||||||
else if(property.tagName() == "item") {
|
else if(property.tagName() == "item") {
|
||||||
RssItem * item = new RssItem(property);
|
RssItem * item = new RssItem(this, property);
|
||||||
if(item->isValid() && !itemAlreadyExists(item->getHash())) {
|
if(item->isValid() && !itemAlreadyExists(item->getTitle())) {
|
||||||
listItem.append(item);
|
(*this)[item->getTitle()] = item;
|
||||||
// Check if the item should be automatically downloaded
|
// Check if the item should be automatically downloaded
|
||||||
FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle());
|
FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle());
|
||||||
if(matching_filter != 0) {
|
if(matching_filter != 0) {
|
||||||
|
@ -565,35 +583,21 @@ short RssStream::readDoc(const QDomDocument& doc) {
|
||||||
}
|
}
|
||||||
channel = channel.nextSibling().toElement();
|
channel = channel.nextSibling().toElement();
|
||||||
}
|
}
|
||||||
sortList();
|
|
||||||
resizeList();
|
resizeList();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RssStream::insertSortElem(QList<RssItem*> &list, RssItem *item) {
|
|
||||||
int i = 0;
|
|
||||||
while(i < list.size() && item->getDate() < list.at(i)->getDate()) {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
list.insert(i, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RssStream::sortList() {
|
|
||||||
QList<RssItem*> new_list;
|
|
||||||
RssItem *item;
|
|
||||||
foreach(item, listItem) {
|
|
||||||
insertSortElem(new_list, item);
|
|
||||||
}
|
|
||||||
listItem = new_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RssStream::resizeList() {
|
void RssStream::resizeList() {
|
||||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||||
unsigned int max_articles = settings.value(QString::fromUtf8("Preferences/RSS/RSSMaxArticlesPerFeed"), 100).toInt();
|
unsigned int max_articles = settings.value(QString::fromUtf8("Preferences/RSS/RSSMaxArticlesPerFeed"), 100).toInt();
|
||||||
int excess = listItem.size() - max_articles;
|
unsigned int nb_articles = this->size();
|
||||||
if(excess <= 0) return;
|
if(nb_articles > max_articles) {
|
||||||
for(int i=0; i<excess; ++i){
|
QList<RssItem*> listItem = sortNewsList(this->values());
|
||||||
delete listItem.takeLast();
|
int excess = nb_articles - max_articles;
|
||||||
|
for(int i=0; i<excess; ++i){
|
||||||
|
RssItem *lastItem = listItem.takeLast();
|
||||||
|
delete this->take(lastItem->getTitle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
52
src/rss.h
52
src/rss.h
|
@ -42,7 +42,6 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QCryptographicHash>
|
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "FeedDownloader.h"
|
#include "FeedDownloader.h"
|
||||||
|
@ -94,6 +93,8 @@ public:
|
||||||
virtual RssFolder* getParent() const = 0;
|
virtual RssFolder* getParent() const = 0;
|
||||||
virtual void setParent(RssFolder*) = 0;
|
virtual void setParent(RssFolder*) = 0;
|
||||||
virtual void refresh() = 0;
|
virtual void refresh() = 0;
|
||||||
|
virtual QList<RssItem*> getNewsList() const = 0;
|
||||||
|
virtual QList<RssItem*> getUnreadNewsList() const = 0;
|
||||||
QStringList getPath() const {
|
QStringList getPath() const {
|
||||||
QStringList path;
|
QStringList path;
|
||||||
if(getParent()) {
|
if(getParent()) {
|
||||||
|
@ -108,14 +109,13 @@ public:
|
||||||
class RssItem: public QObject {
|
class RssItem: public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
|
RssStream* parent;
|
||||||
QString title;
|
QString title;
|
||||||
QString torrent_url;
|
QString torrent_url;
|
||||||
QString news_link;
|
QString news_link;
|
||||||
QString description;
|
QString description;
|
||||||
QDateTime date;
|
QDateTime date;
|
||||||
QString author;
|
QString author;
|
||||||
QString hash;
|
|
||||||
|
|
||||||
|
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
|
@ -255,7 +255,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// public constructor
|
// public constructor
|
||||||
RssItem(const QDomElement& properties): read(false) {
|
RssItem(RssStream* parent, const QDomElement& properties): parent(parent), read(false) {
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
torrent_url = QString::null;
|
torrent_url = QString::null;
|
||||||
news_link = QString::null;
|
news_link = QString::null;
|
||||||
|
@ -292,18 +292,16 @@ public:
|
||||||
author = property.text();
|
author = property.text();
|
||||||
property = property.nextSibling().toElement();
|
property = property.nextSibling().toElement();
|
||||||
}
|
}
|
||||||
hash = QCryptographicHash::hash(QByteArray(title.toLocal8Bit()), QCryptographicHash::Md5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RssItem(QString _title, QString _torrent_url, QString _news_link, QString _description, QDateTime _date, QString _author, bool _read):
|
RssItem(RssStream* parent, QString _title, QString _torrent_url, QString _news_link, QString _description, QDateTime _date, QString _author, bool _read):
|
||||||
title(_title), torrent_url(_torrent_url), news_link(_news_link), description(_description), date(_date), author(_author), read(_read){
|
parent(parent), title(_title), torrent_url(_torrent_url), news_link(_news_link), description(_description), date(_date), author(_author), read(_read){
|
||||||
if(!title.isEmpty() && !torrent_url.isEmpty()) {
|
if(!title.isEmpty() && !torrent_url.isEmpty()) {
|
||||||
is_valid = true;
|
is_valid = true;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "ERROR: an invalid RSS item was saved" << std::endl;
|
std::cerr << "ERROR: an invalid RSS item was saved" << std::endl;
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
}
|
}
|
||||||
hash = QCryptographicHash::hash(QByteArray(title.toLocal8Bit()), QCryptographicHash::Md5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~RssItem(){
|
~RssItem(){
|
||||||
|
@ -321,12 +319,16 @@ public:
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RssItem* fromHash(QHash<QString, QVariant> h) {
|
static RssItem* fromHash(RssStream* parent, QHash<QString, QVariant> h) {
|
||||||
RssItem * item = new RssItem(h["title"].toString(), h["torrent_url"].toString(), h["news_link"].toString(),
|
RssItem * item = new RssItem(parent, h["title"].toString(), h["torrent_url"].toString(), h["news_link"].toString(),
|
||||||
h["description"].toString(), h["date"].toDateTime(), h["author"].toString(), h["read"].toBool());
|
h["description"].toString(), h["date"].toDateTime(), h["author"].toString(), h["read"].toBool());
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RssStream* getParent() const {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
bool isValid() const {
|
bool isValid() const {
|
||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
@ -343,10 +345,6 @@ public:
|
||||||
return torrent_url;
|
return torrent_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getHash() const {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString getLink() const {
|
QString getLink() const {
|
||||||
return news_link;
|
return news_link;
|
||||||
}
|
}
|
||||||
|
@ -371,7 +369,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rss stream, loaded form an xml file
|
// Rss stream, loaded form an xml file
|
||||||
class RssStream: public RssFile {
|
class RssStream: public RssFile, public QHash<QString, RssItem*> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -386,7 +384,6 @@ private:
|
||||||
QString alias;
|
QString alias;
|
||||||
QString filePath;
|
QString filePath;
|
||||||
QString iconPath;
|
QString iconPath;
|
||||||
QList<RssItem*> listItem;
|
|
||||||
bool read;
|
bool read;
|
||||||
bool refreshed;
|
bool refreshed;
|
||||||
bool downloadFailure;
|
bool downloadFailure;
|
||||||
|
@ -419,17 +416,16 @@ public:
|
||||||
QString getIconPath() const;
|
QString getIconPath() const;
|
||||||
bool hasCustomIcon() const;
|
bool hasCustomIcon() const;
|
||||||
void setIconPath(QString path);
|
void setIconPath(QString path);
|
||||||
RssItem* getItem(unsigned int index) const;
|
RssItem* getItem(QString name) const;
|
||||||
unsigned int getNbNews() const;
|
unsigned int getNbNews() const;
|
||||||
void markAllAsRead();
|
void markAllAsRead();
|
||||||
unsigned int getNbUnRead() const;
|
unsigned int getNbUnRead() const;
|
||||||
QList<RssItem*> getNewsList() const;
|
QList<RssItem*> getNewsList() const;
|
||||||
|
QList<RssItem*> getUnreadNewsList() const;
|
||||||
QString getIconUrl();
|
QString getIconUrl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
short readDoc(const QDomDocument& doc);
|
short readDoc(const QDomDocument& doc);
|
||||||
void insertSortElem(QList<RssItem*> &list, RssItem *item);
|
|
||||||
void sortList();
|
|
||||||
void resizeList();
|
void resizeList();
|
||||||
short openRss();
|
short openRss();
|
||||||
};
|
};
|
||||||
|
@ -460,6 +456,8 @@ public:
|
||||||
QString getName() const;
|
QString getName() const;
|
||||||
QString getID() const { return name; }
|
QString getID() const { return name; }
|
||||||
bool hasChild(QString ID) { return this->contains(ID); }
|
bool hasChild(QString ID) { return this->contains(ID); }
|
||||||
|
QList<RssItem*> getNewsList() const;
|
||||||
|
QList<RssItem*> getUnreadNewsList() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refreshAll();
|
void refreshAll();
|
||||||
|
@ -498,4 +496,20 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void insertSortElem(QList<RssItem*> &list, RssItem *item) {
|
||||||
|
int i = 0;
|
||||||
|
while(i < list.size() && item->getDate() < list.at(i)->getDate()) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
list.insert(i, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList<RssItem*> sortNewsList(QList<RssItem*> news_list) {
|
||||||
|
QList<RssItem*> new_list;
|
||||||
|
foreach(RssItem *item, news_list) {
|
||||||
|
insertSortElem(new_list, item);
|
||||||
|
}
|
||||||
|
return new_list;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
18
src/rss.ui
18
src/rss.ui
|
@ -120,13 +120,29 @@ p, li { white-space: pre-wrap; }
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QListWidget" name="listNews">
|
<widget class="QTreeWidget" name="listNews">
|
||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="selectionMode">
|
<property name="selectionMode">
|
||||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<attribute name="headerVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="headerVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>1</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Feed URL</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QTextBrowser" name="textBrowser"/>
|
<widget class="QTextBrowser" name="textBrowser"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -55,11 +55,13 @@ void RSSImp::displayRSSListMenu(const QPoint& pos){
|
||||||
myRSSListMenu.addAction(actionMark_items_read);
|
myRSSListMenu.addAction(actionMark_items_read);
|
||||||
myRSSListMenu.addSeparator();
|
myRSSListMenu.addSeparator();
|
||||||
if(selectedItems.size() == 1) {
|
if(selectedItems.size() == 1) {
|
||||||
myRSSListMenu.addAction(actionRename);
|
if(listStreams->getRSSItem(selectedItems.first()) != rssmanager) {
|
||||||
myRSSListMenu.addAction(actionDelete);
|
myRSSListMenu.addAction(actionRename);
|
||||||
myRSSListMenu.addSeparator();
|
myRSSListMenu.addAction(actionDelete);
|
||||||
if(listStreams->getItemType(selectedItems.first()) == RssFile::FOLDER)
|
myRSSListMenu.addSeparator();
|
||||||
myRSSListMenu.addAction(actionNew_folder);
|
if(listStreams->getItemType(selectedItems.first()) == RssFile::FOLDER)
|
||||||
|
myRSSListMenu.addAction(actionNew_folder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
myRSSListMenu.addAction(actionNew_subscription);
|
myRSSListMenu.addAction(actionNew_subscription);
|
||||||
if(listStreams->getItemType(selectedItems.first()) == RssFile::STREAM) {
|
if(listStreams->getItemType(selectedItems.first()) == RssFile::STREAM) {
|
||||||
|
@ -122,8 +124,8 @@ void RSSImp::askNewFolder() {
|
||||||
|
|
||||||
void RSSImp::displayOverwriteError(QString filename) {
|
void RSSImp::displayOverwriteError(QString filename) {
|
||||||
QMessageBox::warning(this, tr("Overwrite attempt"),
|
QMessageBox::warning(this, tr("Overwrite attempt"),
|
||||||
tr("You cannot overwrite %1 item.", "You cannot overwrite myFolder item.").arg(filename),
|
tr("You cannot overwrite %1 item.", "You cannot overwrite myFolder item.").arg(filename),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a stream by a button
|
// add a stream by a button
|
||||||
|
@ -259,18 +261,18 @@ void RSSImp::on_updateAllButton_clicked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSSImp::downloadTorrent() {
|
void RSSImp::downloadTorrent() {
|
||||||
QList<QListWidgetItem *> selected_items = listNews->selectedItems();
|
QList<QTreeWidgetItem *> selected_items = listNews->selectedItems();
|
||||||
foreach(const QListWidgetItem* item, selected_items) {
|
foreach(const QTreeWidgetItem* item, selected_items) {
|
||||||
RssItem* news = ((RssStream*)listStreams->getCurrentRSSItem())->getItem(listNews->row(item));
|
RssItem* news = listStreams->getRSSItemFromUrl(item->text(1))->getItem(item->text(0));
|
||||||
BTSession->downloadFromUrl(news->getTorrentUrl());
|
BTSession->downloadFromUrl(news->getTorrentUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// open the url of the news in a browser
|
// open the url of the news in a browser
|
||||||
void RSSImp::openNewsUrl() {
|
void RSSImp::openNewsUrl() {
|
||||||
QList<QListWidgetItem *> selected_items = listNews->selectedItems();
|
QList<QTreeWidgetItem *> selected_items = listNews->selectedItems();
|
||||||
foreach(const QListWidgetItem* item, selected_items) {
|
foreach(const QTreeWidgetItem* item, selected_items) {
|
||||||
RssItem* news = ((RssStream*)listStreams->getCurrentRSSItem())->getItem(listNews->row(item));
|
RssItem* news = listStreams->getRSSItemFromUrl(item->text(1))->getItem(item->text(0));
|
||||||
QString link = news->getLink();
|
QString link = news->getLink();
|
||||||
if(!link.isEmpty())
|
if(!link.isEmpty())
|
||||||
QDesktopServices::openUrl(QUrl(link));
|
QDesktopServices::openUrl(QUrl(link));
|
||||||
|
@ -382,27 +384,29 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
|
||||||
listNews->clear();
|
listNews->clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(listStreams->getItemType(item) != RssFile::STREAM) {
|
|
||||||
listNews->clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RssStream *stream = (RssStream*)listStreams->getRSSItem(item);
|
RssFile *rss_item = listStreams->getRSSItem(item);
|
||||||
|
|
||||||
qDebug("Getting the list of news");
|
qDebug("Getting the list of news");
|
||||||
QList<RssItem*> news = stream->getNewsList();
|
QList<RssItem*> news;
|
||||||
|
if(rss_item == rssmanager)
|
||||||
|
news = sortNewsList(rss_item->getUnreadNewsList());
|
||||||
|
else
|
||||||
|
news = sortNewsList(rss_item->getNewsList());
|
||||||
// Clear the list first
|
// Clear the list first
|
||||||
textBrowser->clear();
|
textBrowser->clear();
|
||||||
listNews->clear();
|
listNews->clear();
|
||||||
qDebug("Got the list of news");
|
qDebug("Got the list of news");
|
||||||
foreach(RssItem* article, news){
|
foreach(RssItem* article, news){
|
||||||
QListWidgetItem* it = new QListWidgetItem(article->getTitle(), listNews);
|
QTreeWidgetItem* it = new QTreeWidgetItem(listNews);
|
||||||
|
it->setText(0, article->getTitle());
|
||||||
|
it->setText(1, article->getParent()->getUrl());
|
||||||
if(article->isRead()){
|
if(article->isRead()){
|
||||||
it->setData(Qt::ForegroundRole, QVariant(QColor("grey")));
|
it->setData(0, Qt::ForegroundRole, QVariant(QColor("grey")));
|
||||||
it->setData(Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere.png")));
|
it->setData(0, Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere.png")));
|
||||||
}else{
|
}else{
|
||||||
it->setData(Qt::ForegroundRole, QVariant(QColor("blue")));
|
it->setData(0, Qt::ForegroundRole, QVariant(QColor("blue")));
|
||||||
it->setData(Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere2.png")));
|
it->setData(0, Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere2.png")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug("Added all news to the GUI");
|
qDebug("Added all news to the GUI");
|
||||||
|
@ -410,10 +414,10 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// display a news
|
// display a news
|
||||||
void RSSImp::refreshTextBrowser(QListWidgetItem *item) {
|
void RSSImp::refreshTextBrowser(QTreeWidgetItem *item) {
|
||||||
if(!item) return;
|
if(!item) return;
|
||||||
RssStream *stream = (RssStream*)listStreams->getCurrentRSSItem();
|
RssStream *stream = listStreams->getRSSItemFromUrl(item->text(1));
|
||||||
RssItem* article = stream->getItem(listNews->row(item));
|
RssItem* article = stream->getItem(item->text(0));
|
||||||
QString html;
|
QString html;
|
||||||
html += "<div style='border: 2px solid red; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;'>";
|
html += "<div style='border: 2px solid red; margin-left: 5px; margin-right: 5px; margin-bottom: 5px;'>";
|
||||||
html += "<div style='background-color: #678db2; font-weight: bold; color: #fff;'>"+article->getTitle() + "</div>";
|
html += "<div style='background-color: #678db2; font-weight: bold; color: #fff;'>"+article->getTitle() + "</div>";
|
||||||
|
@ -427,10 +431,11 @@ void RSSImp::refreshTextBrowser(QListWidgetItem *item) {
|
||||||
html += "<divstyle='margin-left: 5px; margin-right: 5px;'>"+article->getDescription()+"</div>";
|
html += "<divstyle='margin-left: 5px; margin-right: 5px;'>"+article->getDescription()+"</div>";
|
||||||
textBrowser->setHtml(html);
|
textBrowser->setHtml(html);
|
||||||
article->setRead();
|
article->setRead();
|
||||||
item->setData(Qt::ForegroundRole, QVariant(QColor("grey")));
|
item->setData(0, Qt::ForegroundRole, QVariant(QColor("grey")));
|
||||||
item->setData(Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere.png")));
|
item->setData(0, Qt::DecorationRole, QVariant(QIcon(":/Icons/sphere.png")));
|
||||||
// Decrement feed nb unread news
|
// Decrement feed nb unread news
|
||||||
updateItemInfos(listStreams->currentFeed());
|
updateItemInfos(listStreams->getUnreadItem());
|
||||||
|
updateItemInfos(listStreams->getTreeItemFromUrl(item->text(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSSImp::saveSlidersPosition() {
|
void RSSImp::saveSlidersPosition() {
|
||||||
|
@ -493,8 +498,11 @@ RSSImp::RSSImp(bittorrent *BTSession) : QWidget(), BTSession(BTSession){
|
||||||
|
|
||||||
listStreams = new FeedList(splitter_h, rssmanager);
|
listStreams = new FeedList(splitter_h, rssmanager);
|
||||||
splitter_h->insertWidget(0, listStreams);
|
splitter_h->insertWidget(0, listStreams);
|
||||||
|
listNews->hideColumn(1);
|
||||||
|
|
||||||
fillFeedsList();
|
fillFeedsList();
|
||||||
|
refreshNewsList(listStreams->currentItem());
|
||||||
|
|
||||||
loadFoldersOpenState();
|
loadFoldersOpenState();
|
||||||
connect(rssmanager, SIGNAL(feedInfosChanged(QString, QString, unsigned int)), this, SLOT(updateFeedInfos(QString, QString, unsigned int)));
|
connect(rssmanager, SIGNAL(feedInfosChanged(QString, QString, unsigned int)), this, SLOT(updateFeedInfos(QString, QString, unsigned int)));
|
||||||
connect(rssmanager, SIGNAL(feedIconChanged(QString, QString)), this, SLOT(updateFeedIcon(QString, QString)));
|
connect(rssmanager, SIGNAL(feedIconChanged(QString, QString)), this, SLOT(updateFeedIcon(QString, QString)));
|
||||||
|
@ -520,8 +528,8 @@ RSSImp::RSSImp(bittorrent *BTSession) : QWidget(), BTSession(BTSession){
|
||||||
connect(listStreams, SIGNAL(foldersAltered(QList<QTreeWidgetItem*>)), this, SLOT(updateItemsInfos(QList<QTreeWidgetItem*>)));
|
connect(listStreams, SIGNAL(foldersAltered(QList<QTreeWidgetItem*>)), this, SLOT(updateItemsInfos(QList<QTreeWidgetItem*>)));
|
||||||
connect(listStreams, SIGNAL(overwriteAttempt(QString)), this, SLOT(displayOverwriteError(QString)));
|
connect(listStreams, SIGNAL(overwriteAttempt(QString)), this, SLOT(displayOverwriteError(QString)));
|
||||||
|
|
||||||
connect(listNews, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(refreshTextBrowser(QListWidgetItem *)));
|
connect(listNews, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(refreshTextBrowser(QTreeWidgetItem *)));
|
||||||
connect(listNews, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(downloadTorrent()));
|
connect(listNews, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(downloadTorrent()));
|
||||||
|
|
||||||
// Refresh all feeds
|
// Refresh all feeds
|
||||||
rssmanager->refreshAll();
|
rssmanager->refreshAll();
|
||||||
|
|
|
@ -60,7 +60,7 @@ protected slots:
|
||||||
void refreshSelectedItems();
|
void refreshSelectedItems();
|
||||||
void copySelectedFeedsURL();
|
void copySelectedFeedsURL();
|
||||||
void refreshNewsList(QTreeWidgetItem* item);
|
void refreshNewsList(QTreeWidgetItem* item);
|
||||||
void refreshTextBrowser(QListWidgetItem *);
|
void refreshTextBrowser(QTreeWidgetItem *);
|
||||||
void updateFeedIcon(QString url, QString icon_path);
|
void updateFeedIcon(QString url, QString icon_path);
|
||||||
void updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread);
|
void updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread);
|
||||||
void updateItemsInfos(QList<QTreeWidgetItem*> items);
|
void updateItemsInfos(QList<QTreeWidgetItem*> items);
|
||||||
|
|
Loading…
Reference in a new issue