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*> 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) {
QSqlDatabase db_handle = qApp->database()->connection(objectName(), DatabaseFactory::FromSettings);

View file

@ -26,6 +26,8 @@
class Category;
class Feed;
class ServiceRoot;
class StandardServiceRoot;
class QTimer;
class FeedsModel : public QAbstractItemModel {
@ -68,6 +70,15 @@ class FeedsModel : public QAbstractItemModel {
// If it is, then it reassigns original_node to 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
// according to auto-update schedule.
// 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.
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.
QList<Feed*> feedsForIndex(const QModelIndex &index);
@ -105,6 +113,9 @@ class FeedsModel : public QAbstractItemModel {
RootItem *itemForIndex(const QModelIndex &index) const;
// 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;
// Determines if any feed has any new messages.

View file

@ -17,8 +17,9 @@
#include "core/rootitem.h"
#include "services/standard/standardcategory.h"
#include "services/standard/standardfeed.h"
#include "services/abstract/serviceroot.h"
#include "services/abstract/feed.h"
#include "services/abstract/category.h"
#include "miscellaneous/application.h"
#include <QVariant>
@ -91,6 +92,26 @@ QList<RootItem*> RootItem::getSubTree() {
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*> children;
QList<RootItem*> traversable_items;
@ -143,6 +164,10 @@ Feed *RootItem::toFeed() {
return static_cast<Feed*>(this);
}
ServiceRoot *RootItem::toServiceRoot() {
return static_cast<ServiceRoot*>(this);
}
int RootItem::countOfUnreadMessages() const {
int total_count = 0;

View file

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

View file

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