Sort cats/feeds in export/import model and in msg filter dialog.

This commit is contained in:
Martin Rotter 2020-09-25 09:29:50 +02:00
parent ebc7634ffc
commit e2198faedc
9 changed files with 109 additions and 30 deletions

View File

@ -18,7 +18,7 @@
#include "services/abstract/feed.h"
FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const QList<ServiceRoot*>& accounts, QWidget* parent)
: QDialog(parent), m_feedsModel(new AccountCheckModel(this)), m_rootItem(new RootItem()),
: QDialog(parent), m_feedsModel(new AccountCheckSortedModel(this)), m_rootItem(new RootItem()),
m_accounts(accounts), m_reader(reader), m_loadingFilter(false) {
m_ui.setupUi(this);
@ -51,10 +51,10 @@ FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const Q
connect(m_ui.m_cmbAccounts, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this,
&FormMessageFiltersManager::onAccountChanged);
connect(m_ui.m_btnCheckAll, &QPushButton::clicked, m_feedsModel, &AccountCheckModel::checkAllItems);
connect(m_ui.m_btnUncheckAll, &QPushButton::clicked, m_feedsModel, &AccountCheckModel::uncheckAllItems);
connect(m_feedsModel, &AccountCheckModel::checkStateChanged, this,
&FormMessageFiltersManager::onFeedChecked);
connect(m_ui.m_btnCheckAll, &QPushButton::clicked, m_feedsModel->sourceModel(), &AccountCheckModel::checkAllItems);
connect(m_ui.m_btnUncheckAll, &QPushButton::clicked, m_feedsModel->sourceModel(), &AccountCheckModel::uncheckAllItems);
connect(m_feedsModel->sourceModel(), &AccountCheckModel::checkStateChanged,
this, &FormMessageFiltersManager::onFeedChecked);
initializeTestingMessage();
loadFilters();
@ -211,7 +211,7 @@ void FormMessageFiltersManager::loadFilterFeedAssignments(MessageFilter* filter,
for (auto* feed : account->getSubTreeFeeds()) {
if (feed->messageFilters().contains(filter)) {
m_feedsModel->setItemChecked(feed, Qt::CheckState::Checked);
m_feedsModel->sourceModel()->setItemChecked(feed, Qt::CheckState::Checked);
}
}

View File

@ -9,7 +9,7 @@
#include "ui_formmessagefiltersmanager.h"
class AccountCheckModel;
class AccountCheckSortedModel;
class MessageFilter;
class FeedReader;
@ -51,7 +51,7 @@ class FormMessageFiltersManager : public QDialog {
private:
Ui::FormMessageFiltersManager m_ui;
AccountCheckModel* m_feedsModel;
AccountCheckSortedModel* m_feedsModel;
RootItem* m_rootItem;
QList<ServiceRoot*> m_accounts;
FeedReader* m_reader;

View File

@ -193,9 +193,6 @@ void Application::eliminateFirstRuns() {
void Application::setFeedReader(FeedReader* feed_reader) {
m_feedReader = feed_reader;
connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted);
connect(m_feedReader, &FeedReader::feedUpdatesProgress, this, &Application::onFeedUpdatesProgress);
connect(m_feedReader, &FeedReader::feedUpdatesFinished, this, &Application::onFeedUpdatesFinished);
}
@ -505,14 +502,6 @@ void Application::downloadRequested(QWebEngineDownloadItem* download_item) {
#endif
void Application::onFeedUpdatesStarted() {}
void Application::onFeedUpdatesProgress(const Feed* feed, int current, int total) {
Q_UNUSED(feed)
Q_UNUSED(current)
Q_UNUSED(total)
}
void Application::onFeedUpdatesFinished(const FeedDownloadResults& results) {
if (!results.updatedFeeds().isEmpty()) {
// Now, inform about results via GUI message/notification.

View File

@ -133,8 +133,6 @@ class RSSGUARD_DLLSPEC Application : public QtSingleApplication {
void downloadRequested(QWebEngineDownloadItem* download_item);
#endif
void onFeedUpdatesStarted();
void onFeedUpdatesProgress(const Feed* feed, int current, int total);
void onFeedUpdatesFinished(const FeedDownloadResults& results);
private:

View File

@ -280,3 +280,71 @@ bool AccountCheckModel::isItemChecked(RootItem* item) {
bool AccountCheckModel::setItemChecked(RootItem* item, Qt::CheckState check) {
return setData(indexForItem(item), check, Qt::CheckStateRole);
}
AccountCheckSortedModel::AccountCheckSortedModel(QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(new AccountCheckModel(parent)) {
setDynamicSortFilter(false);
setSourceModel(m_sourceModel);
sort(0, Qt::SortOrder::AscendingOrder);
}
bool AccountCheckSortedModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const {
auto* lhs = m_sourceModel->itemForIndex(source_left);
auto* rhs = m_sourceModel->itemForIndex(source_right);
if (lhs != nullptr && rhs != nullptr) {
QList<RootItem::Kind> priorities = {
RootItem::Kind::Category,
RootItem::Kind::Feed,
RootItem::Kind::Labels,
RootItem::Kind::Important,
RootItem::Kind::Bin
};
if (lhs->keepOnTop()) {
return sortOrder() == Qt::SortOrder::AscendingOrder;
}
else if (rhs->keepOnTop()) {
return sortOrder() == Qt::SortOrder::DescendingOrder;
}
auto left_priority = priorities.indexOf(lhs->kind());
auto right_priority = priorities.indexOf(rhs->kind());
if (left_priority == right_priority) {
return QString::localeAwareCompare(lhs->title().toLower(), rhs->title().toLower()) < 0;
}
else {
return sortOrder() == Qt::SortOrder::AscendingOrder
? left_priority < right_priority
: right_priority < left_priority;
}
}
return false;
}
AccountCheckModel* AccountCheckSortedModel::sourceModel() const {
return m_sourceModel;
}
void AccountCheckSortedModel::setRootItem(RootItem* root_item, bool delete_previous_root, bool with_layout_change) {
setSourceModel(nullptr);
m_sourceModel->setRootItem(root_item, delete_previous_root, with_layout_change);
setSourceModel(m_sourceModel);
}
void AccountCheckSortedModel::checkAllItems() {
m_sourceModel->checkAllItems();
}
void AccountCheckSortedModel::uncheckAllItems() {
m_sourceModel->uncheckAllItems();
}
bool AccountCheckSortedModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
auto kind = m_sourceModel->itemForIndex(m_sourceModel->index(source_row, 0, source_parent))->kind();
return kind == RootItem::Kind::Root || kind == RootItem::Kind::ServiceRoot ||
kind == RootItem::Kind::Category || kind == RootItem::Kind::Feed;
}

View File

@ -4,6 +4,7 @@
#define ACCOUNTCHECKMODEL_H
#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include "services/abstract/rootitem.h"
@ -54,4 +55,26 @@ class AccountCheckModel : public QAbstractItemModel {
bool m_recursiveChange;
};
class AccountCheckSortedModel : public QSortFilterProxyModel {
Q_OBJECT
public:
explicit AccountCheckSortedModel(QObject* parent = nullptr);
virtual ~AccountCheckSortedModel() = default;
AccountCheckModel* sourceModel() const;
void setRootItem(RootItem* root_item, bool delete_previous_root = true, bool with_layout_change = false);
public slots:
void checkAllItems();
void uncheckAllItems();
protected:
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
virtual bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
private:
AccountCheckModel* m_sourceModel;
};
#endif // ACCOUNTCHECKMODEL_H

View File

@ -16,13 +16,13 @@
#include <QStack>
FeedsImportExportModel::FeedsImportExportModel(QObject* parent)
: AccountCheckModel(parent), m_mode(Mode::Import) {}
: AccountCheckSortedModel(parent), m_mode(Mode::Import) {}
FeedsImportExportModel::~FeedsImportExportModel() {
if (m_rootItem != nullptr && m_mode == Mode::Import) {
if (sourceModel() != nullptr && sourceModel()->rootItem() != nullptr && m_mode == Mode::Import) {
// Delete all model items, but only if we are in import mode. Export mode shares
// root item with main feed model, thus cannot be deleted from memory now.
delete m_rootItem;
delete sourceModel()->rootItem();
}
}
@ -54,7 +54,7 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray& result) {
QDomElement elem_opml_body = opml_document.createElement(QSL("body"));
QStack<RootItem*> items_to_process;
items_to_process.push(m_rootItem);
items_to_process.push(sourceModel()->rootItem());
QStack<QDomElement> elements_to_use;
elements_to_use.push(elem_opml_body);
@ -65,7 +65,7 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray& result) {
RootItem* active_item = items_to_process.pop();
for (RootItem* child_item : active_item->childItems()) {
if (!isItemChecked(child_item)) {
if (!sourceModel()->isItemChecked(child_item)) {
continue;
}
@ -259,12 +259,13 @@ void FeedsImportExportModel::importAsOPML20(const QByteArray& data, bool fetch_m
emit layoutAboutToBeChanged();
setRootItem(root_item);
emit layoutChanged();
emit parsingFinished(failed, succeded, false);
}
bool FeedsImportExportModel::exportToTxtURLPerLine(QByteArray& result) {
for (const Feed* const feed : m_rootItem->getSubTreeFeeds()) {
for (const Feed* const feed : sourceModel()->rootItem()->getSubTreeFeeds()) {
result += feed->url() + QL1S("\n");
}

View File

@ -5,7 +5,7 @@
#include "services/abstract/accountcheckmodel.h"
class FeedsImportExportModel : public AccountCheckModel {
class FeedsImportExportModel : public AccountCheckSortedModel {
Q_OBJECT
public:

View File

@ -197,7 +197,7 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
original_parents.push(target_root_node);
QStack<RootItem*> new_parents;
new_parents.push(model->rootItem());
new_parents.push(model->sourceModel()->rootItem());
bool some_feed_category_error = false;
// Iterate all new items we would like to merge into current model.
@ -206,7 +206,7 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
RootItem* source_parent = new_parents.pop();
for (RootItem* source_item : source_parent->childItems()) {
if (!model->isItemChecked(source_item)) {
if (!model->sourceModel()->isItemChecked(source_item)) {
// We can skip this item, because it is not checked and should not be imported.
// NOTE: All descendants are thus skipped too.
continue;