delay a few things on startup, such as setting the visibility mode, which ensures...
[personal-kdebase.git] / runtime / khelpcenter / toc.cpp
blob1136383e2d2822348c898e7fca45ebefde4ebb35
1 /*
2 * This file is part of the KDE Help Center
4 * Copyright (C) 2002 Frerich Raabe (raabe@kde.org)
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.
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.
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.
21 #include "toc.h"
23 #include "docentry.h"
25 #include <kiconloader.h>
26 #include <kprocess.h>
27 #include <kstandarddirs.h>
28 #include <kdebug.h>
29 #include <kxmlguiwindow.h>
30 #include <KApplication>
31 #include <KStatusBar>
32 #include <klocale.h>
34 #include <QDir>
35 #include <QFileInfo>
36 //Added by qt3to4:
37 #include <QTextStream>
38 #include <QPixmap>
39 #include <sys/stat.h>
41 using namespace KHC;
43 class TOCItem : public NavigatorItem
45 public:
46 TOCItem( TOC *parent, Q3ListViewItem *parentItem, Q3ListViewItem *after, const QString &text );
48 const TOC *toc() const { return m_toc; }
50 private:
51 TOC *m_toc;
54 class TOCChapterItem : public TOCItem
56 public:
57 TOCChapterItem( TOC *toc, NavigatorItem *parent, Q3ListViewItem *after, const QString &title,
58 const QString &name );
60 virtual QString url();
62 private:
63 QString m_name;
66 class TOCSectionItem : public TOCItem
68 public:
69 TOCSectionItem( TOC *toc, TOCChapterItem *parent, Q3ListViewItem *after, const QString &title,
70 const QString &name );
72 virtual QString url();
74 private:
75 QString m_name;
78 bool TOC::m_alreadyWarned = false;
80 TOC::TOC( NavigatorItem *parentItem )
82 m_parentItem = parentItem;
85 void TOC::build( const QString &file )
87 QFileInfo fileInfo( file );
88 QString fileName = fileInfo.absoluteFilePath();
89 const QStringList resourceDirs = KGlobal::dirs()->resourceDirs( "html" );
90 QStringList::ConstIterator it = resourceDirs.begin();
91 QStringList::ConstIterator end = resourceDirs.end();
92 for ( ; it != end; ++it ) {
93 if ( fileName.startsWith( *it ) ) {
94 fileName.remove( 0, ( *it ).length() );
95 break;
99 QString cacheFile = fileName.replace( '/', "__" );
100 #ifdef Q_WS_WIN
101 cacheFile = cacheFile.replace( ':', "_" );
102 #endif
103 m_cacheFile = KStandardDirs::locateLocal( "cache", "help/" + cacheFile );
104 m_sourceFile = file;
106 if ( cacheStatus() == NeedRebuild )
107 buildCache();
108 else
109 fillTree();
112 TOC::CacheStatus TOC::cacheStatus() const
114 if ( !QFile::exists( m_cacheFile ) ||
115 sourceFileCTime() != cachedCTime() )
116 return NeedRebuild;
118 return CacheOk;
121 int TOC::sourceFileCTime() const
123 struct stat stat_buf;
124 stat( QFile::encodeName( m_sourceFile ).data(), &stat_buf );
126 return stat_buf.st_ctime;
129 int TOC::cachedCTime() const
131 QFile f( m_cacheFile );
132 if ( !f.open( QIODevice::ReadOnly ) )
133 return 0;
135 QDomDocument doc;
136 if ( !doc.setContent( &f ) )
137 return 0;
139 QDomComment timestamp = doc.documentElement().lastChild().toComment();
141 return timestamp.data().trimmed().toInt();
144 void TOC::buildCache()
146 KXmlGuiWindow *mainWindow = dynamic_cast<KXmlGuiWindow *>( kapp->activeWindow() );
148 KProcess *meinproc = new KProcess;
149 connect( meinproc, SIGNAL( finished( int, QProcess::ExitStatus) ),
150 this, SLOT( meinprocExited( int, QProcess::ExitStatus) ) );
152 *meinproc << KStandardDirs::locate("exe", "meinproc4");
153 *meinproc << "--stylesheet" << KStandardDirs::locate( "data", "khelpcenter/table-of-contents.xslt" );
154 *meinproc << "--output" << m_cacheFile;
155 *meinproc << m_sourceFile;
157 meinproc->setOutputChannelMode(KProcess::OnlyStderrChannel);
158 meinproc->start();
159 if (!meinproc->waitForStarted()) {
160 kError() << "could not start process" << meinproc->program();
161 if (mainWindow && !m_alreadyWarned) {
162 ; // add warning message box with don't display again option
163 // http://api.kde.org/4.0-api/kdelibs-apidocs/kdeui/html/classKDialog.html
164 m_alreadyWarned = true;
166 delete meinproc;
170 void TOC::meinprocExited( int exitCode, QProcess::ExitStatus exitStatus)
172 KProcess *meinproc = static_cast<KProcess *>(sender());
173 KXmlGuiWindow *mainWindow = dynamic_cast<KXmlGuiWindow *>( kapp->activeWindow() );
175 if ( exitStatus == QProcess::CrashExit || exitCode != 0 ) {
176 kError() << "running" << meinproc->program() << "failed with exitCode" << exitCode;
177 kError() << "stderr output:" << meinproc->readAllStandardError();
178 if (mainWindow && !m_alreadyWarned) {
179 ; // add warning message box with don't display again option
180 // http://api.kde.org/4.0-api/kdelibs-apidocs/kdeui/html/classKDialog.html
181 m_alreadyWarned = true;
183 delete meinproc;
184 return;
187 delete meinproc;
189 QFile f( m_cacheFile );
190 if ( !f.open( QIODevice::ReadWrite ) )
191 return;
193 QDomDocument doc;
194 if ( !doc.setContent( &f ) )
195 return;
197 QDomComment timestamp = doc.createComment( QString::number( sourceFileCTime() ) );
198 doc.documentElement().appendChild( timestamp );
200 f.seek( 0 );
201 QTextStream stream( &f );
202 stream.setCodec( "UTF-8" );
203 stream << doc.toString();
205 f.close();
206 #ifdef Q_WS_WIN
207 kDebug() << "on german systems umlauts are displayed as '?' for unknown (Qt'r related ?) reasons. Please fix.";
208 #endif
210 fillTree();
213 void TOC::fillTree()
215 QFile f( m_cacheFile );
216 if ( !f.open( QIODevice::ReadOnly ) )
217 return;
219 QDomDocument doc;
220 if ( !doc.setContent( &f ) )
221 return;
223 TOCChapterItem *chapItem = 0;
224 QDomNodeList chapters = doc.documentElement().elementsByTagName( "chapter" );
225 for ( int chapterCount = 0; chapterCount < chapters.count(); chapterCount++ ) {
226 QDomElement chapElem = chapters.item( chapterCount ).toElement();
227 QDomElement chapTitleElem = childElement( chapElem, QLatin1String( "title" ) );
228 QString chapTitle = chapTitleElem.text().simplified();
229 QDomElement chapRefElem = childElement( chapElem, QLatin1String( "anchor" ) );
230 QString chapRef = chapRefElem.text().trimmed();
232 chapItem = new TOCChapterItem( this, m_parentItem, chapItem, chapTitle, chapRef );
234 TOCSectionItem *sectItem = 0;
235 QDomNodeList sections = chapElem.elementsByTagName( "section" );
236 for ( int sectCount = 0; sectCount < sections.count(); sectCount++ ) {
237 QDomElement sectElem = sections.item( sectCount ).toElement();
238 QDomElement sectTitleElem = childElement( sectElem, QLatin1String( "title" ) );
239 QString sectTitle = sectTitleElem.text().simplified();
240 QDomElement sectRefElem = childElement( sectElem, QLatin1String( "anchor" ) );
241 QString sectRef = sectRefElem.text().trimmed();
243 sectItem = new TOCSectionItem( this, chapItem, sectItem, sectTitle, sectRef );
247 m_parentItem->setOpen( true );
250 QDomElement TOC::childElement( const QDomElement &element, const QString &name )
252 QDomElement e;
253 for ( e = element.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement() )
254 if ( e.tagName() == name )
255 break;
256 return e;
259 void TOC::slotItemSelected( Q3ListViewItem *item )
261 TOCItem *tocItem;
262 if ( ( tocItem = dynamic_cast<TOCItem *>( item ) ) )
263 emit itemSelected( tocItem->entry()->url() );
265 item->setOpen( !item->isOpen() );
268 TOCItem::TOCItem( TOC *toc, Q3ListViewItem *parentItem, Q3ListViewItem *after, const QString &text )
269 : NavigatorItem( new DocEntry( text ), parentItem, after )
271 setAutoDeleteDocEntry( true );
272 m_toc = toc;
275 TOCChapterItem::TOCChapterItem( TOC *toc, NavigatorItem *parent, Q3ListViewItem *after,
276 const QString &title, const QString &name )
277 : TOCItem( toc, parent, after, title ),
278 m_name( name )
280 setOpen( false );
281 entry()->setUrl(url());
284 QString TOCChapterItem::url()
286 return QLatin1String("help:") + toc()->application() + QLatin1Char('/') + m_name
287 + QLatin1String(".html");
290 TOCSectionItem::TOCSectionItem( TOC *toc, TOCChapterItem *parent, Q3ListViewItem *after,
291 const QString &title, const QString &name )
292 : TOCItem( toc, parent, after, title ),
293 m_name( name )
295 setPixmap( 0, SmallIcon( "text-plain" ) );
296 entry()->setUrl(url());
299 QString TOCSectionItem::url()
301 if ( static_cast<TOCSectionItem *>( parent()->firstChild() ) == this )
302 return static_cast<TOCChapterItem *>( parent() )->url() + '#' + m_name;
304 return "help:" + toc()->application() + '/' + m_name + ".html";
307 #include "toc.moc"
308 // vim:ts=2:sw=2:et