#809 for categories too
This commit is contained in:
parent
2759e4b820
commit
9c9030ab01
4 changed files with 92 additions and 30 deletions
|
@ -14,9 +14,9 @@
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
RootItem::RootItem(RootItem* parent_item)
|
RootItem::RootItem(RootItem* parent_item)
|
||||||
: QObject(nullptr), m_kind(RootItem::Kind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QL1S("")),
|
: QObject(nullptr), m_kind(RootItem::Kind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QL1S("")), m_title(QString()),
|
||||||
m_title(QString()), m_description(QString()), m_creationDate(QDateTime::currentDateTimeUtc()),
|
m_description(QString()), m_creationDate(QDateTime::currentDateTimeUtc()), m_keepOnTop(false),
|
||||||
m_keepOnTop(false), m_sortOrder(NO_PARENT_CATEGORY), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
|
m_sortOrder(NO_PARENT_CATEGORY), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
|
||||||
|
|
||||||
RootItem::RootItem(const RootItem& other) : RootItem(nullptr) {
|
RootItem::RootItem(const RootItem& other) : RootItem(nullptr) {
|
||||||
setTitle(other.title());
|
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
|
// NOTE: We do not need to clone childs, because that would mean that
|
||||||
// either source or target item tree would get corrupted.
|
// either source or target item tree would get corrupted.
|
||||||
//setChildItems(other.childItems());
|
// setChildItems(other.childItems());
|
||||||
|
|
||||||
setParent(other.parent());
|
setParent(other.parent());
|
||||||
setCreationDate(other.creationDate());
|
setCreationDate(other.creationDate());
|
||||||
|
@ -43,10 +43,7 @@ QString RootItem::hashCode() const {
|
||||||
ServiceRoot* root = getParentServiceRoot();
|
ServiceRoot* root = getParentServiceRoot();
|
||||||
int acc_id = root == nullptr ? 0 : root->accountId();
|
int acc_id = root == nullptr ? 0 : root->accountId();
|
||||||
|
|
||||||
return
|
return QString::number(acc_id) + QL1S("-") + QString::number(int(kind())) + QL1S("-") + QString::number(id());
|
||||||
QString::number(acc_id) + QL1S("-") +
|
|
||||||
QString::number(int(kind())) + QL1S("-") +
|
|
||||||
QString::number(id());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString RootItem::additionalTooltip() const {
|
QString RootItem::additionalTooltip() const {
|
||||||
|
@ -176,9 +173,11 @@ QVariant RootItem::data(int column, int role) const {
|
||||||
else {
|
else {
|
||||||
int count_all = countOfAllMessages();
|
int count_all = countOfAllMessages();
|
||||||
|
|
||||||
return qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString()
|
return qApp->settings()
|
||||||
.replace(QSL(PLACEHOLDER_UNREAD_COUNTS), count_unread < 0 ? QSL("-") : QString::number(count_unread))
|
->value(GROUP(Feeds), SETTING(Feeds::CountFormat))
|
||||||
.replace(QSL(PLACEHOLDER_ALL_COUNTS), count_all < 0 ? QSL("-") : QString::number(count_all));
|
.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 {
|
else {
|
||||||
|
@ -217,21 +216,19 @@ bool RootItem::performDragDropChange(RootItem* target_item) {
|
||||||
|
|
||||||
int RootItem::countOfUnreadMessages() const {
|
int RootItem::countOfUnreadMessages() const {
|
||||||
return boolinq::from(m_childItems).sum([](RootItem* it) {
|
return boolinq::from(m_childItems).sum([](RootItem* it) {
|
||||||
return (it->kind() == RootItem::Kind::Important ||
|
return (it->kind() == RootItem::Kind::Important || it->kind() == RootItem::Kind::Unread ||
|
||||||
it->kind() == RootItem::Kind::Unread ||
|
|
||||||
it->kind() == RootItem::Kind::Labels)
|
it->kind() == RootItem::Kind::Labels)
|
||||||
? 0
|
? 0
|
||||||
: it->countOfUnreadMessages();
|
: it->countOfUnreadMessages();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int RootItem::countOfAllMessages() const {
|
int RootItem::countOfAllMessages() const {
|
||||||
return boolinq::from(m_childItems).sum([](RootItem* it) {
|
return boolinq::from(m_childItems).sum([](RootItem* it) {
|
||||||
return (it->kind() == RootItem::Kind::Important ||
|
return (it->kind() == RootItem::Kind::Important || it->kind() == RootItem::Kind::Unread ||
|
||||||
it->kind() == RootItem::Kind::Unread ||
|
|
||||||
it->kind() == RootItem::Kind::Labels)
|
it->kind() == RootItem::Kind::Labels)
|
||||||
? 0
|
? 0
|
||||||
: it->countOfAllMessages();
|
: it->countOfAllMessages();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +338,7 @@ RootItem* RootItem::getItemFromSubTree(std::function<bool(const RootItem*)> test
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, Category*> RootItem::getHashedSubTreeCategories() const {
|
QHash<int, Category*> RootItem::getSubTreeCategoriesForAssemble() const {
|
||||||
QHash<int, Category*> children;
|
QHash<int, Category*> children;
|
||||||
QList<RootItem*> traversable_items;
|
QList<RootItem*> traversable_items;
|
||||||
|
|
||||||
|
@ -361,6 +358,26 @@ QHash<int, Category*> RootItem::getHashedSubTreeCategories() const {
|
||||||
return children;
|
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*> RootItem::getHashedSubTreeFeeds() const {
|
||||||
QHash<QString, Feed*> children;
|
QHash<QString, Feed*> children;
|
||||||
QList<RootItem*> traversable_items;
|
QList<RootItem*> traversable_items;
|
||||||
|
|
|
@ -139,10 +139,14 @@ class RSSGUARD_DLLSPEC RootItem : public QObject {
|
||||||
RootItem* getItemFromSubTree(std::function<bool(const RootItem*)> tester) const;
|
RootItem* getItemFromSubTree(std::function<bool(const RootItem*)> tester) const;
|
||||||
|
|
||||||
// Returns list of categories complemented by their own integer primary ID.
|
// 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.
|
// Returns list of feeds complemented by their own string CUSTOM ID.
|
||||||
QHash<QString, Feed*> getHashedSubTreeFeeds() const;
|
QHash<QString, Feed*> getHashedSubTreeFeeds() const;
|
||||||
|
|
||||||
QList<Feed*> getSubTreeFeeds() const;
|
QList<Feed*> getSubTreeFeeds() const;
|
||||||
QList<Feed*> getSubTreeAutoFetchingWithManualIntervalsFeeds() const;
|
QList<Feed*> getSubTreeAutoFetchingWithManualIntervalsFeeds() const;
|
||||||
QList<Feed*> getSubAutoFetchingEnabledFeeds() const;
|
QList<Feed*> getSubAutoFetchingEnabledFeeds() const;
|
||||||
|
|
|
@ -375,12 +375,10 @@ QMap<QString, QVariantMap> ServiceRoot::storeCustomFeedsData() {
|
||||||
feed_custom_data.insert(QSL("is_quiet"), feed->isQuiet());
|
feed_custom_data.insert(QSL("is_quiet"), feed->isQuiet());
|
||||||
feed_custom_data.insert(QSL("open_articles_directly"), feed->openArticlesDirectly());
|
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
|
// Otherwise the information is lost when list of feeds/folders is refreshed from remote
|
||||||
// service.
|
// service.
|
||||||
feed_custom_data.insert(QSL("sort_order"), feed->sortOrder());
|
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);
|
custom_data.insert(feed->customId(), feed_custom_data);
|
||||||
}
|
}
|
||||||
|
@ -388,6 +386,24 @@ QMap<QString, QVariantMap> ServiceRoot::storeCustomFeedsData() {
|
||||||
return custom_data;
|
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) {
|
void ServiceRoot::restoreCustomFeedsData(const QMap<QString, QVariantMap>& data, const QHash<QString, Feed*>& feeds) {
|
||||||
QMapIterator<QString, QVariantMap> i(data);
|
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 {
|
QNetworkProxy ServiceRoot::networkProxy() const {
|
||||||
return m_networkProxy;
|
return m_networkProxy;
|
||||||
}
|
}
|
||||||
|
@ -447,6 +469,7 @@ void ServiceRoot::syncIn() {
|
||||||
qDebugNN << LOGSEC_CORE << "New feed tree for sync-in obtained.";
|
qDebugNN << LOGSEC_CORE << "New feed tree for sync-in obtained.";
|
||||||
|
|
||||||
auto feed_custom_data = storeCustomFeedsData();
|
auto feed_custom_data = storeCustomFeedsData();
|
||||||
|
auto categories_custom_data = storeCustomCategoriesData();
|
||||||
|
|
||||||
// Remove from feeds model, then from SQL but leave messages intact.
|
// Remove from feeds model, then from SQL but leave messages intact.
|
||||||
bool uses_remote_labels =
|
bool uses_remote_labels =
|
||||||
|
@ -457,9 +480,10 @@ void ServiceRoot::syncIn() {
|
||||||
removeOldAccountFromDatabase(false, uses_remote_labels);
|
removeOldAccountFromDatabase(false, uses_remote_labels);
|
||||||
|
|
||||||
// Re-sort items to accomodate current sort order.
|
// 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.
|
// Restore some local settings to feeds etc.
|
||||||
|
restoreCustomCategoriesData(categories_custom_data, new_tree->getHashedSubTreeCategories());
|
||||||
restoreCustomFeedsData(feed_custom_data, new_tree->getHashedSubTreeFeeds());
|
restoreCustomFeedsData(feed_custom_data, new_tree->getHashedSubTreeFeeds());
|
||||||
|
|
||||||
// Model is clean, now store new tree into DB and
|
// Model is clean, now store new tree into DB and
|
||||||
|
@ -865,7 +889,7 @@ CacheForServiceRoot* ServiceRoot::toCache() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceRoot::assembleFeeds(const Assignment& feeds) {
|
void ServiceRoot::assembleFeeds(const Assignment& feeds) {
|
||||||
QHash<int, Category*> categories = getHashedSubTreeCategories();
|
QHash<int, Category*> categories = getSubTreeCategoriesForAssemble();
|
||||||
|
|
||||||
for (const AssignmentItem& feed : feeds) {
|
for (const AssignmentItem& feed : feeds) {
|
||||||
if (feed.first == NO_PARENT_CATEGORY) {
|
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.
|
// Iterate tree and rearrange children.
|
||||||
QList<RootItem*> traversable_items;
|
QList<RootItem*> traversable_items;
|
||||||
|
|
||||||
|
@ -896,8 +922,14 @@ void ServiceRoot::resortAccountTree(RootItem* tree, const QMap<QString, QVariant
|
||||||
// other item types do not matter.
|
// other item types do not matter.
|
||||||
std::sort(chldr.begin(), chldr.end(), [&](const RootItem* lhs, const RootItem* rhs) {
|
std::sort(chldr.begin(), chldr.end(), [&](const RootItem* lhs, const RootItem* rhs) {
|
||||||
if (lhs->kind() == RootItem::Kind::Feed && rhs->kind() == RootItem::Kind::Feed) {
|
if (lhs->kind() == RootItem::Kind::Feed && rhs->kind() == RootItem::Kind::Feed) {
|
||||||
auto lhs_order = custom_data[lhs->customId()].value(QSL("sort_order")).toInt();
|
auto lhs_order = custom_feed_data[lhs->customId()].value(QSL("sort_order")).toInt();
|
||||||
auto rhs_order = custom_data[rhs->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;
|
return lhs_order < rhs_order;
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,10 +274,19 @@ class ServiceRoot : public RootItem {
|
||||||
void itemRemovalRequested(RootItem* item);
|
void itemRemovalRequested(RootItem* item);
|
||||||
|
|
||||||
private:
|
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();
|
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 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:
|
protected:
|
||||||
RecycleBin* m_recycleBin;
|
RecycleBin* m_recycleBin;
|
||||||
|
|
Loading…
Add table
Reference in a new issue