1/*
2 * This file is part of the KDE Help Center
3 *
4 * Copyright (C) 1999 Matthias Elter (me@kde.org)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include "scrollkeepertreebuilder.h"
22
23#include "navigatoritem.h"
24#include "docentry.h"
25
26#include <KApplication>
27#include <KConfig>
28#include <KDebug>
29#include <KGlobal>
30#include <KLocale>
31#include <KProcess>
32#include <KConfigGroup>
33
34#include <QtXml/QtXml>
35#include <QFile>
36#include <QRegExp>
37
38using namespace KHC;
39
40ScrollKeeperTreeBuilder::ScrollKeeperTreeBuilder( QObject *parent, const char *name )
41 : QObject( parent )
42{
43 setObjectName( name );
44
45 loadConfig();
46}
47
48void ScrollKeeperTreeBuilder::loadConfig()
49{
50 KConfigGroup configGroup( KGlobal::config(), "ScrollKeeper" );
51 mShowEmptyDirs = configGroup.readEntry( "ShowEmptyDirs", false);
52}
53
54NavigatorItem *ScrollKeeperTreeBuilder::build( NavigatorItem *parent,
55 NavigatorItem *after )
56{
57 QString lang = KGlobal::locale()->language();
58
59 kDebug(1400) << "ScrollKeeper language: " << lang;
60
61 KProcess proc;
62 proc << "scrollkeeper-get-content-list";
63 proc << lang;
64
65 proc.setOutputChannelMode(KProcess::OnlyStdoutChannel);
66 proc.start();
67 if ( !proc.waitForFinished() ) {
68 kDebug(1400) << "Could not execute scrollkeeper-get-content-list";
69 return 0;
70 }
71 mContentsList = proc.readAllStandardOutput().trimmed();
72
73 if (!QFile::exists(mContentsList)) {
74 kDebug(1400) << "Scrollkeeper contents file '" << mContentsList
75 << "' does not exist." << endl;
76 return 0;
77 }
78
79 QDomDocument doc("ScrollKeeperContentsList");
80 QFile f(mContentsList);
81 if ( !f.open( QIODevice::ReadOnly ) )
82 return 0;
83 if ( !doc.setContent( &f ) ) {
84 f.close();
85 return 0;
86 }
87 f.close();
88
89 // Create top-level item
90 mItems.append(parent);
91
92 QDomElement docElem = doc.documentElement();
93
94 NavigatorItem *result = 0;
95
96 QDomNode n = docElem.firstChild();
97 while( !n.isNull() ) {
98 QDomElement e = n.toElement();
99 if( !e.isNull() ) {
100 if (e.tagName() == "sect") {
101 NavigatorItem *createdItem;
102 insertSection( parent, after, e, createdItem );
103 if ( createdItem ) result = createdItem;
104 }
105 }
106 n = n.nextSibling();
107 }
108
109 return result;
110}
111
112int ScrollKeeperTreeBuilder::insertSection( NavigatorItem *parent,
113 NavigatorItem *after,
114 const QDomNode &sectNode,
115 NavigatorItem *&sectItem )
116{
117// TODO: was contents2 -> needs to be changed to help-contents-alternate or similar
118 DocEntry *entry = new DocEntry( "", "", "help-contents" );
119 sectItem = new NavigatorItem( entry, parent, after );
120 sectItem->setAutoDeleteDocEntry( true );
121 mItems.append( sectItem );
122
123 int numDocs = 0; // Number of docs created in this section
124
125 QDomNode n = sectNode.firstChild();
126 while( !n.isNull() ) {
127 QDomElement e = n.toElement();
128 if( !e.isNull() ) {
129 if ( e.tagName() == "title" ) {
130 entry->setName( e.text() );
131 sectItem->updateItem();
132 } else if (e.tagName() == "sect") {
133 NavigatorItem *created;
134 numDocs += insertSection( sectItem, 0, e, created );
135 } else if (e.tagName() == "doc") {
136 insertDoc(sectItem,e);
137 ++numDocs;
138 }
139 }
140 n = n.nextSibling();
141 }
142
143 // Remove empty sections
144 if (!mShowEmptyDirs && numDocs == 0) {
145 delete sectItem;
146 sectItem = 0;
147 }
148
149 return numDocs;
150}
151
152void ScrollKeeperTreeBuilder::insertDoc( NavigatorItem *parent,
153 const QDomNode &docNode )
154{
155 DocEntry *entry = new DocEntry( "", "", "text-plain" );
156 NavigatorItem *docItem = new NavigatorItem( entry, parent );
157 docItem->setAutoDeleteDocEntry( true );
158 mItems.append( docItem );
159
160 QString url;
161
162 QDomNode n = docNode.firstChild();
163 while( !n.isNull() ) {
164 QDomElement e = n.toElement();
165 if( !e.isNull() ) {
166 if ( e.tagName() == "doctitle" ) {
167 entry->setName( e.text() );
168 docItem->updateItem();
169 } else if ( e.tagName() == "docsource" ) {
170 url.append( e.text() );
171 } else if ( e.tagName() == "docformat" ) {
172 QString mimeType = e.text();
173 if ( mimeType == "text/html") {
174 // Let the HTML part figure out how to get the doc
175 } else if ( mimeType == "application/xml"
176 || mimeType == "text/xml" /*deprecated name*/ ) {
177 if ( url.left( 5 ) == "file:" ) url = url.mid( 5 );
178 url.prepend( "ghelp:" );
179#if 0
180 url.replace( QRegExp( ".xml$" ), ".html" );
181#endif
182 } else if ( mimeType == "text/sgml" ) {
183 // GNOME docs use this type. We don't have a real viewer for this.
184 url.prepend( "file:" );
185 } else if ( mimeType.left(5) == "text/" ) {
186 url.prepend( "file:" );
187 }
188 }
189 }
190 n = n.nextSibling();
191 }
192
193 entry->setUrl( url );
194}
195
196#include "scrollkeepertreebuilder.moc"
197// vim:sw=2:ts=2:et
198