Refactored assembling methods, TT-RSS is now able to load stored feeds.
This commit is contained in:
parent
cac3aee503
commit
c4a8497471
|
@ -281,6 +281,26 @@ QList<Category*> RootItem::getSubTreeCategories() {
|
|||
return children;
|
||||
}
|
||||
|
||||
QHash<int,Category*> RootItem::getHashedSubTreeCategories() {
|
||||
QHash<int,Category*> 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() == RootItemKind::Category && !children.contains(active_item->id())) {
|
||||
children.insert(active_item->id(), active_item->toCategory());
|
||||
}
|
||||
|
||||
traversable_items.append(active_item->childItems());
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
QList<Feed*> RootItem::getSubTreeFeeds() {
|
||||
QList<Feed*> children;
|
||||
QList<RootItem*> traversable_items;
|
||||
|
|
|
@ -177,6 +177,7 @@ class RootItem : public QObject {
|
|||
QList<RootItem*> getSubTree();
|
||||
QList<RootItem*> getSubTree(RootItemKind::Kind kind_of_item);
|
||||
QList<Category*> getSubTreeCategories();
|
||||
QHash<int,Category*> getHashedSubTreeCategories();
|
||||
QList<Feed*> getSubTreeFeeds();
|
||||
|
||||
// Returns the service root node which is direct or indirect parent of current item.
|
||||
|
|
|
@ -753,6 +753,9 @@
|
|||
<property name="text">
|
||||
<string>Status bar</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "core/feedsmodel.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "services/abstract/category.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
||||
|
@ -89,3 +90,47 @@ int ServiceRoot::accountId() const {
|
|||
void ServiceRoot::setAccountId(int account_id) {
|
||||
m_accountId = account_id;
|
||||
}
|
||||
|
||||
void ServiceRoot::assembleFeeds(Assignment feeds) {
|
||||
QHash<int,Category*> categories = getHashedSubTreeCategories();
|
||||
|
||||
foreach (const AssignmentItem &feed, feeds) {
|
||||
if (feed.first == NO_PARENT_CATEGORY) {
|
||||
// This is top-level feed, add it to the root item.
|
||||
appendChild(feed.second);
|
||||
feed.second->updateCounts(true);
|
||||
}
|
||||
else if (categories.contains(feed.first)) {
|
||||
// This feed belongs to this category.
|
||||
categories.value(feed.first)->appendChild(feed.second);
|
||||
feed.second->updateCounts(true);
|
||||
}
|
||||
else {
|
||||
qWarning("Feed '%s' is loose, skipping it.", qPrintable(feed.second->title()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceRoot::assembleCategories(Assignment categories) {
|
||||
QHash<int,RootItem*> assignments;
|
||||
assignments.insert(NO_PARENT_CATEGORY, this);
|
||||
|
||||
// Add top-level categories.
|
||||
while (!categories.isEmpty()) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
if (assignments.contains(categories.at(i).first)) {
|
||||
// Parent category of this category is already added.
|
||||
assignments.value(categories.at(i).first)->appendChild(categories.at(i).second);
|
||||
|
||||
// Now, added category can be parent for another categories, add it.
|
||||
assignments.insert(categories.at(i).second->id(), categories.at(i).second);
|
||||
|
||||
// Remove the category from the list, because it was
|
||||
// added to the final collection.
|
||||
categories.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ class RecycleBin;
|
|||
class QAction;
|
||||
class QSqlTableModel;
|
||||
|
||||
// Car here represents ID of the item.
|
||||
typedef QList<QPair<int,RootItem*> > Assignment;
|
||||
typedef QPair<int,RootItem*> AssignmentItem;
|
||||
|
||||
// THIS IS the root node of the service.
|
||||
// NOTE: The root usually contains some core functionality of the
|
||||
// service like service account username/password etc.
|
||||
|
@ -149,6 +153,11 @@ class ServiceRoot : public RootItem {
|
|||
int accountId() const;
|
||||
void setAccountId(int account_id);
|
||||
|
||||
protected:
|
||||
// Takes lists of feeds/categories and assembles them into the tree structure.
|
||||
void assembleCategories(Assignment categories);
|
||||
void assembleFeeds(Assignment feeds);
|
||||
|
||||
signals:
|
||||
// Emitted if data in any item belonging to this root are changed.
|
||||
void dataChanged(QList<RootItem*> items);
|
||||
|
|
|
@ -763,7 +763,6 @@ QNetworkReply::NetworkError StandardFeed::networkError() const {
|
|||
}
|
||||
|
||||
StandardFeed::StandardFeed(const QSqlRecord &record) : Feed(NULL) {
|
||||
setKind(RootItemKind::Feed);
|
||||
setTitle(record.value(FDS_DB_TITLE_INDEX).toString());
|
||||
setId(record.value(FDS_DB_ID_INDEX).toInt());
|
||||
setDescription(record.value(FDS_DB_DESCRIPTION_INDEX).toString());
|
||||
|
@ -782,6 +781,6 @@ StandardFeed::StandardFeed(const QSqlRecord &record) : Feed(NULL) {
|
|||
}
|
||||
|
||||
|
||||
setAutoUpdateType(static_cast<StandardFeed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
|
||||
setAutoUpdateType(static_cast<Feed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
|
||||
setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
|
||||
}
|
||||
|
|
|
@ -331,8 +331,8 @@ bool StandardServiceRoot::emptyBin() {
|
|||
|
||||
void StandardServiceRoot::loadFromDatabase(){
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
|
||||
CategoryAssignment categories;
|
||||
FeedAssignment feeds;
|
||||
Assignment categories;
|
||||
Assignment feeds;
|
||||
|
||||
// Obtain data for categories from the database.
|
||||
QSqlQuery query_categories(database);
|
||||
|
@ -344,7 +344,7 @@ void StandardServiceRoot::loadFromDatabase(){
|
|||
}
|
||||
|
||||
while (query_categories.next()) {
|
||||
CategoryAssignmentItem pair;
|
||||
AssignmentItem pair;
|
||||
pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt();
|
||||
pair.second = new StandardCategory(query_categories.record());
|
||||
|
||||
|
@ -369,10 +369,10 @@ void StandardServiceRoot::loadFromDatabase(){
|
|||
case StandardFeed::Rdf:
|
||||
case StandardFeed::Rss0X:
|
||||
case StandardFeed::Rss2X: {
|
||||
FeedAssignmentItem pair;
|
||||
AssignmentItem pair;
|
||||
pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt();
|
||||
pair.second = new StandardFeed(query_feeds.record());
|
||||
pair.second->setType(type);
|
||||
qobject_cast<StandardFeed*>(pair.second)->setType(type);
|
||||
|
||||
feeds << pair;
|
||||
break;
|
||||
|
@ -419,6 +419,7 @@ QHash<int,StandardCategory*> StandardServiceRoot::categoriesForItem(RootItem *ro
|
|||
}
|
||||
|
||||
QHash<int,StandardCategory*> StandardServiceRoot::allCategories() {
|
||||
// TODO: změnit na qlist, použít getsubtree možná
|
||||
return categoriesForItem(this);
|
||||
}
|
||||
|
||||
|
@ -436,26 +437,6 @@ QList<QAction*> StandardServiceRoot::getContextMenuForFeed(StandardFeed *feed) {
|
|||
return m_feedContextMenu;
|
||||
}
|
||||
|
||||
void StandardServiceRoot::assembleFeeds(FeedAssignment feeds) {
|
||||
QHash<int,StandardCategory*> categories = categoriesForItem(this);
|
||||
|
||||
foreach (const FeedAssignmentItem &feed, feeds) {
|
||||
if (feed.first == NO_PARENT_CATEGORY) {
|
||||
// This is top-level feed, add it to the root item.
|
||||
appendChild(feed.second);
|
||||
feed.second->updateCounts(true);
|
||||
}
|
||||
else if (categories.contains(feed.first)) {
|
||||
// This feed belongs to this category.
|
||||
categories.value(feed.first)->appendChild(feed.second);
|
||||
feed.second->updateCounts(true);
|
||||
}
|
||||
else {
|
||||
qWarning("Feed '%s' is loose, skipping it.", qPrintable(feed.second->title()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel *model, QString &output_message) {
|
||||
QStack<RootItem*> original_parents; original_parents.push(this);
|
||||
QStack<RootItem*> new_parents; new_parents.push(model->rootItem());
|
||||
|
@ -696,26 +677,3 @@ bool StandardServiceRoot::onAfterMessagesRestoredFromBin(RootItem *selected_item
|
|||
requestFeedReadFilterReload();
|
||||
return true;
|
||||
}
|
||||
|
||||
void StandardServiceRoot::assembleCategories(CategoryAssignment categories) {
|
||||
QHash<int,RootItem*> assignments;
|
||||
assignments.insert(NO_PARENT_CATEGORY, this);
|
||||
|
||||
// Add top-level categories.
|
||||
while (!categories.isEmpty()) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
if (assignments.contains(categories.at(i).first)) {
|
||||
// Parent category of this category is already added.
|
||||
assignments.value(categories.at(i).first)->appendChild(categories.at(i).second);
|
||||
|
||||
// Now, added category can be parent for another categories, add it.
|
||||
assignments.insert(categories.at(i).second->id(), categories.at(i).second);
|
||||
|
||||
// Remove the category from the list, because it was
|
||||
// added to the final collection.
|
||||
categories.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,12 +30,6 @@ class StandardFeed;
|
|||
class FeedsImportExportModel;
|
||||
class QMenu;
|
||||
|
||||
typedef QList<QPair<int, StandardCategory*> > CategoryAssignment;
|
||||
typedef QPair<int, StandardCategory*> CategoryAssignmentItem;
|
||||
|
||||
typedef QList<QPair<int, StandardFeed*> > FeedAssignment;
|
||||
typedef QPair<int, StandardFeed*> FeedAssignmentItem;
|
||||
|
||||
class StandardServiceRoot : public ServiceRoot {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -117,11 +111,6 @@ class StandardServiceRoot : public ServiceRoot {
|
|||
// which are suitable as IN clause for SQL queries.
|
||||
QStringList textualFeedIds(const QList<Feed *> &feeds);
|
||||
|
||||
// Takes lists of feeds/categories and assembles
|
||||
// them into the tree structure.
|
||||
void assembleCategories(CategoryAssignment categories);
|
||||
void assembleFeeds(FeedAssignment feeds);
|
||||
|
||||
StandardRecycleBin *m_recycleBin;
|
||||
|
||||
// Menus.
|
||||
|
|
|
@ -18,11 +18,22 @@
|
|||
#include "services/tt-rss/ttrsscategory.h"
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
|
||||
TtRssCategory::TtRssCategory(RootItem *parent) : Category(parent), m_customId(NO_PARENT_CATEGORY) {
|
||||
}
|
||||
|
||||
TtRssCategory::TtRssCategory(const QSqlRecord &record) : Category(NULL) {
|
||||
setId(record.value(CAT_DB_ID_INDEX).toInt());
|
||||
setTitle(record.value(CAT_DB_TITLE_INDEX).toString());
|
||||
setIcon(qApp->icons()->fromByteArray(record.value(CAT_DB_ICON_INDEX).toByteArray()));
|
||||
setCustomId(record.value(CAT_DB_CUSTOM_ID_INDEX).toInt());
|
||||
}
|
||||
|
||||
TtRssCategory::~TtRssCategory() {
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,13 @@
|
|||
|
||||
#include "services/abstract/category.h"
|
||||
|
||||
#include <QSqlRecord>
|
||||
|
||||
|
||||
class TtRssCategory : public Category {
|
||||
public:
|
||||
explicit TtRssCategory(RootItem *parent = NULL);
|
||||
explicit TtRssCategory(const QSqlRecord &record);
|
||||
virtual ~TtRssCategory();
|
||||
|
||||
int customId() const;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/tt-rss/ttrssserviceroot.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
@ -29,6 +30,15 @@ TtRssFeed::TtRssFeed(RootItem *parent)
|
|||
: Feed(parent), m_customId(NO_PARENT_CATEGORY), m_totalCount(0), m_unreadCount(0) {
|
||||
}
|
||||
|
||||
TtRssFeed::TtRssFeed(const QSqlRecord &record) : Feed(NULL), m_totalCount(0), m_unreadCount(0) {
|
||||
setTitle(record.value(FDS_DB_TITLE_INDEX).toString());
|
||||
setId(record.value(FDS_DB_ID_INDEX).toInt());
|
||||
setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray()));
|
||||
setAutoUpdateType(static_cast<Feed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
|
||||
setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
|
||||
setCustomId(record.value(FDS_DB_CUSTOM_ID_INDEX).toInt());
|
||||
}
|
||||
|
||||
TtRssFeed::~TtRssFeed() {
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,15 @@
|
|||
|
||||
#include "services/abstract/feed.h"
|
||||
|
||||
#include <QSqlRecord>
|
||||
|
||||
|
||||
class TtRssServiceRoot;
|
||||
|
||||
class TtRssFeed : public Feed {
|
||||
public:
|
||||
explicit TtRssFeed(RootItem *parent = NULL);
|
||||
explicit TtRssFeed(const QSqlRecord &record);
|
||||
virtual ~TtRssFeed();
|
||||
|
||||
TtRssServiceRoot *serviceRoot();
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QPointer>
|
||||
#include <QPair>
|
||||
|
||||
|
||||
TtRssServiceRoot::TtRssServiceRoot(RootItem *parent)
|
||||
|
@ -220,6 +221,48 @@ void TtRssServiceRoot::saveAccountDataToDatabase() {
|
|||
|
||||
void TtRssServiceRoot::loadFromDatabase() {
|
||||
// TODO: Load feeds/categories from DB.
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
|
||||
Assignment categories;
|
||||
Assignment feeds;
|
||||
|
||||
// Obtain data for categories from the database.
|
||||
QSqlQuery query_categories(database);
|
||||
query_categories.setForwardOnly(true);
|
||||
|
||||
if (!query_categories.exec(QString("SELECT * FROM Categories WHERE account_id = %1;").arg(accountId())) || query_categories.lastError().isValid()) {
|
||||
qFatal("Query for obtaining categories failed. Error message: '%s'.",
|
||||
qPrintable(query_categories.lastError().text()));
|
||||
}
|
||||
|
||||
while (query_categories.next()) {
|
||||
AssignmentItem pair;
|
||||
pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt();
|
||||
pair.second = new TtRssCategory(query_categories.record());
|
||||
|
||||
categories << pair;
|
||||
}
|
||||
|
||||
// All categories are now loaded.
|
||||
QSqlQuery query_feeds(database);
|
||||
query_feeds.setForwardOnly(true);
|
||||
|
||||
if (!query_feeds.exec(QString("SELECT * FROM Feeds WHERE account_id = %1;").arg(accountId())) || query_feeds.lastError().isValid()) {
|
||||
qFatal("Query for obtaining feeds failed. Error message: '%s'.",
|
||||
qPrintable(query_feeds.lastError().text()));
|
||||
}
|
||||
|
||||
while (query_feeds.next()) {
|
||||
AssignmentItem pair;
|
||||
pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt();
|
||||
pair.second = new TtRssFeed(query_feeds.record());
|
||||
|
||||
feeds << pair;
|
||||
}
|
||||
|
||||
// All data are now obtained, lets create the hierarchy.
|
||||
assembleCategories(categories);
|
||||
assembleFeeds(feeds);
|
||||
}
|
||||
|
||||
void TtRssServiceRoot::updateTitle() {
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <QCoreApplication>
|
||||
|
||||
|
||||
class TtRssCategory;
|
||||
class TtRssFeed;
|
||||
class TtRssNetworkFactory;
|
||||
|
||||
class TtRssServiceRoot : public ServiceRoot {
|
||||
|
|
Loading…
Reference in New Issue