bookmarks/xbelreader.cpp
changeset 9 1d51612454b5
child 15 5ea3798f1248
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bookmarks/xbelreader.cpp	Fri Sep 17 12:10:47 2010 -0400
@@ -0,0 +1,201 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, version 2.1 of the License.
+* 
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, 
+* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
+*
+*/
+#include <QXmlStreamReader>
+#include <QIODevice>
+#include <QList>
+
+#include "xbelreader.h"
+#include "BookmarksManager.h"
+
+XbelReader::XbelReader(BookmarksManager *bmgr) : 
+    m_bmgr(bmgr), m_xml(new QXmlStreamReader)
+{
+}
+
+XbelReader::~XbelReader() {
+    if(m_xml) delete m_xml;
+}
+
+bool XbelReader::read(QIODevice *device)
+{
+    if(!device) {
+        m_xml->raiseError(QObject::tr("Invalid Device passed into XBEL Reader."));
+    }
+    if(!m_bmgr) { 
+        m_xml->raiseError(QObject::tr("Invalid BookmarkManager passed into XBEL Reader."));
+    } else {
+        m_xml->setDevice(device);
+        if(m_xml->readNextStartElement()) {
+           if(m_xml->name() == "xbel" && 
+              m_xml->attributes().value("version") == "1.0")
+               readXBEL();
+           else
+               m_xml->raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
+        } else 
+            m_xml->raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
+    }
+        
+    return !m_xml->error();
+}
+
+/**
+ * This function should be called before reading any xml elements
+ * It attempts to validate that the file being read is actually an 
+ * xbel file.
+ * @return whether the file is an XBEL file.
+ */
+bool XbelReader::isValidXbel() 
+{
+    // The xbel element must exist and must be version 1.0
+    return true;
+}
+
+QString XbelReader::errorString() const
+{
+    return QObject::tr("%1\nLine %2, column %3")
+            .arg(m_xml->errorString())
+            .arg(m_xml->lineNumber())
+            .arg(m_xml->columnNumber());
+}
+
+void XbelReader::readXBEL()
+{
+    QString folder = "";
+    QList<QString> folders;
+    while (m_xml->readNextStartElement()) {
+        if (m_xml->name() == "folder")
+            readFolder(folders);
+        else if (m_xml->name() == "bookmark")
+            readBookmark(folders);
+        else
+            m_xml->skipCurrentElement();
+    }
+}
+
+QString XbelReader::readFolder(QList<QString>& parentFolders)
+{
+    QString folderName = "";
+
+    while (m_xml->readNextStartElement()) {
+        if (m_xml->name() == "title")
+            folderName = m_xml->readElementText();
+        else if (m_xml->name() == "folder") {
+            QList<QString> folders;
+            folders = folders + parentFolders;
+            if(!folderName.isEmpty())
+                folders.append(folderName);
+            readFolder(folders);
+        } else if (m_xml->name() == "bookmark") {
+            QList<QString> folders;
+            folders = folders + parentFolders;
+            if(!folderName.isEmpty())
+                folders.append(folderName);
+            readBookmark(folders);
+        } else
+            m_xml->skipCurrentElement();
+    }
+    return folderName;
+}
+
+void XbelReader::readBookmark(QList<QString>& parentFolders)
+{
+    QXmlStreamAttributes attrs = m_xml->attributes();
+    
+    // if there is no URL attribute skip this bookmark.
+    if(!attrs.hasAttribute("href")) {
+        m_xml->skipCurrentElement();
+        return;
+    }
+    
+    QString url = attrs.value("href").toString();
+    QString title = "Untitled";
+    QString desc = "";
+    QList<QString> tags;
+    tags = tags + parentFolders;
+    
+    while (m_xml->readNextStartElement()) {
+        if (m_xml->name() == "title")
+            title = m_xml->readElementText();
+        else if(m_xml->name() == "desc")
+            desc = m_xml->readElementText();
+        else if(m_xml->name() == "info")
+            readInfo(tags);
+        else
+            m_xml->skipCurrentElement();
+    }
+
+    int bmID = m_bmgr->addBookmark(title, url);
+    if (bmID > 0) {
+        QList<QString>::iterator iter;
+        for (iter = tags.begin(); iter != tags.end(); ++iter)
+            m_bmgr->addTag(bmID, *iter);
+    }
+}
+
+/**
+ * Reads the info element.
+ * @param tags - A reference to a list of string tags
+ */
+void XbelReader::readInfo(QList<QString>& tags) 
+{
+    QString owner = "http://www.nokia.com";
+    while(m_xml->readNextStartElement()) {
+        if(m_xml->name() == "metadata")
+            readMetadata(tags, owner);
+        else
+            m_xml->skipCurrentElement();
+    }
+}
+
+/**
+ * This function reads the metadata XBEL tag.
+ * @param tags - A reference to a list of strings. This is passed into
+ * readTags.
+ * @param owner - A reference to the owner string. This is to allow for
+ * future support for this attribute.
+ */
+void XbelReader::readMetadata(QList<QString>& tags, QString &owner) 
+{
+    if(m_xml->attributes().hasAttribute("owner"))
+    owner = m_xml->attributes().value("owner").toString();
+    while(m_xml->readNextStartElement()) {
+        if(m_xml->name() == "tags")
+            readTags(tags);
+        else
+            m_xml->skipCurrentElement();
+    }
+    
+}
+
+/**
+ * Reads the tags and tag attributes, adding all tags found to 
+ * the list of string tags passed into the function.
+ * @param tags - Reference to a list of string tags.
+ */
+void XbelReader::readTags(QList<QString>& tags) 
+{
+    while(m_xml->readNextStartElement()) {
+        if(m_xml->name() == "tag") 
+            tags.append(m_xml->readElementText());
+        else
+            m_xml->skipCurrentElement();
+    }
+
+}
+