diff options
Diffstat (limited to 'tools/assistant/docuparser.cpp')
-rw-r--r-- | tools/assistant/docuparser.cpp | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/tools/assistant/docuparser.cpp b/tools/assistant/docuparser.cpp new file mode 100644 index 000000000..30b6a1d8f --- /dev/null +++ b/tools/assistant/docuparser.cpp @@ -0,0 +1,397 @@ +/********************************************************************** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the TQt Assistant. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at [email protected]. +** +** Licensees holding valid TQt Commercial licenses may use this file in +** accordance with the TQt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "docuparser.h" +#include "profile.h" + +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qregexp.h> +#include <qstring.h> +#include <qxml.h> + +TQDataStream &operator>>( TQDataStream &s, ContentItem &ci ) +{ + s >> ci.title; + s >> ci.reference; + s >> ci.depth; + return s; +} + +TQDataStream &operator<<( TQDataStream &s, const ContentItem &ci ) +{ + s << ci.title; + s << ci.reference; + s << ci.depth; + return s; +} + +const TQString DocuParser::DocumentKey = "/TQt Assistant/" + TQString(QT_VERSION_STR) + "/"; + +DocuParser *DocuParser::createParser( const TQString &fileName ) +{ + TQFile file( fileName ); + if( !file.open( IO_ReadOnly ) ) { + return 0; + } + + TQString str; + int read = 0; + int maxlen = 1024; + int majVer = 0, minVer = 0, serVer = 0; + static TQRegExp re( "assistantconfig +version=\"(\\d)\\.(\\d)\\.(\\d)\"", FALSE ); + Q_ASSERT( re.isValid() ); + while( read != -1 ) { + read = file.readLine( str, maxlen ); + if( re.search( str ) >= 0 ) { + majVer = re.cap( 1 ).toInt(); + minVer = re.cap( 2 ).toInt(); + serVer = re.cap( 3 ).toInt(); + } + } + + if( majVer == 3 && minVer >= 2 ) + return new DocuParser320; + + return new DocuParser310; +} + + +bool DocuParser::parse( TQFile *file ) +{ + TQXmlInputSource source( file ); + TQXmlSimpleReader reader; + reader.setContentHandler( this ); + reader.setErrorHandler( this ); + setFileName( TQFileInfo( *file ).absFilePath() ); + return reader.parse( source ); +} + + +TQString DocuParser::errorProtocol() const +{ + return errorProt; +} + + +TQValueList<ContentItem> DocuParser::getContentItems() +{ + return contentList; +} + + +TQPtrList<IndexItem> DocuParser::getIndexItems() +{ + return indexList; +} + +TQString DocuParser::absolutify( const TQString &name ) const +{ + TQFileInfo orgPath( name ); + if( orgPath.isRelative() ) + return TQFileInfo( fname ).dirPath() + TQDir::separator() + name; + 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 = ""; + + contentRef = ""; + indexRef = ""; + depth = 0; + contentList.clear(); + indexList.clear(); + + return TRUE; +} + + +bool DocuParser310::startElement( const TQString &, const TQString &, + const TQString &qname, + const TQXmlAttributes &attr ) +{ + if (qname == "DCF" && state == StateInit) { + state = StateContent; + contentRef = absolutify( attr.value( "ref" ) ); + conURL = contentRef; + docTitle = attr.value( "title" ); + iconName = absolutify( attr.value( "icon" ) ); + contentList.append( ContentItem( docTitle, contentRef, depth ) ); + } else if (qname == "section" && (state == StateContent || state == StateSect)) { + state = StateSect; + contentRef = absolutify( attr.value( "ref" ) ); + title = attr.value( "title" ); + depth++; + contentList.append( ContentItem( title, contentRef, depth ) ); + } else if (qname == "keyword" && state == StateSect) { + state = StateKeyword; + indexRef = absolutify( attr.value( "ref" ) ); + } else + return FALSE; + return TRUE; +} + +bool DocuParser310::endElement( const TQString &nameSpace, const TQString &localName, + const TQString &qName ) +{ + switch( state ) { + case StateInit: + break; + case StateContent: + state = StateInit; + break; + case StateSect: + state = --depth ? StateSect : StateContent; + break; + case StateKeyword: + state = StateSect; + break; + } + return TRUE; +} + + +bool DocuParser310::characters( const TQString& ch ) +{ + TQString str = ch.simplifyWhiteSpace(); + 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 TQXmlParseException& exception ) +{ + errorProt += TQString( "fatal parsing error: %1 in line %2, column %3\n" ) + .arg( exception.message() ) + .arg( exception.lineNumber() ) + .arg( exception.columnNumber() ); + + return TQXmlDefaultHandler::fatalError( exception ); +} + + +DocuParser320::DocuParser320() + : prof( new Profile ) +{ +} + + +void DocuParser320::addTo( Profile *p ) +{ + TQMap<TQString,TQString>::ConstIterator it; + + for (it = prof->dcfTitles.begin(); it != prof->dcfTitles.end(); ++it) + p->dcfTitles[it.key()] = *it; + + for (it = prof->icons.begin(); it != prof->icons.end(); ++it) + p->icons[it.key()] = *it; + + for (it = prof->indexPages.begin(); it != prof->indexPages.end(); ++it) + p->indexPages[it.key()] = *it; +} + + +bool DocuParser320::startDocument() +{ + state = StateInit; + errorProt = ""; + + contentRef = ""; + indexRef = ""; + depth = 0; + contentList.clear(); + indexList.clear(); + + prof->addDCF( fname ); + + return TRUE; +} + +bool DocuParser320::startElement( const TQString &, const TQString &, + const TQString &qname, + const TQXmlAttributes &attr ) +{ + TQString lower = qname.lower(); + + switch( state ) { + + case StateInit: + if( lower == "assistantconfig" ) + state = StateDocRoot; + break; + + case StateDocRoot: + if( lower == "dcf" ) { + state = StateContent; + contentRef = absolutify( attr.value( "ref" ) ); + conURL = contentRef; + docTitle = attr.value( "title" ); + iconName = absolutify( attr.value( "icon" ) ); + contentList.append( ContentItem( docTitle, contentRef, depth ) ); + } else if( lower == "profile" ) { + state = StateProfile; + } + break; + + case StateSect: + if ( lower == "keyword" && state == StateSect ) { + state = StateKeyword; + indexRef = absolutify( attr.value( "ref" ) ); + break; + } // else if (lower == "section") + case StateContent: + if( lower == "section" ) { + state = StateSect; + contentRef = absolutify( attr.value( "ref" ) ); + title = attr.value( "title" ); + depth++; + contentList.append( ContentItem( title, contentRef, depth ) ); + } + break; + + case StateProfile: + if( lower == "property" ) { + state = StateProperty; + propertyName = attr.value( "name" ); + } + break; + + case StateProperty: + break; + } + + return TRUE; +} + +bool DocuParser320::endElement( const TQString &nameSpace, + const TQString &localName, + const TQString &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 TQStringList lst = TQStringList() << "startpage" << "abouturl" + << "applicationicon" << "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 TQString& ch ) +{ + TQString str = ch.simplifyWhiteSpace(); + 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 TQXmlParseException& exception ) +{ + errorProt += TQString( "fatal parsing error: %1 in line %2, column %3\n" ) + .arg( exception.message() ) + .arg( exception.lineNumber() ) + .arg( exception.columnNumber() ); + + return TQXmlDefaultHandler::fatalError( exception ); +} |