From 48b14d10664e4a95ea995d134487479d7d21061b Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Sun, 23 Aug 2009 12:22:19 +0000 Subject: [PATCH] - Major rewrite of rss grouping code because I did not like my first approach. It is not complete yet but it is far more clean and stable --- src/FeedDownloader.h | 12 +-- src/feedList.h | 94 ++++++++++++++------ src/rss.cpp | 207 +++++++++++++------------------------------ src/rss.h | 34 ++++--- src/rss_imp.cpp | 181 ++++++++++++++++++------------------- src/rss_imp.h | 5 -- 6 files changed, 248 insertions(+), 285 deletions(-) diff --git a/src/FeedDownloader.h b/src/FeedDownloader.h index b0476a9b6..70b94b40f 100644 --- a/src/FeedDownloader.h +++ b/src/FeedDownloader.h @@ -353,7 +353,7 @@ protected slots: if(!filters.hasFilter(new_name)) { validated = true; } else { - QMessageBox::critical(0, tr("Invalid filter name"), tr("This filter name is already in use.")); + QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use.")); } }while(!validated); // Rename the filter @@ -392,7 +392,7 @@ protected slots: new_name = new_name.trimmed(); if(new_name.isEmpty()) { // Cannot be left empty - QMessageBox::critical(0, tr("Invalid filter name"), tr("The filter name cannot be left empty.")); + QMessageBox::warning(0, tr("Invalid filter name"), tr("The filter name cannot be left empty.")); } else { validated = true; } @@ -408,7 +408,7 @@ protected slots: if(filter_name.isNull()) return; if(filters.hasFilter(filter_name)) { // Filter alread exists - QMessageBox::critical(0, tr("Invalid filter name"), tr("This filter name is already in use.")); + QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use.")); } else { validated = true; } @@ -430,7 +430,7 @@ protected slots: if(selected_filter.isEmpty()) return; QString s = test_line->text().trimmed(); if(s.isEmpty()) { - QMessageBox::critical(0, tr("Filter testing error"), tr("Please specify a test torrent name.")); + QMessageBox::warning(0, tr("Filter testing error"), tr("Please specify a test torrent name.")); return; } // Get current filter @@ -455,7 +455,7 @@ protected slots: filtersList->setCurrentItem(filtersList->item(0)); QMessageBox::information(0, tr("Import successful"), tr("Filters import was successful.")); } else { - QMessageBox::critical(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error.")); + QMessageBox::warning(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error.")); } } @@ -472,7 +472,7 @@ protected slots: if(filters.serialize(destination)) QMessageBox::information(0, tr("Export successful"), tr("Filters export was successful.")); else - QMessageBox::critical(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error.")); + QMessageBox::warning(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error.")); } }; diff --git a/src/feedList.h b/src/feedList.h index e34ddafa1..304891be0 100644 --- a/src/feedList.h +++ b/src/feedList.h @@ -6,44 +6,83 @@ #include #include #include +#include +#include #include "rss.h" class FeedList : public QTreeWidget { private: RssManager *rssmanager; + QHash mapping; + QHash feeds_items; + QTreeWidgetItem* current_feed; public: FeedList(QWidget *parent, RssManager *rssmanager): QTreeWidget(parent), rssmanager(rssmanager) { setContextMenuPolicy(Qt::CustomContextMenu); setDragDropMode(QAbstractItemView::InternalMove); setSelectionMode(QAbstractItemView::ExtendedSelection); - setColumnCount(3); + setColumnCount(1); QTreeWidgetItem *___qtreewidgetitem = headerItem(); - ___qtreewidgetitem->setText(2, QApplication::translate("RSS", "type", 0, QApplication::UnicodeUTF8)); - ___qtreewidgetitem->setText(1, QApplication::translate("RSS", "url", 0, QApplication::UnicodeUTF8)); ___qtreewidgetitem->setText(0, QApplication::translate("RSS", "RSS feeds", 0, QApplication::UnicodeUTF8)); - // Hide second column (url) and third column (type) - hideColumn(1); - hideColumn(2); + connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*))); } - QStringList getItemPath(QTreeWidgetItem *item) const { - QStringList path; - if(item) { - if(item->parent()) { - path = getItemPath(item->parent()); - } - Q_ASSERT(!item->text(1).isEmpty()); - path << item->text(1); - } - return path; + void itemAdded(QTreeWidgetItem *item, RssFile* file) { + mapping[item] = file; + if(file->getType() == RssFile::STREAM) + feeds_items[file->getID()] = item; + } + + void itemRemoved(QTreeWidgetItem *item) { + RssFile* file = mapping.take(item); + if(file->getType() == RssFile::STREAM) + feeds_items.remove(file->getID()); + } + + bool hasFeed(QString url) { + return feeds_items.contains(QUrl(url).toString()); + } + + RssFile* getRSSItem(QTreeWidgetItem *item) { + return mapping[item]; + } + + RssFile* getCurrentRSSItem() { + return mapping[current_feed]; + } + + RssFile::FileType getItemType(QTreeWidgetItem *item) { + return mapping[item]->getType(); + } + + QString getItemID(QTreeWidgetItem *item) { + return mapping[item]->getID(); + } + + QTreeWidgetItem* getTreeItemFromUrl(QString url) const{ + return feeds_items[url]; + } + + QTreeWidgetItem* currentItem() const { + return current_feed; + } + + QTreeWidgetItem* currentFeed() const { + return current_feed; + } + +protected slots: + void updateCurrentFeed(QTreeWidgetItem* new_item) { + if(getItemType(new_item) == RssFile::STREAM) + current_feed = new_item; } protected: void dragMoveEvent(QDragMoveEvent * event) { QTreeWidgetItem *item = itemAt(event->pos()); - if(item && rssmanager->getFile(getItemPath(item))->getType() != RssFile::FOLDER) + if(item && getItemType(item) != RssFile::FOLDER) event->ignore(); else { QTreeWidget::dragMoveEvent(event); @@ -52,19 +91,20 @@ protected: void dropEvent(QDropEvent *event) { qDebug("dropEvent"); - QTreeWidgetItem *dest_item = itemAt(event->pos()); - QStringList dest_folder_path = getItemPath(dest_item); + QTreeWidgetItem *dest_folder_item = itemAt(event->pos()); + RssFolder *dest_folder; + if(dest_folder_item) + dest_folder = (RssFolder*)getRSSItem(dest_folder_item); + else + dest_folder = rssmanager; QList src_items = selectedItems(); foreach(QTreeWidgetItem *src_item, src_items) { - QStringList src_path = getItemPath(src_item); - QStringList dest_path = dest_folder_path; - dest_path << src_item->text(1); - qDebug("Moving file %s to %s", src_path.join("\\").toLocal8Bit().data(), dest_path.join("\\").toLocal8Bit().data()); - rssmanager->moveFile(src_path, dest_path); + RssFile *file = getRSSItem(src_item); + rssmanager->moveFile(file, dest_folder); } - QTreeWidget::dropEvent (event); - if(dest_item) - dest_item->setExpanded(true); + QTreeWidget::dropEvent(event); + if(dest_folder_item) + dest_folder_item->setExpanded(true); } }; diff --git a/src/rss.cpp b/src/rss.cpp index 50c1330af..214d98a53 100644 --- a/src/rss.cpp +++ b/src/rss.cpp @@ -30,6 +30,7 @@ #include "rss.h" #include +#include /** RssFolder **/ @@ -56,15 +57,6 @@ RssFile::FileType RssFolder::getType() const { return RssFile::FOLDER; } -QStringList RssFolder::getPath() const { - QStringList path; - if(parent) { - path = parent->getPath(); - path.append(name); - } - return path; -} - void RssFolder::refreshAll(){ qDebug("Refreshing all rss feeds"); QList items = this->values(); @@ -87,98 +79,52 @@ void RssFolder::refreshAll(){ } } -void RssFolder::removeFile(QStringList full_path) { - QString name = full_path.last(); - if(full_path.size() == 1) { - Q_ASSERT(this->contains(name)); - delete this->take(name); - } else { - QString subfolder_name = full_path.takeFirst(); - Q_ASSERT(this->contains(subfolder_name)); - RssFolder *subfolder = (RssFolder*)this->value(subfolder_name); - subfolder->removeFile(full_path); - } +void RssFolder::removeFile(QString ID) { + if(this->contains(ID)) + delete this->take(ID); } -RssFolder* RssFolder::addFolder(QStringList full_path) { - QString name = full_path.last(); - if(full_path.size() == 1) { - Q_ASSERT(!this->contains(name)); - RssFolder *subfolder = new RssFolder(this, rssmanager, BTSession, name); +RssFolder* RssFolder::addFolder(QString name) { + RssFolder *subfolder; + if(!this->contains(name)) { + subfolder = new RssFolder(this, rssmanager, BTSession, name); (*this)[name] = subfolder; - return subfolder; } else { - QString subfolder_name = full_path.takeFirst(); - // Check if the subfolder exists and create it if it does not - if(!this->contains(subfolder_name)) { - qDebug("Creating subfolder %s which did not exist", subfolder_name.toLocal8Bit().data()); - (*this)[subfolder_name] = new RssFolder(this, rssmanager, BTSession, subfolder_name); - } - Q_ASSERT(this->contains(subfolder_name)); - RssFolder *subfolder = (RssFolder*)this->value(subfolder_name); - return subfolder->addFolder(full_path); + subfolder = (RssFolder*)this->value(name); } + return subfolder; } -RssStream* RssFolder::addStream(QStringList full_path) { - QString url = full_path.last(); - if(full_path.size() == 1) { - if(this->contains(url)){ - qDebug("Not adding the Rss stream because it is already in the list"); - return 0; - } - RssStream* stream = new RssStream(this, rssmanager, BTSession, url); - (*this)[url] = stream; - refresh(full_path); - return stream; - } else { - QString subfolder_name = full_path.takeFirst(); - // Check if the subfolder exists and create it if it does not - if(!this->contains(subfolder_name)) { - qDebug("Creating subfolder %s which did not exist", subfolder_name.toLocal8Bit().data()); - (*this)[subfolder_name] = new RssFolder(this, rssmanager, BTSession, subfolder_name); - } - Q_ASSERT(this->contains(subfolder_name)); - RssFolder *subfolder = (RssFolder*)this->value(subfolder_name); - return subfolder->addStream(full_path); - } -} - -void RssFolder::refresh(QStringList full_path) { - QString url = full_path.last(); - if(full_path.size() == 1) { - qDebug("Refreshing feed: %s", url.toLocal8Bit().data()); - Q_ASSERT(this->contains(url)); - RssStream *stream = (RssStream*)this->value(url); - if(stream->isLoading()) return; - stream->setLoading(true); - downloader->downloadUrl(url); - if(!stream->hasCustomIcon()){ - downloader->downloadUrl(stream->getIconUrl()); - }else{ - qDebug("No need to download this feed's icon, it was already downloaded"); - } - } else { - QString subfolder_name = full_path.takeFirst(); - Q_ASSERT(this->contains(subfolder_name)); - RssFolder *subfolder = (RssFolder*)this->value(subfolder_name); - subfolder->refresh(full_path); +RssStream* RssFolder::addStream(QString url) { + Q_ASSERT(!this->contains(url)); + RssStream* stream = new RssStream(this, rssmanager, BTSession, url); + (*this)[url] = stream; + refreshStream(url); + return stream; +} + +// Refresh All Children +void RssFolder::refresh() { + foreach(RssFile *child, this->values()) { + // Little optimization child->refresh() would work too + if(child->getType() == RssFile::STREAM) + refreshStream(child->getID()); + else + child->refresh(); } } -RssFile* RssFolder::getFile(QStringList full_path) const { - if(full_path.isEmpty()) return rssmanager; - QString file_name = full_path.last(); - Q_ASSERT(!file_name.isEmpty()); - if(full_path.size() == 1) { - qDebug("getFile: %s from folder %s", file_name.toLocal8Bit().data(), name.toLocal8Bit().data()); - Q_ASSERT(this->contains(file_name)); - return (*this)[file_name]; - } else { - QString subfolder_name = full_path.takeFirst(); - Q_ASSERT(this->contains(subfolder_name)); - RssFolder *subfolder = (RssFolder*)this->value(subfolder_name); - return subfolder->getFile(full_path); +void RssFolder::refreshStream(QString url) { + qDebug("Refreshing feed: %s", url.toLocal8Bit().data()); + Q_ASSERT(this->contains(url)); + RssStream *stream = (RssStream*)this->value(url); + if(stream->isLoading()) return; + stream->setLoading(true); + downloader->downloadUrl(url); + if(!stream->hasCustomIcon()){ + downloader->downloadUrl(stream->getIconUrl()); + }else{ + qDebug("No need to download this feed's icon, it was already downloaded"); } } @@ -225,7 +171,7 @@ void RssFolder::processFinishedDownload(QString url, QString path) { // this is more user friendly if(stream->getName().isEmpty()){ if(!stream->getTitle().isEmpty()) - stream->rename(QStringList(), stream->getTitle()); + stream->rename(stream->getTitle()); } rssmanager->forwardFeedInfosChanged(url, stream->getName(), stream->getNbUnRead()); } @@ -261,19 +207,13 @@ QString RssFolder::getName() const { return name; } -void RssFolder::rename(QStringList full_path, QString new_name) { - if(full_path.size() == 1) { +void RssFolder::rename(QString new_name) { + Q_ASSERT(parent->contains(new_name)); + if(!parent->contains(new_name)) { + // Update parent + (*parent)[new_name] = parent->take(name); + // Actually rename name = new_name; - } else { - QString child_name = full_path.takeFirst(); - Q_ASSERT(this->contains(child_name)); - RssFile *child = (RssFile*)this->value(child_name); - if(full_path.empty()) { - // Child is renamed, update QHash - Q_ASSERT(!this->contains(new_name)); - (*this)[new_name] = this->take(child_name); - } - child->rename(full_path, new_name); } } @@ -297,16 +237,6 @@ QList RssFolder::getAllFeeds() const { return streams; } -void RssFolder::removeFileRef(RssFile* item) { - if(item->getType() == RssFile::STREAM) { - Q_ASSERT(this->contains(((RssStream*)item)->getUrl())); - this->remove(((RssStream*)item)->getUrl()); - } else { - Q_ASSERT(this->contains(((RssFolder*)item)->getName())); - this->remove(((RssFolder*)item)->getName()); - } -} - void RssFolder::addFile(RssFile * item) { if(item->getType() == RssFile::STREAM) { Q_ASSERT(!this->contains(((RssStream*)item)->getUrl())); @@ -349,10 +279,17 @@ void RssManager::loadStreamList(){ foreach(QString s, streamsUrl){ QStringList path = s.split("\\"); if(path.empty()) continue; - RssStream *stream = this->addStream(path); + QString feed_url = path.takeLast(); + // Create feed path (if it does not exists) + RssFolder * feed_parent = this; + foreach(QString folder_name, path) { + feed_parent = feed_parent->addFolder(folder_name); + } + // Create feed + RssStream *stream = feed_parent->addStream(feed_url); QString alias = aliases.at(i); if(!alias.isEmpty()) { - stream->rename(QStringList(), alias); + stream->rename(alias); } ++i; } @@ -367,29 +304,16 @@ void RssManager::forwardFeedIconChanged(QString url, QString icon_path) { emit feedIconChanged(url, icon_path); } -void RssManager::moveFile(QStringList old_path, QStringList new_path) { - RssFile* item = getFile(old_path); - RssFolder* src_folder = item->getParent(); - QString new_name = new_path.takeLast(); - RssFolder* dest_folder = (RssFolder*)getFile(new_path); +void RssManager::moveFile(RssFile* file, RssFolder* dest_folder) { + RssFolder* src_folder = file->getParent(); if(dest_folder != src_folder) { // Copy to new Folder - dest_folder->addFile(item); + dest_folder->addFile(file); // Remove reference in old folder - src_folder->removeFileRef(item); + src_folder->remove(file->getID()); } else { qDebug("Nothing to move, same destination folder"); } - // Need to rename? - QString current_name; - if(item->getType() == RssFile::FOLDER) - current_name = item->getName(); - else - current_name = ((RssStream*)item)->getUrl(); - if(current_name != new_name) { - qDebug("Renaming file from %s to %s...", current_name.toLocal8Bit().data(), new_name.toLocal8Bit().data()); - dest_folder->rename(item->getPath(), new_name); - } } void RssManager::saveStreamList(){ @@ -413,9 +337,10 @@ void RssManager::saveStreamList(){ /** RssStream **/ -RssStream::RssStream(RssFolder* parent, RssManager *rssmanager, bittorrent *BTSession, QString _url): parent(parent), rssmanager(rssmanager), BTSession(BTSession), url(_url), alias(""), iconPath(":/Icons/rss16.png"), refreshed(false), downloadFailure(false), currently_loading(false) { +RssStream::RssStream(RssFolder* parent, RssManager *rssmanager, bittorrent *BTSession, QString _url): parent(parent), rssmanager(rssmanager), BTSession(BTSession), alias(""), iconPath(":/Icons/rss16.png"), refreshed(false), downloadFailure(false), currently_loading(false) { qDebug("RSSStream constructed"); QSettings qBTRSS("qBittorrent", "qBittorrent-rss"); + url = QUrl(_url).toString(); QHash all_old_items = qBTRSS.value("old_items", QHash()).toHash(); QVariantList old_items = all_old_items.value(url, QVariantList()).toList(); qDebug("Loading %d old items for feed %s", old_items.size(), getName().toLocal8Bit().data()); @@ -454,15 +379,7 @@ RssFile::FileType RssStream::getType() const { } void RssStream::refresh() { - QStringList path; - path << url; - parent->refresh(path); -} - -QStringList RssStream::getPath() const { - QStringList path = parent->getPath(); - path.append(url); - return path; + parent->refreshStream(url); } // delete all the items saved @@ -491,7 +408,7 @@ QString RssStream::getTitle() const{ return title; } -void RssStream::rename(QStringList, QString new_name){ +void RssStream::rename(QString new_name){ qDebug("Renaming stream to %s", new_name.toLocal8Bit().data()); alias = new_name; } @@ -603,7 +520,7 @@ short RssStream::readDoc(const QDomDocument& doc) { if (property.tagName() == "title") { title = property.text(); if(alias==getUrl()) - rename(QStringList(), title); + rename(title); } else if (property.tagName() == "link") link = property.text(); diff --git a/src/rss.h b/src/rss.h index fba9f43d9..a8002795b 100644 --- a/src/rss.h +++ b/src/rss.h @@ -87,12 +87,21 @@ public: virtual unsigned int getNbUnRead() const = 0; virtual FileType getType() const = 0; - virtual QStringList getPath() const = 0; virtual QString getName() const = 0; - virtual void rename(QStringList path, QString new_name) = 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 void refresh() = 0; + QStringList getPath() const { + QStringList path; + if(getParent()) { + path = ((RssFile*)getParent())->getPath(); + path.append(getID()); + } + return path; + } }; // Item of a rss stream, single information @@ -394,13 +403,13 @@ public: void setParent(RssFolder* _parent) { parent = _parent; } FileType getType() const; void refresh(); - QStringList getPath() const; + QString getID() const { return url; } void removeAllItems(); bool itemAlreadyExists(QString hash); void setLoading(bool val); bool isLoading(); QString getTitle() const; - void rename(QStringList path, QString _alias); + void rename(QString _alias); QString getName() const; QString getLink() const; QString getUrl() const; @@ -442,25 +451,24 @@ public: void setParent(RssFolder* _parent) { parent = _parent; } unsigned int getNbUnRead() const; FileType getType() const; - RssStream* addStream(QStringList full_path); - RssFolder* addFolder(QStringList full_path); + RssStream* addStream(QString url); + RssFolder* addFolder(QString name); QList findFeedsWithIcon(QString icon_url) const; unsigned int getNbFeeds() const; QList getContent() const; - RssFile* getFile(QStringList full_path) const; QList getAllFeeds() const; QString getName() const; - QStringList getPath() const; + QString getID() const { return name; } public slots: void refreshAll(); - void removeFileRef(RssFile* item); void addFile(RssFile * item); - void removeFile(QStringList full_path); - void refresh(QStringList full_path); + void removeFile(QString ID); + void refresh(); + void refreshStream(QString url); void processFinishedDownload(QString url, QString path); void handleDownloadFailure(QString url, QString reason); - void rename(QStringList full_path, QString new_name); + void rename(QString new_name); void markAllAsRead(); }; @@ -481,7 +489,7 @@ public slots: void saveStreamList(); void forwardFeedInfosChanged(QString url, QString aliasOrUrl, unsigned int nbUnread); void forwardFeedIconChanged(QString url, QString icon_path); - void moveFile(QStringList old_path, QStringList new_path); + void moveFile(RssFile* file, RssFolder* dest_folder); public: RssManager(bittorrent *BTSession); diff --git a/src/rss_imp.cpp b/src/rss_imp.cpp index e76e01047..09b79daa7 100644 --- a/src/rss_imp.cpp +++ b/src/rss_imp.cpp @@ -56,18 +56,20 @@ void RSSImp::displayRSSListMenu(const QPoint& pos){ myRSSListMenu.addSeparator(); if(selectedItems.size() == 1) { myRSSListMenu.addAction(actionRename); - RssFile *rss_item = rssmanager->getFile(listStreams->getItemPath(selectedItems.first())); - if(rss_item->getType() == RssFile::FOLDER) + myRSSListMenu.addAction(actionDelete); + myRSSListMenu.addSeparator(); + if(listStreams->getItemType(selectedItems.first()) == RssFile::FOLDER) myRSSListMenu.addAction(actionNew_folder); } - myRSSListMenu.addAction(actionDelete); - myRSSListMenu.addSeparator(); - myRSSListMenu.addAction(actionCopy_feed_URL); - if(selectedItems.size() == 1) { + myRSSListMenu.addAction(actionNew_subscription); + if(listStreams->getItemType(selectedItems.first()) == RssFile::STREAM) { myRSSListMenu.addSeparator(); - myRSSListMenu.addAction(actionRSS_feed_downloader); + myRSSListMenu.addAction(actionCopy_feed_URL); + if(selectedItems.size() == 1) { + myRSSListMenu.addSeparator(); + myRSSListMenu.addAction(actionRSS_feed_downloader); + } } - }else{ myRSSListMenu.addAction(actionNew_subscription); myRSSListMenu.addAction(actionNew_folder); @@ -87,38 +89,29 @@ void RSSImp::displayItemsListMenu(const QPoint&){ myItemListMenu.exec(QCursor::pos()); } -QStringList RSSImp::getCurrentFeedPath() const { - return listStreams->getItemPath(listStreams->currentItem()); -} - -RssFile::FileType RSSImp::getItemType(QTreeWidgetItem *item) const { - if(!item) - return RssFile::FOLDER; - return (RssFile::FileType)item->text(2).toInt(); -} - void RSSImp::askNewFolder() { - QStringList dest_path; QTreeWidgetItem *parent_item = 0; + RssFolder *rss_parent; if(listStreams->selectedItems().size() > 0) { parent_item = listStreams->selectedItems().at(0); - foreach(QString name, listStreams->getItemPath(parent_item)) { - dest_path << name; - } + rss_parent = (RssFolder*)listStreams->getRSSItem(parent_item); + Q_ASSERT(rss_parent->getType() == RssFile::FOLDER); + } else { + rss_parent = rssmanager; } bool ok; - QString newFolder = QInputDialog::getText(this, tr("Please choose a folder name"), tr("Folder name:"), QLineEdit::Normal, tr("New folder"), &ok); + QString new_name = QInputDialog::getText(this, tr("Please choose a folder name"), tr("Folder name:"), QLineEdit::Normal, tr("New folder"), &ok); if(ok) { - dest_path << newFolder; - RssFolder* new_folder = rssmanager->addFolder(dest_path); + RssFolder* new_folder = rss_parent->addFolder(new_name); QTreeWidgetItem* folder_item; if(parent_item) folder_item = new QTreeWidgetItem(parent_item); else folder_item = new QTreeWidgetItem(listStreams); + // Notify TreeWidget + listStreams->itemAdded(folder_item, new_folder); + // Set Text folder_item->setText(0, new_folder->getName() + QString::fromUtf8(" (0)")); - folder_item->setText(1, new_folder->getName()); - folder_item->setData(2,Qt::DisplayRole, QVariant((int)RssFile::FOLDER)); folder_item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/folder.png"))); // Expand parent folder to display new folder if(parent_item) @@ -129,12 +122,22 @@ void RSSImp::askNewFolder() { // add a stream by a button void RSSImp::on_newFeedButton_clicked() { - QStringList dest_path; - QTreeWidgetItem *current_item = listStreams->currentItem(); - if(getItemType(current_item) != RssFile::FOLDER) - dest_path = listStreams->getItemPath(current_item->parent()); - else - dest_path = listStreams->getItemPath(current_item); + // Determine parent folder for new feed + QTreeWidgetItem *parent_item =0; + QList selected_items = listStreams->selectedItems(); + if(!selected_items.empty()) + parent_item = selected_items.first(); + RssFolder *rss_parent; + if(parent_item) { + RssFile* tmp = listStreams->getRSSItem(parent_item); + if(tmp->getType() == RssFile::FOLDER) + rss_parent = (RssFolder*)tmp; + else + rss_parent = tmp->getParent(); + } else { + rss_parent = rssmanager; + } + // Ask for feed URL bool ok; QString clip_txt = qApp->clipboard()->text(); QString default_url = "http://"; @@ -145,19 +148,19 @@ void RSSImp::on_newFeedButton_clicked() { if(ok) { newUrl = newUrl.trimmed(); if(!newUrl.isEmpty()){ - dest_path.append(newUrl); - RssStream *stream = rssmanager->addStream(dest_path); - if(stream == 0){ - // Already existing + if(listStreams->hasFeed(newUrl)) { QMessageBox::warning(this, tr("qBittorrent"), tr("This rss feed is already in the list."), QMessageBox::Ok); return; } + RssStream *stream = rss_parent->addStream(newUrl); + // Create TreeWidget item QTreeWidgetItem* item = new QTreeWidgetItem(listStreams); + // Notify TreeWidget + listStreams->itemAdded(item, stream); + // Set text item->setText(0, stream->getName() + QString::fromUtf8(" (0)")); - item->setText(1, stream->getUrl()); - item->setData(2,Qt::DisplayRole, QVariant((int)RssFile::STREAM)); item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png"))); if(listStreams->topLevelItemCount() == 1) selectFirstFeed(); @@ -171,17 +174,26 @@ void RSSImp::on_newFeedButton_clicked() { void RSSImp::deleteSelectedItems() { QList selectedItems = listStreams->selectedItems(); if(selectedItems.size() == 0) return; - if(!selectedItems.size()) return; - int ret = QMessageBox::question(this, tr("Are you sure? -- qBittorrent"), tr("Are you sure you want to delete this RSS feed from the list?"), - tr("&Yes"), tr("&No"), - QString(), 0, 1); + int ret; + if(selectedItems.size() > 1) + ret = QMessageBox::question(this, tr("Are you sure? -- qBittorrent"), tr("Are you sure you want to delete these elements from the list?"), + tr("&Yes"), tr("&No"), + QString(), 0, 1); + else + ret = QMessageBox::question(this, tr("Are you sure? -- qBittorrent"), tr("Are you sure you want to delete this element from the list?"), + tr("&Yes"), tr("&No"), + QString(), 0, 1); if(!ret) { foreach(QTreeWidgetItem *item, selectedItems){ - if(listStreams->currentItem() == item){ + if(listStreams->currentFeed() == item){ textBrowser->clear(); listNews->clear(); } - rssmanager->removeFile(listStreams->getItemPath(item)); + RssFile *rss_item = listStreams->getRSSItem(item); + rss_item->getParent()->removeFile(rss_item->getID()); + // Notify TreeWidget + listStreams->itemRemoved(item); + // Actually delete the item delete item; } rssmanager->saveStreamList(); @@ -199,7 +211,7 @@ void RSSImp::on_updateAllButton_clicked() { void RSSImp::downloadTorrent() { QList selected_items = listNews->selectedItems(); foreach(const QListWidgetItem* item, selected_items) { - RssItem* news = ((RssStream*)rssmanager->getFile(getCurrentFeedPath()))->getItem(listNews->row(item)); + RssItem* news = ((RssStream*)listStreams->getCurrentRSSItem())->getItem(listNews->row(item)); BTSession->downloadFromUrl(news->getTorrentUrl()); } } @@ -208,7 +220,7 @@ void RSSImp::downloadTorrent() { void RSSImp::openNewsUrl() { QList selected_items = listNews->selectedItems(); foreach(const QListWidgetItem* item, selected_items) { - RssItem* news = ((RssStream*)rssmanager->getFile(getCurrentFeedPath()))->getItem(listNews->row(item)); + RssItem* news = ((RssStream*)listStreams->getCurrentRSSItem())->getItem(listNews->row(item)); QString link = news->getLink(); if(!link.isEmpty()) QDesktopServices::openUrl(QUrl(link)); @@ -220,16 +232,22 @@ void RSSImp::renameFiles() { QList selectedItems = listStreams->selectedItems(); Q_ASSERT(selectedItems.size() == 1); QTreeWidgetItem *item = selectedItems.at(0); + RssFile *rss_item = listStreams->getRSSItem(item); bool ok; - QString newName = QInputDialog::getText(this, tr("Please choose a new name for this RSS feed"), tr("New feed name:"), QLineEdit::Normal, rssmanager->getFile(listStreams->getItemPath(item))->getName(), &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); + // Check if name is already taken + if(ok && rss_item->getParent()->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; + } + }while(!ok); if(ok) { - QStringList item_path = listStreams->getItemPath(item); - rssmanager->rename(item_path, newName); - item->setText(0, newName); - if(rssmanager->getFile(item_path)->getType() == RssFile::FOLDER) { - // If it is a folder, we must update second column too - item->setText(1, newName); - } + // Rename item + rss_item->rename(newName); + // Update TreeWidget + item->setText(0, newName+ QString(" (")+QString::number(rss_item->getNbUnRead())+QString(")")); } } @@ -238,8 +256,10 @@ void RSSImp::refreshSelectedStreams() { QList selectedItems = listStreams->selectedItems(); QTreeWidgetItem* item; foreach(item, selectedItems){ - rssmanager->refresh(listStreams->getItemPath(item)); - if(getItemType(item) == RssFile::STREAM) + RssFile* file = listStreams->getRSSItem(item); + file->refresh(); + // FIXME: Should recursively set icons for feeds in a folder + if(file->getType() == RssFile::STREAM) item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/loading.png"))); } } @@ -249,23 +269,23 @@ void RSSImp::copySelectedFeedsURL() { QList selectedItems = listStreams->selectedItems(); QTreeWidgetItem* item; foreach(item, selectedItems){ - URLs << item->text(1); + URLs << listStreams->getItemID(item); } qApp->clipboard()->setText(URLs.join("\n")); } void RSSImp::showFeedDownloader() { QTreeWidgetItem* item = listStreams->selectedItems()[0]; - RssFile* rss_item = rssmanager->getFile(listStreams->getItemPath(item)); + RssFile* rss_item = listStreams->getRSSItem(item); if(rss_item->getType() == RssFile::STREAM) - new FeedDownloaderDlg(this, item->text(1), rss_item->getName(), BTSession); + new FeedDownloaderDlg(this, listStreams->getItemID(item), rss_item->getName(), BTSession); } void RSSImp::on_markReadButton_clicked() { QList selectedItems = listStreams->selectedItems(); QTreeWidgetItem* item; foreach(item, selectedItems){ - RssFile *rss_item = rssmanager->getFile(listStreams->getItemPath(item)); + RssFile *rss_item = listStreams->getRSSItem(item); rss_item->markAllAsRead(); item->setData(0, Qt::DisplayRole, rss_item->getName()+ QString::fromUtf8(" (0)")); } @@ -287,14 +307,13 @@ void RSSImp::fillFeedsList(QTreeWidgetItem *parent, RssFolder *rss_parent) { else item = new QTreeWidgetItem(parent); item->setData(0, Qt::DisplayRole, rss_child->getName()+ QString::fromUtf8(" (")+QString::number(rss_child->getNbUnRead(), 10)+QString(")")); + // Notify TreeWidget of item addition + listStreams->itemAdded(item, rss_child); + // Set Icon if(rss_child->getType() == RssFile::STREAM) { item->setData(0,Qt::DecorationRole, QVariant(QIcon(QString::fromUtf8(":/Icons/loading.png")))); - item->setData(1, Qt::DisplayRole, ((RssStream*)rss_child)->getUrl()); - item->setData(2, Qt::DisplayRole, QVariant((int)rss_child->getType())); } else { item->setData(0,Qt::DecorationRole, QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/folder.png")))); - item->setData(1, Qt::DisplayRole, ((RssFolder*)rss_child)->getName()); - item->setData(2, Qt::DisplayRole, QVariant((int)rss_child->getType())); // Recurvive call to load sub folders/files fillFeedsList(item, (RssFolder*)rss_child); } @@ -307,14 +326,12 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) { listNews->clear(); return; } - qDebug("RefreshNewsList for item: %s", item->text(1).toLocal8Bit().data()); - qDebug("Item path: %s", listStreams->getItemPath(item).join("\\").toLocal8Bit().data()); - RssFile *file = rssmanager->getFile(listStreams->getItemPath(item)); - if(file->getType() != RssFile::STREAM) { + if(listStreams->getItemType(item) != RssFile::STREAM) { listNews->clear(); return; } - RssStream *stream = (RssStream*)file; + + RssStream *stream = (RssStream*)listStreams->getRSSItem(item); qDebug("Getting the list of news"); QList news = stream->getNewsList(); @@ -333,14 +350,13 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) { } } qDebug("Added all news to the GUI"); - //selectFirstNews(); qDebug("First news selected"); } // display a news void RSSImp::refreshTextBrowser(QListWidgetItem *item) { if(!item) return; - RssStream *stream = (RssStream*)rssmanager->getFile(getCurrentFeedPath()); + RssStream *stream = (RssStream*)listStreams->getCurrentRSSItem(); RssItem* article = stream->getItem(listNews->row(item)); QString html; html += "
"; @@ -380,32 +396,19 @@ void RSSImp::restoreSlidersPosition() { } } -QTreeWidgetItem* RSSImp::getTreeItemFromUrl(QString url) const{ - QList items = listStreams->findItems(url, Qt::MatchExactly, 1); - Q_ASSERT(items.size() == 1); - return items.at(0); -} - void RSSImp::updateFeedIcon(QString url, QString icon_path){ - QTreeWidgetItem *item = getTreeItemFromUrl(url); + QTreeWidgetItem *item = listStreams->getTreeItemFromUrl(url); item->setData(0,Qt::DecorationRole, QVariant(QIcon(icon_path))); } void RSSImp::updateFeedNbNews(RssStream* stream){ - QTreeWidgetItem *item = getTreeItemFromUrl(stream->getUrl()); + QTreeWidgetItem *item = listStreams->getTreeItemFromUrl(stream->getUrl()); item->setText(0, stream->getName() + QString::fromUtf8(" (") + QString::number(stream->getNbUnRead(), 10)+ QString(")")); } -QString RSSImp::getCurrentFeedUrl() const { - QTreeWidgetItem *item = listStreams->currentItem(); - if(item) - return item->text(1); - return QString::null; -} - void RSSImp::updateFeedInfos(QString url, QString aliasOrUrl, unsigned int nbUnread){ - QTreeWidgetItem *item = getTreeItemFromUrl(url); - RssStream *stream = (RssStream*)rssmanager->getFile(listStreams->getItemPath(item)); + QTreeWidgetItem *item = listStreams->getTreeItemFromUrl(url); + RssStream *stream = (RssStream*)listStreams->getRSSItem(item); item->setText(0, aliasOrUrl + QString::fromUtf8(" (") + QString::number(nbUnread, 10)+ QString(")")); item->setData(0,Qt::DecorationRole, QVariant(QIcon(stream->getIconPath()))); // If the feed is selected, update the displayed news diff --git a/src/rss_imp.h b/src/rss_imp.h index acf63b890..b06051ba0 100644 --- a/src/rss_imp.h +++ b/src/rss_imp.h @@ -76,11 +76,6 @@ protected slots: public: RSSImp(bittorrent *BTSession); ~RSSImp(); - QTreeWidgetItem* getTreeItemFromUrl(QString url) const; - QString getCurrentFeedUrl() const; - QTreeWidgetItem* getItemFromPath(QStringList path) const; - QStringList getCurrentFeedPath() const; - RssFile::FileType getItemType(QTreeWidgetItem *item) const; };