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.
272 lines
7.0 KiB
272 lines
7.0 KiB
15 years ago
|
/*
|
||
|
* 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
|