diff -r 000000000000 -r 1918ee327afb tools/assistant/compat/docuparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/assistant/compat/docuparser.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,433 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "docuparser.h" +#include "profile.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDataStream &operator>>(QDataStream &s, ContentItem &ci) +{ + s >> ci.title; + s >> ci.reference; + s >> ci.depth; + return s; +} + +QDataStream &operator<<(QDataStream &s, const ContentItem &ci) +{ + s << ci.title; + s << ci.reference; + s << ci.depth; + return s; +} + +const QString DocuParser::DocumentKey = QLatin1String("/Qt Assistant/") + QLatin1String(QT_VERSION_STR) + QLatin1String("/"); + +DocuParser *DocuParser::createParser(const QString &fileName) +{ + QFile file(fileName); + if(!file.open(QFile::ReadOnly)) { + return 0; + } + + QString str; + int maxlen = 1024; + int majVer = 0, minVer = 0, serVer = 0; + static QRegExp re(QLatin1String("assistantconfig +version=\"(\\d)\\.(\\d)\\.(\\d)\""), Qt::CaseInsensitive); + Q_ASSERT(re.isValid()); + while(!(str = QLatin1String(file.readLine(maxlen))).isEmpty()) { + if(re.indexIn(str) >= 0) { + majVer = re.cap(1).toInt(); + minVer = re.cap(2).toInt(); + serVer = re.cap(3).toInt(); + break; + } + } + + if (majVer < 3 || (majVer == 3 && minVer < 2)) { + return new DocuParser310; + } + + return new DocuParser320; +} + + +bool DocuParser::parse(QFile *file) +{ + QXmlInputSource source(file); + QXmlSimpleReader reader; + reader.setContentHandler(this); + reader.setErrorHandler(this); + setFileName(QFileInfo(*file).absoluteFilePath()); + return reader.parse(source); +} + + +QString DocuParser::errorProtocol() const +{ + return errorProt; +} + + +QList DocuParser::getContentItems() +{ + return contentList; +} + + +QList DocuParser::getIndexItems() +{ + return indexList; +} + +QString DocuParser::absolutify(const QString &name, bool makeUrl) const +{ + if (!name.isEmpty()) { + QString s = name; + s.replace(QLatin1String("\\"), QLatin1String("/")); + QFileInfo orgPath(name); + if(orgPath.isRelative()) + s = QFileInfo(fname).path() + QLatin1Char('/') + name; + if (makeUrl) + s.prepend(QLatin1String("file:")); + return s; + } + return name; +} + + +void DocuParser310::addTo(Profile *p) +{ + p->addDCFTitle(fname, docTitle); + p->addDCFIcon(docTitle, iconName); + p->addDCFIndexPage(docTitle, conURL); +} + + +bool DocuParser310::startDocument() +{ + state = StateInit; + errorProt = QLatin1String(""); + + contentRef = QLatin1String(""); + indexRef = QLatin1String(""); + depth = 0; + + contentList.clear(); + qDeleteAll(indexList); + indexList.clear(); + + return true; +} + + +bool DocuParser310::startElement(const QString &, const QString &, + const QString &qname, + const QXmlAttributes &attr) +{ + if (qname == QLatin1String("DCF") && state == StateInit) { + state = StateContent; + contentRef = absolutify(attr.value(QLatin1String("ref")), false); + conURL = contentRef; + docTitle = attr.value(QLatin1String("title")); + iconName = absolutify(attr.value(QLatin1String("icon")), false); + contentList.append(ContentItem(docTitle, absolutify(contentRef), depth)); + } else if (qname == QLatin1String("section") && (state == StateContent || state == StateSect)) { + state = StateSect; + contentRef = absolutify(attr.value(QLatin1String("ref"))); + title = attr.value(QLatin1String("title")); + depth++; + contentList.append(ContentItem(title, contentRef, depth)); + } else if (qname == QLatin1String("keyword") && state == StateSect) { + state = StateKeyword; + indexRef = absolutify(attr.value(QLatin1String("ref"))); + } else + return false; + return true; +} + +bool DocuParser310::endElement(const QString &nameSpace, const QString &localName, + const QString &qName) +{ + Q_UNUSED(nameSpace); + Q_UNUSED(localName); + Q_UNUSED(qName); + + switch(state) { + case StateInit: + break; + case StateContent: + state = StateInit; + break; + case StateSect: + state = --depth ? StateSect : StateContent; + break; + case StateKeyword: + state = StateSect; + break; + default: + break; + } + return true; +} + + +bool DocuParser310::characters(const QString& ch) +{ + QString str = ch.simplified(); + if (str.isEmpty()) + return true; + + switch (state) { + case StateInit: + case StateContent: + case StateSect: + return false; + break; + case StateKeyword: + indexList.append(new IndexItem(str, indexRef)); + break; + default: + return false; + } + return true; +} + + +bool DocuParser310::fatalError(const QXmlParseException& exception) +{ + errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n") + .arg(exception.message()) + .arg(exception.lineNumber()) + .arg(exception.columnNumber()); + + return QXmlDefaultHandler::fatalError(exception); +} + + +DocuParser320::DocuParser320() + : prof(new Profile) +{ +} + + +void DocuParser320::addTo(Profile *p) +{ + QMap::ConstIterator it; + + for (it = prof->dcfTitles.constBegin(); it != prof->dcfTitles.constEnd(); ++it) + p->dcfTitles[it.key()] = *it; + + for (it = prof->icons.constBegin(); it != prof->icons.constEnd(); ++it) + p->icons[it.key()] = *it; + + for (it = prof->indexPages.constBegin(); it != prof->indexPages.constEnd(); ++it) + p->indexPages[it.key()] = *it; +} + + +bool DocuParser320::startDocument() +{ + state = StateInit; + errorProt = QLatin1String(""); + + contentRef = QLatin1String(""); + indexRef = QLatin1String(""); + depth = 0; + contentList.clear(); + indexList.clear(); + + prof->addDCF(fname); + + return true; +} + +bool DocuParser320::startElement(const QString &, const QString &, + const QString &qname, + const QXmlAttributes &attr) +{ + QString lower = qname.toLower(); + + switch(state) { + + case StateInit: + if(lower == QLatin1String("assistantconfig")) + state = StateDocRoot; + break; + + case StateDocRoot: + if(lower == QLatin1String("dcf")) { + state = StateContent; + contentRef = absolutify(attr.value(QLatin1String("ref"))); + conURL = contentRef; + docTitle = attr.value(QLatin1String("title")); + iconName = absolutify(attr.value(QLatin1String("icon"))); + contentList.append(ContentItem(docTitle, contentRef, depth)); + } else if(lower == QLatin1String("profile")) { + state = StateProfile; + } + break; + + case StateSect: + if (lower == QLatin1String("keyword") && state == StateSect) { + state = StateKeyword; + indexRef = absolutify(attr.value(QLatin1String("ref"))); + break; + } // else if (lower == "section") + case StateContent: + if(lower == QLatin1String("section")) { + state = StateSect; + contentRef = absolutify(attr.value(QLatin1String("ref"))); + title = attr.value(QLatin1String("title")); + depth++; + contentList.append(ContentItem(title, contentRef, depth)); + } + break; + + case StateProfile: + if(lower == QLatin1String("property")) { + state = StateProperty; + propertyName = attr.value(QLatin1String("name")); + } + break; + + case StateProperty: + break; + + default: + break; + } + + return true; +} + +bool DocuParser320::endElement(const QString &nameSpace, + const QString &localName, + const QString &qName) +{ + Q_UNUSED(nameSpace); + Q_UNUSED(localName); + Q_UNUSED(qName); + + switch(state) { + case StateInit: + break; + case StateDocRoot: + state = StateInit; + break; + case StateProfile: + state = StateDocRoot; + break; + case StateProperty: + state = StateProfile; + if(propertyName.isEmpty() || propertyValue.isEmpty()) + return false; + { + static const QStringList lst = QStringList() + << QLatin1String("startpage") << QLatin1String("abouturl") + << QLatin1String("applicationicon") << QLatin1String("assistantdocs"); + + if (lst.contains(propertyName)) + propertyValue = absolutify(propertyValue); + } + prof->addProperty(propertyName, propertyValue); + break; + case StateContent: + if(!iconName.isEmpty()) + prof->addDCFIcon(docTitle, iconName); + if(contentRef.isEmpty()) + return false; + prof->addDCFIndexPage(docTitle, conURL); + prof->addDCFTitle(fname, docTitle); + state = StateDocRoot; + break; + case StateSect: + state = --depth ? StateSect : StateContent; + break; + case StateKeyword: + state = StateSect; + break; + } + return true; +} + +bool DocuParser320::characters(const QString& ch) +{ + QString str = ch.simplified(); + if (str.isEmpty()) + return true; + + switch (state) { + case StateInit: + case StateContent: + case StateSect: + return false; + break; + case StateKeyword: + indexList.append(new IndexItem(str, indexRef)); + break; + case StateProperty: + propertyValue = ch; + break; + default: + return false; + } + return true; +} + +bool DocuParser320::fatalError(const QXmlParseException& exception) +{ + errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n") + .arg(exception.message()) + .arg(exception.lineNumber()) + .arg(exception.columnNumber()); + return QXmlDefaultHandler::fatalError(exception); +} + +QT_END_NAMESPACE