From e4d9e9f63ffcb5856a4d9dc48d2b003d512070ee Mon Sep 17 00:00:00 2001 From: Tim Delaney Date: Sun, 29 Jan 2017 09:24:41 +1100 Subject: [PATCH 1/2] Follow project coding style. Issue #2192. --HG-- branch : magao-dev --- src/gui/rss/automatedrssdownloader.cpp | 17 +++++++++-------- src/gui/rss/automatedrssdownloader.h | 7 ++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/gui/rss/automatedrssdownloader.cpp b/src/gui/rss/automatedrssdownloader.cpp index 8aafb5237..c6de83cc9 100644 --- a/src/gui/rss/automatedrssdownloader.cpp +++ b/src/gui/rss/automatedrssdownloader.cpp @@ -28,14 +28,14 @@ * Contact : chris@qbittorrent.org */ -#include -#include -#include -#include #include +#include +#include +#include +#include -#include "base/preferences.h" #include "base/bittorrent/session.h" +#include "base/preferences.h" #include "base/rss/rssdownloadrulelist.h" #include "base/rss/rssmanager.h" #include "base/rss/rssfolder.h" @@ -48,9 +48,10 @@ #include "automatedrssdownloader.h" AutomatedRssDownloader::AutomatedRssDownloader(const QWeakPointer &manager, QWidget *parent) - : QDialog(parent), - ui(new Ui::AutomatedRssDownloader), - m_manager(manager), m_editedRule(0) + : QDialog(parent) + , ui(new Ui::AutomatedRssDownloader) + , m_manager(manager) + , m_editedRule(0) { ui->setupUi(this); // Icons diff --git a/src/gui/rss/automatedrssdownloader.h b/src/gui/rss/automatedrssdownloader.h index 4c9d12d69..a9b1b1644 100644 --- a/src/gui/rss/automatedrssdownloader.h +++ b/src/gui/rss/automatedrssdownloader.h @@ -32,14 +32,15 @@ #define AUTOMATEDRSSDOWNLOADER_H #include -#include -#include #include +#include +#include #include "base/rss/rssdownloadrule.h" QT_BEGIN_NAMESPACE -namespace Ui { +namespace Ui +{ class AutomatedRssDownloader; } QT_END_NAMESPACE From f96eb587ff8bff255e8692f91560be089714dded Mon Sep 17 00:00:00 2001 From: Tim Delaney Date: Sun, 22 Jan 2017 15:36:27 +1100 Subject: [PATCH 2/2] Bugfix RSS feed list and rules editor. Closes #3782, #6281. --HG-- branch : magao-dev --- src/gui/rss/automatedrssdownloader.cpp | 263 ++++++++++++++++++------- src/gui/rss/automatedrssdownloader.h | 16 +- src/gui/rss/automatedrssdownloader.ui | 8 +- src/gui/rss/rss_imp.cpp | 38 +++- 4 files changed, 237 insertions(+), 88 deletions(-) diff --git a/src/gui/rss/automatedrssdownloader.cpp b/src/gui/rss/automatedrssdownloader.cpp index c6de83cc9..1337943ad 100644 --- a/src/gui/rss/automatedrssdownloader.cpp +++ b/src/gui/rss/automatedrssdownloader.cpp @@ -62,6 +62,7 @@ AutomatedRssDownloader::AutomatedRssDownloader(const QWeakPointer ui->listRules->setSortingEnabled(true); ui->listRules->setSelectionMode(QAbstractItemView::ExtendedSelection); ui->treeMatchingArticles->setSortingEnabled(true); + ui->treeMatchingArticles->sortByColumn(0, Qt::AscendingOrder); ui->hsplitter->setCollapsible(0, false); ui->hsplitter->setCollapsible(1, false); ui->hsplitter->setCollapsible(2, true); // Only the preview list is collapsible @@ -85,16 +86,7 @@ AutomatedRssDownloader::AutomatedRssDownloader(const QWeakPointer + "
  • " + tr("Infinite range: 1x25-; matches episodes 25 and upward of season one, and all episodes of later seasons") + "
  • " + ""; ui->lineEFilter->setToolTip(tip); initCategoryCombobox(); - loadFeedList(); loadSettings(); - ok = connect(ui->listRules, SIGNAL(itemSelectionChanged()), SLOT(updateRuleDefinitionBox())); - Q_ASSERT(ok); - ok = connect(ui->listRules, SIGNAL(itemSelectionChanged()), SLOT(updateFeedList())); - Q_ASSERT(ok); - ok = connect(ui->listRules, SIGNAL(itemChanged(QListWidgetItem *)), SLOT(handleRuleCheckStateChange(QListWidgetItem *))); - Q_ASSERT(ok); - ok = connect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem *)), SLOT(handleFeedCheckStateChange(QListWidgetItem *))); - Q_ASSERT(ok); // Update matching articles when necessary ok = connect(ui->lineContains, SIGNAL(textEdited(QString)), SLOT(updateMatchingArticles())); Q_ASSERT(ok); @@ -124,8 +116,8 @@ AutomatedRssDownloader::AutomatedRssDownloader(const QWeakPointer deleteHotkey = new QShortcut(QKeySequence::Delete, ui->listRules, 0, 0, Qt::WidgetShortcut); ok = connect(deleteHotkey, SIGNAL(activated()), SLOT(on_removeRuleBtn_clicked())); Q_ASSERT(ok); + updateRuleDefinitionBox(); - updateFeedList(); } AutomatedRssDownloader::~AutomatedRssDownloader() @@ -138,6 +130,22 @@ AutomatedRssDownloader::~AutomatedRssDownloader() delete m_episodeRegex; } +void AutomatedRssDownloader::connectRuleFeedSlots() +{ + qDebug() << Q_FUNC_INFO << "Connecting rule and feed slots"; + connect(ui->listRules, SIGNAL(itemSelectionChanged()), this, SLOT(updateRuleDefinitionBox()), Qt::UniqueConnection); + connect(ui->listRules, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(handleRuleCheckStateChange(QListWidgetItem *)), Qt::UniqueConnection); + connect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(handleFeedCheckStateChange(QListWidgetItem *)), Qt::UniqueConnection); +} + +void AutomatedRssDownloader::disconnectRuleFeedSlots() +{ + qDebug() << Q_FUNC_INFO << "Disconnecting rule and feed slots"; + disconnect(ui->listRules, SIGNAL(itemSelectionChanged()), this, SLOT(updateRuleDefinitionBox())); + disconnect(ui->listRules, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(handleRuleCheckStateChange(QListWidgetItem *))); + disconnect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(handleFeedCheckStateChange(QListWidgetItem *))); +} + void AutomatedRssDownloader::loadSettings() { // load dialog geometry @@ -161,9 +169,9 @@ void AutomatedRssDownloader::saveSettings() void AutomatedRssDownloader::loadRulesList() { // Make sure we save the current item before clearing - if (m_editedRule) - saveEditedRule(); + saveEditedRule(); ui->listRules->clear(); + foreach (const QString &rule_name, m_editableRuleList->ruleNames()) { QListWidgetItem *item = new QListWidgetItem(rule_name, ui->listRules); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); @@ -172,36 +180,53 @@ void AutomatedRssDownloader::loadRulesList() else item->setCheckState(Qt::Unchecked); } - if (( ui->listRules->count() > 0) && !ui->listRules->currentItem()) - ui->listRules->setCurrentRow(0); } void AutomatedRssDownloader::loadFeedList() { + disconnectRuleFeedSlots(); + const Preferences *const pref = Preferences::instance(); const QStringList feed_aliases = pref->getRssFeedsAliases(); const QStringList feed_urls = pref->getRssFeedsUrls(); - QStringList existing_urls; - for (int i = 0; ilistFeeds->clear(); + + for (int i = 0; i < feed_aliases.size(); ++i) { QString feed_url = feed_urls.at(i); feed_url = feed_url.split("\\").last(); qDebug() << Q_FUNC_INFO << feed_url; - if (existing_urls.contains(feed_url)) continue; + QListWidgetItem *item = new QListWidgetItem(feed_aliases.at(i), ui->listFeeds); item->setData(Qt::UserRole, feed_url); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - existing_urls << feed_url; + item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); } + + // Reconnects slots + updateFeedList(); } -void AutomatedRssDownloader::updateFeedList() +void AutomatedRssDownloader::updateFeedList(QListWidgetItem *selected) { - disconnect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(handleFeedCheckStateChange(QListWidgetItem *))); + disconnectRuleFeedSlots(); + + QList selection; + + if (selected) + selection << selected; + else + selection = ui->listRules->selectedItems(); + + bool enable = !selection.isEmpty(); + for (int i = 0; ilistFeeds->count(); ++i) { QListWidgetItem *item = ui->listFeeds->item(i); const QString feed_url = item->data(Qt::UserRole).toString(); - bool all_enabled = false; - foreach (const QListWidgetItem *ruleItem, ui->listRules->selectedItems()) { + item->setHidden(!enable); + + bool allEnabled = true; + bool anyEnabled = false; + + foreach (const QListWidgetItem *ruleItem, selection) { Rss::DownloadRulePtr rule = m_editableRuleList->getRule(ruleItem->text()); if (!rule) continue; qDebug() << "Rule" << rule->name() << "affects" << rule->rssFeeds().size() << "feeds."; @@ -209,21 +234,33 @@ void AutomatedRssDownloader::updateFeedList() qDebug() << "Feed is " << test; if (rule->rssFeeds().contains(feed_url)) { qDebug() << "Rule " << rule->name() << " affects feed " << feed_url; - all_enabled = true; + anyEnabled = true; } else { qDebug() << "Rule " << rule->name() << " does NOT affect feed " << feed_url; - all_enabled = false; - break; + allEnabled = false; } } - if (all_enabled) + + if (anyEnabled && allEnabled) item->setCheckState(Qt::Checked); + else if (anyEnabled) + item->setCheckState(Qt::PartiallyChecked); else item->setCheckState(Qt::Unchecked); } - ui->listFeeds->setEnabled(!ui->listRules->selectedItems().isEmpty()); - connect(ui->listFeeds, SIGNAL(itemChanged(QListWidgetItem *)), SLOT(handleFeedCheckStateChange(QListWidgetItem *))); + + ui->listFeeds->sortItems(); + ui->lblListFeeds->setEnabled(enable); + ui->listFeeds->setEnabled(enable); + + if (selected) { + m_editedRule = selected; + ui->listRules->clearSelection(); + ui->listRules->setCurrentItem(selected); + } + + connectRuleFeedSlots(); updateMatchingArticles(); } @@ -232,16 +269,27 @@ bool AutomatedRssDownloader::isRssDownloaderEnabled() const return ui->checkEnableDownloader->isChecked(); } -void AutomatedRssDownloader::updateRuleDefinitionBox() +void AutomatedRssDownloader::updateRuleDefinitionBox(QListWidgetItem *selected) { + disconnectRuleFeedSlots(); + qDebug() << Q_FUNC_INFO; // Save previous rule first saveEditedRule(); // Update rule definition box const QList selection = ui->listRules->selectedItems(); - if (selection.count() == 1) { - m_editedRule = selection.first(); - Rss::DownloadRulePtr rule = getCurrentRule(); + + if (!selected && (selection.count() == 1)) + selected = selection.first(); + + if (selected) { + m_editedRule = selected; + + // Cannot call getCurrentRule() here as the current item hasn't been updated yet + // and we could get the details from the wrong rule. + // Also can't set the current item here or the selected items gets messed up. + Rss::DownloadRulePtr rule = m_editableRuleList->getRule(m_editedRule->text()); + if (rule) { ui->lineContains->setText(rule->mustContain()); ui->lineNotContains->setText(rule->mustNotContain()); @@ -269,37 +317,46 @@ void AutomatedRssDownloader::updateRuleDefinitionBox() ui->lblLastMatch->setText(lMatch); updateMustLineValidity(); updateMustNotLineValidity(); + updateEpisodeFilterValidity(); } else { // New rule clearRuleDefinitionBox(); - ui->lineContains->setText(selection.first()->text()); ui->comboAddPaused->setCurrentIndex(0); + ui->comboCategory->setCurrentIndex(0); + ui->spinIgnorePeriod->setValue(0); } + updateFieldsToolTips(ui->checkRegex->isChecked()); - // Enable ui->ruleDefBox->setEnabled(true); } else { m_editedRule = 0; - // Clear clearRuleDefinitionBox(); ui->ruleDefBox->setEnabled(false); } + + // Reconnects slots + updateFeedList(selected); } void AutomatedRssDownloader::clearRuleDefinitionBox() { ui->lineContains->clear(); ui->lineNotContains->clear(); + ui->lineEFilter->clear(); ui->saveDiffDir_check->setChecked(false); ui->lineSavePath->clear(); ui->comboCategory->clearEditText(); + ui->comboCategory->setCurrentIndex(-1); ui->checkRegex->setChecked(false); ui->spinIgnorePeriod->setValue(0); + ui->comboAddPaused->clearEditText(); + ui->comboAddPaused->setCurrentIndex(-1); updateFieldsToolTips(ui->checkRegex->isChecked()); updateMustLineValidity(); updateMustNotLineValidity(); + updateEpisodeFilterValidity(); } Rss::DownloadRulePtr AutomatedRssDownloader::getCurrentRule() const @@ -321,7 +378,8 @@ void AutomatedRssDownloader::initCategoryCombobox() void AutomatedRssDownloader::saveEditedRule() { - if (!m_editedRule) return; + if (!m_editedRule || !ui->ruleDefBox->isEnabled()) return; + qDebug() << Q_FUNC_INFO << m_editedRule; if (ui->listRules->findItems(m_editedRule->text(), Qt::MatchExactly).isEmpty()) { qDebug() << "Could not find rule" << m_editedRule->text() << "in the UI list"; @@ -356,6 +414,8 @@ void AutomatedRssDownloader::saveEditedRule() void AutomatedRssDownloader::on_addRuleBtn_clicked() { + saveEditedRule(); + // Ask for a rule name const QString rule_name = AutoExpandableDialog::getText(this, tr("New rule name"), tr("Please type the name of the new download rule.")); if (rule_name.isEmpty()) return; @@ -364,12 +424,17 @@ void AutomatedRssDownloader::on_addRuleBtn_clicked() QMessageBox::warning(this, tr("Rule name conflict"), tr("A rule with this name already exists, please choose another name.")); return; } + + disconnectRuleFeedSlots(); + // Add the new rule to the list QListWidgetItem *item = new QListWidgetItem(rule_name, ui->listRules); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); item->setCheckState(Qt::Checked); // Enable as a default - ui->listRules->clearSelection(); - ui->listRules->setCurrentItem(item); + m_editedRule = 0; + + // Reconnects slots + updateRuleDefinitionBox(item); } void AutomatedRssDownloader::on_removeRuleBtn_clicked() @@ -384,6 +449,9 @@ void AutomatedRssDownloader::on_removeRuleBtn_clicked() confirm_text = tr("Are you sure you want to remove the selected download rules?"); if (QMessageBox::question(this, tr("Rule deletion confirmation"), confirm_text, QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes) return; + + disconnectRuleFeedSlots(); + foreach (QListWidgetItem *item, selection) { // Actually remove the item ui->listRules->removeItemWidget(item); @@ -394,6 +462,10 @@ void AutomatedRssDownloader::on_removeRuleBtn_clicked() // Remove it from the m_editableRuleList m_editableRuleList->removeRule(rule_name); } + + m_editedRule = 0; + // Reconnects slots + updateRuleDefinitionBox(); } void AutomatedRssDownloader::on_browseSP_clicked() @@ -493,31 +565,27 @@ void AutomatedRssDownloader::renameSelectedRule() void AutomatedRssDownloader::handleRuleCheckStateChange(QListWidgetItem *rule_item) { - if (ui->ruleDefBox->isEnabled()) - // Make sure the current rule is saved - saveEditedRule(); + // Make sure the current rule is saved + saveEditedRule(); // Make sure we save the rule that was enabled or disabled - it might not be the current selection. m_editedRule = rule_item; saveEditedRule(); - m_editedRule = 0; + updateRuleDefinitionBox(); } void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feed_item) { - if (ui->ruleDefBox->isEnabled()) - // Make sure the current rule is saved - saveEditedRule(); + // Make sure the current rule is saved + saveEditedRule(); const QString feed_url = feed_item->data(Qt::UserRole).toString(); foreach (QListWidgetItem *rule_item, ui->listRules->selectedItems()) { Rss::DownloadRulePtr rule = m_editableRuleList->getRule(rule_item->text()); Q_ASSERT(rule); QStringList affected_feeds = rule->rssFeeds(); - if (feed_item->checkState() == Qt::Checked) { - if (!affected_feeds.contains(feed_url)) - affected_feeds << feed_url; - } - else if (affected_feeds.contains(feed_url)) + if ((feed_item->checkState() == Qt::Checked) && !affected_feeds.contains(feed_url)) + affected_feeds << feed_url; + else if ((feed_item->checkState() == Qt::Unchecked) && affected_feeds.contains(feed_url)) affected_feeds.removeOne(feed_url); // Save the updated rule if (affected_feeds.size() != rule->rssFeeds().size()) { @@ -552,10 +620,15 @@ void AutomatedRssDownloader::updateMatchingArticles() addFeedArticlesToTree(feed, matching_articles); } } + + m_treeListEntries.clear(); } void AutomatedRssDownloader::addFeedArticlesToTree(const Rss::FeedPtr &feed, const QStringList &articles) { + // Turn off sorting while inserting + ui->treeMatchingArticles->setSortingEnabled(false); + // Check if this feed is already in the tree QTreeWidgetItem *treeFeedItem = 0; for (int i = 0; itreeMatchingArticles->topLevelItemCount(); ++i) { @@ -565,6 +638,7 @@ void AutomatedRssDownloader::addFeedArticlesToTree(const Rss::FeedPtr &feed, con break; } } + // If there is none, create it if (!treeFeedItem) { treeFeedItem = new QTreeWidgetItem(QStringList() << feed->displayName()); @@ -576,13 +650,22 @@ void AutomatedRssDownloader::addFeedArticlesToTree(const Rss::FeedPtr &feed, con treeFeedItem->setData(0, Qt::UserRole, feed->url()); ui->treeMatchingArticles->addTopLevelItem(treeFeedItem); } + // Insert the articles foreach (const QString &art, articles) { - QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << art); - item->setToolTip(0, art); - treeFeedItem->addChild(item); + QPair key(feed->displayName(), art); + + if (!m_treeListEntries.contains(key)) { + m_treeListEntries << key; + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << art); + item->setToolTip(0, art); + treeFeedItem->addChild(item); + } } + ui->treeMatchingArticles->expandItem(treeFeedItem); + ui->treeMatchingArticles->sortItems(0, Qt::AscendingOrder); + ui->treeMatchingArticles->setSortingEnabled(true); } void AutomatedRssDownloader::updateFieldsToolTips(bool regex) @@ -609,18 +692,22 @@ void AutomatedRssDownloader::updateMustLineValidity() { const QString text = ui->lineContains->text(); bool valid = true; - QStringList tokens; - if (ui->checkRegex->isChecked()) - tokens << text; - else - tokens << text.split(" "); - foreach (const QString &token, tokens) { - QRegExp reg(token, Qt::CaseInsensitive, ui->checkRegex->isChecked() ? QRegExp::RegExp : QRegExp::Wildcard); - if (!reg.isValid()) { - valid = false; - break; + + if (!text.isEmpty()) { + QStringList tokens; + if (ui->checkRegex->isChecked()) + tokens << text; + else + tokens << text.split("|"); + foreach (const QString &token, tokens) { + QRegExp reg(token, Qt::CaseInsensitive, ui->checkRegex->isChecked() ? QRegExp::RegExp : QRegExp::Wildcard); + if (!reg.isValid()) { + valid = false; + break; + } } } + if (valid) { ui->lineContains->setStyleSheet(""); ui->lbl_must_stat->setPixmap(QPixmap()); @@ -635,18 +722,22 @@ void AutomatedRssDownloader::updateMustNotLineValidity() { const QString text = ui->lineNotContains->text(); bool valid = true; - QStringList tokens; - if (ui->checkRegex->isChecked()) - tokens << text; - else - tokens << text.split("|"); - foreach (const QString &token, tokens) { - QRegExp reg(token, Qt::CaseInsensitive, ui->checkRegex->isChecked() ? QRegExp::RegExp : QRegExp::Wildcard); - if (!reg.isValid()) { - valid = false; - break; + + if (!text.isEmpty()) { + QStringList tokens; + if (ui->checkRegex->isChecked()) + tokens << text; + else + tokens << text.split("|"); + foreach (const QString &token, tokens) { + QRegExp reg(token, Qt::CaseInsensitive, ui->checkRegex->isChecked() ? QRegExp::RegExp : QRegExp::Wildcard); + if (!reg.isValid()) { + valid = false; + break; + } } } + if (valid) { ui->lineNotContains->setStyleSheet(""); ui->lbl_mustnot_stat->setPixmap(QPixmap()); @@ -660,7 +751,8 @@ void AutomatedRssDownloader::updateMustNotLineValidity() void AutomatedRssDownloader::updateEpisodeFilterValidity() { const QString text = ui->lineEFilter->text(); - bool valid = m_episodeRegex->indexIn(text) != -1; + bool valid = text.isEmpty() || m_episodeRegex->indexIn(text) != -1; + if (valid) { ui->lineEFilter->setStyleSheet(""); ui->lbl_epfilter_stat->setPixmap(QPixmap()); @@ -671,12 +763,31 @@ void AutomatedRssDownloader::updateEpisodeFilterValidity() } } +void AutomatedRssDownloader::showEvent(QShowEvent *event) +{ + // Connects the signals and slots + loadFeedList(); + QDialog::showEvent(event); +} + +void AutomatedRssDownloader::hideEvent(QHideEvent *event) +{ + disconnectRuleFeedSlots(); + QDialog::hideEvent(event); +} + void AutomatedRssDownloader::onFinished(int result) { Q_UNUSED(result); + disconnectRuleFeedSlots(); + // Save current item on exit saveEditedRule(); + ui->listRules->clearSelection(); m_ruleList->replace(m_editableRuleList); m_ruleList->saveRulesToStorage(); saveSettings(); + + m_treeListEntries.clear(); + ui->treeMatchingArticles->clear(); } diff --git a/src/gui/rss/automatedrssdownloader.h b/src/gui/rss/automatedrssdownloader.h index a9b1b1644..3e1f68f2c 100644 --- a/src/gui/rss/automatedrssdownloader.h +++ b/src/gui/rss/automatedrssdownloader.h @@ -32,8 +32,13 @@ #define AUTOMATEDRSSDOWNLOADER_H #include +#include +#include #include +#include #include +#include +#include #include #include "base/rss/rssdownloadrule.h" @@ -64,17 +69,21 @@ public: ~AutomatedRssDownloader(); bool isRssDownloaderEnabled() const; +protected: + virtual void showEvent(QShowEvent *event) override; + virtual void hideEvent(QHideEvent *event) override; + protected slots: void loadSettings(); void saveSettings(); void loadRulesList(); void handleRuleCheckStateChange(QListWidgetItem *rule_item); void handleFeedCheckStateChange(QListWidgetItem *feed_item); - void updateRuleDefinitionBox(); + void updateRuleDefinitionBox(QListWidgetItem *selected = 0); void clearRuleDefinitionBox(); void saveEditedRule(); void loadFeedList(); - void updateFeedList(); + void updateFeedList(QListWidgetItem *selected = 0); private slots: void displayRulesListMenu(const QPoint &pos); @@ -95,6 +104,8 @@ private: Rss::DownloadRulePtr getCurrentRule() const; void initCategoryCombobox(); void addFeedArticlesToTree(const Rss::FeedPtr &feed, const QStringList &articles); + void disconnectRuleFeedSlots(); + void connectRuleFeedSlots(); private: Ui::AutomatedRssDownloader *ui; @@ -105,6 +116,7 @@ private: QRegExp *m_episodeRegex; QShortcut *editHotkey; QShortcut *deleteHotkey; + QSet> m_treeListEntries; }; #endif // AUTOMATEDRSSDOWNLOADER_H diff --git a/src/gui/rss/automatedrssdownloader.ui b/src/gui/rss/automatedrssdownloader.ui index 0338419cd..c99e950fd 100644 --- a/src/gui/rss/automatedrssdownloader.ui +++ b/src/gui/rss/automatedrssdownloader.ui @@ -249,12 +249,18 @@ + + Disabled + true days + + 0 + 365 @@ -314,7 +320,7 @@ - + 50 diff --git a/src/gui/rss/rss_imp.cpp b/src/gui/rss/rss_imp.cpp index 35f951137..b7e1e06cb 100644 --- a/src/gui/rss/rss_imp.cpp +++ b/src/gui/rss/rss_imp.cpp @@ -164,6 +164,7 @@ void RSSImp::askNewFolder() // Expand parent folder to display new folder if (parent_item) parent_item->setExpanded(true); + m_feedList->setCurrentItem(folderItem); m_rssManager->saveStreamList(); } @@ -219,7 +220,10 @@ void RSSImp::on_newFeedButton_clicked() m_feedList->addTopLevelItem(item); // Notify TreeWidget m_feedList->itemAdded(item, stream); - + // Expand parent folder to display new feed + if (parent_item) + parent_item->setExpanded(true); + m_feedList->setCurrentItem(item); m_rssManager->saveStreamList(); } @@ -238,6 +242,8 @@ void RSSImp::deleteSelectedItems() if (answer == QMessageBox::No) return; + QList deleted; + foreach (QTreeWidgetItem *item, selectedItems) { if (item == m_feedList->stickyUnreadItem()) continue; @@ -247,6 +253,7 @@ void RSSImp::deleteSelectedItems() m_feedList->itemAboutToBeRemoved(item); // Actually delete the item rss_item->parentFolder()->removeChild(rss_item->id()); + deleted << rss_item->id(); delete item; // Update parents count while (parent && (parent != m_feedList->invisibleRootItem())) { @@ -255,6 +262,10 @@ void RSSImp::deleteSelectedItems() } } m_rssManager->saveStreamList(); + + foreach (const QString &feed_id, deleted) + m_rssManager->forwardFeedInfosChanged(feed_id, "", 0); + // Update Unread items updateItemInfos(m_feedList->stickyUnreadItem()); if (m_feedList->currentItem() == m_feedList->stickyUnreadItem()) @@ -393,6 +404,7 @@ void RSSImp::renameSelectedRssFile() } while (!ok); // Rename item rss_item->rename(newName); + m_rssManager->saveStreamList(); // Update TreeWidget updateItemInfos(item); } @@ -647,20 +659,26 @@ void RSSImp::updateItemInfos(QTreeWidgetItem *item) void RSSImp::updateFeedIcon(const QString &url, const QString &iconPath) { QTreeWidgetItem *item = m_feedList->getTreeItemFromUrl(url); - item->setData(0, Qt::DecorationRole, QVariant(QIcon(iconPath))); + + if (item) + item->setData(0, Qt::DecorationRole, QVariant(QIcon(iconPath))); } void RSSImp::updateFeedInfos(const QString &url, const QString &display_name, uint nbUnread) { qDebug() << Q_FUNC_INFO << display_name; QTreeWidgetItem *item = m_feedList->getTreeItemFromUrl(url); - Rss::FeedPtr stream = qSharedPointerCast(m_feedList->getRSSItem(item)); - item->setText(0, display_name + QString::fromUtf8(" (") + QString::number(nbUnread) + QString(")")); - if (!stream->isLoading()) - item->setData(0, Qt::DecorationRole, QIcon(stream->iconPath())); - // Update parent - if (item->parent()) - updateItemInfos(item->parent()); + + if (item) { + Rss::FeedPtr stream = qSharedPointerCast(m_feedList->getRSSItem(item)); + item->setText(0, display_name + QString::fromUtf8(" (") + QString::number(nbUnread) + QString(")")); + if (!stream->isLoading()) + item->setData(0, Qt::DecorationRole, QIcon(stream->iconPath())); + // Update parent + if (item->parent()) + updateItemInfos(item->parent()); + } + // Update Unread item updateItemInfos(m_feedList->stickyUnreadItem()); } @@ -713,7 +731,9 @@ RSSImp::RSSImp(QWidget *parent) connect(deleteHotkey, SIGNAL(activated()), SLOT(deleteSelectedItems())); m_rssManager->loadStreamList(); + m_feedList->setSortingEnabled(false); fillFeedsList(); + m_feedList->setSortingEnabled(true); populateArticleList(m_feedList->currentItem()); loadFoldersOpenState();