You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/khelpcenter/toc.cpp

272 lines
7.0 KiB

/*
* 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 <tqdir.h>
#include <tqfileinfo.h>
#include <sys/stat.h>
using namespace KHC;
class TOCItem : public NavigatorItem
{
public:
TOCItem( TOC *parent, TQListViewItem *parentItem, TQListViewItem *after, const TQString &text );
const TOC *toc() const { return m_toc; }
private:
TOC *m_toc;
};
class TOCChapterItem : public TOCItem
{
public:
TOCChapterItem( TOC *toc, NavigatorItem *parent, TQListViewItem *after, const TQString &title,
const TQString &name );
virtual TQString url();
private:
TQString m_name;
};
class TOCSectionItem : public TOCItem
{
public:
TOCSectionItem( TOC *toc, TOCChapterItem *parent, TQListViewItem *after, const TQString &title,
const TQString &name );
virtual TQString url();
private:
TQString m_name;
};
TOC::TOC( NavigatorItem *parentItem )
{
m_parentItem = parentItem;
}
void TOC::build( const TQString &file )
{
TQFileInfo fileInfo( file );
TQString fileName = fileInfo.absFilePath();
const TQStringList resourceDirs = KGlobal::dirs()->resourceDirs( "html" );
TQStringList::ConstIterator it = resourceDirs.begin();
TQStringList::ConstIterator end = resourceDirs.end();
for ( ; it != end; ++it ) {
if ( fileName.startsWith( *it ) ) {
fileName.remove( 0, ( *it ).length() );
break;
}
}
TQString cacheFile = fileName.tqreplace( TQDir::separator(), "__" );
m_cacheFile = locateLocal( "cache", "help/" + cacheFile );
m_sourceFile = file;
if ( cacheStatus() == NeedRebuild )
buildCache();
else
fillTree();
}
TOC::CacheStatus TOC::cacheStatus() const
{
if ( !TQFile::exists( m_cacheFile ) ||
sourceFileCTime() != cachedCTime() )
return NeedRebuild;
return CacheOk;
}
int TOC::sourceFileCTime() const
{
struct stat stat_buf;
stat( TQFile::encodeName( m_sourceFile ).data(), &stat_buf );
return stat_buf.st_ctime;
}
int TOC::cachedCTime() const
{
TQFile f( m_cacheFile );
if ( !f.open( IO_ReadOnly ) )
return 0;
TQDomDocument doc;
if ( !doc.setContent( &f ) )
return 0;
TQDomComment timestamp = doc.documentElement().lastChild().toComment();
return timestamp.data().stripWhiteSpace().toInt();
}
void TOC::buildCache()
{
KProcess *meinproc = new KProcess;
connect( meinproc, TQT_SIGNAL( processExited( KProcess * ) ),
this, TQT_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;
TQFile f( m_cacheFile );
if ( !f.open( IO_ReadWrite ) )
return;
TQDomDocument doc;
if ( !doc.setContent( &f ) )
return;
TQDomComment timestamp = doc.createComment( TQString::number( sourceFileCTime() ) );
doc.documentElement().appendChild( timestamp );
f.at( 0 );
TQTextStream stream( &f );
stream.setEncoding( TQTextStream::UnicodeUTF8 );
stream << doc.toString();
f.close();
fillTree();
}
void TOC::fillTree()
{
TQFile f( m_cacheFile );
if ( !f.open( IO_ReadOnly ) )
return;
TQDomDocument doc;
if ( !doc.setContent( &f ) )
return;
TOCChapterItem *chapItem = 0;
TQDomNodeList chapters = doc.documentElement().elementsByTagName( "chapter" );
for ( unsigned int chapterCount = 0; chapterCount < chapters.count(); chapterCount++ ) {
TQDomElement chapElem = chapters.item( chapterCount ).toElement();
TQDomElement chapTitleElem = childElement( chapElem, TQString::tqfromLatin1( "title" ) );
TQString chapTitle = chapTitleElem.text().simplifyWhiteSpace();
TQDomElement chapRefElem = childElement( chapElem, TQString::tqfromLatin1( "anchor" ) );
TQString chapRef = chapRefElem.text().stripWhiteSpace();
chapItem = new TOCChapterItem( this, m_parentItem, chapItem, chapTitle, chapRef );
TOCSectionItem *sectItem = 0;
TQDomNodeList sections = chapElem.elementsByTagName( "section" );
for ( unsigned int sectCount = 0; sectCount < sections.count(); sectCount++ ) {
TQDomElement sectElem = sections.item( sectCount ).toElement();
TQDomElement sectTitleElem = childElement( sectElem, TQString::tqfromLatin1( "title" ) );
TQString sectTitle = sectTitleElem.text().simplifyWhiteSpace();
TQDomElement sectRefElem = childElement( sectElem, TQString::tqfromLatin1( "anchor" ) );
TQString sectRef = sectRefElem.text().stripWhiteSpace();
sectItem = new TOCSectionItem( this, chapItem, sectItem, sectTitle, sectRef );
}
}
m_parentItem->setOpen( true );
}
TQDomElement TOC::childElement( const TQDomElement &element, const TQString &name )
{
TQDomElement e;
for ( e = element.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement() )
if ( e.tagName() == name )
break;
return e;
}
void TOC::slotItemSelected( TQListViewItem *item )
{
TOCItem *tocItem;
if ( ( tocItem = dynamic_cast<TOCItem *>( item ) ) )
emit itemSelected( tocItem->entry()->url() );
item->setOpen( !item->isOpen() );
}
TOCItem::TOCItem( TOC *toc, TQListViewItem *parentItem, TQListViewItem *after, const TQString &text )
: NavigatorItem( new DocEntry( text ), parentItem, after )
{
setAutoDeleteDocEntry( true );
m_toc = toc;
}
TOCChapterItem::TOCChapterItem( TOC *toc, NavigatorItem *parent, TQListViewItem *after,
const TQString &title, const TQString &name )
: TOCItem( toc, parent, after, title ),
m_name( name )
{
setOpen( false );
entry()->setUrl(url());
}
TQString TOCChapterItem::url()
{
return "help:" + toc()->application() + "/" + m_name + ".html";
}
TOCSectionItem::TOCSectionItem( TOC *toc, TOCChapterItem *parent, TQListViewItem *after,
const TQString &title, const TQString &name )
: TOCItem( toc, parent, after, title ),
m_name( name )
{
setPixmap( 0, SmallIcon( "document" ) );
entry()->setUrl(url());
}
TQString TOCSectionItem::url()
{
if ( static_cast<TOCSectionItem *>( tqparent()->firstChild() ) == this )
return static_cast<TOCChapterItem *>( tqparent() )->url() + "#" + m_name;
return "help:" + toc()->application() + "/" + m_name + ".html";
}
#include "toc.moc"
// vim:ts=2:sw=2:et