source: trunk/tools/assistant/docuparser.cpp@ 203

Last change on this file since 203 was 191, checked in by rudi, 14 years ago

Qt Assistant added

File size: 9.5 KB
Line 
1/**********************************************************************
2** Copyright (C) 2000-2007 Trolltech ASA. All rights reserved.
3**
4** This file is part of the Qt Assistant.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "docuparser.h"
28#include "profile.h"
29
30#include <qdir.h>
31#include <qfile.h>
32#include <qfileinfo.h>
33#include <qregexp.h>
34#include <qstring.h>
35#include <qxml.h>
36
37QDataStream &operator>>( QDataStream &s, ContentItem &ci )
38{
39 s >> ci.title;
40 s >> ci.reference;
41 s >> ci.depth;
42 return s;
43}
44
45QDataStream &operator<<( QDataStream &s, const ContentItem &ci )
46{
47 s << ci.title;
48 s << ci.reference;
49 s << ci.depth;
50 return s;
51}
52
53const QString DocuParser::DocumentKey = "/Qt Assistant/" + QString(QT_VERSION_STR) + "/";
54
55DocuParser *DocuParser::createParser( const QString &fileName )
56{
57 QFile file( fileName );
58 if( !file.open( IO_ReadOnly ) ) {
59 return 0;
60 }
61
62 QString str;
63 int read = 0;
64 int maxlen = 1024;
65 int majVer = 0, minVer = 0, serVer = 0;
66 static QRegExp re( "assistantconfig +version=\"(\\d)\\.(\\d)\\.(\\d)\"", FALSE );
67 Q_ASSERT( re.isValid() );
68 while( read != -1 ) {
69 read = file.readLine( str, maxlen );
70 if( re.search( str ) >= 0 ) {
71 majVer = re.cap( 1 ).toInt();
72 minVer = re.cap( 2 ).toInt();
73 serVer = re.cap( 3 ).toInt();
74 }
75 }
76
77 if( majVer == 3 && minVer >= 2 )
78 return new DocuParser320;
79
80 return new DocuParser310;
81}
82
83
84bool DocuParser::parse( QFile *file )
85{
86 QXmlInputSource source( file );
87 QXmlSimpleReader reader;
88 reader.setContentHandler( this );
89 reader.setErrorHandler( this );
90 setFileName( QFileInfo( *file ).absFilePath() );
91 return reader.parse( source );
92}
93
94
95QString DocuParser::errorProtocol() const
96{
97 return errorProt;
98}
99
100
101QValueList<ContentItem> DocuParser::getContentItems()
102{
103 return contentList;
104}
105
106
107QPtrList<IndexItem> DocuParser::getIndexItems()
108{
109 return indexList;
110}
111
112QString DocuParser::absolutify( const QString &name ) const
113{
114 QFileInfo orgPath( name );
115 if( orgPath.isRelative() )
116 return QFileInfo( fname ).dirPath() + QDir::separator() + name;
117 return name;
118}
119
120
121void DocuParser310::addTo( Profile *p )
122{
123 p->addDCFTitle( fname, docTitle );
124 p->addDCFIcon( docTitle, iconName );
125 p->addDCFIndexPage( docTitle, conURL );
126}
127
128
129bool DocuParser310::startDocument()
130{
131 state = StateInit;
132 errorProt = "";
133
134 contentRef = "";
135 indexRef = "";
136 depth = 0;
137 contentList.clear();
138 indexList.clear();
139
140 return TRUE;
141}
142
143
144bool DocuParser310::startElement( const QString &, const QString &,
145 const QString &qname,
146 const QXmlAttributes &attr )
147{
148 if (qname == "DCF" && state == StateInit) {
149 state = StateContent;
150 contentRef = absolutify( attr.value( "ref" ) );
151 conURL = contentRef;
152 docTitle = attr.value( "title" );
153 iconName = absolutify( attr.value( "icon" ) );
154 contentList.append( ContentItem( docTitle, contentRef, depth ) );
155 } else if (qname == "section" && (state == StateContent || state == StateSect)) {
156 state = StateSect;
157 contentRef = absolutify( attr.value( "ref" ) );
158 title = attr.value( "title" );
159 depth++;
160 contentList.append( ContentItem( title, contentRef, depth ) );
161 } else if (qname == "keyword" && state == StateSect) {
162 state = StateKeyword;
163 indexRef = absolutify( attr.value( "ref" ) );
164 } else
165 return FALSE;
166 return TRUE;
167}
168
169bool DocuParser310::endElement( const QString &nameSpace, const QString &localName,
170 const QString &qName )
171{
172 switch( state ) {
173 case StateInit:
174 break;
175 case StateContent:
176 state = StateInit;
177 break;
178 case StateSect:
179 state = --depth ? StateSect : StateContent;
180 break;
181 case StateKeyword:
182 state = StateSect;
183 break;
184 }
185 return TRUE;
186}
187
188
189bool DocuParser310::characters( const QString& ch )
190{
191 QString str = ch.simplifyWhiteSpace();
192 if ( str.isEmpty() )
193 return TRUE;
194
195 switch ( state ) {
196 case StateInit:
197 case StateContent:
198 case StateSect:
199 return FALSE;
200 break;
201 case StateKeyword:
202 indexList.append( new IndexItem( str, indexRef ) );
203 break;
204 default:
205 return FALSE;
206 }
207 return TRUE;
208}
209
210
211bool DocuParser310::fatalError( const QXmlParseException& exception )
212{
213 errorProt += QString( "fatal parsing error: %1 in line %2, column %3\n" )
214 .arg( exception.message() )
215 .arg( exception.lineNumber() )
216 .arg( exception.columnNumber() );
217
218 return QXmlDefaultHandler::fatalError( exception );
219}
220
221
222DocuParser320::DocuParser320()
223 : prof( new Profile )
224{
225}
226
227
228void DocuParser320::addTo( Profile *p )
229{
230 QMap<QString,QString>::ConstIterator it;
231
232 for (it = prof->dcfTitles.begin(); it != prof->dcfTitles.end(); ++it)
233 p->dcfTitles[it.key()] = *it;
234
235 for (it = prof->icons.begin(); it != prof->icons.end(); ++it)
236 p->icons[it.key()] = *it;
237
238 for (it = prof->indexPages.begin(); it != prof->indexPages.end(); ++it)
239 p->indexPages[it.key()] = *it;
240}
241
242
243bool DocuParser320::startDocument()
244{
245 state = StateInit;
246 errorProt = "";
247
248 contentRef = "";
249 indexRef = "";
250 depth = 0;
251 contentList.clear();
252 indexList.clear();
253
254 prof->addDCF( fname );
255
256 return TRUE;
257}
258
259bool DocuParser320::startElement( const QString &, const QString &,
260 const QString &qname,
261 const QXmlAttributes &attr )
262{
263 QString lower = qname.lower();
264
265 switch( state ) {
266
267 case StateInit:
268 if( lower == "assistantconfig" )
269 state = StateDocRoot;
270 break;
271
272 case StateDocRoot:
273 if( lower == "dcf" ) {
274 state = StateContent;
275 contentRef = absolutify( attr.value( "ref" ) );
276 conURL = contentRef;
277 docTitle = attr.value( "title" );
278 iconName = absolutify( attr.value( "icon" ) );
279 contentList.append( ContentItem( docTitle, contentRef, depth ) );
280 } else if( lower == "profile" ) {
281 state = StateProfile;
282 }
283 break;
284
285 case StateSect:
286 if ( lower == "keyword" && state == StateSect ) {
287 state = StateKeyword;
288 indexRef = absolutify( attr.value( "ref" ) );
289 break;
290 } // else if (lower == "section")
291 case StateContent:
292 if( lower == "section" ) {
293 state = StateSect;
294 contentRef = absolutify( attr.value( "ref" ) );
295 title = attr.value( "title" );
296 depth++;
297 contentList.append( ContentItem( title, contentRef, depth ) );
298 }
299 break;
300
301 case StateProfile:
302 if( lower == "property" ) {
303 state = StateProperty;
304 propertyName = attr.value( "name" );
305 }
306 break;
307
308 case StateProperty:
309 break;
310 }
311
312 return TRUE;
313}
314
315bool DocuParser320::endElement( const QString &nameSpace,
316 const QString &localName,
317 const QString &qName )
318{
319 switch( state ) {
320 case StateInit:
321 break;
322 case StateDocRoot:
323 state = StateInit;
324 break;
325 case StateProfile:
326 state = StateDocRoot;
327 break;
328 case StateProperty:
329 state = StateProfile;
330 if( propertyName.isEmpty() || propertyValue.isEmpty() )
331 return FALSE;
332 {
333 static const QStringList lst = QStringList() << "startpage" << "abouturl"
334 << "applicationicon" << "assistantdocs";
335 if (lst.contains(propertyName))
336 propertyValue = absolutify( propertyValue );
337 }
338 prof->addProperty( propertyName, propertyValue );
339 break;
340 case StateContent:
341 if( !iconName.isEmpty() ) prof->addDCFIcon( docTitle, iconName );
342 if( contentRef.isEmpty() )
343 return FALSE;
344 prof->addDCFIndexPage( docTitle, conURL );
345 prof->addDCFTitle( fname, docTitle );
346 state = StateDocRoot;
347 break;
348 case StateSect:
349 state = --depth ? StateSect : StateContent;
350 break;
351 case StateKeyword:
352 state = StateSect;
353 break;
354 }
355 return TRUE;
356}
357
358bool DocuParser320::characters( const QString& ch )
359{
360 QString str = ch.simplifyWhiteSpace();
361 if ( str.isEmpty() )
362 return TRUE;
363
364 switch ( state ) {
365 case StateInit:
366 case StateContent:
367 case StateSect:
368 return FALSE;
369 break;
370 case StateKeyword:
371 indexList.append( new IndexItem( str, indexRef ) );
372 break;
373 case StateProperty:
374 propertyValue = ch;
375 break;
376 default:
377 return FALSE;
378 }
379 return TRUE;
380}
381
382bool DocuParser320::fatalError( const QXmlParseException& exception )
383{
384 errorProt += QString( "fatal parsing error: %1 in line %2, column %3\n" )
385 .arg( exception.message() )
386 .arg( exception.lineNumber() )
387 .arg( exception.columnNumber() );
388
389 return QXmlDefaultHandler::fatalError( exception );
390}
Note: See TracBrowser for help on using the repository browser.