diff --git a/CMakeLists.txt b/CMakeLists.txt index 3670204c0..f6a644e8a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,6 +254,7 @@ set(APP_SOURCES src/gui/messagesview.cpp src/gui/statusbar.cpp src/gui/messagebox.cpp + src/gui/iconfactory.cpp # CORE sources. src/core/debugging.cpp diff --git a/resources/misc/db_init.sql b/resources/misc/db_init.sql index 61824cc1c..e1ba478ee 100644 --- a/resources/misc/db_init.sql +++ b/resources/misc/db_init.sql @@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS Categories ( description TEXT, date_created TEXT NOT NULL CHECK (date_created != ''), icon BLOB, - type INTEGER NOT NULL, + type INTEGER NOT NULL, FOREIGN KEY (parent_id) REFERENCES Categories (id) ); @@ -33,7 +33,7 @@ CREATE TABLE IF NOT EXISTS Feeds ( encoding TEXT NOT NULL CHECK (encoding != ''), url TEXT NOT NULL UNIQUE CHECK (url != ''), language TEXT, - type INTEGER NOT NULL + type INTEGER NOT NULL CHECK (type > 0) ); -- ! DROP TABLE IF EXISTS FeedsData; @@ -63,4 +63,11 @@ CREATE TABLE IF NOT EXISTS Messages ( contents TEXT, FOREIGN KEY (feed) REFERENCES Feeds (id) -); \ No newline at end of file +); +-- ! +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 ('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 ('tttt', '1994-11-05T08:15:30-05:00', 1, 'UTF-8', 'http://www.seznam4.cz', 1); +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 (1, 0, 'bbb', '1994-11-05T08:15:30-05:00', 0); \ No newline at end of file diff --git a/src/core/databasefactory.cpp b/src/core/databasefactory.cpp index 66259ef07..b62ffccca 100644 --- a/src/core/databasefactory.cpp +++ b/src/core/databasefactory.cpp @@ -135,11 +135,6 @@ QSqlDatabase DatabaseFactory::addConnection(const QString &connection_name) { // Setup database file path. database.setDatabaseName(db_file.fileName()); - if (!database.open()) { - qFatal("Database was NOT opened. Delivered error message: '%s'", - qPrintable(database.lastError().text())); - } - return database; } } diff --git a/src/core/defs.h.in b/src/core/defs.h.in index 6622009e9..21d060c6e 100755 --- a/src/core/defs.h.in +++ b/src/core/defs.h.in @@ -65,9 +65,30 @@ #define MSG_DB_DUPDATED_INDEX 9 #define MSG_DB_CONTENTS_INDEX 10 +// Indexes of columns as they are DEFINED IN THE TABLE for CATEGORIES. +#define CAT_DB_ID_INDEX 0 +#define CAT_DB_PARENT_ID_INDEX 1 +#define CAT_DB_TITLE_INDEX 2 +#define CAT_DB_DESCRIPTION_INDEX 3 +#define CAT_DB_DCREATED_INDEX 4 +#define CAT_DB_ICON_INDEX 5 +#define CAT_DB_TYPE_INDEX 6 + +// Indexes of columns as they are DEFINED IN THE TABLE for FEEDS. +#define FDS_DB_ID_INDEX 0 +#define FDS_DB_TITLE_INDEX 1 +#define FDS_DB_DESCRIPTION_INDEX 2 +#define FDS_DB_DCREATED_INDEX 3 +#define FDS_DB_ICON_INDEX 4 +#define FDS_DB_CATEGORY_INDEX 5 +#define FDS_DB_ENCODING_INDEX 6 +#define FDS_DB_URL_INDEX 7 +#define FDS_DB_LANGUAGE_INDEX 8 +#define FDS_DB_TYPE_INDEX 9 + // Indexes of columns for feed models. -#define FDS_TITLE_INDEX 0 -#define FDS_COUNTS_INDEX 1 +#define FDS_MODEL_TITLE_INDEX 0 +#define FDS_MODEL_COUNTS_INDEX 1 #if defined(Q_OS_LINUX) #define APP_DESKTOP_ENTRY_PATH "@DESKTOP_ENTRY_PATH@" diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index bbb206023..d810026a0 100644 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -1,11 +1,19 @@ +#include +#include +#include +#include + #include "core/feedsmodel.h" #include "core/feedsmodelstandardcategory.h" #include "core/feedsmodelstandardfeed.h" #include "core/defs.h" +#include "core/databasefactory.h" #include "gui/iconthemefactory.h" FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) { + setObjectName("FeedsModel"); + m_rootItem = new FeedsModelRootItem(); m_countsIcon = IconThemeFactory::getInstance()->fromTheme("mail-mark-unread"); @@ -13,6 +21,8 @@ FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) { m_tooltipData << tr("Titles of feeds/categories.") << tr("Counts of unread/all meesages."); + loadFromDatabase(); + FeedsModelStandardCategory *cat1 = new FeedsModelStandardCategory(); FeedsModelStandardCategory *cat2 = new FeedsModelStandardCategory(); FeedsModelStandardFeed *feed1 = new FeedsModelStandardFeed(); @@ -61,8 +71,8 @@ QVariant FeedsModel::headerData(int section, switch (role) { case Qt::DisplayRole: - if (section == FDS_TITLE_INDEX) { - return m_headerData.at(FDS_TITLE_INDEX); + if (section == FDS_MODEL_TITLE_INDEX) { + return m_headerData.at(FDS_MODEL_TITLE_INDEX); } else { return QVariant(); @@ -72,7 +82,7 @@ QVariant FeedsModel::headerData(int section, return m_tooltipData.at(section); case Qt::DecorationRole: - if (section == FDS_COUNTS_INDEX) { + if (section == FDS_MODEL_COUNTS_INDEX) { return m_countsIcon; } else { @@ -149,3 +159,71 @@ int FeedsModel::columnCount(const QModelIndex &parent) const { return m_rootItem->columnCount(); } } + +void FeedsModel::loadFromDatabase() { + QSqlDatabase database = DatabaseFactory::getInstance()->addConnection(objectName()); + QList > categories; + QList > feeds; + + if (!database.open()) { + qFatal("Database was NOT opened. Delivered error message: '%s'", + qPrintable(database.lastError().text())); + } + + QSqlQuery query_categories = database.exec("SELECT * FROM Categories;"); + + if (query_categories.lastError().isValid()) { + qFatal("Query for obtaining categories failed."); + } + + while (query_categories.next()) { + // Process this category. + FeedsModelCategory::Type type = static_cast(query_categories.value(CAT_DB_TYPE_INDEX).toInt()); + + switch (type) { + case FeedsModelCategory::Standard: { + QPair pair; + pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt(); + pair.second = FeedsModelStandardCategory::loadFromRecord(query_categories.record()); + + categories << pair; + break; + } + + case FeedsModelCategory::Feedly: + case FeedsModelCategory::TinyTinyRss: + default: + // NOTE: Not yet implemented. + break; + } + } + + // All categories are now loaded. + QSqlQuery query_feeds = database.exec("SELECT * FROM Feeds;"); + + if (query_feeds.lastError().isValid()) { + qFatal("Query for obtaining feeds failed."); + } + + while (query_feeds.next()) { + // Process this feed. + FeedsModelFeed::Type type = static_cast(query_feeds.value(FDS_DB_TYPE_INDEX).toInt()); + + switch (type) { + case FeedsModelFeed::StandardAtom: + case FeedsModelFeed::StandardRdf: + case FeedsModelFeed::StandardRss: { + QPair pair; + pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt(); + // TODO: pokračovat tady, ve stejnym stylu jako u kategorii + break; + } + + + default: + break; + } + + } + +} diff --git a/src/core/feedsmodel.h b/src/core/feedsmodel.h index 9e511e1d7..d429e5b87 100644 --- a/src/core/feedsmodel.h +++ b/src/core/feedsmodel.h @@ -22,6 +22,8 @@ class FeedsModel : public QAbstractItemModel { int columnCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const; + void loadFromDatabase(); + private: FeedsModelRootItem *m_rootItem; QList m_headerData; diff --git a/src/core/feedsmodelcategory.cpp b/src/core/feedsmodelcategory.cpp index 78adecf29..c6a97cc7b 100644 --- a/src/core/feedsmodelcategory.cpp +++ b/src/core/feedsmodelcategory.cpp @@ -27,3 +27,11 @@ int FeedsModelCategory::countOfUnreadMessages() const { return total_count; } + +FeedsModelCategory:: Type FeedsModelCategory::type() const { + return m_type; +} + +void FeedsModelCategory::setType(const Type &type) { + m_type = type; +} diff --git a/src/core/feedsmodelcategory.h b/src/core/feedsmodelcategory.h index 5ef38c3a6..8bbbf7bca 100644 --- a/src/core/feedsmodelcategory.h +++ b/src/core/feedsmodelcategory.h @@ -8,6 +8,14 @@ // NOTE: This class should be derived to create PARTICULAR category types. class FeedsModelCategory : public FeedsModelRootItem { public: + // Describes possible types of categories. + // NOTE: This is equivavelnt to Categories(type). + enum Type { + Standard = 0, + Feedly = 1, + TinyTinyRss = 2 + }; + // Constructors and destructors explicit FeedsModelCategory(FeedsModelRootItem *parent_item = NULL); virtual ~FeedsModelCategory(); @@ -15,6 +23,12 @@ class FeedsModelCategory : public FeedsModelRootItem { int countOfAllMessages() const; int countOfUnreadMessages() const; + Type type() const; + void setType(const Type &type); + + protected: + Type m_type; + }; #endif // FEEDSMODELCLASSICCATEGORY_H diff --git a/src/core/feedsmodelfeed.cpp b/src/core/feedsmodelfeed.cpp index e97f5627d..a8d86c16f 100644 --- a/src/core/feedsmodelfeed.cpp +++ b/src/core/feedsmodelfeed.cpp @@ -13,6 +13,7 @@ int FeedsModelFeed::childCount() const { return 0; } + int FeedsModelFeed::countOfAllMessages() const { return m_totalCount; } @@ -20,3 +21,20 @@ int FeedsModelFeed::countOfAllMessages() const { int FeedsModelFeed::countOfUnreadMessages() const { return m_unreadCount; } + +void FeedsModelFeed::setCountOfAllMessages(int count_total) { + m_totalCount = count_total; +} + +void FeedsModelFeed::setCountOfUnreadMessages(int count_unread) { + m_unreadCount = count_unread; +} + +FeedsModelFeed::Type FeedsModelFeed::type() const { + return m_type; +} + +void FeedsModelFeed::setType(const Type &type) { + m_type = type; +} + diff --git a/src/core/feedsmodelfeed.h b/src/core/feedsmodelfeed.h index f5fd0b0d0..2818bf192 100644 --- a/src/core/feedsmodelfeed.h +++ b/src/core/feedsmodelfeed.h @@ -22,10 +22,16 @@ class FeedsModelFeed : public FeedsModelRootItem { int childCount() const; - int countOfUnreadMessages() const; int countOfAllMessages() const; + int countOfUnreadMessages() const; + void setCountOfAllMessages(int count_total); + void setCountOfUnreadMessages(int count_unread); + + Type type() const; + void setType(const Type &type); protected: + Type m_type; int m_totalCount; int m_unreadCount; }; diff --git a/src/core/feedsmodelrootitem.cpp b/src/core/feedsmodelrootitem.cpp index 7c04c83d0..cfad097ca 100644 --- a/src/core/feedsmodelrootitem.cpp +++ b/src/core/feedsmodelrootitem.cpp @@ -64,3 +64,11 @@ int FeedsModelRootItem::countOfUnreadMessages() const { void FeedsModelRootItem::setIcon(const QIcon &icon) { m_icon = icon; } + +int FeedsModelRootItem::id() const { + return m_id; +} + +void FeedsModelRootItem::setId(int id) { + m_id = id; +} diff --git a/src/core/feedsmodelrootitem.h b/src/core/feedsmodelrootitem.h index 850306de1..551c3a33f 100644 --- a/src/core/feedsmodelrootitem.h +++ b/src/core/feedsmodelrootitem.h @@ -27,7 +27,11 @@ class FeedsModelRootItem { void setIcon(const QIcon &icon); + int id() const; + void setId(int id); + protected: + int m_id; QIcon m_icon; QList m_childItems; FeedsModelRootItem *m_parentItem; diff --git a/src/core/feedsmodelstandardcategory.cpp b/src/core/feedsmodelstandardcategory.cpp index 6c4c26e1d..63ac623a2 100644 --- a/src/core/feedsmodelstandardcategory.cpp +++ b/src/core/feedsmodelstandardcategory.cpp @@ -1,11 +1,14 @@ #include +#include "core/textfactory.h" #include "core/feedsmodelstandardcategory.h" #include "core/defs.h" +#include "gui/iconfactory.h" FeedsModelStandardCategory::FeedsModelStandardCategory(FeedsModelRootItem *parent_item) : FeedsModelCategory(parent_item) { + m_type = Standard; } FeedsModelStandardCategory::~FeedsModelStandardCategory() { @@ -15,20 +18,20 @@ FeedsModelStandardCategory::~FeedsModelStandardCategory() { QVariant FeedsModelStandardCategory::data(int column, int role) const { switch (role) { case Qt::DisplayRole: - if (column == FDS_TITLE_INDEX) { + if (column == FDS_MODEL_TITLE_INDEX) { return "m_title"; } - else if (column == FDS_COUNTS_INDEX) { + else if (column == FDS_MODEL_COUNTS_INDEX) { return QString("(%1)").arg(QString::number(countOfUnreadMessages())); } case Qt::DecorationRole: - return column == FDS_TITLE_INDEX ? + return column == FDS_MODEL_TITLE_INDEX ? m_icon : QVariant(); case Qt::TextAlignmentRole: - if (column == FDS_COUNTS_INDEX) { + if (column == FDS_MODEL_COUNTS_INDEX) { return Qt::AlignCenter; } else { @@ -39,3 +42,43 @@ QVariant FeedsModelStandardCategory::data(int column, int role) const { return QVariant(); } } + +FeedsModelStandardCategory *FeedsModelStandardCategory::loadFromRecord(const QSqlRecord &record) { + FeedsModelStandardCategory *category = new FeedsModelStandardCategory(NULL); + + category->setId(record.value(CAT_DB_ID_INDEX).toInt()); + category->setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); + category->setDescription(record.value(CAT_DB_DESCRIPTION_INDEX).toString()); + category->setCreationDate(QDateTime::fromString(record.value(CAT_DB_DCREATED_INDEX).toString(), + Qt::ISODate)); + category->setIcon(IconFactory::fromByteArray(record.value(CAT_DB_ICON_INDEX).toByteArray())); + + return category; +} + +QString FeedsModelStandardCategory::title() const { + return m_title; +} + +void FeedsModelStandardCategory::setTitle(const QString &title) { + m_title = title; +} + +QString FeedsModelStandardCategory::description() const { + return m_description; +} + +void FeedsModelStandardCategory::setDescription(const QString &description) { + m_description = description; +} + +QDateTime FeedsModelStandardCategory::creationDate() const { + return m_creationDate; +} + +void FeedsModelStandardCategory::setCreationDate(const QDateTime &creation_date) { + m_creationDate = creation_date; +} + + + diff --git a/src/core/feedsmodelstandardcategory.h b/src/core/feedsmodelstandardcategory.h index d18a1c75a..b87c04229 100644 --- a/src/core/feedsmodelstandardcategory.h +++ b/src/core/feedsmodelstandardcategory.h @@ -1,6 +1,9 @@ #ifndef FEEDSMODELSTANDARDCATEGORY_H #define FEEDSMODELSTANDARDCATEGORY_H +#include +#include + #include "core/feedsmodelcategory.h" @@ -16,6 +19,23 @@ class FeedsModelStandardCategory : public FeedsModelCategory { virtual ~FeedsModelStandardCategory(); QVariant data(int column, int role) const; + + static FeedsModelStandardCategory *loadFromRecord(const QSqlRecord &record); + + QString title() const; + void setTitle(const QString &title); + + QString description() const; + void setDescription(const QString &description); + + QDateTime creationDate() const; + void setCreationDate(const QDateTime &creation_date); + + private: + QDateTime m_creationDate; + QString m_title; + QString m_description; + }; #endif // FEEDSMODELSTANDARDCATEGORY_H diff --git a/src/core/feedsmodelstandardfeed.cpp b/src/core/feedsmodelstandardfeed.cpp index e9001a86a..f16ee673f 100644 --- a/src/core/feedsmodelstandardfeed.cpp +++ b/src/core/feedsmodelstandardfeed.cpp @@ -24,20 +24,20 @@ void FeedsModelStandardFeed::setTitle(const QString &title) { QVariant FeedsModelStandardFeed::data(int column, int role) const { switch (role) { case Qt::DisplayRole: - if (column == FDS_TITLE_INDEX) { + if (column == FDS_MODEL_TITLE_INDEX) { return m_title; } - else if (column == FDS_COUNTS_INDEX) { + else if (column == FDS_MODEL_COUNTS_INDEX) { return QString("(%1)").arg(QString::number(countOfUnreadMessages())); } case Qt::DecorationRole: - return column == FDS_TITLE_INDEX ? + return column == FDS_MODEL_TITLE_INDEX ? m_icon : QVariant(); case Qt::TextAlignmentRole: - if (column == FDS_COUNTS_INDEX) { + if (column == FDS_MODEL_COUNTS_INDEX) { return Qt::AlignCenter; } else { diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index e6df3c1d7..85756a079 100644 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -25,7 +25,6 @@ MessagesModel::MessagesModel(QObject *parent) // via model, but DIRECT SQL calls are used to do persistent messages. setEditStrategy(QSqlTableModel::OnManualSubmit); setTable("Messages"); - loadMessages(QList()); } @@ -146,12 +145,6 @@ QVariant MessagesModel::data(const QModelIndex &idx, int role) const { return record(idx.row()).value(MSG_DB_READ_INDEX).toInt() == 1 ? m_normalFont : m_boldFont; - /* - case Qt::BackgroundRole: - return record(idx.row()).value(MSG_DB_DELETED_INDEX).toInt() == 1 ? - QColor(255, 0, 0, 100) : - QVariant(); - */ case Qt::DecorationRole: { int index_column = idx.column(); diff --git a/src/core/textfactory.cpp b/src/core/textfactory.cpp index 2190d9d69..2e8c13900 100644 --- a/src/core/textfactory.cpp +++ b/src/core/textfactory.cpp @@ -10,9 +10,6 @@ TextFactory::TextFactory() { } -TextFactory::~TextFactory() { -} - QDateTime TextFactory::parseDateTime(const QString &date_time) { QString date = date_time.simplified(); QDateTime dt; diff --git a/src/core/textfactory.h b/src/core/textfactory.h index 36b5978a9..d14da7b54 100644 --- a/src/core/textfactory.h +++ b/src/core/textfactory.h @@ -11,8 +11,6 @@ class TextFactory { explicit TextFactory(); public: - virtual ~TextFactory(); - // Tries to parse input textual date/time representation. // Returns invalid date/time if processing fails. static QDateTime parseDateTime(const QString &date_time); diff --git a/src/gui/feedsview.cpp b/src/gui/feedsview.cpp index 17c94b6cd..ca0ee7d8a 100644 --- a/src/gui/feedsview.cpp +++ b/src/gui/feedsview.cpp @@ -21,12 +21,12 @@ FeedsView::~FeedsView() { void FeedsView::setupAppearance() { #if QT_VERSION >= 0x050000 // Setup column resize strategies. - header()->setSectionResizeMode(FDS_TITLE_INDEX, QHeaderView::Stretch); - header()->setSectionResizeMode(FDS_COUNTS_INDEX, QHeaderView::ResizeToContents); + header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch); + header()->setSectionResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeToContents); #else // Setup column resize strategies. - header()->setResizeMode(FDS_TITLE_INDEX, QHeaderView::Stretch); - header()->setResizeMode(FDS_COUNTS_INDEX, QHeaderView::ResizeToContents); + header()->setResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch); + header()->setResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeToContents); #endif header()->setStretchLastSection(false); diff --git a/src/gui/iconfactory.cpp b/src/gui/iconfactory.cpp new file mode 100644 index 000000000..e90eb8003 --- /dev/null +++ b/src/gui/iconfactory.cpp @@ -0,0 +1,31 @@ +#include + +#include "gui/iconfactory.h" + + +IconFactory::IconFactory() { +} + +QIcon IconFactory::fromByteArray(QByteArray array) { + QIcon icon; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + + QDataStream in(&buffer); + in >> icon; + + buffer.close(); + return icon; +} + +QByteArray IconFactory::toByteArray(const QIcon &icon) { + QByteArray array; + QBuffer buffer(&array); + buffer.open(QIODevice::WriteOnly); + + QDataStream out(&buffer); + out << icon; + + buffer.close(); + return array; +} diff --git a/src/gui/iconfactory.h b/src/gui/iconfactory.h new file mode 100644 index 000000000..c1c13c085 --- /dev/null +++ b/src/gui/iconfactory.h @@ -0,0 +1,17 @@ +#ifndef ICONFACTORY_H +#define ICONFACTORY_H + +#include + + +class IconFactory { + private: + IconFactory(); + + public: + static QIcon fromByteArray(QByteArray array); + static QByteArray toByteArray(const QIcon &icon); + +}; + +#endif // ICONFACTORY_H