bookmarks/xbelreader.cpp
author hgs
Fri, 17 Sep 2010 12:10:47 -0400
changeset 9 1d51612454b5
child 15 5ea3798f1248
permissions -rw-r--r--
201037

/*
* 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();
    }

}