Hard work on feeds-related things.
This commit is contained in:
parent
f4f61435ef
commit
68b85b5549
19 changed files with 331 additions and 121 deletions
|
@ -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);
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue