tools/assistant/compat/docuparser.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Assistant of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "docuparser.h"
       
    43 #include "profile.h"
       
    44 
       
    45 #include <QDir>
       
    46 #include <QFile>
       
    47 #include <QFileInfo>
       
    48 #include <QRegExp>
       
    49 #include <QString>
       
    50 #include <QDataStream>
       
    51 
       
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 QDataStream &operator>>(QDataStream &s, ContentItem &ci)
       
    55 {
       
    56     s >> ci.title;
       
    57     s >> ci.reference;
       
    58     s >> ci.depth;
       
    59     return s;
       
    60 }
       
    61 
       
    62 QDataStream &operator<<(QDataStream &s, const ContentItem &ci)
       
    63 {
       
    64     s << ci.title;
       
    65     s << ci.reference;
       
    66     s << ci.depth;
       
    67     return s;
       
    68 }
       
    69 
       
    70 const QString DocuParser::DocumentKey = QLatin1String("/Qt Assistant/") + QLatin1String(QT_VERSION_STR) + QLatin1String("/");
       
    71 
       
    72 DocuParser *DocuParser::createParser(const QString &fileName)
       
    73 {
       
    74     QFile file(fileName);
       
    75     if(!file.open(QFile::ReadOnly)) {
       
    76         return 0;
       
    77     }
       
    78 
       
    79     QString str;
       
    80     int maxlen = 1024;
       
    81     int majVer = 0, minVer = 0, serVer = 0;
       
    82     static QRegExp re(QLatin1String("assistantconfig +version=\"(\\d)\\.(\\d)\\.(\\d)\""), Qt::CaseInsensitive);
       
    83     Q_ASSERT(re.isValid());
       
    84     while(!(str = QLatin1String(file.readLine(maxlen))).isEmpty()) {
       
    85         if(re.indexIn(str) >= 0) {
       
    86             majVer = re.cap(1).toInt();
       
    87             minVer = re.cap(2).toInt();
       
    88             serVer = re.cap(3).toInt();
       
    89             break;
       
    90         }
       
    91     }
       
    92 
       
    93     if (majVer < 3 || (majVer == 3 && minVer < 2)) {
       
    94         return new DocuParser310;
       
    95     }
       
    96 
       
    97     return new DocuParser320;
       
    98 }
       
    99 
       
   100 
       
   101 bool DocuParser::parse(QFile *file)
       
   102 {
       
   103     QXmlInputSource source(file);
       
   104     QXmlSimpleReader reader;
       
   105     reader.setContentHandler(this);
       
   106     reader.setErrorHandler(this);
       
   107     setFileName(QFileInfo(*file).absoluteFilePath());
       
   108     return reader.parse(source);
       
   109 }
       
   110 
       
   111 
       
   112 QString DocuParser::errorProtocol() const
       
   113 {
       
   114     return errorProt;
       
   115 }
       
   116 
       
   117 
       
   118 QList<ContentItem> DocuParser::getContentItems()
       
   119 {
       
   120     return contentList;
       
   121 }
       
   122 
       
   123 
       
   124 QList<IndexItem*> DocuParser::getIndexItems()
       
   125 {
       
   126     return indexList;
       
   127 }
       
   128 
       
   129 QString DocuParser::absolutify(const QString &name, bool makeUrl) const
       
   130 {
       
   131     if (!name.isEmpty()) {
       
   132         QString s = name;
       
   133         s.replace(QLatin1String("\\"), QLatin1String("/"));
       
   134         QFileInfo orgPath(name);
       
   135         if(orgPath.isRelative())
       
   136             s = QFileInfo(fname).path() + QLatin1Char('/') + name;
       
   137         if (makeUrl)
       
   138             s.prepend(QLatin1String("file:"));
       
   139         return s;
       
   140     }
       
   141     return name;
       
   142 }
       
   143 
       
   144 
       
   145 void DocuParser310::addTo(Profile *p)
       
   146 {
       
   147     p->addDCFTitle(fname, docTitle);
       
   148     p->addDCFIcon(docTitle, iconName);
       
   149     p->addDCFIndexPage(docTitle, conURL);
       
   150 }
       
   151 
       
   152 
       
   153 bool DocuParser310::startDocument()
       
   154 {
       
   155     state = StateInit;
       
   156     errorProt = QLatin1String("");
       
   157 
       
   158     contentRef = QLatin1String("");
       
   159     indexRef = QLatin1String("");
       
   160     depth = 0;
       
   161 
       
   162     contentList.clear();
       
   163     qDeleteAll(indexList);
       
   164     indexList.clear();
       
   165 
       
   166     return true;
       
   167 }
       
   168 
       
   169 
       
   170 bool DocuParser310::startElement(const QString &, const QString &,
       
   171                                const QString &qname,
       
   172                                const QXmlAttributes &attr)
       
   173 {
       
   174     if (qname == QLatin1String("DCF") && state == StateInit) {
       
   175         state = StateContent;
       
   176         contentRef = absolutify(attr.value(QLatin1String("ref")), false);
       
   177         conURL = contentRef;
       
   178         docTitle = attr.value(QLatin1String("title"));
       
   179         iconName = absolutify(attr.value(QLatin1String("icon")), false);
       
   180         contentList.append(ContentItem(docTitle, absolutify(contentRef), depth));
       
   181     } else if (qname == QLatin1String("section") && (state == StateContent || state == StateSect)) {
       
   182         state = StateSect;
       
   183         contentRef = absolutify(attr.value(QLatin1String("ref")));
       
   184         title = attr.value(QLatin1String("title"));
       
   185         depth++;
       
   186         contentList.append(ContentItem(title, contentRef, depth));
       
   187     } else if (qname == QLatin1String("keyword") && state == StateSect) {
       
   188         state = StateKeyword;
       
   189         indexRef = absolutify(attr.value(QLatin1String("ref")));
       
   190     } else
       
   191         return false;
       
   192     return true;
       
   193 }
       
   194 
       
   195 bool DocuParser310::endElement(const QString &nameSpace, const QString &localName,
       
   196                              const QString &qName)
       
   197 {
       
   198     Q_UNUSED(nameSpace);
       
   199     Q_UNUSED(localName);
       
   200     Q_UNUSED(qName);
       
   201 
       
   202     switch(state) {
       
   203     case StateInit:
       
   204         break;
       
   205     case StateContent:
       
   206         state = StateInit;
       
   207         break;
       
   208     case StateSect:
       
   209         state = --depth ? StateSect : StateContent;
       
   210         break;
       
   211     case StateKeyword:
       
   212         state = StateSect;
       
   213         break;
       
   214     default:
       
   215         break;
       
   216     }
       
   217     return true;
       
   218 }
       
   219 
       
   220 
       
   221 bool DocuParser310::characters(const QString& ch)
       
   222 {
       
   223     QString str = ch.simplified();
       
   224     if (str.isEmpty())
       
   225         return true;
       
   226 
       
   227     switch (state) {
       
   228         case StateInit:
       
   229         case StateContent:
       
   230         case StateSect:
       
   231             return false;
       
   232             break;
       
   233         case StateKeyword:
       
   234             indexList.append(new IndexItem(str, indexRef));
       
   235             break;
       
   236         default:
       
   237             return false;
       
   238     }
       
   239     return true;
       
   240 }
       
   241 
       
   242 
       
   243 bool DocuParser310::fatalError(const QXmlParseException& exception)
       
   244 {
       
   245     errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n")
       
   246         .arg(exception.message())
       
   247         .arg(exception.lineNumber())
       
   248         .arg(exception.columnNumber());
       
   249 
       
   250     return QXmlDefaultHandler::fatalError(exception);
       
   251 }
       
   252 
       
   253 
       
   254 DocuParser320::DocuParser320()
       
   255     : prof(new Profile)
       
   256 {
       
   257 }
       
   258 
       
   259 
       
   260 void DocuParser320::addTo(Profile *p)
       
   261 {
       
   262     QMap<QString,QString>::ConstIterator it;
       
   263 
       
   264     for (it = prof->dcfTitles.constBegin(); it != prof->dcfTitles.constEnd(); ++it)
       
   265         p->dcfTitles[it.key()] = *it;
       
   266 
       
   267     for (it = prof->icons.constBegin(); it != prof->icons.constEnd(); ++it)
       
   268         p->icons[it.key()] = *it;
       
   269 
       
   270     for (it = prof->indexPages.constBegin(); it != prof->indexPages.constEnd(); ++it)
       
   271         p->indexPages[it.key()] = *it;
       
   272 }
       
   273 
       
   274 
       
   275 bool DocuParser320::startDocument()
       
   276 {
       
   277     state = StateInit;
       
   278     errorProt = QLatin1String("");
       
   279 
       
   280     contentRef = QLatin1String("");
       
   281     indexRef = QLatin1String("");
       
   282     depth = 0;
       
   283     contentList.clear();
       
   284     indexList.clear();
       
   285 
       
   286     prof->addDCF(fname);
       
   287 
       
   288     return true;
       
   289 }
       
   290 
       
   291 bool DocuParser320::startElement(const QString &, const QString &,
       
   292                                const QString &qname,
       
   293                                const QXmlAttributes &attr)
       
   294 {
       
   295     QString lower = qname.toLower();
       
   296 
       
   297     switch(state) {
       
   298 
       
   299     case StateInit:
       
   300         if(lower == QLatin1String("assistantconfig"))
       
   301             state = StateDocRoot;
       
   302         break;
       
   303 
       
   304     case StateDocRoot:
       
   305         if(lower == QLatin1String("dcf")) {
       
   306             state = StateContent;
       
   307             contentRef = absolutify(attr.value(QLatin1String("ref")));
       
   308             conURL = contentRef;
       
   309             docTitle = attr.value(QLatin1String("title"));
       
   310             iconName = absolutify(attr.value(QLatin1String("icon")));
       
   311             contentList.append(ContentItem(docTitle, contentRef, depth));
       
   312         } else if(lower == QLatin1String("profile")) {
       
   313             state = StateProfile;
       
   314         }
       
   315         break;
       
   316 
       
   317     case StateSect:
       
   318         if (lower == QLatin1String("keyword") && state == StateSect) {
       
   319             state = StateKeyword;
       
   320             indexRef = absolutify(attr.value(QLatin1String("ref")));
       
   321             break;
       
   322         } // else if (lower == "section")
       
   323     case StateContent:
       
   324         if(lower == QLatin1String("section")) {
       
   325             state = StateSect;
       
   326             contentRef = absolutify(attr.value(QLatin1String("ref")));
       
   327             title = attr.value(QLatin1String("title"));
       
   328             depth++;
       
   329             contentList.append(ContentItem(title, contentRef, depth));
       
   330         }
       
   331         break;
       
   332 
       
   333     case StateProfile:
       
   334         if(lower == QLatin1String("property")) {
       
   335             state = StateProperty;
       
   336             propertyName = attr.value(QLatin1String("name"));
       
   337         }
       
   338         break;
       
   339 
       
   340     case StateProperty:
       
   341         break;
       
   342 
       
   343     default:
       
   344         break;
       
   345     }
       
   346 
       
   347     return true;
       
   348 }
       
   349 
       
   350 bool DocuParser320::endElement(const QString &nameSpace,
       
   351                                 const QString &localName,
       
   352                                 const QString &qName)
       
   353 {
       
   354     Q_UNUSED(nameSpace);
       
   355     Q_UNUSED(localName);
       
   356     Q_UNUSED(qName);
       
   357 
       
   358     switch(state) {
       
   359     case StateInit:
       
   360         break;
       
   361     case StateDocRoot:
       
   362         state = StateInit;
       
   363         break;
       
   364     case StateProfile:
       
   365         state = StateDocRoot;
       
   366         break;
       
   367     case StateProperty:
       
   368         state = StateProfile;
       
   369         if(propertyName.isEmpty() || propertyValue.isEmpty())
       
   370             return false;
       
   371         {
       
   372             static const QStringList lst = QStringList()
       
   373                 << QLatin1String("startpage") << QLatin1String("abouturl")
       
   374                 << QLatin1String("applicationicon") << QLatin1String("assistantdocs");
       
   375 
       
   376             if (lst.contains(propertyName))
       
   377                 propertyValue = absolutify(propertyValue);
       
   378         }
       
   379         prof->addProperty(propertyName, propertyValue);
       
   380         break;
       
   381     case StateContent:
       
   382         if(!iconName.isEmpty())
       
   383             prof->addDCFIcon(docTitle, iconName);
       
   384         if(contentRef.isEmpty())
       
   385             return false;
       
   386         prof->addDCFIndexPage(docTitle, conURL);
       
   387         prof->addDCFTitle(fname, docTitle);
       
   388         state = StateDocRoot;
       
   389         break;
       
   390     case StateSect:
       
   391         state = --depth ? StateSect : StateContent;
       
   392         break;
       
   393     case StateKeyword:
       
   394         state = StateSect;
       
   395         break;
       
   396     }
       
   397     return true;
       
   398 }
       
   399 
       
   400 bool DocuParser320::characters(const QString& ch)
       
   401 {
       
   402     QString str = ch.simplified();
       
   403     if (str.isEmpty())
       
   404         return true;
       
   405 
       
   406     switch (state) {
       
   407     case StateInit:
       
   408     case StateContent:
       
   409     case StateSect:
       
   410         return false;
       
   411         break;
       
   412     case StateKeyword:
       
   413         indexList.append(new IndexItem(str, indexRef));
       
   414         break;
       
   415     case StateProperty:
       
   416         propertyValue = ch;
       
   417         break;
       
   418     default:
       
   419         return false;
       
   420     }
       
   421     return true;
       
   422 }
       
   423 
       
   424 bool DocuParser320::fatalError(const QXmlParseException& exception)
       
   425 {
       
   426     errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n")
       
   427         .arg(exception.message())
       
   428         .arg(exception.lineNumber())
       
   429         .arg(exception.columnNumber());
       
   430     return QXmlDefaultHandler::fatalError(exception);
       
   431 }
       
   432 
       
   433 QT_END_NAMESPACE