Unified methods for getting subtrees.

This commit is contained in:
Martin Rotter 2015-11-04 09:35:49 +01:00
parent 0176a73e51
commit f85b723b43
5 changed files with 93 additions and 43 deletions

View file

@ -263,6 +263,30 @@ void FeedsModel::reassignNodeToNewParent(RootItem *original_node, RootItem *new_
} }
} }
QList<ServiceRoot*> FeedsModel::serviceRoots() {
QList<ServiceRoot*> roots;
foreach (RootItem *root, m_rootItem->childItems()) {
if (root->kind() == RootItemKind::ServiceRoot) {
roots.append(root->toServiceRoot());
}
}
return roots;
}
StandardServiceRoot *FeedsModel::standardServiceRoot() {
foreach (RootItem *root, m_rootItem->childItems()) {
StandardServiceRoot *std_service_root;
if ((std_service_root = dynamic_cast<StandardServiceRoot*>(root)) != NULL) {
return std_service_root;
}
}
return NULL;
}
QList<Feed*> FeedsModel::feedsForScheduledUpdate(bool auto_update_now) { QList<Feed*> FeedsModel::feedsForScheduledUpdate(bool auto_update_now) {
QList<Feed*> feeds_for_update; QList<Feed*> feeds_for_update;
@ -430,28 +454,6 @@ Feed *FeedsModel::feedForIndex(const QModelIndex &index) {
} }
} }
/*
QList<Feed*> FeedsModel::feedsForIndexes(const QModelIndexList &indexes) {
QList<Feed*> feeds;
// Get selected feeds for each index.
foreach (const QModelIndex &index, indexes) {
feeds.append(feedsForIndex(index));
}
// Now we obtained all feeds from corresponding indexes.
if (indexes.size() != feeds.size()) {
// Selection contains duplicate feeds (for
// example situation where feed and its parent category are both
// selected). So, remove duplicates from the list.
qSort(feeds.begin(), feeds.end(), RootItem::lessThan);
feeds.erase(std::unique(feeds.begin(), feeds.end(), RootItem::isEqual), feeds.end());
}
return feeds;
}
*/
bool FeedsModel::markFeedsRead(const QList<Feed*> &feeds, int read) { bool FeedsModel::markFeedsRead(const QList<Feed*> &feeds, int read) {
QSqlDatabase db_handle = qApp->database()->connection(objectName(), DatabaseFactory::FromSettings); QSqlDatabase db_handle = qApp->database()->connection(objectName(), DatabaseFactory::FromSettings);

View file

@ -26,6 +26,8 @@
class Category; class Category;
class Feed; class Feed;
class ServiceRoot;
class StandardServiceRoot;
class QTimer; class QTimer;
class FeedsModel : public QAbstractItemModel { class FeedsModel : public QAbstractItemModel {
@ -68,6 +70,15 @@ class FeedsModel : public QAbstractItemModel {
// If it is, then it reassigns original_node to new parent. // If it is, then it reassigns original_node to new parent.
void reassignNodeToNewParent(RootItem *original_node, RootItem *new_parent); void reassignNodeToNewParent(RootItem *original_node, RootItem *new_parent);
// Returns all activated service roots.
// NOTE: Service root nodes are lying directly UNDER
// the model root item.
QList<ServiceRoot*> serviceRoots();
// Direct and the only global accessor to standard service root.
// NOTE: Standard service root is always activated.
StandardServiceRoot *standardServiceRoot();
// Returns the list of feeds which should be updated // Returns the list of feeds which should be updated
// according to auto-update schedule. // according to auto-update schedule.
// Variable "auto_update_now" is true, when global timeout // Variable "auto_update_now" is true, when global timeout
@ -86,9 +97,6 @@ class FeedsModel : public QAbstractItemModel {
// Returns list of all feeds contained in the model. // Returns list of all feeds contained in the model.
QList<Feed*> allFeeds(); QList<Feed*> allFeeds();
// Returns list of ALL CHILD feeds which belong to given parent indexes.
//QList<Feed*> feedsForIndexes(const QModelIndexList &indexes);
// Returns ALL RECURSIVE CHILD feeds contained within single index. // Returns ALL RECURSIVE CHILD feeds contained within single index.
QList<Feed*> feedsForIndex(const QModelIndex &index); QList<Feed*> feedsForIndex(const QModelIndex &index);
@ -105,6 +113,9 @@ class FeedsModel : public QAbstractItemModel {
RootItem *itemForIndex(const QModelIndex &index) const; RootItem *itemForIndex(const QModelIndex &index) const;
// Returns source QModelIndex on which lies given item. // Returns source QModelIndex on which lies given item.
// NOTE: This goes through all available indexes and
// checks their bound items manually, there is no
// other way to to this.
QModelIndex indexForItem(RootItem *item) const; QModelIndex indexForItem(RootItem *item) const;
// Determines if any feed has any new messages. // Determines if any feed has any new messages.

View file

@ -17,8 +17,9 @@
#include "core/rootitem.h" #include "core/rootitem.h"
#include "services/standard/standardcategory.h" #include "services/abstract/serviceroot.h"
#include "services/standard/standardfeed.h" #include "services/abstract/feed.h"
#include "services/abstract/category.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include <QVariant> #include <QVariant>
@ -91,6 +92,26 @@ QList<RootItem*> RootItem::getSubTree() {
return children; return children;
} }
QList<RootItem*> RootItem::getSubTree(RootItemKind::Kind kind_of_item) {
QList<RootItem*> children;
QList<RootItem*> traversable_items;
traversable_items.append(this);
// Iterate all nested items.
while (!traversable_items.isEmpty()) {
RootItem *active_item = traversable_items.takeFirst();
if ((active_item->kind() & kind_of_item) > 0) {
children.append(active_item);
}
traversable_items.append(active_item->childItems());
}
return children;
}
QList<Category*> RootItem::getSubTreeCategories() { QList<Category*> RootItem::getSubTreeCategories() {
QList<Category*> children; QList<Category*> children;
QList<RootItem*> traversable_items; QList<RootItem*> traversable_items;
@ -143,6 +164,10 @@ Feed *RootItem::toFeed() {
return static_cast<Feed*>(this); return static_cast<Feed*>(this);
} }
ServiceRoot *RootItem::toServiceRoot() {
return static_cast<ServiceRoot*>(this);
}
int RootItem::countOfUnreadMessages() const { int RootItem::countOfUnreadMessages() const {
int total_count = 0; int total_count = 0;

View file

@ -22,18 +22,24 @@
#include <QDateTime> #include <QDateTime>
#include <QFont> #include <QFont>
class Category; class Category;
class Feed; class Feed;
class ServiceRoot;
namespace RootItemKind { namespace RootItemKind {
// Describes the kind of the item. // Describes the kind of the item.
enum Kind { enum Kind {
Root = 1001, Root = 1,
Bin = 1002, Bin = 2,
Feed = 1003, Feed = 4,
Category = 1004, Category = 8,
ServiceRoot = 1005 ServiceRoot = 16
}; };
inline Kind operator|(Kind a, Kind b) {
return static_cast<Kind>(static_cast<int>(a) | static_cast<int>(b));
}
} }
// Represents ROOT item of FeedsModel. // Represents ROOT item of FeedsModel.
@ -147,6 +153,7 @@ class RootItem {
// Returns flat list of all items from subtree where this item is a root. // Returns flat list of all items from subtree where this item is a root.
// Returned list includes this item too. // Returned list includes this item too.
QList<RootItem*> getSubTree(); QList<RootItem*> getSubTree();
QList<RootItem*> getSubTree(RootItemKind::Kind kind_of_item);
QList<Category*> getSubTreeCategories(); QList<Category*> getSubTreeCategories();
QList<Feed*> getSubTreeFeeds(); QList<Feed*> getSubTreeFeeds();
@ -205,6 +212,7 @@ class RootItem {
// Converters // Converters
Category *toCategory(); Category *toCategory();
Feed *toFeed(); Feed *toFeed();
ServiceRoot *toServiceRoot();
// Compares two model items. // Compares two model items.
static bool isEqual(RootItem *lhs, RootItem *rhs); static bool isEqual(RootItem *lhs, RootItem *rhs);

View file

@ -91,9 +91,10 @@ RootItem *FeedsView::selectedItem() const {
if (selected_rows.isEmpty()) { if (selected_rows.isEmpty()) {
return NULL; return NULL;
} }
else {
RootItem *selected_item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(selected_rows.at(0))); RootItem *selected_item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(selected_rows.at(0)));
return selected_item == m_sourceModel->rootItem() ? NULL : selected_item; return selected_item == m_sourceModel->rootItem() ? NULL : selected_item;
}
} }
Category *FeedsView::selectedCategory() const { Category *FeedsView::selectedCategory() const {
@ -108,28 +109,31 @@ Feed *FeedsView::selectedFeed() const {
void FeedsView::saveExpandedStates() { void FeedsView::saveExpandedStates() {
Settings *settings = qApp->settings(); Settings *settings = qApp->settings();
QList<RootItem*> expandable_items;
expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItemKind::Category));
// Iterate all categories and save their expand statuses. // Iterate all categories and save their expand statuses.
foreach (Category *category, sourceModel()->allCategories()) { foreach (RootItem *item, expandable_items) {
QString setting_name = QString::number(qHash(category->title())) + QL1S("-") + QString::number(category->id()); QString setting_name = QString::number(qHash(item->title())) + QL1S("-") + QString::number(item->id());
settings->setValue(GROUP(Categories), settings->setValue(GROUP(Categories),
setting_name, setting_name,
isExpanded(model()->mapFromSource(sourceModel()->indexForItem(category)))); isExpanded(model()->mapFromSource(sourceModel()->indexForItem(item))));
} }
} }
void FeedsView::loadExpandedStates() { void FeedsView::loadExpandedStates() {
Settings *settings = qApp->settings(); Settings *settings = qApp->settings();
QList<RootItem*> expandable_items;
// TODO: nastavit všechny service rooty automaticky na expanded expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot));
// toto obnáší vytvoření metody sourceModel()->serviceRoots()
// Iterate all categories and save their expand statuses. // Iterate all categories and save their expand statuses.
foreach (Category *category, sourceModel()->allCategories()) { foreach (RootItem *item, expandable_items) {
QString setting_name = QString::number(qHash(category->title())) + QL1S("-") + QString::number(category->id()); QString setting_name = QString::number(qHash(item->title())) + QL1S("-") + QString::number(item->id());
setExpanded(model()->mapFromSource(sourceModel()->indexForItem(category)), setExpanded(model()->mapFromSource(sourceModel()->indexForItem(item)),
settings->value(GROUP(Categories), setting_name, true).toBool()); settings->value(GROUP(Categories), setting_name, true).toBool());
} }
} }