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+
232255void 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+
653741void AutomatedRssDownloader::updateMatchingArticles ()
654742{
655743 m_ui->matchingArticlesTree ->clear ();
0 commit comments