Commit e06c3f4c authored by Enrico Ros's avatar Enrico Ros

FixCrash 2/3: getMetaData modified. mutex locks. performance fix for TOC

generation (was 50 times slower after the all-in-one generation patch)

svn path=/trunk/kdegraphics/kpdf/; revision=376083
parent 4b86155c
......@@ -252,9 +252,9 @@ bool KPDFDocument::okToPrint() const
return generator ? generator->allowed( Generator::Print ) : false;
}
QString KPDFDocument::getMetaData( const QString &key ) const
QString KPDFDocument::getMetaData( const QString & key, const QString & option ) const
{
return generator ? generator->getMetaData( key ) : QString();
return generator ? generator->getMetaData( key, option ) : QString();
}
void KPDFDocument::requestPixmaps( const QValueList< PixmapRequest * > & requests, bool async )
......
......@@ -64,7 +64,7 @@ class KPDFDocument : public QObject // only for a private slot..
uint currentPage() const;
uint pages() const;
bool okToPrint() const;
QString getMetaData( const QString &key ) const;
QString getMetaData( const QString & key, const QString & option = QString() ) const;
// perform actions on document / pages
void requestPixmaps( const QValueList< PixmapRequest * > & requests, bool asyncronous );
......@@ -103,6 +103,7 @@ class KPDFDocument : public QObject // only for a private slot..
void slotGeneratedContents( int id, int pageNumber );
};
/**
* @short A window on the document.
*
......@@ -113,9 +114,8 @@ struct DocumentViewport
int lastPage;
};
/**
* @short Metadata that describes the document.
* @short A dom tree containing informations about the document.
*
* The Info structure can be filled in by generators to display metadata
* about the currently opened file.
......@@ -146,13 +146,11 @@ class DocumentInfo : public QDomDocument
* a dom tree where each nod has an internal name (displayed in the listview)
* and one or more attributes.
*
* To fill in a valid synopsis tree just add domElements where the tag name
* is the screen name of the entry.
*
* The following attributes are valid [more may be added in future]:
* - Page: The page to which the node refers.
* - Position: The position inside the page, where 0 means top and 100 is
* the bottom.
* In the tree the tag name is the 'screen' name of the entry. A tag can have
* attributes. Here follows the list of tag attributes with meaning:
* - PageNumber: The internal number of referred page.
* - PageName: A 'named reference' to the page that must be converted using
* getMetaData( "NamedLink", page_name_attribute )
*/
class DocumentSynopsis : public QDomDocument
{
......
......@@ -66,7 +66,7 @@ class Generator : public QObject
virtual bool reparseConfig() { return false; }
// Access meta data of the generator
virtual QString getMetaData( const QString &/*key*/ ) const { return QString(); }
virtual QString getMetaData( const QString &/*key*/, const QString &/*option*/ ) { return QString(); }
signals:
void contentsChanged( int id, int pageNumber );
......
......@@ -188,9 +188,11 @@ const DocumentSynopsis * PDFGenerator::documentSynopsis()
if ( !items || items->getLength() < 1 )
return NULL;
docLock.lock();
docSyn = DocumentSynopsis();
if ( items->getLength() > 0 )
addSynopsisChildren( &docSyn, items );
docLock.unlock();
docSynopsisDirty = false;
return &docSyn;
......@@ -204,30 +206,47 @@ void PDFGenerator::addSynopsisChildren( QDomNode * parent, GList * items )
// iterate over every object in 'items'
OutlineItem * outlineItem = (OutlineItem *)items->get( i );
// create element using outlineItem's title as tagName
// 1. create element using outlineItem's title as tagName
QString name;
Unicode * uniChar = outlineItem->getTitle();
for ( int i = 0; i < outlineItem->getTitleLength(); ++i )
name += uniChar[ i ];
int titleLength = outlineItem->getTitleLength();
for ( int j = 0; j < titleLength; ++j )
name += uniChar[ j ];
if ( name.isEmpty() )
continue;
QDomElement item = docSyn.createElement( name );
parent->appendChild( item );
// set element's attributes
if ( kpdfOutputDev )
// 2. find the page the link refers to
LinkAction * a = outlineItem->getAction();
if ( a && a->getKind() == actionGoTo )
{
KPDFLink * link = kpdfOutputDev->generateLink( outlineItem->getAction() );
if ( link && link->linkType() == KPDFLink::Goto )
// page number is contained/referenced in a LinkGoTo
LinkGoTo * g = static_cast< LinkGoTo * >( a );
LinkDest * destination = g->getDest();
if ( !destination && g->getNamedDest() )
{
// no 'destination' but an internal 'named reference'. we could
// get the destination for the page now, but it's VERY time consuming,
// so better storing the reference and provide page number as metadata
// on demand
item.setAttribute( "PageName", g->getNamedDest()->getCString() );
}
else if ( destination->isOk() )
{
KPDFLinkGoto * linkGoto = static_cast< KPDFLinkGoto * >( link );
item.setAttribute( "Page", linkGoto->destViewport().page );
//TODO item.setAttribute( "Position", 0 );
// we have valid 'destination' -> get page number
int pageNumber = destination->getPageNum() - 1;
if ( destination->isPageRef() )
{
Ref ref = destination->getPageRef();
pageNumber = pdfdoc->findPage( ref.num, ref.gen ) - 1;
}
// set page as attribute to node (note: the viewport should be set too)
item.setAttribute( "PageNumber", pageNumber );
}
delete link;
}
// recursively descend over children
// 3. recursively descend over children
outlineItem->open();
GList * children = outlineItem->getKids();
if ( children )
......@@ -459,14 +478,38 @@ bool PDFGenerator::reparseConfig()
return false;
}
QString PDFGenerator::getMetaData( const QString &key ) const
QString PDFGenerator::getMetaData( const QString & key, const QString & option )
{
if ( key == "StartFullScreen" ) {
if ( pdfdoc->getCatalog()->getPageMode() == Catalog::FullScreen )
return "yes";
}
return QString();
if ( key == "StartFullScreen" )
{
// asking for the 'start in fullscreen mode' (pdf property)
if ( pdfdoc->getCatalog()->getPageMode() == Catalog::FullScreen )
return "yes";
}
else if ( key == "NamedLink" && !option.isEmpty() )
{
// asking for the page related to a 'named link destination'. the
// option is the link name. @see addSynopsisChildren.
int pageNumber = -1;
GString * namedDest = new GString( option.latin1() );
docLock.lock();
LinkDest * destination = pdfdoc->findDest( namedDest );
if ( destination )
{
if ( !destination->isPageRef() )
pageNumber = destination->getPageNum() - 1;
else
{
Ref ref = destination->getPageRef();
pageNumber = pdfdoc->findPage( ref.num, ref.gen ) - 1;
}
}
docLock.unlock();
delete namedDest;
if ( pageNumber >= 0 )
return QString::number( pageNumber );
}
return QString();
}
KPDFLinkGoto::Viewport PDFGenerator::decodeLinkViewport( GString * namedDest, LinkDest * dest )
......
......@@ -61,7 +61,7 @@ class PDFGenerator : public Generator
// [INHERITED] reparse configuration
bool reparseConfig();
QString getMetaData( const QString &key ) const;
QString getMetaData( const QString & key, const QString & option );
// used by the KPDFOutputDev child
KPDFLinkGoto::Viewport decodeLinkViewport( class GString * namedDest, class LinkDest * dest );
......
......@@ -118,11 +118,21 @@ void TOC::addChildren( const QDomNode & parentNode, KListViewItem * parentItem )
void TOC::slotExecuted( QListViewItem *i )
{
const QDomElement & e = static_cast< TOCItem* >( i )->element();
// if the node has a referred page, jump to it
if ( e.hasAttribute( "Page" ) )
if ( e.hasAttribute( "PageNumber" ) )
{
// if the node has a page number, follow it
m_document->setCurrentPage( e.attribute( "Page" ).toUInt() );
// may check for other properties here
// ...
}
else if ( e.hasAttribute( "PageName" ) )
{
// if the node has a named reference, ask for conversion
const QString & page = e.attribute( "PageName" );
const QString & pageNumber = m_document->getMetaData( "NamedLink", page );
bool ok;
int n = pageNumber.toUInt( &ok );
if ( ok )
m_document->setCurrentPage( n );
}
}
#include "toc.moc"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment