Hard work on feeds-related things.

This commit is contained in:
Martin Rotter 2013-12-14 11:45:43 +01:00
parent f4f61435ef
commit 68b85b5549
19 changed files with 331 additions and 121 deletions

View file

@ -1,73 +1,75 @@
DROP TABLE IF EXISTS Information; DROP TABLE IF EXISTS Information;
-- ! -- !
CREATE TABLE IF NOT EXISTS Information ( CREATE TABLE IF NOT EXISTS Information (
key TEXT PRIMARY KEY, key TEXT PRIMARY KEY,
value TEXT NOT NULL value TEXT NOT NULL
); );
-- ! -- !
INSERT INTO Information VALUES ('schema_version', '0.0.1'); INSERT INTO Information VALUES ('schema_version', '0.0.1');
-- ! -- !
DROP TABLE IF EXISTS Categories; DROP TABLE IF EXISTS Categories;
-- ! -- !
CREATE TABLE IF NOT EXISTS Categories ( CREATE TABLE IF NOT EXISTS Categories (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
parent_id INTEGER NOT NULL, parent_id INTEGER NOT NULL,
title TEXT NOT NULL UNIQUE CHECK (title != ''), title TEXT NOT NULL UNIQUE CHECK (title != ''),
description TEXT, description TEXT,
date_created TEXT NOT NULL CHECK (date_created != ''), date_created TEXT NOT NULL CHECK (date_created != ''),
icon BLOB, icon BLOB,
type INTEGER NOT NULL, type INTEGER NOT NULL,
FOREIGN KEY (parent_id) REFERENCES Categories (id) FOREIGN KEY (parent_id) REFERENCES Categories (id)
); );
-- ! -- !
DROP TABLE IF EXISTS Feeds; DROP TABLE IF EXISTS Feeds;
-- ! -- !
CREATE TABLE IF NOT EXISTS Feeds ( CREATE TABLE IF NOT EXISTS Feeds (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
title TEXT NOT NULL CHECK (title != ''), title TEXT NOT NULL CHECK (title != ''),
description TEXT, description TEXT,
date_created TEXT NOT NULL CHECK (date_created != ''), date_created TEXT NOT NULL CHECK (date_created != ''),
icon BLOB, icon BLOB,
category INTEGER NOT NULL CHECK (category >= -1), category INTEGER NOT NULL CHECK (category >= -1),
encoding TEXT NOT NULL CHECK (encoding != ''), encoding TEXT NOT NULL CHECK (encoding != ''),
url TEXT NOT NULL UNIQUE CHECK (url != ''), url TEXT NOT NULL UNIQUE CHECK (url != ''),
language TEXT, language TEXT,
type INTEGER NOT NULL CHECK (type > 0) type INTEGER NOT NULL CHECK (type >= 0)
); );
-- ! -- !
DROP TABLE IF EXISTS FeedsData; DROP TABLE IF EXISTS FeedsData;
-- ! -- !
CREATE TABLE IF NOT EXISTS FeedsData ( CREATE TABLE IF NOT EXISTS FeedsData (
id INTEGER NOT NULL, id INTEGER NOT NULL,
key TEXT NOT NULL, key TEXT NOT NULL,
value TEXT, value TEXT,
PRIMARY KEY (id, key), PRIMARY KEY (id, key),
FOREIGN KEY (id) REFERENCES Feeds (id) FOREIGN KEY (id) REFERENCES Feeds (id)
); );
-- ! -- !
DROP TABLE IF EXISTS Messages; DROP TABLE IF EXISTS Messages;
-- ! -- !
CREATE TABLE IF NOT EXISTS Messages ( CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
read INTEGER(1) NOT NULL CHECK (read >= 0 AND read <= 1) DEFAULT (0), read INTEGER(1) NOT NULL CHECK (read >= 0 AND read <= 1) DEFAULT (0),
deleted INTEGER(1) NOT NULL CHECK (deleted >= 0 AND deleted <= 1) DEFAULT (0), deleted INTEGER(1) NOT NULL CHECK (deleted >= 0 AND deleted <= 1) DEFAULT (0),
important INTEGER(1) NOT NULL CHECK (important >= 0 AND important <= 1) DEFAULT (0), important INTEGER(1) NOT NULL CHECK (important >= 0 AND important <= 1) DEFAULT (0),
feed INTEGER NOT NULL, feed INTEGER NOT NULL,
title TEXT NOT NULL CHECK (title != ''), title TEXT NOT NULL CHECK (title != ''),
url TEXT, url TEXT,
author TEXT, author TEXT,
date_created TEXT NOT NULL CHECK (date_created != ''), date_created TEXT NOT NULL CHECK (date_created != ''),
date_updated TEXT, date_updated TEXT,
contents TEXT, contents TEXT,
FOREIGN KEY (feed) REFERENCES Feeds (id) FOREIGN KEY (feed) REFERENCES Feeds (id)
); );
-- ! -- !
INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('abcd', '1994-11-05T08:15:30-05:00', -1, 'UTF-8', 'http://www.seznam1.cz', 1); INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('qqq', '1994-11-05T08:15:30-05:00', 0, 'UTF-8', 'http://www.seznam2.cz', 1);
INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('qqq', '1994-11-05T08:15:30-05:00', 0, 'UTF-8', 'http://www.seznam2.cz', 1); INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('vwvw', '1994-11-05T08:15:30-05:00', 1, 'UTF-8', 'http://www.seznam3.cz', 1);
INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('vwvw', '1994-11-05T08:15:30-05:00', 1, 'UTF-8', 'http://www.seznam3.cz', 1); INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('cbcd', '1994-11-05T08:15:30-05:00', -1, 'UTF-8', 'http://www.seznam1.cz', 1);
INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('tttt', '1994-11-05T08:15:30-05:00', 1, 'UTF-8', 'http://www.seznam4.cz', 1); INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('attt', '1994-11-05T08:15:30-05:00', 1, 'UTF-8', 'http://www.seznam4.cz', 0);
INSERT INTO Categories (id, parent_id, title, date_created, type) VALUES (0, -1, 'aaa', '1994-11-05T08:15:30-05:00', 0); INSERT INTO Feeds (title, date_created, category, encoding, url, type) VALUES ('ahht', '1994-11-05T08:15:30-05:00', -1, 'UTF-8', 'http://www.seznam6.cz', 0);
INSERT INTO Categories (id, parent_id, title, date_created, type) VALUES (1, 0, 'bbb', '1994-11-05T08:15:30-05:00', 0); INSERT INTO Categories (id, parent_id, title, date_created, type) VALUES (1, 0, 'bbb', '1994-11-05T08:15:30-05:00', 0);
INSERT INTO Categories (id, parent_id, title, date_created, type) VALUES (0, -1, 'aaa', '1994-11-05T08:15:30-05:00', 0);
INSERT INTO Categories (id, parent_id, title, date_created, type) VALUES (2, 0, 'ccc', '1994-11-05T08:15:30-05:00', 0);

View file

@ -135,6 +135,11 @@ QSqlDatabase DatabaseFactory::addConnection(const QString &connection_name) {
// Setup database file path. // Setup database file path.
database.setDatabaseName(db_file.fileName()); database.setDatabaseName(db_file.fileName());
if (!database.open()) {
qFatal("Database was NOT opened. Delivered error message: '%s'",
qPrintable(database.lastError().text()));
}
return database; return database;
} }
} }

View file

@ -37,6 +37,8 @@ class DatabaseFactory : public QObject {
QString getDatabasePath(); QString getDatabasePath();
// Database manipulators. // Database manipulators.
// NOTE: This returns OPENED database.
QSqlDatabase addConnection(const QString &connection_name); QSqlDatabase addConnection(const QString &connection_name);
QSqlDatabase getConnection(const QString &connection_name); QSqlDatabase getConnection(const QString &connection_name);
void removeConnection(const QString &connection_name); void removeConnection(const QString &connection_name);

View file

@ -26,6 +26,8 @@
#define MAX_ZOOM_FACTOR 10.0 #define MAX_ZOOM_FACTOR 10.0
#define ICON_SIZE_SETTINGS 16 #define ICON_SIZE_SETTINGS 16
#define DATABASE_DRIVER "QSQLITE" #define DATABASE_DRIVER "QSQLITE"
#define NO_PARENT_FEED -1
#define NO_PARENT_CATEGORY -1
#define APP_DB_INIT_FILE "db_init.sql" #define APP_DB_INIT_FILE "db_init.sql"
#define APP_DB_INIT_SPLIT "-- !\n" #define APP_DB_INIT_SPLIT "-- !\n"

View file

@ -9,6 +9,7 @@
#include "core/defs.h" #include "core/defs.h"
#include "core/databasefactory.h" #include "core/databasefactory.h"
#include "gui/iconthemefactory.h" #include "gui/iconthemefactory.h"
#include "gui/iconfactory.h"
FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) { FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) {
@ -22,7 +23,7 @@ FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) {
tr("Counts of unread/all meesages."); tr("Counts of unread/all meesages.");
loadFromDatabase(); loadFromDatabase();
/*
FeedsModelStandardCategory *cat1 = new FeedsModelStandardCategory(); FeedsModelStandardCategory *cat1 = new FeedsModelStandardCategory();
FeedsModelStandardCategory *cat2 = new FeedsModelStandardCategory(); FeedsModelStandardCategory *cat2 = new FeedsModelStandardCategory();
FeedsModelStandardFeed *feed1 = new FeedsModelStandardFeed(); FeedsModelStandardFeed *feed1 = new FeedsModelStandardFeed();
@ -46,11 +47,13 @@ FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) {
m_rootItem->appendChild(cat1); m_rootItem->appendChild(cat1);
m_rootItem->appendChild(feed3); m_rootItem->appendChild(feed3);
*/
} }
FeedsModel::~FeedsModel() { FeedsModel::~FeedsModel() {
qDebug("Destroying FeedsModel instance."); qDebug("Destroying FeedsModel instance.");
delete m_rootItem; delete m_rootItem;
DatabaseFactory::getInstance()->removeConnection(objectName());
} }
QVariant FeedsModel::data(const QModelIndex &index, int role) const { QVariant FeedsModel::data(const QModelIndex &index, int role) const {
@ -161,15 +164,13 @@ int FeedsModel::columnCount(const QModelIndex &parent) const {
} }
void FeedsModel::loadFromDatabase() { void FeedsModel::loadFromDatabase() {
qDeleteAll(m_rootItem->m_childItems);
QSqlDatabase database = DatabaseFactory::getInstance()->addConnection(objectName()); QSqlDatabase database = DatabaseFactory::getInstance()->addConnection(objectName());
QList<QPair<int, FeedsModelCategory*> > categories; CategoryAssignment categories;
QList<QPair<int, FeedsModelFeed*> > feeds; FeedAssignment feeds;
if (!database.open()) {
qFatal("Database was NOT opened. Delivered error message: '%s'",
qPrintable(database.lastError().text()));
}
// Obtain data for categories from the database.
QSqlQuery query_categories = database.exec("SELECT * FROM Categories;"); QSqlQuery query_categories = database.exec("SELECT * FROM Categories;");
if (query_categories.lastError().isValid()) { if (query_categories.lastError().isValid()) {
@ -182,7 +183,7 @@ void FeedsModel::loadFromDatabase() {
switch (type) { switch (type) {
case FeedsModelCategory::Standard: { case FeedsModelCategory::Standard: {
QPair<int, FeedsModelCategory*> pair; CategoryAssignmentItem pair;
pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt(); pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt();
pair.second = FeedsModelStandardCategory::loadFromRecord(query_categories.record()); pair.second = FeedsModelStandardCategory::loadFromRecord(query_categories.record());
@ -213,17 +214,82 @@ void FeedsModel::loadFromDatabase() {
case FeedsModelFeed::StandardAtom: case FeedsModelFeed::StandardAtom:
case FeedsModelFeed::StandardRdf: case FeedsModelFeed::StandardRdf:
case FeedsModelFeed::StandardRss: { case FeedsModelFeed::StandardRss: {
QPair<int, FeedsModelFeed*> pair; FeedAssignmentItem pair;
pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt(); pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt();
// TODO: pokračovat tady, ve stejnym stylu jako u kategorii pair.second = FeedsModelStandardFeed::loadFromRecord(query_feeds.record());
pair.second->setType(type);
feeds << pair;
break; break;
} }
default: default:
break; break;
} }
} }
// All data are now obtained, lets create the hierarchy.
assembleCategories(categories);
assembleFeeds(feeds);
}
QHash<int, FeedsModelCategory *> FeedsModel::getCategories(FeedsModelRootItem *root) {
QHash<int, FeedsModelCategory*> categories;
foreach (FeedsModelRootItem *child, root->m_childItems) {
FeedsModelCategory *converted = dynamic_cast<FeedsModelCategory*>(child);
if (converted != NULL) {
// This child is some kind of category.
categories.insert(converted->id(), converted);
// Moreover, add all child categories of this category.
categories.unite(getCategories(converted));
}
}
return categories;
}
QHash<int, FeedsModelCategory *> FeedsModel::getCategories() {
return getCategories(m_rootItem);
}
void FeedsModel::assembleFeeds(FeedAssignment feeds) {
QHash<int, FeedsModelCategory*> categories = getCategories();
foreach (FeedAssignmentItem feed, feeds) {
if (feed.first == NO_PARENT_CATEGORY) {
// This is top-level feed, add it to the root item.
m_rootItem->appendChild(feed.second);
}
else {
// This feed belongs to some category.
categories.value(feed.first)->appendChild(feed.second);
}
}
}
void FeedsModel::assembleCategories(CategoryAssignment categories) {
QHash<int, FeedsModelRootItem*> assignments;
assignments.insert(-1, m_rootItem);
// 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--;
}
}
}
} }

View file

@ -6,6 +6,13 @@
class FeedsModelRootItem; class FeedsModelRootItem;
class FeedsModelCategory;
class FeedsModelFeed;
typedef QList<QPair<int, FeedsModelCategory*> > CategoryAssignment;
typedef QPair<int, FeedsModelCategory*> CategoryAssignmentItem;
typedef QList<QPair<int, FeedsModelFeed*> > FeedAssignment;
typedef QPair<int, FeedsModelFeed*> FeedAssignmentItem;
class FeedsModel : public QAbstractItemModel { class FeedsModel : public QAbstractItemModel {
Q_OBJECT Q_OBJECT
@ -24,6 +31,15 @@ class FeedsModel : public QAbstractItemModel {
void loadFromDatabase(); void loadFromDatabase();
QHash<int, FeedsModelCategory*> getCategories();
QHash<int, FeedsModelCategory*> getCategories(FeedsModelRootItem *root);
bool addFeed(FeedsModelFeed *feed, int parent_id);
protected:
void assembleCategories(CategoryAssignment categories);
void assembleFeeds(FeedAssignment feeds);
private: private:
FeedsModelRootItem *m_rootItem; FeedsModelRootItem *m_rootItem;
QList<QString> m_headerData; QList<QString> m_headerData;

View file

@ -35,3 +35,11 @@ FeedsModelCategory:: Type FeedsModelCategory::type() const {
void FeedsModelCategory::setType(const Type &type) { void FeedsModelCategory::setType(const Type &type) {
m_type = type; m_type = type;
} }
QString FeedsModelCategory::title() const {
return m_title;
}
void FeedsModelCategory::setTitle(const QString &title) {
m_title = title;
}

View file

@ -26,9 +26,12 @@ class FeedsModelCategory : public FeedsModelRootItem {
Type type() const; Type type() const;
void setType(const Type &type); void setType(const Type &type);
protected: QString title() const;
Type m_type; void setTitle(const QString &title);
protected:
QString m_title;
Type m_type;
}; };
#endif // FEEDSMODELCLASSICCATEGORY_H #endif // FEEDSMODELCLASSICCATEGORY_H

View file

@ -2,7 +2,7 @@
FeedsModelFeed::FeedsModelFeed(FeedsModelRootItem *parent_item) FeedsModelFeed::FeedsModelFeed(FeedsModelRootItem *parent_item)
: FeedsModelRootItem(parent_item), m_totalCount(0), m_unreadCount(1) { : FeedsModelRootItem(parent_item), m_totalCount(0), m_unreadCount(0) {
} }
FeedsModelFeed::~FeedsModelFeed() { FeedsModelFeed::~FeedsModelFeed() {
@ -38,3 +38,10 @@ void FeedsModelFeed::setType(const Type &type) {
m_type = type; m_type = type;
} }
void FeedsModelFeed::setTitle(const QString &title) {
m_title = title;
}
QString FeedsModelFeed::title() const {
return m_title;
}

View file

@ -30,7 +30,11 @@ class FeedsModelFeed : public FeedsModelRootItem {
Type type() const; Type type() const;
void setType(const Type &type); void setType(const Type &type);
QString title() const;
void setTitle(const QString &title);
protected: protected:
QString m_title;
Type m_type; Type m_type;
int m_totalCount; int m_totalCount;
int m_unreadCount; int m_unreadCount;

View file

@ -8,6 +8,8 @@
// NOTE: This class is derived to add functionality for // NOTE: This class is derived to add functionality for
// all other non-root items of FeedsModel. // all other non-root items of FeedsModel.
class FeedsModelRootItem { class FeedsModelRootItem {
friend class FeedsModel;
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsModelRootItem(FeedsModelRootItem *parent_item = NULL); explicit FeedsModelRootItem(FeedsModelRootItem *parent_item = NULL);

View file

@ -19,7 +19,7 @@ QVariant FeedsModelStandardCategory::data(int column, int role) const {
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
if (column == FDS_MODEL_TITLE_INDEX) { if (column == FDS_MODEL_TITLE_INDEX) {
return "m_title"; return QString("%1%2").arg(m_title, "-C");
} }
else if (column == FDS_MODEL_COUNTS_INDEX) { else if (column == FDS_MODEL_COUNTS_INDEX) {
return QString("(%1)").arg(QString::number(countOfUnreadMessages())); return QString("(%1)").arg(QString::number(countOfUnreadMessages()));
@ -56,14 +56,6 @@ FeedsModelStandardCategory *FeedsModelStandardCategory::loadFromRecord(const QSq
return category; return category;
} }
QString FeedsModelStandardCategory::title() const {
return m_title;
}
void FeedsModelStandardCategory::setTitle(const QString &title) {
m_title = title;
}
QString FeedsModelStandardCategory::description() const { QString FeedsModelStandardCategory::description() const {
return m_description; return m_description;
} }
@ -79,6 +71,3 @@ QDateTime FeedsModelStandardCategory::creationDate() const {
void FeedsModelStandardCategory::setCreationDate(const QDateTime &creation_date) { void FeedsModelStandardCategory::setCreationDate(const QDateTime &creation_date) {
m_creationDate = creation_date; m_creationDate = creation_date;
} }

View file

@ -20,20 +20,16 @@ class FeedsModelStandardCategory : public FeedsModelCategory {
QVariant data(int column, int role) const; QVariant data(int column, int role) const;
static FeedsModelStandardCategory *loadFromRecord(const QSqlRecord &record);
QString title() const;
void setTitle(const QString &title);
QString description() const; QString description() const;
void setDescription(const QString &description); void setDescription(const QString &description);
QDateTime creationDate() const; QDateTime creationDate() const;
void setCreationDate(const QDateTime &creation_date); void setCreationDate(const QDateTime &creation_date);
static FeedsModelStandardCategory *loadFromRecord(const QSqlRecord &record);
private: private:
QDateTime m_creationDate; QDateTime m_creationDate;
QString m_title;
QString m_description; QString m_description;
}; };

View file

@ -1,6 +1,7 @@
#include <QVariant> #include <QVariant>
#include "core/defs.h" #include "core/defs.h"
#include "gui/iconfactory.h"
#include "gui/iconthemefactory.h" #include "gui/iconthemefactory.h"
#include "core/feedsmodelstandardfeed.h" #include "core/feedsmodelstandardfeed.h"
@ -17,8 +18,56 @@ void FeedsModelStandardFeed::setDescription(const QString &description) {
m_description = description; m_description = description;
} }
void FeedsModelStandardFeed::setTitle(const QString &title) { FeedsModelStandardFeed *FeedsModelStandardFeed::loadFromRecord(const QSqlRecord &record) {
m_title = title; FeedsModelStandardFeed *feed = new FeedsModelStandardFeed(NULL);
feed->setTitle(record.value(FDS_DB_TITLE_INDEX).toString());
feed->setId(record.value(FDS_DB_ID_INDEX).toInt());
feed->setDescription(record.value(FDS_DB_DESCRIPTION_INDEX).toString());
feed->setCreationDate(QDateTime::fromString(record.value(FDS_DB_DCREATED_INDEX).toString(),
Qt::ISODate));
feed->setIcon(IconFactory::fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray()));
feed->setEncoding(record.value(FDS_DB_ENCODING_INDEX).toString());
feed->setUrl(record.value(FDS_DB_URL_INDEX).toString());
feed->setLanguage(record.value(FDS_DB_LANGUAGE_INDEX).toString());
return feed;
}
QDateTime FeedsModelStandardFeed::creationDate() const {
return m_creationDate;
}
void FeedsModelStandardFeed::setCreationDate(const QDateTime &creation_date) {
m_creationDate = creation_date;
}
QString FeedsModelStandardFeed::encoding() const {
return m_encoding;
}
void FeedsModelStandardFeed::setEncoding(const QString &encoding) {
m_encoding = encoding;
}
QString FeedsModelStandardFeed::url() const {
return m_url;
}
void FeedsModelStandardFeed::setUrl(const QString &url) {
m_url = url;
}
QString FeedsModelStandardFeed::language() const {
return m_language;
}
void FeedsModelStandardFeed::setLanguage(const QString &language) {
m_language = language;
}
QString FeedsModelStandardFeed::description() const {
return m_description;
} }
QVariant FeedsModelStandardFeed::data(int column, int role) const { QVariant FeedsModelStandardFeed::data(int column, int role) const {

View file

@ -2,6 +2,7 @@
#define FEEDSMODELSTANDARDFEED_H #define FEEDSMODELSTANDARDFEED_H
#include <QDateTime> #include <QDateTime>
#include <QSqlRecord>
#include "core/feedsmodelfeed.h" #include "core/feedsmodelfeed.h"
@ -17,11 +18,25 @@ class FeedsModelStandardFeed : public FeedsModelFeed {
QVariant data(int column, int role) const; QVariant data(int column, int role) const;
void setTitle(const QString &title); // Various getters/setters.
QString description() const;
void setDescription(const QString &description); void setDescription(const QString &description);
QDateTime creationDate() const;
void setCreationDate(const QDateTime &creation_date);
QString encoding() const;
void setEncoding(const QString &encoding);
QString url() const;
void setUrl(const QString &url);
QString language() const;
void setLanguage(const QString &language);
static FeedsModelStandardFeed *loadFromRecord(const QSqlRecord &record);
private: private:
QString m_title;
QDateTime m_creationDate; QDateTime m_creationDate;
QString m_encoding; QString m_encoding;
QString m_url; QString m_url;

View file

@ -1,5 +1,8 @@
#include "core/feedsproxymodel.h" #include "core/feedsproxymodel.h"
#include "core/feedsmodel.h" #include "core/feedsmodel.h"
#include "core/feedsmodelcategory.h"
#include "core/feedsmodelfeed.h"
#include "core/feedsmodelrootitem.h"
FeedsProxyModel::FeedsProxyModel(QObject *parent) FeedsProxyModel::FeedsProxyModel(QObject *parent)
@ -8,7 +11,13 @@ FeedsProxyModel::FeedsProxyModel(QObject *parent)
setObjectName("FeedsProxyModel");
setSortRole(Qt::EditRole);
setSortCaseSensitivity(Qt::CaseInsensitive);
setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterKeyColumn(-1);
setFilterRole(Qt::EditRole);
setDynamicSortFilter(true);
setSourceModel(m_sourceModel); setSourceModel(m_sourceModel);
} }
@ -22,5 +31,37 @@ FeedsModel *FeedsProxyModel::sourceModel() {
bool FeedsProxyModel::lessThan(const QModelIndex &left, bool FeedsProxyModel::lessThan(const QModelIndex &left,
const QModelIndex &right) const { const QModelIndex &right) const {
return QSortFilterProxyModel::lessThan(left, right); if (left.isValid() && right.isValid()) {
FeedsModelRootItem *left_item = static_cast<FeedsModelRootItem*>(left.internalPointer());
FeedsModelRootItem *right_item = static_cast<FeedsModelRootItem*>(right.internalPointer());
FeedsModelFeed *left_feed = dynamic_cast<FeedsModelFeed*>(left_item);
FeedsModelFeed *right_feed = dynamic_cast<FeedsModelFeed*>(right_item);
FeedsModelCategory *left_category = dynamic_cast<FeedsModelCategory*>(left_item);
FeedsModelCategory *right_category = dynamic_cast<FeedsModelCategory*>(right_item);
if (left_feed != NULL && right_feed != NULL) {
// Both items are feeds.
return left_feed->title() < right_feed->title();
}
else if (left_category != NULL && right_category != NULL) {
// Both items are categories.
return left_category->title() < right_category->title();
}
else if (left_feed != NULL) {
// Left item is feed, right item is category.
return false;
}
else {
// Left item is category, right item is feed.
return true;
}
return true;
}
else {
return false;
}
} }

View file

@ -18,6 +18,11 @@ FeedsView::~FeedsView() {
qDebug("Destroying FeedsView instance."); qDebug("Destroying FeedsView instance.");
} }
void FeedsView::setSortingEnabled(bool enable) {
QTreeView::setSortingEnabled(enable);
header()->setSortIndicatorShown(false);
}
void FeedsView::setupAppearance() { void FeedsView::setupAppearance() {
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
// Setup column resize strategies. // Setup column resize strategies.
@ -33,6 +38,8 @@ void FeedsView::setupAppearance() {
setUniformRowHeights(true); setUniformRowHeights(true);
setAcceptDrops(false); setAcceptDrops(false);
setDragEnabled(false); setDragEnabled(false);
setSortingEnabled(true);
sortByColumn(0, Qt::AscendingOrder);
setDragDropMode(QAbstractItemView::NoDragDrop); setDragDropMode(QAbstractItemView::NoDragDrop);
setAllColumnsShowFocus(true); setAllColumnsShowFocus(true);
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);

View file

@ -14,6 +14,8 @@ class FeedsView : public QTreeView {
// Constructors and destructors. // Constructors and destructors.
explicit FeedsView(QWidget *parent = 0); explicit FeedsView(QWidget *parent = 0);
virtual ~FeedsView(); virtual ~FeedsView();
void setSortingEnabled(bool enable);
protected: protected:
void setupAppearance(); void setupAppearance();

View file

@ -30,7 +30,8 @@ int main(int argc, char *argv[]) {
//: Name of language, e.g. English. //: Name of language, e.g. English.
QObject::tr("LANG_NAME"); QObject::tr("LANG_NAME");
//: Abbreviation of language, e.g. en. //: Abbreviation of language, e.g. en.
//: Use ISO 639-1 code here! //: Use ISO 639-1 code here. They may be combined with ISO 3166-1 (alpha-2) codes.
//: Examples: "cs", "nl", "en", "cs_CZ", "en_GB", "en_US".
QObject::tr("LANG_ABBREV"); QObject::tr("LANG_ABBREV");
//: Version of your translation, e.g. 1.0. //: Version of your translation, e.g. 1.0.
QObject::tr("LANG_VERSION"); QObject::tr("LANG_VERSION");
@ -61,13 +62,6 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
// Add 3rd party plugin directory to application PATH variable.
// This is useful for styles, encoders, ...
// This is probably not needed on Windows or Linux, not sure about Mac OS X.
#if defined(Q_OS_MAC)
QtSingleApplication::addLibraryPath(APP_PLUGIN_PATH);
#endif
// Add an extra path for non-system icon themes and set current icon theme // Add an extra path for non-system icon themes and set current icon theme
// and skin. // and skin.
IconThemeFactory::getInstance()->setupSearchPaths(); IconThemeFactory::getInstance()->setupSearchPaths();