Added support older RSS formats and ATOM. Moreover, message SQL updates are now done in transactions.
This commit is contained in:
		
							parent
							
								
									b4d60e01f1
								
							
						
					
					
						commit
						c04805a6f7
					
				
					 8 changed files with 104 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
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);
 | 
			
		||||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -255,10 +255,9 @@ void FeedsModel::loadFromDatabase() {
 | 
			
		|||
    FeedsModelFeed::Type type = static_cast<FeedsModelFeed::Type>(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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -182,6 +182,7 @@ void FeedsModelStandardFeed::update() {
 | 
			
		|||
  QList<Message> 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<Message> &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<Message> &messages) {
 | 
			
		|||
      // online feed.
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!database.commit()) {
 | 
			
		||||
    database.rollback();
 | 
			
		||||
 | 
			
		||||
    qDebug("Transaction commit for message downloader failed.");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,75 @@ ParsingFactory::ParsingFactory() {
 | 
			
		|||
 | 
			
		||||
QList<Message> ParsingFactory::parseAsATOM10(const QString &data) {
 | 
			
		||||
  // TODO: Implement this.
 | 
			
		||||
  return QList<Message>();
 | 
			
		||||
 | 
			
		||||
  QList<Message> 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<Message> ParsingFactory::parseAsRDF(const QString &data) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue