summaryrefslogtreecommitdiffstats
path: root/khelpcenter/toc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khelpcenter/toc.cpp')
-rw-r--r--khelpcenter/toc.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/khelpcenter/toc.cpp b/khelpcenter/toc.cpp
new file mode 100644
index 000000000..6b2beadc9
--- /dev/null
+++ b/khelpcenter/toc.cpp
@@ -0,0 +1,271 @@
+/*
+ * This file is part of the KDE Help Center
+ *
+ * Copyright (C) 2002 Frerich Raabe (raabe@kde.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "toc.h"
+
+#include "docentry.h"
+
+#include <kiconloader.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+#include <qdir.h>
+#include <qfileinfo.h>
+
+#include <sys/stat.h>
+
+using namespace KHC;
+
+class TOCItem : public NavigatorItem
+{
+ public:
+ TOCItem( TOC *parent, QListViewItem *parentItem, QListViewItem *after, const QString &text );
+
+ const TOC *toc() const { return m_toc; }
+
+ private:
+ TOC *m_toc;
+};
+
+class TOCChapterItem : public TOCItem
+{
+ public:
+ TOCChapterItem( TOC *toc, NavigatorItem *parent, QListViewItem *after, const QString &title,
+ const QString &name );
+
+ virtual QString url();
+
+ private:
+ QString m_name;
+};
+
+class TOCSectionItem : public TOCItem
+{
+ public:
+ TOCSectionItem( TOC *toc, TOCChapterItem *parent, QListViewItem *after, const QString &title,
+ const QString &name );
+
+ virtual QString url();
+
+ private:
+ QString m_name;
+};
+
+TOC::TOC( NavigatorItem *parentItem )
+{
+ m_parentItem = parentItem;
+}
+
+void TOC::build( const QString &file )
+{
+ QFileInfo fileInfo( file );
+ QString fileName = fileInfo.absFilePath();
+ const QStringList resourceDirs = KGlobal::dirs()->resourceDirs( "html" );
+ QStringList::ConstIterator it = resourceDirs.begin();
+ QStringList::ConstIterator end = resourceDirs.end();
+ for ( ; it != end; ++it ) {
+ if ( fileName.startsWith( *it ) ) {
+ fileName.remove( 0, ( *it ).length() );
+ break;
+ }
+ }
+
+ QString cacheFile = fileName.replace( QDir::separator(), "__" );
+ m_cacheFile = locateLocal( "cache", "help/" + cacheFile );
+ m_sourceFile = file;
+
+ if ( cacheStatus() == NeedRebuild )
+ buildCache();
+ else
+ fillTree();
+}
+
+TOC::CacheStatus TOC::cacheStatus() const
+{
+ if ( !QFile::exists( m_cacheFile ) ||
+ sourceFileCTime() != cachedCTime() )
+ return NeedRebuild;
+
+ return CacheOk;
+}
+
+int TOC::sourceFileCTime() const
+{
+ struct stat stat_buf;
+ stat( QFile::encodeName( m_sourceFile ).data(), &stat_buf );
+
+ return stat_buf.st_ctime;
+}
+
+int TOC::cachedCTime() const
+{
+ QFile f( m_cacheFile );
+ if ( !f.open( IO_ReadOnly ) )
+ return 0;
+
+ QDomDocument doc;
+ if ( !doc.setContent( &f ) )
+ return 0;
+
+ QDomComment timestamp = doc.documentElement().lastChild().toComment();
+
+ return timestamp.data().stripWhiteSpace().toInt();
+}
+
+void TOC::buildCache()
+{
+ KProcess *meinproc = new KProcess;
+ connect( meinproc, SIGNAL( processExited( KProcess * ) ),
+ this, SLOT( meinprocExited( KProcess * ) ) );
+
+ *meinproc << locate( "exe", "meinproc" );
+ *meinproc << "--stylesheet" << locate( "data", "khelpcenter/table-of-contents.xslt" );
+ *meinproc << "--output" << m_cacheFile;
+ *meinproc << m_sourceFile;
+
+ meinproc->start( KProcess::NotifyOnExit );
+}
+
+void TOC::meinprocExited( KProcess *meinproc )
+{
+ if ( !meinproc->normalExit() || meinproc->exitStatus() != 0 ) {
+ delete meinproc;
+ return;
+ }
+
+ delete meinproc;
+
+ QFile f( m_cacheFile );
+ if ( !f.open( IO_ReadWrite ) )
+ return;
+
+ QDomDocument doc;
+ if ( !doc.setContent( &f ) )
+ return;
+
+ QDomComment timestamp = doc.createComment( QString::number( sourceFileCTime() ) );
+ doc.documentElement().appendChild( timestamp );
+
+ f.at( 0 );
+ QTextStream stream( &f );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ stream << doc.toString();
+
+ f.close();
+
+ fillTree();
+}
+
+void TOC::fillTree()
+{
+ QFile f( m_cacheFile );
+ if ( !f.open( IO_ReadOnly ) )
+ return;
+
+ QDomDocument doc;
+ if ( !doc.setContent( &f ) )
+ return;
+
+ TOCChapterItem *chapItem = 0;
+ QDomNodeList chapters = doc.documentElement().elementsByTagName( "chapter" );
+ for ( unsigned int chapterCount = 0; chapterCount < chapters.count(); chapterCount++ ) {
+ QDomElement chapElem = chapters.item( chapterCount ).toElement();
+ QDomElement chapTitleElem = childElement( chapElem, QString::fromLatin1( "title" ) );
+ QString chapTitle = chapTitleElem.text().simplifyWhiteSpace();
+ QDomElement chapRefElem = childElement( chapElem, QString::fromLatin1( "anchor" ) );
+ QString chapRef = chapRefElem.text().stripWhiteSpace();
+
+ chapItem = new TOCChapterItem( this, m_parentItem, chapItem, chapTitle, chapRef );
+
+ TOCSectionItem *sectItem = 0;
+ QDomNodeList sections = chapElem.elementsByTagName( "section" );
+ for ( unsigned int sectCount = 0; sectCount < sections.count(); sectCount++ ) {
+ QDomElement sectElem = sections.item( sectCount ).toElement();
+ QDomElement sectTitleElem = childElement( sectElem, QString::fromLatin1( "title" ) );
+ QString sectTitle = sectTitleElem.text().simplifyWhiteSpace();
+ QDomElement sectRefElem = childElement( sectElem, QString::fromLatin1( "anchor" ) );
+ QString sectRef = sectRefElem.text().stripWhiteSpace();
+
+ sectItem = new TOCSectionItem( this, chapItem, sectItem, sectTitle, sectRef );
+ }
+ }
+
+ m_parentItem->setOpen( true );
+}
+
+QDomElement TOC::childElement( const QDomElement &element, const QString &name )
+{
+ QDomElement e;
+ for ( e = element.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement() )
+ if ( e.tagName() == name )
+ break;
+ return e;
+}
+
+void TOC::slotItemSelected( QListViewItem *item )
+{
+ TOCItem *tocItem;
+ if ( ( tocItem = dynamic_cast<TOCItem *>( item ) ) )
+ emit itemSelected( tocItem->entry()->url() );
+
+ item->setOpen( !item->isOpen() );
+}
+
+TOCItem::TOCItem( TOC *toc, QListViewItem *parentItem, QListViewItem *after, const QString &text )
+ : NavigatorItem( new DocEntry( text ), parentItem, after )
+{
+ setAutoDeleteDocEntry( true );
+ m_toc = toc;
+}
+
+TOCChapterItem::TOCChapterItem( TOC *toc, NavigatorItem *parent, QListViewItem *after,
+ const QString &title, const QString &name )
+ : TOCItem( toc, parent, after, title ),
+ m_name( name )
+{
+ setOpen( false );
+ entry()->setUrl(url());
+}
+
+QString TOCChapterItem::url()
+{
+ return "help:" + toc()->application() + "/" + m_name + ".html";
+}
+
+TOCSectionItem::TOCSectionItem( TOC *toc, TOCChapterItem *parent, QListViewItem *after,
+ const QString &title, const QString &name )
+ : TOCItem( toc, parent, after, title ),
+ m_name( name )
+{
+ setPixmap( 0, SmallIcon( "document" ) );
+ entry()->setUrl(url());
+}
+
+QString TOCSectionItem::url()
+{
+ if ( static_cast<TOCSectionItem *>( parent()->firstChild() ) == this )
+ return static_cast<TOCChapterItem *>( parent() )->url() + "#" + m_name;
+
+ return "help:" + toc()->application() + "/" + m_name + ".html";
+}
+
+#include "toc.moc"
+// vim:ts=2:sw=2:et