Now the DjVu generator is able to extract the list of bookmarks (aka Table of Contents) from the DjVy document, if it has any.

svn path=/trunk/playground/graphics/okular/; revision=555320
This commit is contained in:
Pino Toscano 2006-06-27 00:08:42 +00:00
parent 70423d2f95
commit a5795e2726
4 changed files with 127 additions and 3 deletions

View file

@ -9,16 +9,48 @@
#include "generator_djvu.h"
#include "kdjvu.h"
#include "core/document.h"
#include "core/page.h"
#include <qdom.h>
#include <qstring.h>
#include <kdebug.h>
#include <klocale.h>
static void recurseCreateTOC( QDomDocument &maindoc, QDomNode &parent, QDomNode &parentDestination )
{
QDomNode n = parent.firstChild();
while( !n.isNull() )
{
QDomElement el = n.toElement();
QDomElement newel = maindoc.createElement( el.attribute( "title" ) );
parentDestination.appendChild( newel );
if ( !el.attribute( "destination" ).isEmpty() )
{
bool ok = true;
int page = el.attribute( "destination" ).toInt( &ok );
if ( ok && ( page > 0 ) )
{
DocumentViewport vp;
vp.pageNumber = page - 1;
newel.setAttribute( "Viewport", vp.toString() );
}
}
if ( el.hasChildNodes() )
{
recurseCreateTOC( maindoc, n, newel );
}
n = n.nextSibling();
}
}
OKULAR_EXPORT_PLUGIN(DjVuGenerator)
DjVuGenerator::DjVuGenerator( KPDFDocument * doc ) : Generator ( doc ),
m_docInfo( 0 ), ready( false )
m_docInfo( 0 ), m_docSyn( 0 ), ready( false )
{
m_djvu = new KDjVu();
connect( m_djvu, SIGNAL( pixmapGenerated( int, const QPixmap & ) ), this, SLOT( djvuPixmapGenerated( int, const QPixmap & ) ) );
@ -28,6 +60,8 @@ bool DjVuGenerator::loadDocument( const QString & fileName, QVector< KPDFPage *
{
delete m_docInfo;
m_docInfo = 0;
delete m_docSyn;
m_docSyn = 0;
if ( !m_djvu->openFile( fileName ) )
return false;
@ -87,6 +121,21 @@ const DocumentInfo * DjVuGenerator::generateDocumentInfo()
return m_docInfo;
}
const DocumentSynopsis * DjVuGenerator::generateDocumentSynopsis()
{
if ( m_docSyn )
return m_docSyn;
const QDomDocument *doc = m_djvu->documentBookmarks();
if ( doc )
{
m_docSyn = new DocumentSynopsis();
recurseCreateTOC( *m_docSyn, *const_cast<QDomDocument*>( doc ), *m_docSyn );
}
return m_docSyn;
}
void DjVuGenerator::setOrientation( QVector<KPDFPage*> & pagesVector, int orientation )
{
loadPages( pagesVector, orientation );

View file

@ -28,6 +28,7 @@ class DjVuGenerator : public Generator
// document information
const DocumentInfo * generateDocumentInfo();
const DocumentSynopsis * generateDocumentSynopsis();
// rotation handling
bool supportsRotation() { return true; };
@ -42,6 +43,7 @@ class DjVuGenerator : public Generator
KDjVu *m_djvu;
DocumentInfo *m_docInfo;
DocumentSynopsis *m_docSyn;
bool ready;
PixmapRequest *m_request;

View file

@ -9,15 +9,18 @@
#include "kdjvu.h"
#include <qdom.h>
#include <qfile.h>
#include <qlist.h>
#include <qmap.h>
#include <qpainter.h>
#include <qstring.h>
#include <kdebug.h>
#include <klocale.h>
#include <libdjvu/ddjvuapi.h>
#include <libdjvu/miniexp.h>
kdbgstream &operator<<( kdbgstream & s, const ddjvu_rect_t &r )
{
@ -134,13 +137,17 @@ class KDjVu::Private
{
public:
Private()
: m_djvu_cxt( 0 ), m_djvu_document( 0 ), m_format( 0 )
: m_djvu_cxt( 0 ), m_djvu_document( 0 ), m_format( 0 ), m_docBookmarks( 0 )
{
}
QPixmap generatePixmapTile( ddjvu_page_t *djvupage, int& res,
int width, int row, int xdelta, int height, int col, int ydelta );
void readBookmarks();
void fillBookmarksRecurse( QDomDocument& maindoc, QDomNode& curnode,
miniexp_t exp, int offset = -1 );
ddjvu_context_t *m_djvu_cxt;
ddjvu_document_t *m_djvu_document;
ddjvu_format_t *m_format;
@ -151,6 +158,7 @@ class KDjVu::Private
QList<PixmapCacheItem*> mPixCache;
QMap<QString, QString> m_metaData;
QDomDocument * m_docBookmarks;
};
QPixmap KDjVu::Private::generatePixmapTile( ddjvu_page_t *djvupage, int& res,
@ -187,6 +195,57 @@ QPixmap KDjVu::Private::generatePixmapTile( ddjvu_page_t *djvupage, int& res,
return pix;
}
void KDjVu::Private::readBookmarks()
{
if ( !m_djvu_document )
return;
miniexp_t outline;
while ( ( outline = ddjvu_document_get_outline( m_djvu_document ) ) == miniexp_dummy )
handle_ddjvu_messages( m_djvu_cxt, true );
if ( miniexp_listp( outline ) &&
( miniexp_length( outline ) > 0 ) &&
miniexp_symbolp( miniexp_nth( 0, outline ) ) &&
( QString::fromUtf8( miniexp_to_name( miniexp_nth( 0, outline ) ) ) == QLatin1String( "bookmarks" ) ) )
{
m_docBookmarks = new QDomDocument( "KDjVuBookmarks" );
fillBookmarksRecurse( *m_docBookmarks, *m_docBookmarks, outline, 1 );
}
}
void KDjVu::Private::fillBookmarksRecurse( QDomDocument& maindoc, QDomNode& curnode,
miniexp_t exp, int offset )
{
if ( !miniexp_listp( exp ) )
return;
int l = miniexp_length( exp );
for ( int i = qMax( offset, 0 ); i < l; ++i )
{
miniexp_t cur = miniexp_nth( i, exp );
if ( miniexp_consp( cur ) && ( miniexp_length( cur ) > 0 ) &&
miniexp_stringp( miniexp_nth( 0, cur ) ) && miniexp_stringp( miniexp_nth( 1, cur ) ) )
{
QString title = QString::fromUtf8( miniexp_to_str( miniexp_nth( 0, cur ) ) );
QString dest = QString::fromUtf8( miniexp_to_str( miniexp_nth( 1, cur ) ) );
QDomElement el;
if ( dest.isEmpty() || ( ( dest.at( 0 ) == QLatin1Char( '#' ) ) && ( dest.remove( 0, 1 ) != title ) ) )
{
el = maindoc.createElement( "item" );
el.setAttribute( "title", title );
el.setAttribute( "destination", dest );
curnode.appendChild( el );
}
if ( !el.isNull() && ( miniexp_length( cur ) > 2 ) )
{
fillBookmarksRecurse( maindoc, el, cur, 2 );
}
}
}
}
KDjVu::KDjVu() : QObject(), d( new Private )
{
@ -288,6 +347,9 @@ bool KDjVu::openFile( const QString & fileName )
void KDjVu::closeFile()
{
// deleting the old TOC
delete d->m_docBookmarks;
d->m_docBookmarks = 0;
// deleting the pages
qDeleteAll( d->m_pages );
// releasing the djvu pages
@ -310,6 +372,13 @@ QString KDjVu::getMetaData( const QString & key ) const
return d->m_metaData.contains( key ) ? d->m_metaData[ key ] : QString();
}
const QDomDocument * KDjVu::documentBookmarks() const
{
if ( !d->m_docBookmarks )
d->readBookmarks();
return d->m_docBookmarks;
}
const QVector<KDjVu::Page*> &KDjVu::pages() const
{
return d->m_pages;

View file

@ -14,6 +14,8 @@
#include <qpixmap.h>
#include <qvector.h>
class QDomDocument;
/**
* @brief Qt (KDE) encapsulation of the DjVuLibre
*/
@ -69,6 +71,8 @@ class KDjVu : public QObject
*/
QString getMetaData( const QString & key ) const;
const QDomDocument * documentBookmarks() const;
// pixmap handling
/**
* Check if the pixmap for the specified \p page with the specified
@ -85,7 +89,7 @@ class KDjVu : public QObject
signals:
void pixmapGenerated( int page, const QPixmap & pix );
private:
private:
class Private;
Private * const d;
};