#809 for categories too

This commit is contained in:
Martin Rotter 2023-01-20 12:01:13 +01:00
parent 2759e4b820
commit 9c9030ab01
4 changed files with 92 additions and 30 deletions

View file

@ -14,9 +14,9 @@
#include <QVariant>
RootItem::RootItem(RootItem* parent_item)
: QObject(nullptr), m_kind(RootItem::Kind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QL1S("")),
m_title(QString()), m_description(QString()), m_creationDate(QDateTime::currentDateTimeUtc()),
m_keepOnTop(false), m_sortOrder(NO_PARENT_CATEGORY), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
: QObject(nullptr), m_kind(RootItem::Kind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QL1S("")), m_title(QString()),
m_description(QString()), m_creationDate(QDateTime::currentDateTimeUtc()), m_keepOnTop(false),
m_sortOrder(NO_PARENT_CATEGORY), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
RootItem::RootItem(const RootItem& other) : RootItem(nullptr) {
setTitle(other.title());
@ -28,7 +28,7 @@ RootItem::RootItem(const RootItem& other) : RootItem(nullptr) {
// NOTE: We do not need to clone childs, because that would mean that
// either source or target item tree would get corrupted.
//setChildItems(other.childItems());
// setChildItems(other.childItems());
setParent(other.parent());
setCreationDate(other.creationDate());
@ -43,10 +43,7 @@ QString RootItem::hashCode() const {
ServiceRoot* root = getParentServiceRoot();
int acc_id = root == nullptr ? 0 : root->accountId();
return
QString::number(acc_id) + QL1S("-") +
QString::number(int(kind())) + QL1S("-") +
QString::number(id());
return QString::number(acc_id) + QL1S("-") + QString::number(int(kind())) + QL1S("-") + QString::number(id());
}
QString RootItem::additionalTooltip() const {
@ -176,9 +173,11 @@ QVariant RootItem::data(int column, int role) const {
else {
int count_all = countOfAllMessages();
return qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString()
.replace(QSL(PLACEHOLDER_UNREAD_COUNTS), count_unread < 0 ? QSL("-") : QString::number(count_unread))
.replace(QSL(PLACEHOLDER_ALL_COUNTS), count_all < 0 ? QSL("-") : QString::number(count_all));
return qApp->settings()
->value(GROUP(Feeds), SETTING(Feeds::CountFormat))
.toString()
.replace(QSL(PLACEHOLDER_UNREAD_COUNTS), count_unread < 0 ? QSL("-") : QString::number(count_unread))
.replace(QSL(PLACEHOLDER_ALL_COUNTS), count_all < 0 ? QSL("-") : QString::number(count_all));
}
}
else {
@ -217,21 +216,19 @@ bool RootItem::performDragDropChange(RootItem* target_item) {
int RootItem::countOfUnreadMessages() const {
return boolinq::from(m_childItems).sum([](RootItem* it) {
return (it->kind() == RootItem::Kind::Important ||
it->kind() == RootItem::Kind::Unread ||
return (it->kind() == RootItem::Kind::Important || it->kind() == RootItem::Kind::Unread ||
it->kind() == RootItem::Kind::Labels)
? 0
: it->countOfUnreadMessages();
? 0
: it->countOfUnreadMessages();
});
}
int RootItem::countOfAllMessages() const {
return boolinq::from(m_childItems).sum([](RootItem* it) {
return (it->kind() == RootItem::Kind::Important ||
it->kind() == RootItem::Kind::Unread ||
return (it->kind() == RootItem::Kind::Important || it->kind() == RootItem::Kind::Unread ||
it->kind() == RootItem::Kind::Labels)
? 0
: it->countOfAllMessages();
? 0
: it->countOfAllMessages();
});
}
@ -341,7 +338,7 @@ RootItem* RootItem::getItemFromSubTree(std::function<bool(const RootItem*)> test
return nullptr;
}
QHash<int, Category*> RootItem::getHashedSubTreeCategories() const {
QHash<int, Category*> RootItem::getSubTreeCategoriesForAssemble() const {
QHash<int, Category*> children;
QList<RootItem*> traversable_items;
@ -361,6 +358,26 @@ QHash<int, Category*> RootItem::getHashedSubTreeCategories() const {
return children;
}
QHash<QString, Category*> RootItem::getHashedSubTreeCategories() const {
QHash<QString, Category*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
while (!traversable_items.isEmpty()) {
RootItem* active_item = traversable_items.takeFirst();
if (active_item->kind() == RootItem::Kind::Category && !children.contains(active_item->customId())) {
children.insert(active_item->customId(), active_item->toCategory());
}
traversable_items.append(active_item->childItems());
}
return children;
}
QHash<QString, Feed*> RootItem::getHashedSubTreeFeeds() const {
QHash<QString, Feed*> children;
QList<RootItem*> traversable_items;

View file

@ -139,10 +139,14 @@ class RSSGUARD_DLLSPEC RootItem : public QObject {
RootItem* getItemFromSubTree(std::function<bool(const RootItem*)> tester) const;
// Returns list of categories complemented by their own integer primary ID.
QHash<int, Category*> getHashedSubTreeCategories() const;
QHash<int, Category*> getSubTreeCategoriesForAssemble() const;
// Returns list of categories complemented by their own string CUSTOM ID.
QHash<QString, Category *> getHashedSubTreeCategories() const;
// Returns list of feeds complemented by their own string CUSTOM ID.
QHash<QString, Feed*> getHashedSubTreeFeeds() const;
QList<Feed*> getSubTreeFeeds() const;
QList<Feed*> getSubTreeAutoFetchingWithManualIntervalsFeeds() const;
QList<Feed*> getSubAutoFetchingEnabledFeeds() const;

View file

@ -375,12 +375,10 @@ QMap<QString, QVariantMap> ServiceRoot::storeCustomFeedsData() {
feed_custom_data.insert(QSL("is_quiet"), feed->isQuiet());
feed_custom_data.insert(QSL("open_articles_directly"), feed->openArticlesDirectly());
// NOTE: These is here specifically to be able to restore custom sort order.
// NOTE: This is here specifically to be able to restore custom sort order.
// Otherwise the information is lost when list of feeds/folders is refreshed from remote
// service.
feed_custom_data.insert(QSL("sort_order"), feed->sortOrder());
// feed_custom_data.insert(QSL("custom_id"), feed->customId());
// feed_custom_data.insert(QSL("category"), feed->parent()->id());
custom_data.insert(feed->customId(), feed_custom_data);
}
@ -388,6 +386,24 @@ QMap<QString, QVariantMap> ServiceRoot::storeCustomFeedsData() {
return custom_data;
}
QMap<QString, QVariantMap> ServiceRoot::storeCustomCategoriesData() {
QMap<QString, QVariantMap> custom_data;
auto str = getSubTreeCategories();
for (const Category* cat : qAsConst(str)) {
QVariantMap cat_custom_data;
// NOTE: This is here specifically to be able to restore custom sort order.
// Otherwise the information is lost when list of feeds/folders is refreshed from remote
// service.
cat_custom_data.insert(QSL("sort_order"), cat->sortOrder());
custom_data.insert(cat->customId(), cat_custom_data);
}
return custom_data;
}
void ServiceRoot::restoreCustomFeedsData(const QMap<QString, QVariantMap>& data, const QHash<QString, Feed*>& feeds) {
QMapIterator<QString, QVariantMap> i(data);
@ -411,6 +427,12 @@ void ServiceRoot::restoreCustomFeedsData(const QMap<QString, QVariantMap>& data,
}
}
void ServiceRoot::restoreCustomCategoriesData(const QMap<QString, QVariantMap>& data,
const QHash<QString, Category*>& cats) {
Q_UNUSED(data)
Q_UNUSED(cats)
}
QNetworkProxy ServiceRoot::networkProxy() const {
return m_networkProxy;
}
@ -447,6 +469,7 @@ void ServiceRoot::syncIn() {
qDebugNN << LOGSEC_CORE << "New feed tree for sync-in obtained.";
auto feed_custom_data = storeCustomFeedsData();
auto categories_custom_data = storeCustomCategoriesData();
// Remove from feeds model, then from SQL but leave messages intact.
bool uses_remote_labels =
@ -457,9 +480,10 @@ void ServiceRoot::syncIn() {
removeOldAccountFromDatabase(false, uses_remote_labels);
// Re-sort items to accomodate current sort order.
resortAccountTree(new_tree, feed_custom_data);
resortAccountTree(new_tree, categories_custom_data, feed_custom_data);
// Restore some local settings to feeds etc.
restoreCustomCategoriesData(categories_custom_data, new_tree->getHashedSubTreeCategories());
restoreCustomFeedsData(feed_custom_data, new_tree->getHashedSubTreeFeeds());
// Model is clean, now store new tree into DB and
@ -865,7 +889,7 @@ CacheForServiceRoot* ServiceRoot::toCache() const {
}
void ServiceRoot::assembleFeeds(const Assignment& feeds) {
QHash<int, Category*> categories = getHashedSubTreeCategories();
QHash<int, Category*> categories = getSubTreeCategoriesForAssemble();
for (const AssignmentItem& feed : feeds) {
if (feed.first == NO_PARENT_CATEGORY) {
@ -882,7 +906,9 @@ void ServiceRoot::assembleFeeds(const Assignment& feeds) {
}
}
void ServiceRoot::resortAccountTree(RootItem* tree, const QMap<QString, QVariantMap>& custom_data) const {
void ServiceRoot::resortAccountTree(RootItem* tree,
const QMap<QString, QVariantMap>& custom_category_data,
const QMap<QString, QVariantMap>& custom_feed_data) const {
// Iterate tree and rearrange children.
QList<RootItem*> traversable_items;
@ -896,8 +922,14 @@ void ServiceRoot::resortAccountTree(RootItem* tree, const QMap<QString, QVariant
// other item types do not matter.
std::sort(chldr.begin(), chldr.end(), [&](const RootItem* lhs, const RootItem* rhs) {
if (lhs->kind() == RootItem::Kind::Feed && rhs->kind() == RootItem::Kind::Feed) {
auto lhs_order = custom_data[lhs->customId()].value(QSL("sort_order")).toInt();
auto rhs_order = custom_data[rhs->customId()].value(QSL("sort_order")).toInt();
auto lhs_order = custom_feed_data[lhs->customId()].value(QSL("sort_order")).toInt();
auto rhs_order = custom_feed_data[rhs->customId()].value(QSL("sort_order")).toInt();
return lhs_order < rhs_order;
}
else if (lhs->kind() == RootItem::Kind::Category && rhs->kind() == RootItem::Kind::Category) {
auto lhs_order = custom_category_data[lhs->customId()].value(QSL("sort_order")).toInt();
auto rhs_order = custom_category_data[rhs->customId()].value(QSL("sort_order")).toInt();
return lhs_order < rhs_order;
}

View file

@ -274,10 +274,19 @@ class ServiceRoot : public RootItem {
void itemRemovalRequested(RootItem* item);
private:
void resortAccountTree(RootItem* tree, const QMap<QString, QVariantMap>& custom_data) const;
void resortAccountTree(RootItem* tree,
const QMap<QString, QVariantMap>& custom_category_data,
const QMap<QString, QVariantMap>& custom_feed_data) const;
// Key is feed's custom ID.
virtual QMap<QString, QVariantMap> storeCustomFeedsData();
// Key is category's custom ID.
virtual QMap<QString, QVariantMap> storeCustomCategoriesData();
virtual void restoreCustomFeedsData(const QMap<QString, QVariantMap>& data, const QHash<QString, Feed*>& feeds);
virtual void restoreCustomCategoriesData(const QMap<QString, QVariantMap>& data,
const QHash<QString, Category*>& cats);
protected:
RecycleBin* m_recycleBin;