From 44661b36d8f6a84cdcadaf634524fa03025749b2 Mon Sep 17 00:00:00 2001
From: Martin Rotter <rotter.martinos@gmail.com>
Date: Sat, 14 Dec 2013 18:54:35 +0100
Subject: [PATCH] grulich je gej

---
 CMakeLists.txt                          |  1 +
 src/core/feedsmodel.cpp                 |  5 +++
 src/core/feedsmodel.h                   |  5 +++
 src/core/feedsmodelcategory.cpp         | 16 +++++++
 src/core/feedsmodelcategory.h           | 14 ++++++-
 src/core/feedsmodelfeed.cpp             | 14 +++----
 src/core/feedsmodelfeed.h               |  5 ++-
 src/core/feedsmodelrootitem.cpp         |  3 ++
 src/core/feedsmodelrootitem.h           |  8 +++-
 src/core/feedsmodelstandardcategory.cpp | 23 ++++------
 src/core/feedsmodelstandardcategory.h   | 13 +-----
 src/core/feedsmodelstandardfeed.cpp     |  4 ++
 src/core/feedsmodelstandardfeed.h       |  3 ++
 src/core/messagesmodel.h                |  9 +---
 src/core/parsingfactory.cpp             | 56 +++++++++++++++++++++++++
 src/core/parsingfactory.h               | 20 +++++++++
 src/core/textfactory.cpp                |  4 ++
 src/core/textfactory.h                  |  3 ++
 18 files changed, 159 insertions(+), 47 deletions(-)
 create mode 100644 src/core/parsingfactory.cpp
 create mode 100644 src/core/parsingfactory.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6a644e8a..054c4b9ea 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -276,6 +276,7 @@ set(APP_SOURCES
   src/core/feedsmodelfeed.cpp
   src/core/feedsmodelstandardcategory.cpp
   src/core/feedsmodelstandardfeed.cpp
+  src/core/parsingfactory.cpp
 
   # Basic application sources.
   src/main.cpp
diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp
index 46a93733d..5965c85cd 100644
--- a/src/core/feedsmodel.cpp
+++ b/src/core/feedsmodel.cpp
@@ -163,6 +163,11 @@ int FeedsModel::columnCount(const QModelIndex &parent) const {
   }
 }
 
+FeedsModelRootItem *FeedsModel::itemForIndex(const QModelIndex &index) {
+  FeedsModelRootItem *item = static_cast<FeedsModelRootItem*>(index.internalPointer());
+  return item;
+}
+
 void FeedsModel::loadFromDatabase() {
   qDeleteAll(m_rootItem->m_childItems);
 
diff --git a/src/core/feedsmodel.h b/src/core/feedsmodel.h
index 8b62bd704..c93e60650 100644
--- a/src/core/feedsmodel.h
+++ b/src/core/feedsmodel.h
@@ -22,6 +22,7 @@ class FeedsModel : public QAbstractItemModel {
     explicit FeedsModel(QObject *parent = 0);
     virtual ~FeedsModel();
 
+    // Model implementation.
     QVariant data(const QModelIndex &index, int role) const;
     QVariant headerData(int section, Qt::Orientation orientation, int role) const;
     QModelIndex index(int row, int column, const QModelIndex &parent) const;
@@ -29,6 +30,10 @@ class FeedsModel : public QAbstractItemModel {
     int columnCount(const QModelIndex &parent) const;
     int rowCount(const QModelIndex &parent) const;
 
+    // Returns feed/category which lies at the specified index.
+    FeedsModelRootItem *itemForIndex(const QModelIndex &index);
+
+    // Loads feed/categories from the database.
     void loadFromDatabase();
 
     // Returns all categories.
diff --git a/src/core/feedsmodelcategory.cpp b/src/core/feedsmodelcategory.cpp
index 96a05a3a1..9e4c2f058 100644
--- a/src/core/feedsmodelcategory.cpp
+++ b/src/core/feedsmodelcategory.cpp
@@ -43,3 +43,19 @@ QString FeedsModelCategory::title() const {
 void FeedsModelCategory::setTitle(const QString &title) {
   m_title = title;
 }
+
+QString FeedsModelCategory::description() const {
+  return m_description;
+}
+
+void FeedsModelCategory::setDescription(const QString &description) {
+  m_description = description;
+}
+
+QDateTime FeedsModelCategory::creationDate() const {
+  return m_creationDate;
+}
+
+void FeedsModelCategory::setCreationDate(const QDateTime &creation_date) {
+  m_creationDate = creation_date;
+}
diff --git a/src/core/feedsmodelcategory.h b/src/core/feedsmodelcategory.h
index 0ce01d97d..f2e0116f7 100644
--- a/src/core/feedsmodelcategory.h
+++ b/src/core/feedsmodelcategory.h
@@ -1,11 +1,14 @@
 #ifndef FEEDSMODELCLASSICCATEGORY_H
 #define FEEDSMODELCLASSICCATEGORY_H
 
+#include <QDateTime>
+
 #include "core/feedsmodelrootitem.h"
 
 
 // Base class for all categories contained in FeedsModel.
 // NOTE: This class should be derived to create PARTICULAR category types.
+// NOTE: This class should not be instantiated directly.
 class FeedsModelCategory : public FeedsModelRootItem {
   public:
     // Describes possible types of categories.
@@ -23,15 +26,24 @@ class FeedsModelCategory : public FeedsModelRootItem {
     int countOfAllMessages() const;
     int countOfUnreadMessages() const;
 
+    // All types of categories offer these getters/setters.
     Type type() const;
     void setType(const Type &type);
 
     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);
+
   protected:
-    QString m_title;
     Type m_type;
+    QString m_title;
+    QDateTime m_creationDate;
+    QString m_description;
 };
 
 #endif // FEEDSMODELCLASSICCATEGORY_H
diff --git a/src/core/feedsmodelfeed.cpp b/src/core/feedsmodelfeed.cpp
index 85e77ad5e..7bffba50e 100644
--- a/src/core/feedsmodelfeed.cpp
+++ b/src/core/feedsmodelfeed.cpp
@@ -1,3 +1,8 @@
+#include <QSqlDatabase>
+#include <QSqlQuery>
+#include <QSqlError>
+
+#include "core/databasefactory.h"
 #include "core/feedsmodelfeed.h"
 
 
@@ -13,7 +18,6 @@ int FeedsModelFeed::childCount() const {
   return 0;
 }
 
-
 int FeedsModelFeed::countOfAllMessages() const {
   return m_totalCount;
 }
@@ -22,14 +26,6 @@ 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;
 }
diff --git a/src/core/feedsmodelfeed.h b/src/core/feedsmodelfeed.h
index 0423b0f93..2d01d3c55 100644
--- a/src/core/feedsmodelfeed.h
+++ b/src/core/feedsmodelfeed.h
@@ -20,13 +20,14 @@ class FeedsModelFeed : public FeedsModelRootItem {
     explicit FeedsModelFeed(FeedsModelRootItem *parent_item = NULL);
     virtual ~FeedsModelFeed();
 
+    // Returns 0, feeds have no children.
     int childCount() const;
 
+    // Getters/setters for count of messages.
     int countOfAllMessages() const;
     int countOfUnreadMessages() const;
-    void setCountOfAllMessages(int count_total);
-    void setCountOfUnreadMessages(int count_unread);
 
+    // Other getters/setters.
     Type type() const;
     void setType(const Type &type);
 
diff --git a/src/core/feedsmodelrootitem.cpp b/src/core/feedsmodelrootitem.cpp
index cfad097ca..398700389 100644
--- a/src/core/feedsmodelrootitem.cpp
+++ b/src/core/feedsmodelrootitem.cpp
@@ -20,6 +20,9 @@ void FeedsModelRootItem::setParent(FeedsModelRootItem *parent_item) {
   m_parentItem = parent_item;
 }
 
+void FeedsModelRootItem::update() {
+}
+
 FeedsModelRootItem *FeedsModelRootItem::child(int row) {
   return m_childItems.value(row);
 }
diff --git a/src/core/feedsmodelrootitem.h b/src/core/feedsmodelrootitem.h
index 36d01bc23..bdb11c236 100644
--- a/src/core/feedsmodelrootitem.h
+++ b/src/core/feedsmodelrootitem.h
@@ -15,6 +15,7 @@ class FeedsModelRootItem {
     explicit FeedsModelRootItem(FeedsModelRootItem *parent_item = NULL);
     virtual ~FeedsModelRootItem();
 
+    // Basic operations.
     virtual void setParent(FeedsModelRootItem *parent_item);
     virtual FeedsModelRootItem *parent();
     virtual FeedsModelRootItem *child(int row);
@@ -24,11 +25,17 @@ class FeedsModelRootItem {
     virtual int row() const;
     virtual QVariant data(int column, int role) const;
 
+    // Each item offers "counts" of messages.
     virtual int countOfUnreadMessages() const;
     virtual int countOfAllMessages() const;
 
+    // Each item can be "updated".
+    virtual void update();
+
+    // Each item has icon.
     void setIcon(const QIcon &icon);
 
+    // Each item has some kind of id.
     int id() const;
     void setId(int id);
 
@@ -37,7 +44,6 @@ class FeedsModelRootItem {
     QIcon m_icon;
     QList<FeedsModelRootItem*> m_childItems;
     FeedsModelRootItem *m_parentItem;
-
 };
 
 #endif // FEEDMODELROOTITEM_H
diff --git a/src/core/feedsmodelstandardcategory.cpp b/src/core/feedsmodelstandardcategory.cpp
index 00e571266..8287b44b0 100644
--- a/src/core/feedsmodelstandardcategory.cpp
+++ b/src/core/feedsmodelstandardcategory.cpp
@@ -43,6 +43,13 @@ QVariant FeedsModelStandardCategory::data(int column, int role) const {
   }
 }
 
+void FeedsModelStandardCategory::update() {
+  // Update all children.
+  foreach (FeedsModelRootItem *child, m_childItems) {
+    child->update();
+  }
+}
+
 FeedsModelStandardCategory *FeedsModelStandardCategory::loadFromRecord(const QSqlRecord &record) {
   FeedsModelStandardCategory *category = new FeedsModelStandardCategory(NULL);
 
@@ -55,19 +62,3 @@ FeedsModelStandardCategory *FeedsModelStandardCategory::loadFromRecord(const QSq
 
   return category;
 }
-
-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 40d60d05b..112236fef 100644
--- a/src/core/feedsmodelstandardcategory.h
+++ b/src/core/feedsmodelstandardcategory.h
@@ -18,20 +18,11 @@ class FeedsModelStandardCategory : public FeedsModelCategory {
     explicit FeedsModelStandardCategory(FeedsModelRootItem *parent_item = NULL);
     virtual ~FeedsModelStandardCategory();
 
+    void update();
+
     QVariant data(int column, int role) const;
 
-    QString description() const;
-    void setDescription(const QString &description);
-
-    QDateTime creationDate() const;
-    void setCreationDate(const QDateTime &creation_date);
-
     static FeedsModelStandardCategory *loadFromRecord(const QSqlRecord &record);
-
-  private:
-    QDateTime m_creationDate;
-    QString m_description;
-
 };
 
 #endif // FEEDSMODELSTANDARDCATEGORY_H
diff --git a/src/core/feedsmodelstandardfeed.cpp b/src/core/feedsmodelstandardfeed.cpp
index a06b67b11..6a3f112f4 100644
--- a/src/core/feedsmodelstandardfeed.cpp
+++ b/src/core/feedsmodelstandardfeed.cpp
@@ -97,3 +97,7 @@ QVariant FeedsModelStandardFeed::data(int column, int role) const {
       return QVariant();
   }
 }
+
+void FeedsModelStandardFeed::update() {
+  // TODO: Perform fetching of new messages.
+}
diff --git a/src/core/feedsmodelstandardfeed.h b/src/core/feedsmodelstandardfeed.h
index 38e2bcba5..8553b8f53 100644
--- a/src/core/feedsmodelstandardfeed.h
+++ b/src/core/feedsmodelstandardfeed.h
@@ -18,6 +18,9 @@ class FeedsModelStandardFeed : public FeedsModelFeed {
 
     QVariant data(int column, int role) const;
 
+    // Perform fetching of new messages.
+    void update();
+
     // Various getters/setters.
     QString description() const;
     void setDescription(const QString &description);
diff --git a/src/core/messagesmodel.h b/src/core/messagesmodel.h
index 8016ad356..17edc341a 100644
--- a/src/core/messagesmodel.h
+++ b/src/core/messagesmodel.h
@@ -10,18 +10,13 @@
 
 
 // Represents single message.
-// NOTE: This is primarily used for transfering data
-// to WebBrowser responsible for displaying of messages.
 class Message {
-    friend class WebBrowser;
-    friend class MessagesModel;
-    friend class MessagesView;
-
-  private:
+  public:
     QString m_title;
     QString m_url;
     QString m_author;
     QString m_contents;
+    QDateTime m_created;
     QDateTime m_updated;
 };
 
diff --git a/src/core/parsingfactory.cpp b/src/core/parsingfactory.cpp
new file mode 100644
index 000000000..494ff8c62
--- /dev/null
+++ b/src/core/parsingfactory.cpp
@@ -0,0 +1,56 @@
+#include <QDomDocument>
+#include <QDomElement>
+
+#include "core/parsingfactory.h"
+#include "core/textfactory.h"
+
+
+ParsingFactory::ParsingFactory() {
+}
+
+QList<Message> ParsingFactory::parseAsRSS20(const QString &data) {
+  QList<Message> messages;
+  QDomDocument xml_file;
+  xml_file.setContent(data, true);
+  QDomNodeList messages_in_xml = xml_file.elementsByTagName("item");
+
+  for (int i = 0; i < messages_in_xml.size(); i++) {
+    QDomElement elem_link = messages_in_xml.item(i).namedItem("link").toElement();
+    QDomElement elem_description = messages_in_xml.item(i).namedItem("description").toElement();
+    QDomElement elem_description2 = messages_in_xml.item(i).namedItem("encoded").toElement();
+    QDomElement elem_title = messages_in_xml.item(i).namedItem("title").toElement();
+    QDomElement elem_updated = messages_in_xml.item(i).namedItem("pubDate").toElement();
+    QDomElement elem_author = messages_in_xml.item(i).namedItem("author").toElement();
+    QDomElement elem_author2 = messages_in_xml.item(i).namedItem("creator").toElement();
+
+    // RSS 1.0 requires to have title and link valid.
+    if (elem_description.text().isEmpty() && elem_title.text().isEmpty()) {
+      continue;
+    }
+
+    Message new_message;
+    new_message.m_title = TextFactory::stripTags(elem_title.text().simplified());
+
+    if (new_message.m_title.isEmpty()) {
+      new_message.m_title = TextFactory::stripTags(elem_description.text().simplified());
+    }
+
+    new_message.m_contents = elem_description2.text();
+    if (new_message.m_contents.isEmpty()) {
+      new_message.m_contents = elem_description.text();
+    }
+
+    new_message.m_url = elem_link.text();
+    new_message.m_author = elem_author.text();
+
+    if (new_message.m_author.isEmpty()) {
+      new_message.m_author = elem_author2.text();
+    }
+
+    new_message.m_updated = TextFactory::parseDateTime(elem_updated.text());
+
+    messages.append(new_message);
+  }
+
+  return messages;
+}
diff --git a/src/core/parsingfactory.h b/src/core/parsingfactory.h
new file mode 100644
index 000000000..2f67115d2
--- /dev/null
+++ b/src/core/parsingfactory.h
@@ -0,0 +1,20 @@
+#ifndef PARSINGFACTORY_H
+#define PARSINGFACTORY_H
+
+#include <QNetworkReply>
+
+#include "core/messagesmodel.h"
+
+
+class ParsingFactory {
+  private:
+    ParsingFactory();
+
+  public:
+    // Parses inpute textual data into Message objects.
+    // NOTE: Input is correctly encoded in Unicode.
+    QList<Message> parseAsRSS20(const QString &data);
+
+};
+
+#endif // PARSINGFACTORY_H
diff --git a/src/core/textfactory.cpp b/src/core/textfactory.cpp
index 2e8c13900..4f5a47454 100644
--- a/src/core/textfactory.cpp
+++ b/src/core/textfactory.cpp
@@ -45,3 +45,7 @@ QString TextFactory::shorten(const QString &input, int text_length_limit) {
     return input;
   }
 }
+
+QString TextFactory::stripTags(QString text) {
+  return text.remove(QRegExp("<[^>]*>"));
+}
diff --git a/src/core/textfactory.h b/src/core/textfactory.h
index d14da7b54..d3f1dcfee 100644
--- a/src/core/textfactory.h
+++ b/src/core/textfactory.h
@@ -15,6 +15,9 @@ class TextFactory {
     // Returns invalid date/time if processing fails.
     static QDateTime parseDateTime(const QString &date_time);
 
+    // Strips "<....>" tags from given text.
+    static QString stripTags(QString text);
+
     // Shortens input string according to given length limit.
     static QString shorten(const QString &input, int text_length_limit = TEXT_TITLE_LIMIT);
 };