Skip to content

Commit 4bdb186

Browse files
Add bulk RSS feed rule toggles
1 parent 8cded3c commit 4bdb186

3 files changed

Lines changed: 152 additions & 30 deletions

File tree

src/gui/rss/automatedrssdownloader.cpp

Lines changed: 107 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "automatedrssdownloader.h"
3131

3232
#include <QtVersionChecks>
33+
#include <QCheckBox>
3334
#include <QCursor>
3435
#include <QFileDialog>
3536
#include <QMenu>
@@ -87,6 +88,14 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
8788
connect(m_ui->importBtn, &QPushButton::clicked, this, &AutomatedRssDownloader::onImportBtnClicked);
8889
connect(m_ui->renameRuleBtn, &QPushButton::clicked, this, &AutomatedRssDownloader::onRenameRuleBtnClicked);
8990
connect(m_ui->cloneRuleBtn, &QPushButton::clicked, this, &AutomatedRssDownloader::cloneSelectedRule);
91+
connect(m_ui->checkAllFeedsBtn, &QPushButton::clicked, this, [this]
92+
{
93+
setAllFeedsCheckState(Qt::Checked);
94+
});
95+
connect(m_ui->uncheckAllFeedsBtn, &QPushButton::clicked, this, [this]
96+
{
97+
setAllFeedsCheckState(Qt::Unchecked);
98+
});
9099

91100
// Icons
92101
m_ui->cloneRuleBtn->setIcon(UIThemeManager::instance()->getIcon(u"edit-copy"_s));
@@ -150,8 +159,6 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
150159
connect(m_ui->spinIgnorePeriod, qOverload<int>(&QSpinBox::valueChanged)
151160
, this, &AutomatedRssDownloader::handleRuleDefinitionChanged);
152161

153-
connect(m_ui->listFeeds, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleFeedCheckStateChange);
154-
155162
connect(m_ui->ruleList, &QListWidget::itemSelectionChanged, this, &AutomatedRssDownloader::updateRuleDefinitionBox);
156163
connect(m_ui->ruleList, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleRuleCheckStateChange);
157164

@@ -221,24 +228,35 @@ void AutomatedRssDownloader::loadFeedList()
221228

222229
for (const auto *feed : asConst(RSS::Session::instance()->feeds()))
223230
{
224-
QListWidgetItem *item = new QListWidgetItem(feed->name(), m_ui->listFeeds);
231+
QListWidgetItem *item = new QListWidgetItem(m_ui->listFeeds);
225232
item->setData(Qt::UserRole, feed->url());
226-
item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate);
233+
auto *checkBox = new QCheckBox(feed->name(), m_ui->listFeeds);
234+
checkBox->setCheckState(Qt::Unchecked);
235+
item->setSizeHint(checkBox->sizeHint());
236+
m_ui->listFeeds->setItemWidget(item, checkBox);
237+
238+
connect(checkBox, &QAbstractButton::clicked, this, [this, item, checkBox]
239+
{
240+
handleFeedCheckStateChange(item, checkBox->checkState());
241+
});
227242
}
228243

229244
updateFeedList();
230245
}
231246

247+
QList<QListWidgetItem *> AutomatedRssDownloader::selectedRuleItems() const
248+
{
249+
if (m_currentRuleItem)
250+
return {m_currentRuleItem};
251+
252+
return m_ui->ruleList->selectedItems();
253+
}
254+
232255
void AutomatedRssDownloader::updateFeedList()
233256
{
234257
const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds);
235258

236-
QList<QListWidgetItem *> selection;
237-
238-
if (m_currentRuleItem)
239-
selection << m_currentRuleItem;
240-
else
241-
selection = m_ui->ruleList->selectedItems();
259+
const QList<QListWidgetItem *> selection = selectedRuleItems();
242260

243261
bool enable = !selection.isEmpty();
244262

@@ -253,23 +271,34 @@ void AutomatedRssDownloader::updateFeedList()
253271

254272
for (const QListWidgetItem *ruleItem : asConst(selection))
255273
{
256-
const auto rule = RSS::AutoDownloader::instance()->ruleByName(ruleItem->text());
274+
const auto rule = (ruleItem == m_currentRuleItem)
275+
? m_currentRule
276+
: RSS::AutoDownloader::instance()->ruleByName(ruleItem->text());
257277
if (rule.feedURLs().contains(feedURL))
258278
anyEnabled = true;
259279
else
260280
allEnabled = false;
261281
}
262282

283+
Qt::CheckState checkState = Qt::Unchecked;
263284
if (anyEnabled && allEnabled)
264-
item->setCheckState(Qt::Checked);
285+
checkState = Qt::Checked;
265286
else if (anyEnabled)
266-
item->setCheckState(Qt::PartiallyChecked);
267-
else
268-
item->setCheckState(Qt::Unchecked);
287+
checkState = Qt::PartiallyChecked;
288+
289+
if (auto *checkBox = qobject_cast<QCheckBox *>(m_ui->listFeeds->itemWidget(item)))
290+
{
291+
const QSignalBlocker checkBoxSignalBlocker(checkBox);
292+
checkBox->setTristate(selection.size() > 1);
293+
checkBox->setEnabled(enable);
294+
checkBox->setCheckState(checkState);
295+
}
269296
}
270297

271298
m_ui->listFeeds->sortItems();
272299
m_ui->lblListFeeds->setEnabled(enable);
300+
m_ui->checkAllFeedsBtn->setEnabled(enable);
301+
m_ui->uncheckAllFeedsBtn->setEnabled(enable);
273302
m_ui->listFeeds->setEnabled(enable);
274303
}
275304

@@ -626,18 +655,19 @@ void AutomatedRssDownloader::clearSelectedRuleDownloadedEpisodeList()
626655
}
627656
}
628657

629-
void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedItem)
658+
void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedItem, const Qt::CheckState checkState)
630659
{
631660
const QString feedURL = feedItem->data(Qt::UserRole).toString();
632-
for (QListWidgetItem *ruleItem : asConst(m_ui->ruleList->selectedItems()))
661+
const QList<QListWidgetItem *> selection = selectedRuleItems();
662+
for (QListWidgetItem *ruleItem : selection)
633663
{
634664
RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem
635665
? m_currentRule
636666
: RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()));
637667
QStringList affectedFeeds = rule.feedURLs();
638-
if ((feedItem->checkState() == Qt::Checked) && !affectedFeeds.contains(feedURL))
668+
if ((checkState == Qt::Checked) && !affectedFeeds.contains(feedURL))
639669
affectedFeeds << feedURL;
640-
else if ((feedItem->checkState() == Qt::Unchecked) && affectedFeeds.contains(feedURL))
670+
else if ((checkState == Qt::Unchecked) && affectedFeeds.contains(feedURL))
641671
affectedFeeds.removeOne(feedURL);
642672

643673
rule.setFeedURLs(affectedFeeds);
@@ -650,6 +680,64 @@ void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedIte
650680
handleRuleDefinitionChanged();
651681
}
652682

683+
void AutomatedRssDownloader::setAllFeedsCheckState(const Qt::CheckState checkState)
684+
{
685+
const QList<QListWidgetItem *> selection = selectedRuleItems();
686+
if (selection.isEmpty())
687+
return;
688+
689+
QStringList feedURLs;
690+
feedURLs.reserve(m_ui->listFeeds->count());
691+
for (int i = 0; i < m_ui->listFeeds->count(); ++i)
692+
{
693+
const QListWidgetItem *item = m_ui->listFeeds->item(i);
694+
if (!item->isHidden())
695+
feedURLs << item->data(Qt::UserRole).toString();
696+
}
697+
698+
if (feedURLs.isEmpty())
699+
return;
700+
701+
for (QListWidgetItem *ruleItem : selection)
702+
{
703+
RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem
704+
? m_currentRule
705+
: RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()));
706+
QStringList affectedFeeds = rule.feedURLs();
707+
for (const QString &feedURL : asConst(feedURLs))
708+
{
709+
if (checkState == Qt::Checked)
710+
{
711+
if (!affectedFeeds.contains(feedURL))
712+
affectedFeeds << feedURL;
713+
}
714+
else
715+
{
716+
affectedFeeds.removeAll(feedURL);
717+
}
718+
}
719+
720+
rule.setFeedURLs(affectedFeeds);
721+
if (ruleItem != m_currentRuleItem)
722+
RSS::AutoDownloader::instance()->setRule(rule);
723+
else
724+
m_currentRule = rule;
725+
}
726+
727+
const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds);
728+
for (int i = 0; i < m_ui->listFeeds->count(); ++i)
729+
{
730+
QListWidgetItem *item = m_ui->listFeeds->item(i);
731+
if (!item->isHidden())
732+
{
733+
if (auto *checkBox = qobject_cast<QCheckBox *>(m_ui->listFeeds->itemWidget(item)))
734+
checkBox->setCheckState(checkState);
735+
}
736+
}
737+
738+
handleRuleDefinitionChanged();
739+
}
740+
653741
void AutomatedRssDownloader::updateMatchingArticles()
654742
{
655743
m_ui->matchingArticlesTree->clear();

src/gui/rss/automatedrssdownloader.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#include <QDialog>
3535
#include <QHash>
36+
#include <QList>
3637
#include <QSet>
3738

3839
#include "base/rss/rss_autodownloadrule.h"
@@ -69,7 +70,7 @@ private slots:
6970
void onImportBtnClicked();
7071
void onRenameRuleBtnClicked();
7172
void handleRuleCheckStateChange(QListWidgetItem *ruleItem);
72-
void handleFeedCheckStateChange(QListWidgetItem *feedItem);
73+
void handleFeedCheckStateChange(QListWidgetItem *feedItem, Qt::CheckState checkState);
7374
void displayRulesListMenu();
7475
void cloneSelectedRule();
7576
void renameSelectedRule();
@@ -91,12 +92,14 @@ private slots:
9192
void loadSettings();
9293
void saveSettings();
9394
void createRuleItem(const RSS::AutoDownloadRule &rule);
95+
QList<QListWidgetItem *> selectedRuleItems() const;
9496
void clearRuleDefinitionBox();
9597
void updateEditedRule();
9698
void updateMatchingArticles();
9799
void saveEditedRule();
98100
void loadFeedList();
99101
void updateFeedList();
102+
void setAllFeedsCheckState(Qt::CheckState checkState);
100103
void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles);
101104

102105
const QString m_formatFilterJSON;

src/gui/rss/automatedrssdownloader.ui

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -354,16 +354,47 @@ Supports the formats: S01E01, 1x1, 2017.12.31 and 31.12.2017 (Date formats also
354354
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
355355
</property>
356356
<item>
357-
<widget class="QLabel" name="lblListFeeds">
358-
<property name="font">
359-
<font>
360-
<bold>false</bold>
361-
</font>
362-
</property>
363-
<property name="text">
364-
<string>Apply Rule to Feeds:</string>
365-
</property>
366-
</widget>
357+
<layout class="QHBoxLayout" name="feedButtonsLayout">
358+
<item>
359+
<widget class="QLabel" name="lblListFeeds">
360+
<property name="font">
361+
<font>
362+
<bold>false</bold>
363+
</font>
364+
</property>
365+
<property name="text">
366+
<string>Apply Rule to Feeds:</string>
367+
</property>
368+
</widget>
369+
</item>
370+
<item>
371+
<spacer name="feedButtonsSpacer">
372+
<property name="orientation">
373+
<enum>Qt::Orientation::Horizontal</enum>
374+
</property>
375+
<property name="sizeHint" stdset="0">
376+
<size>
377+
<width>40</width>
378+
<height>20</height>
379+
</size>
380+
</property>
381+
</spacer>
382+
</item>
383+
<item>
384+
<widget class="QPushButton" name="checkAllFeedsBtn">
385+
<property name="text">
386+
<string>Check All</string>
387+
</property>
388+
</widget>
389+
</item>
390+
<item>
391+
<widget class="QPushButton" name="uncheckAllFeedsBtn">
392+
<property name="text">
393+
<string>Uncheck All</string>
394+
</property>
395+
</widget>
396+
</item>
397+
</layout>
367398
</item>
368399
<item>
369400
<widget class="QListWidget" name="listFeeds"/>

0 commit comments

Comments
 (0)