This commit is contained in:
Pioooooo 2025-08-18 18:22:48 -05:00 committed by GitHub
commit f484681da0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 133 additions and 48 deletions

View file

@ -100,6 +100,7 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
m_ui->mainSplitter->setCollapsible(0, false); m_ui->mainSplitter->setCollapsible(0, false);
m_ui->mainSplitter->setCollapsible(1, false); m_ui->mainSplitter->setCollapsible(1, false);
m_ui->mainSplitter->setCollapsible(2, true); // Only the preview list is collapsible m_ui->mainSplitter->setCollapsible(2, true); // Only the preview list is collapsible
m_ui->listFeeds->setHeaderHidden(true);
connect(m_ui->checkRegex, &QAbstractButton::toggled, this, &AutomatedRssDownloader::updateFieldsToolTips); connect(m_ui->checkRegex, &QAbstractButton::toggled, this, &AutomatedRssDownloader::updateFieldsToolTips);
connect(m_ui->ruleList, &QWidget::customContextMenuRequested, this, &AutomatedRssDownloader::displayRulesListMenu); connect(m_ui->ruleList, &QWidget::customContextMenuRequested, this, &AutomatedRssDownloader::displayRulesListMenu);
@ -145,7 +146,7 @@ AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent)
connect(m_ui->spinIgnorePeriod, qOverload<int>(&QSpinBox::valueChanged) connect(m_ui->spinIgnorePeriod, qOverload<int>(&QSpinBox::valueChanged)
, this, &AutomatedRssDownloader::handleRuleDefinitionChanged); , this, &AutomatedRssDownloader::handleRuleDefinitionChanged);
connect(m_ui->listFeeds, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleFeedCheckStateChange); connect(m_ui->listFeeds, &QTreeWidget::itemChanged, this, &AutomatedRssDownloader::handleFeedCheckStateChange);
connect(m_ui->ruleList, &QListWidget::itemSelectionChanged, this, &AutomatedRssDownloader::updateRuleDefinitionBox); connect(m_ui->ruleList, &QListWidget::itemSelectionChanged, this, &AutomatedRssDownloader::updateRuleDefinitionBox);
connect(m_ui->ruleList, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleRuleCheckStateChange); connect(m_ui->ruleList, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleRuleCheckStateChange);
@ -213,17 +214,84 @@ void AutomatedRssDownloader::createRuleItem(const RSS::AutoDownloadRule &rule)
void AutomatedRssDownloader::loadFeedList() void AutomatedRssDownloader::loadFeedList()
{ {
const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds); const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds);
QTreeWidgetItem *rssRoot = createFeedTreeItem(RSS::Session::instance()->rootFolder(), nullptr);
for (const auto *feed : asConst(RSS::Session::instance()->feeds())) loadFeedTree(rssRoot, RSS::Session::instance()->rootFolder());
{
QListWidgetItem *item = new QListWidgetItem(feed->name(), m_ui->listFeeds);
item->setData(Qt::UserRole, feed->url());
item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate);
}
updateFeedList(); updateFeedList();
} }
QTreeWidgetItem * AutomatedRssDownloader::createFeedTreeItem(const RSS::Item *rssItem, QTreeWidgetItem *parentItem)
{
auto *item = new QTreeWidgetItem;
item->setData(0, Qt::UserRole, QVariant::fromValue(rssItem));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate);
item->setCheckState(0, Qt::Unchecked); // Init state for folders as we don't manually set them later
QIcon icon;
if(auto feed = qobject_cast<const RSS::Feed *>(rssItem))
{
const QPixmap pixmap{feed->iconPath().data()};
if(!pixmap.isNull())
icon = {pixmap};
else
icon = UIThemeManager::instance()->getIcon(u"application-rss"_qs);
}
else
{
icon = UIThemeManager::instance()->getIcon(u"directory"_qs);
}
item->setData(0, Qt::DecorationRole, icon);
if(!parentItem)
{
item->setData(0, Qt::DisplayRole, u"/"_qs);
m_ui->listFeeds->addTopLevelItem(item);
item->setExpanded(true);
}
else
{
item->setData(0, Qt::DisplayRole, rssItem->name());
parentItem->addChild(item);
}
return item;
}
void AutomatedRssDownloader::loadFeedTree(QTreeWidgetItem *parent, const RSS::Folder *rssParent)
{
for (const auto *rssItem : asConst(rssParent->items()))
{
QTreeWidgetItem *item = createFeedTreeItem(rssItem, parent);
// Recursive call if this is a folder.
if (const auto *folder = qobject_cast<const RSS::Folder *>(rssItem))
loadFeedTree(item, folder);
}
}
QList<QTreeWidgetItem *> AutomatedRssDownloader::getAllFeedTreeItems(QTreeWidgetItem *parent) const
{
QList<QTreeWidgetItem *> feedItems;
int nbChildren = (parent ? parent->childCount() : m_ui->listFeeds->topLevelItemCount());
for (int i = 0; i < nbChildren; ++i)
{
QTreeWidgetItem *item (parent ? parent->child(i) : m_ui->listFeeds->topLevelItem(i));
if (qobject_cast<RSS::Feed *>(item->data(0, Qt::UserRole).value<RSS::Item *>()))
feedItems << item;
else
feedItems << getAllFeedTreeItems(item);
}
return feedItems;
}
void AutomatedRssDownloader::sortTreeRecursively(QTreeWidgetItem *item)
{
for (int i = 0; i < item->childCount(); i++) {
QTreeWidgetItem *child = item->child(i);
sortTreeRecursively(child);
}
item->sortChildren(0, Qt::AscendingOrder);
}
void AutomatedRssDownloader::updateFeedList() void AutomatedRssDownloader::updateFeedList()
{ {
const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds); const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds);
@ -237,33 +305,37 @@ void AutomatedRssDownloader::updateFeedList()
bool enable = !selection.isEmpty(); bool enable = !selection.isEmpty();
for (int i = 0; i < m_ui->listFeeds->count(); ++i) for (int i = 0; i < m_ui->listFeeds->topLevelItemCount(); ++i)
m_ui->listFeeds->topLevelItem(i)->setHidden(!enable);
for (QTreeWidgetItem* item: asConst(getAllFeedTreeItems()))
{ {
QListWidgetItem *item = m_ui->listFeeds->item(i); if (auto rssItem = qobject_cast<const RSS::Feed *>(item->data(0, Qt::UserRole).value<RSS::Item *>()))
const QString feedURL = item->data(Qt::UserRole).toString();
item->setHidden(!enable);
bool allEnabled = true;
bool anyEnabled = false;
for (const QListWidgetItem *ruleItem : asConst(selection))
{ {
const auto rule = RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()); const QString feedURL = rssItem->url();
if (rule.feedURLs().contains(feedURL)) item->setHidden(!enable);
anyEnabled = true;
else
allEnabled = false;
}
if (anyEnabled && allEnabled) bool allEnabled = true;
item->setCheckState(Qt::Checked); bool anyEnabled = false;
else if (anyEnabled)
item->setCheckState(Qt::PartiallyChecked); for (const QListWidgetItem *ruleItem : asConst(selection))
else {
item->setCheckState(Qt::Unchecked); const auto rule = RSS::AutoDownloader::instance()->ruleByName(ruleItem->text());
if (rule.feedURLs().contains(feedURL))
anyEnabled = true;
else
allEnabled = false;
}
if (anyEnabled && allEnabled)
item->setCheckState(0, Qt::Checked);
else if (anyEnabled)
item->setCheckState(0, Qt::PartiallyChecked);
else
item->setCheckState(0, Qt::Unchecked);
}
} }
m_ui->listFeeds->sortItems(); sortTreeRecursively(m_ui->listFeeds->invisibleRootItem());
m_ui->lblListFeeds->setEnabled(enable); m_ui->lblListFeeds->setEnabled(enable);
m_ui->listFeeds->setEnabled(enable); m_ui->listFeeds->setEnabled(enable);
} }
@ -578,25 +650,30 @@ void AutomatedRssDownloader::clearSelectedRuleDownloadedEpisodeList()
} }
} }
void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedItem) void AutomatedRssDownloader::handleFeedCheckStateChange(QTreeWidgetItem *feedItem, int column)
{ {
const QString feedURL = feedItem->data(Qt::UserRole).toString(); Q_ASSERT(column == 0);
for (QListWidgetItem *ruleItem : asConst(m_ui->ruleList->selectedItems())) const RSS::Item *rssItem = feedItem->data(0, Qt::UserRole).value<const RSS::Item *>();
if (auto *feed = qobject_cast<const RSS::Feed *>(rssItem))
{ {
RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem const QString feedURL = feed->url();
? m_currentRule for (QListWidgetItem *ruleItem : asConst(m_ui->ruleList->selectedItems()))
: RSS::AutoDownloader::instance()->ruleByName(ruleItem->text())); {
QStringList affectedFeeds = rule.feedURLs(); RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem
if ((feedItem->checkState() == Qt::Checked) && !affectedFeeds.contains(feedURL)) ? m_currentRule
affectedFeeds << feedURL; : RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()));
else if ((feedItem->checkState() == Qt::Unchecked) && affectedFeeds.contains(feedURL)) QStringList affectedFeeds = rule.feedURLs();
affectedFeeds.removeOne(feedURL); if ((feedItem->checkState(0) == Qt::Checked) && !affectedFeeds.contains(feedURL))
affectedFeeds << feedURL;
else if ((feedItem->checkState(0) == Qt::Unchecked) && affectedFeeds.contains(feedURL))
affectedFeeds.removeOne(feedURL);
rule.setFeedURLs(affectedFeeds); rule.setFeedURLs(affectedFeeds);
if (ruleItem != m_currentRuleItem) if (ruleItem != m_currentRuleItem)
RSS::AutoDownloader::instance()->setRule(rule); RSS::AutoDownloader::instance()->setRule(rule);
else else
m_currentRule = rule; m_currentRule = rule;
}
} }
handleRuleDefinitionChanged(); handleRuleDefinitionChanged();

View file

@ -34,16 +34,20 @@
#include <QDialog> #include <QDialog>
#include <QHash> #include <QHash>
#include <QSet> #include <QSet>
#include <QList>
#include "base/rss/rss_autodownloadrule.h" #include "base/rss/rss_autodownloadrule.h"
#include "base/settingvalue.h" #include "base/settingvalue.h"
class QListWidgetItem; class QListWidgetItem;
class QTreeWidgetItem;
class QRegularExpression; class QRegularExpression;
namespace RSS namespace RSS
{ {
class Feed; class Feed;
class Folder;
class Item;
} }
namespace Ui namespace Ui
@ -69,7 +73,7 @@ private slots:
void onImportBtnClicked(); void onImportBtnClicked();
void onRenameRuleBtnClicked(); void onRenameRuleBtnClicked();
void handleRuleCheckStateChange(QListWidgetItem *ruleItem); void handleRuleCheckStateChange(QListWidgetItem *ruleItem);
void handleFeedCheckStateChange(QListWidgetItem *feedItem); void handleFeedCheckStateChange(QTreeWidgetItem *feedItem, int column);
void displayRulesListMenu(); void displayRulesListMenu();
void renameSelectedRule(); void renameSelectedRule();
void updateRuleDefinitionBox(); void updateRuleDefinitionBox();
@ -95,6 +99,10 @@ private:
void updateMatchingArticles(); void updateMatchingArticles();
void saveEditedRule(); void saveEditedRule();
void loadFeedList(); void loadFeedList();
QTreeWidgetItem *createFeedTreeItem(const RSS::Item *rssItem, QTreeWidgetItem *parentItem);
QList<QTreeWidgetItem *>getAllFeedTreeItems(QTreeWidgetItem *parent = nullptr) const;
void loadFeedTree(QTreeWidgetItem *parent, const RSS::Folder *rssParent);
void sortTreeRecursively(QTreeWidgetItem *item);
void updateFeedList(); void updateFeedList();
void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles); void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles);

View file

@ -356,7 +356,7 @@ Supports the formats: S01E01, 1x1, 2017.12.31 and 31.12.2017 (Date formats also
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QListWidget" name="listFeeds"/> <widget class="QTreeWidget" name="listFeeds"/>
</item> </item>
</layout> </layout>
</widget> </widget>