diff --git a/resources/misc/db_init.sql b/resources/misc/db_init.sql index 01afb1d04..f5234141a 100644 --- a/resources/misc/db_init.sql +++ b/resources/misc/db_init.sql @@ -68,12 +68,12 @@ INSERT INTO Categories (id, parent_id, title, description, date_created, type) V -- ! INSERT INTO Categories (id, parent_id, title, description, date_created, type) VALUES (2, -1, 'RSS Guard', 'News and updates on RSS Guard.', '2013-12-20T08:00:00-05:00', 0); -- ! -INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Linux Today', 'Linux Today - Linux News on Internet Time.', '2013-12-20T08:00:00-05:00', 1, 'UTF-8', 'http://feeds.feedburner.com/linuxtoday/linux?format=xml', 2); +INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Linux Today', 'Linux Today - Linux News on Internet Time.', '2013-12-20T08:00:00-05:00', 1, 'UTF-8', 'http://feeds.feedburner.com/linuxtoday/linux?format=xml', 1); -- ! -INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('LinuxInsider', 'LinuxInsider: Linux News & Information from Around the World.', '2013-12-20T08:00:00-05:00', 1, 'UTF-8', 'http://www.linuxinsider.com/perl/syndication/rssfull.pl', 3); +INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('LinuxInsider', 'LinuxInsider: Linux News & Information from Around the World.', '2013-12-20T08:00:00-05:00', 1, 'UTF-8', 'http://www.linuxinsider.com/perl/syndication/rssfull.pl', 2); -- ! -INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Recent Commits', 'Recent commits for RSS Guard project.', '2013-12-20T08:00:00-05:00', 2, 'UTF-8', 'https://github.com/martinrotter/rssguard/commits/master.atom', 4); +INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Recent Commits', 'Recent commits for RSS Guard project.', '2013-12-20T08:00:00-05:00', 2, 'UTF-8', 'https://github.com/martinrotter/rssguard/commits/master.atom', 3); -- ! -INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Releases', 'Releases for RSS Guard.', '2013-12-20T08:00:00-05:00', 2, 'UTF-8', 'https://github.com/martinrotter/rssguard/releases.atom', 4); +INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Releases', 'Releases for RSS Guard.', '2013-12-20T08:00:00-05:00', 2, 'UTF-8', 'https://github.com/martinrotter/rssguard/releases.atom', 3); -- ! -INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Author''s Activity', 'RSS Guard author public activity overview.', '2013-12-20T08:00:00-05:00', 2, 'UTF-8', 'https://github.com/martinrotter.atom', 4); \ No newline at end of file +INSERT INTO Feeds (title, description, date_created, category, encoding, url, type) VALUES ('Author''s Activity', 'RSS Guard author public activity overview.', '2013-12-20T08:00:00-05:00', 2, 'UTF-8', 'https://github.com/martinrotter.atom', 3); \ No newline at end of file diff --git a/src/core/databasefactory.cpp b/src/core/databasefactory.cpp index 894330da9..b50683002 100644 --- a/src/core/databasefactory.cpp +++ b/src/core/databasefactory.cpp @@ -99,7 +99,7 @@ QSqlDatabase DatabaseFactory::initialize(const QString &connection_name) { QStringList statements = QString(file_init.readAll()).split(APP_DB_INIT_SPLIT, QString::SkipEmptyParts); - query_db.exec("BEGIN TRANSACTION"); + database.transaction(); foreach(const QString &statement, statements) { query_db.exec(statement); @@ -110,7 +110,7 @@ QSqlDatabase DatabaseFactory::initialize(const QString &connection_name) { } } - query_db.exec("COMMIT"); + database.commit(); qDebug("Database backend should be ready now."); } else { diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index 75b0e035a..de6b68a1c 100644 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -255,10 +255,9 @@ void FeedsModel::loadFromDatabase() { FeedsModelFeed::Type type = static_cast(query_feeds.value(FDS_DB_TYPE_INDEX).toInt()); switch (type) { - case FeedsModelFeed::StandardAtom: + case FeedsModelFeed::StandardAtom10: case FeedsModelFeed::StandardRdf: case FeedsModelFeed::StandardRss0X: - case FeedsModelFeed::StandardRss1X: case FeedsModelFeed::StandardRss2X: { FeedAssignmentItem pair; pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt(); diff --git a/src/core/feedsmodelfeed.cpp b/src/core/feedsmodelfeed.cpp index 1bf5ac571..a62bf74c1 100755 --- a/src/core/feedsmodelfeed.cpp +++ b/src/core/feedsmodelfeed.cpp @@ -50,7 +50,7 @@ void FeedsModelFeed::setType(const Type &type) { QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) { switch (type) { - case StandardAtom: + case StandardAtom10: return QObject::tr("ATOM 1.0"); case StandardRdf: diff --git a/src/core/feedsmodelfeed.h b/src/core/feedsmodelfeed.h index 3c785e936..3def6582e 100755 --- a/src/core/feedsmodelfeed.h +++ b/src/core/feedsmodelfeed.h @@ -12,10 +12,9 @@ class FeedsModelFeed : public FeedsModelRootItem { // NOTE: This is equivalent to attribute Feeds(type). enum Type { StandardRss0X = 0, - StandardRss1X = 1, - StandardRss2X = 2, - StandardRdf = 3, - StandardAtom = 4 + StandardRss2X = 1, + StandardRdf = 2, + StandardAtom10 = 3 }; // Constructors and destructors. @@ -44,6 +43,7 @@ class FeedsModelFeed : public FeedsModelRootItem { Type type() const; void setType(const Type &type); + // Converts particular feed type to string. static QString typeToString(Type type); public slots: diff --git a/src/core/feedsmodelstandardfeed.cpp b/src/core/feedsmodelstandardfeed.cpp index b200b858b..a2add5354 100755 --- a/src/core/feedsmodelstandardfeed.cpp +++ b/src/core/feedsmodelstandardfeed.cpp @@ -182,6 +182,7 @@ void FeedsModelStandardFeed::update() { QList messages; switch (type()) { + case FeedsModelFeed::StandardRss0X: case FeedsModelFeed::StandardRss2X: messages = ParsingFactory::parseAsRSS20(formatted_feed_contents); break; @@ -190,6 +191,9 @@ void FeedsModelStandardFeed::update() { messages = ParsingFactory::parseAsRDF(formatted_feed_contents); break; + case FeedsModelFeed::StandardAtom10: + messages = ParsingFactory::parseAsATOM10(formatted_feed_contents); + // TODO: Add support for other standard formats. default: @@ -214,6 +218,13 @@ void FeedsModelStandardFeed::updateMessages(const QList &messages) { "(feed, title, url, author, date_created, contents) " "VALUES (:feed, :title, :url, :author, :date_created, :contents);"); + if (!database.transaction()) { + database.rollback(); + + qDebug("Transaction start for message downloader failed."); + return; + } + foreach (const Message &message, messages) { query_select.bindValue(":feed", feed_id); query_select.bindValue(":title", message.m_title); @@ -248,4 +259,10 @@ void FeedsModelStandardFeed::updateMessages(const QList &messages) { // online feed. } } + + if (!database.commit()) { + database.rollback(); + + qDebug("Transaction commit for message downloader failed."); + } } diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index e226c1055..b32e23f8f 100644 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -145,6 +145,11 @@ QVariant MessagesModel::data(const QModelIndex &index, int role) const { return TextFactory::parseDateTime(QSqlTableModel::data(index, role).toString()).toString(Qt::DefaultLocaleShortDate); } + else if (index_column == MSG_DB_AUTHOR_INDEX) { + QString author_name = QSqlTableModel::data(index, role).toString(); + + return author_name.isEmpty() ? "-" : author_name; + } else if (index_column != MSG_DB_IMPORTANT_INDEX && index_column != MSG_DB_READ_INDEX) { return QSqlTableModel::data(index, role); diff --git a/src/core/parsingfactory.cpp b/src/core/parsingfactory.cpp index d4e50efa1..916f16617 100644 --- a/src/core/parsingfactory.cpp +++ b/src/core/parsingfactory.cpp @@ -11,7 +11,75 @@ ParsingFactory::ParsingFactory() { QList ParsingFactory::parseAsATOM10(const QString &data) { // TODO: Implement this. - return QList(); + + QList messages; + QDomDocument xml_file; + QDateTime current_time = QDateTime::currentDateTime(); + + xml_file.setContent(data, true); + + // Pull out all messages. + QDomNodeList messages_in_xml = xml_file.elementsByTagName("entry"); + + for (int i = 0; i < messages_in_xml.size(); i++) { + QDomNode message_item = messages_in_xml.item(i); + Message new_message; + + // Deal with titles & descriptions. + QString elem_title = message_item.namedItem("title").toElement().text().simplified(); + QString elem_summary = message_item.namedItem("summary").toElement().text(); + + if (elem_summary.isEmpty()) { + elem_summary = message_item.namedItem("content").toElement().text(); + } + + // Now we obtained maximum of informations for title & description. + if (elem_title.isEmpty()) { + if (elem_summary.isEmpty()) { + // BOTH title and description are empty, skip this message. + continue; + } + else { + // Title is empty but description is not. + new_message.m_title = TextFactory::stripTags(elem_summary.simplified()); + new_message.m_contents = elem_summary; + } + } + else { + // Title is not empty, description does not matter. + new_message.m_title = TextFactory::stripTags(elem_title); + new_message.m_contents = elem_summary; + } + + // Deal with link. + QDomNodeList elem_links = message_item.toElement().elementsByTagName("link"); + + for (int i = 0; i < elem_links.size(); i++) { + QDomNode elem_link = elem_links.at(i); + + if (elem_link.attributes().namedItem("rel").toAttr().value() == "alternate") { + new_message.m_url = elem_link.attributes().namedItem("href").toAttr().value(); + break; + } + } + + // Deal with authors. + new_message.m_author = TextFactory::escapeHtml(message_item.namedItem("author").namedItem("name").toElement().text()); + + // Deal with creation date. + new_message.m_created = TextFactory::parseDateTime(message_item.namedItem("updated").toElement().text()); + new_message.m_createdFromFeed = !new_message.m_created.isNull(); + + if (!new_message.m_createdFromFeed) { + // Date was NOT obtained from the feed, + // set current date as creation date for the message. + new_message.m_created = current_time; + } + + messages.append(new_message); + } + + return messages; } QList ParsingFactory::parseAsRDF(const QString &data) {