Sort cats/feeds in export/import model and in msg filter dialog.
This commit is contained in:
parent
ebc7634ffc
commit
e2198faedc
9 changed files with 109 additions and 30 deletions
|
@ -18,7 +18,7 @@
|
||||||
#include "services/abstract/feed.h"
|
#include "services/abstract/feed.h"
|
||||||
|
|
||||||
FormMessageFiltersManager::FormMessageFiltersManager(FeedReader* reader, const QList<ServiceRoot*>& accounts, QWidget* parent)
|
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_accounts(accounts), m_reader(reader), m_loadingFilter(false) {
|
||||||
m_ui.setupUi(this);
|
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),
|
connect(m_ui.m_cmbAccounts, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||||
this,
|
this,
|
||||||
&FormMessageFiltersManager::onAccountChanged);
|
&FormMessageFiltersManager::onAccountChanged);
|
||||||
connect(m_ui.m_btnCheckAll, &QPushButton::clicked, m_feedsModel, &AccountCheckModel::checkAllItems);
|
connect(m_ui.m_btnCheckAll, &QPushButton::clicked, m_feedsModel->sourceModel(), &AccountCheckModel::checkAllItems);
|
||||||
connect(m_ui.m_btnUncheckAll, &QPushButton::clicked, m_feedsModel, &AccountCheckModel::uncheckAllItems);
|
connect(m_ui.m_btnUncheckAll, &QPushButton::clicked, m_feedsModel->sourceModel(), &AccountCheckModel::uncheckAllItems);
|
||||||
connect(m_feedsModel, &AccountCheckModel::checkStateChanged, this,
|
connect(m_feedsModel->sourceModel(), &AccountCheckModel::checkStateChanged,
|
||||||
&FormMessageFiltersManager::onFeedChecked);
|
this, &FormMessageFiltersManager::onFeedChecked);
|
||||||
|
|
||||||
initializeTestingMessage();
|
initializeTestingMessage();
|
||||||
loadFilters();
|
loadFilters();
|
||||||
|
@ -211,7 +211,7 @@ void FormMessageFiltersManager::loadFilterFeedAssignments(MessageFilter* filter,
|
||||||
|
|
||||||
for (auto* feed : account->getSubTreeFeeds()) {
|
for (auto* feed : account->getSubTreeFeeds()) {
|
||||||
if (feed->messageFilters().contains(filter)) {
|
if (feed->messageFilters().contains(filter)) {
|
||||||
m_feedsModel->setItemChecked(feed, Qt::CheckState::Checked);
|
m_feedsModel->sourceModel()->setItemChecked(feed, Qt::CheckState::Checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "ui_formmessagefiltersmanager.h"
|
#include "ui_formmessagefiltersmanager.h"
|
||||||
|
|
||||||
class AccountCheckModel;
|
class AccountCheckSortedModel;
|
||||||
class MessageFilter;
|
class MessageFilter;
|
||||||
class FeedReader;
|
class FeedReader;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class FormMessageFiltersManager : public QDialog {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FormMessageFiltersManager m_ui;
|
Ui::FormMessageFiltersManager m_ui;
|
||||||
AccountCheckModel* m_feedsModel;
|
AccountCheckSortedModel* m_feedsModel;
|
||||||
RootItem* m_rootItem;
|
RootItem* m_rootItem;
|
||||||
QList<ServiceRoot*> m_accounts;
|
QList<ServiceRoot*> m_accounts;
|
||||||
FeedReader* m_reader;
|
FeedReader* m_reader;
|
||||||
|
|
|
@ -193,9 +193,6 @@ void Application::eliminateFirstRuns() {
|
||||||
|
|
||||||
void Application::setFeedReader(FeedReader* feed_reader) {
|
void Application::setFeedReader(FeedReader* feed_reader) {
|
||||||
m_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);
|
connect(m_feedReader, &FeedReader::feedUpdatesFinished, this, &Application::onFeedUpdatesFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,14 +502,6 @@ void Application::downloadRequested(QWebEngineDownloadItem* download_item) {
|
||||||
|
|
||||||
#endif
|
#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) {
|
void Application::onFeedUpdatesFinished(const FeedDownloadResults& results) {
|
||||||
if (!results.updatedFeeds().isEmpty()) {
|
if (!results.updatedFeeds().isEmpty()) {
|
||||||
// Now, inform about results via GUI message/notification.
|
// Now, inform about results via GUI message/notification.
|
||||||
|
|
|
@ -133,8 +133,6 @@ class RSSGUARD_DLLSPEC Application : public QtSingleApplication {
|
||||||
void downloadRequested(QWebEngineDownloadItem* download_item);
|
void downloadRequested(QWebEngineDownloadItem* download_item);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void onFeedUpdatesStarted();
|
|
||||||
void onFeedUpdatesProgress(const Feed* feed, int current, int total);
|
|
||||||
void onFeedUpdatesFinished(const FeedDownloadResults& results);
|
void onFeedUpdatesFinished(const FeedDownloadResults& results);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -280,3 +280,71 @@ bool AccountCheckModel::isItemChecked(RootItem* item) {
|
||||||
bool AccountCheckModel::setItemChecked(RootItem* item, Qt::CheckState check) {
|
bool AccountCheckModel::setItemChecked(RootItem* item, Qt::CheckState check) {
|
||||||
return setData(indexForItem(item), check, Qt::CheckStateRole);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define ACCOUNTCHECKMODEL_H
|
#define ACCOUNTCHECKMODEL_H
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
#include "services/abstract/rootitem.h"
|
#include "services/abstract/rootitem.h"
|
||||||
|
|
||||||
|
@ -54,4 +55,26 @@ class AccountCheckModel : public QAbstractItemModel {
|
||||||
bool m_recursiveChange;
|
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
|
#endif // ACCOUNTCHECKMODEL_H
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
|
|
||||||
FeedsImportExportModel::FeedsImportExportModel(QObject* parent)
|
FeedsImportExportModel::FeedsImportExportModel(QObject* parent)
|
||||||
: AccountCheckModel(parent), m_mode(Mode::Import) {}
|
: AccountCheckSortedModel(parent), m_mode(Mode::Import) {}
|
||||||
|
|
||||||
FeedsImportExportModel::~FeedsImportExportModel() {
|
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
|
// 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.
|
// 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"));
|
QDomElement elem_opml_body = opml_document.createElement(QSL("body"));
|
||||||
QStack<RootItem*> items_to_process;
|
QStack<RootItem*> items_to_process;
|
||||||
|
|
||||||
items_to_process.push(m_rootItem);
|
items_to_process.push(sourceModel()->rootItem());
|
||||||
QStack<QDomElement> elements_to_use;
|
QStack<QDomElement> elements_to_use;
|
||||||
|
|
||||||
elements_to_use.push(elem_opml_body);
|
elements_to_use.push(elem_opml_body);
|
||||||
|
@ -65,7 +65,7 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray& result) {
|
||||||
RootItem* active_item = items_to_process.pop();
|
RootItem* active_item = items_to_process.pop();
|
||||||
|
|
||||||
for (RootItem* child_item : active_item->childItems()) {
|
for (RootItem* child_item : active_item->childItems()) {
|
||||||
if (!isItemChecked(child_item)) {
|
if (!sourceModel()->isItemChecked(child_item)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,12 +259,13 @@ void FeedsImportExportModel::importAsOPML20(const QByteArray& data, bool fetch_m
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
|
|
||||||
setRootItem(root_item);
|
setRootItem(root_item);
|
||||||
|
|
||||||
emit layoutChanged();
|
emit layoutChanged();
|
||||||
emit parsingFinished(failed, succeded, false);
|
emit parsingFinished(failed, succeded, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FeedsImportExportModel::exportToTxtURLPerLine(QByteArray& result) {
|
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");
|
result += feed->url() + QL1S("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "services/abstract/accountcheckmodel.h"
|
#include "services/abstract/accountcheckmodel.h"
|
||||||
|
|
||||||
class FeedsImportExportModel : public AccountCheckModel {
|
class FeedsImportExportModel : public AccountCheckSortedModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -197,7 +197,7 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
|
||||||
original_parents.push(target_root_node);
|
original_parents.push(target_root_node);
|
||||||
QStack<RootItem*> new_parents;
|
QStack<RootItem*> new_parents;
|
||||||
|
|
||||||
new_parents.push(model->rootItem());
|
new_parents.push(model->sourceModel()->rootItem());
|
||||||
bool some_feed_category_error = false;
|
bool some_feed_category_error = false;
|
||||||
|
|
||||||
// Iterate all new items we would like to merge into current model.
|
// 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();
|
RootItem* source_parent = new_parents.pop();
|
||||||
|
|
||||||
for (RootItem* source_item : source_parent->childItems()) {
|
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.
|
// We can skip this item, because it is not checked and should not be imported.
|
||||||
// NOTE: All descendants are thus skipped too.
|
// NOTE: All descendants are thus skipped too.
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Reference in a new issue