Commit e9e3d4a4 authored by Albert Astals Cid's avatar Albert Astals Cid

Make documentInfo be Hash based instead of XML based

parent c5c3be9a
......@@ -2473,8 +2473,8 @@ void Document::closeDocument()
d->m_pageSize = PageSize();
d->m_pageSizes.clear();
delete d->m_documentInfo;
d->m_documentInfo = 0;
d->m_documentInfo = DocumentInfo();
d->m_documentInfoAskedKeys.clear();
AudioPlayer::instance()->d->m_currentDocument = KUrl();
......@@ -2574,42 +2574,59 @@ bool Document::canConfigurePrinter( ) const
return 0;
}
const DocumentInfo * Document::documentInfo() const
DocumentInfo Document::documentInfo() const
{
if ( d->m_documentInfo )
return d->m_documentInfo;
QSet<DocumentInfo::Key> keys;
for (Okular::DocumentInfo::Key ks = Okular::DocumentInfo::Title;
ks < Okular::DocumentInfo::Invalid;
ks = Okular::DocumentInfo::Key( ks+1 ) )
{
keys << ks;
}
if ( d->m_generator )
return documentInfo( keys );
}
DocumentInfo Document::documentInfo( const QSet<DocumentInfo::Key> &keys ) const
{
DocumentInfo result = d->m_documentInfo;
const QSet<DocumentInfo::Key> missingKeys = keys - d->m_documentInfoAskedKeys;
if ( d->m_generator && !missingKeys.isEmpty() )
{
DocumentInfo *info = new DocumentInfo();
const DocumentInfo *tmp = d->m_generator->generateDocumentInfo();
if ( tmp )
*info = *tmp;
DocumentInfo info = d->m_generator->generateDocumentInfo( missingKeys );
if ( missingKeys.contains( DocumentInfo::FilePath ) )
{
info.set( DocumentInfo::FilePath, currentDocument().prettyUrl() );
}
info->set( DocumentInfo::FilePath, currentDocument().prettyUrl() );
const QString pagesSize = d->pagesSizeString();
if ( d->m_docSize != -1 )
if ( d->m_docSize != -1 && missingKeys.contains( DocumentInfo::DocumentSize ) )
{
const QString sizeString = KGlobal::locale()->formatByteSize( d->m_docSize );
info->set( DocumentInfo::DocumentSize, sizeString );
info.set( DocumentInfo::DocumentSize, sizeString );
}
if (!pagesSize.isEmpty())
if ( missingKeys.contains( DocumentInfo::PagesSize ) )
{
info->set( DocumentInfo::PagesSize, pagesSize );
const QString pagesSize = d->pagesSizeString();
if ( !pagesSize.isEmpty() )
{
info.set( DocumentInfo::PagesSize, pagesSize );
}
}
const DocumentInfo::Key keyPages = DocumentInfo::Pages;
const QString keyString = DocumentInfo::getKeyString( keyPages );
if ( info->get( keyString ).isEmpty() ) {
info->set( keyString, QString::number( this->pages() ),
DocumentInfo::getKeyTitle( keyPages ) );
if ( missingKeys.contains( DocumentInfo::Pages ) && info.get( DocumentInfo::Pages ).isEmpty() ) {
info.set( DocumentInfo::Pages, QString::number( this->pages() ) );
}
d->m_documentInfo = info;
return info;
d->m_documentInfo.d->values.unite(info.d->values);
d->m_documentInfo.d->titles.unite(info.d->titles);
result.d->values.unite(info.d->values);
result.d->titles.unite(info.d->titles);
}
else return NULL;
d->m_documentInfoAskedKeys += keys;
return result;
}
const DocumentSynopsis * Document::documentSynopsis() const
......@@ -4641,52 +4658,51 @@ bool DocumentViewport::operator<( const DocumentViewport & vp ) const
/** DocumentInfo **/
DocumentInfo::DocumentInfo()
: QDomDocument( "DocumentInformation" )
DocumentInfo::DocumentInfo() : d(new DocumentInfoPrivate())
{
QDomElement docElement = createElement( "DocumentInfo" );
appendChild( docElement );
}
void DocumentInfo::set( const QString &key, const QString &value,
const QString &title )
DocumentInfo::DocumentInfo(const DocumentInfo &info) : d(new DocumentInfoPrivate())
{
QDomElement docElement = documentElement();
QDomElement element;
*this = info;
}
// check whether key already exists
QDomNodeList list = docElement.elementsByTagName( key );
if ( list.count() > 0 )
element = list.item( 0 ).toElement();
else
element = createElement( key );
DocumentInfo& DocumentInfo::operator=(const DocumentInfo &info)
{
d->values = info.d->values;
d->titles = info.d->titles;
return *this;
}
element.setAttribute( "value", value );
element.setAttribute( "title", title );
DocumentInfo::~DocumentInfo()
{
delete d;
}
if ( list.count() == 0 )
docElement.appendChild( element );
void DocumentInfo::set( const QString &key, const QString &value, const QString &title )
{
d->values[ key ] = value;
d->titles[ key ] = title;
}
void DocumentInfo::set( Key key, const QString &value )
{
const QString keyString = getKeyString( key );
if ( !keyString.isEmpty() )
set( keyString, value, getKeyTitle( key ) );
else
kWarning(OkularDebug) << "Invalid key passed";
d->values[ getKeyString( key ) ] = value;
}
QString DocumentInfo::get( const QString &key ) const
QStringList DocumentInfo::keys() const
{
const QDomElement docElement = documentElement();
return d->values.keys();
}
// check whether key already exists
const QDomNodeList list = docElement.elementsByTagName( key );
if ( list.count() > 0 )
return list.item( 0 ).toElement().attribute( "value" );
else
return QString();
QString DocumentInfo::get( Key key ) const
{
return get( getKeyString( key ) );
}
QString DocumentInfo::get( const QString &key ) const
{
return d->values[ key ];
}
QString DocumentInfo::getKeyString( Key key ) //const
......@@ -4741,11 +4757,33 @@ QString DocumentInfo::getKeyString( Key key ) //const
return "pageSize";
break;
default:
kWarning() << "Unknown" << key;
return QString();
break;
}
}
DocumentInfo::Key DocumentInfo::getKeyFromString( const QString &key ) //const
{
if (key == "title") return Title;
else if (key == "subject") return Subject;
else if (key == "description") return Description;
else if (key == "author") return Author;
else if (key == "creator") return Creator;
else if (key == "producer") return Producer;
else if (key == "copyright") return Copyright;
else if (key == "pages") return Pages;
else if (key == "creationDate") return CreationDate;
else if (key == "modificationDate") return ModificationDate;
else if (key == "mimeType") return MimeType;
else if (key == "category") return Category;
else if (key == "keywords") return Keywords;
else if (key == "filePath") return FilePath;
else if (key == "documentSize") return DocumentSize;
else if (key == "pageSize") return PagesSize;
else return Invalid;
}
QString DocumentInfo::getKeyTitle( Key key ) //const
{
switch ( key ) {
......@@ -4803,6 +4841,15 @@ QString DocumentInfo::getKeyTitle( Key key ) //const
}
}
QString DocumentInfo::getKeyTitle( const QString &key ) const
{
QString title = getKeyTitle ( getKeyFromString( key ) );
if ( title.isEmpty() )
title = d->titles[ key ];
return title;
}
/** DocumentSynopsis **/
......
......@@ -36,7 +36,7 @@ namespace Okular {
class Annotation;
class BookmarkManager;
class DocumentInfo;
class DocumentInfoPrivate;
class DocumentObserver;
class DocumentPrivate;
class DocumentSynopsis;
......@@ -63,6 +63,110 @@ class VisiblePageRect;
#define SW_SEARCH_ID 3
#define PRESENTATION_SEARCH_ID 4
/**
* The DocumentInfo structure can be filled in by generators to display
* metadata about the currently opened file.
*/
class OKULAR_EXPORT DocumentInfo
{
friend class Document;
public:
/**
* The list of predefined keys.
*/
enum Key {
Title, ///< The title of the document
Subject, ///< The subject of the document
Description, ///< The description of the document
Author, ///< The author of the document
Creator, ///< The creator of the document (this can be different from the author)
Producer, ///< The producer of the document (e.g. some software)
Copyright, ///< The copyright of the document
Pages, ///< The number of pages of the document
CreationDate, ///< The date of creation of the document
ModificationDate, ///< The date of last modification of the document
MimeType, ///< The mime type of the document
Category, ///< The category of the document
Keywords, ///< The keywords which describe the content of the document
FilePath, ///< The path of the file @since 0.10 (KDE 4.4)
DocumentSize, ///< The size of the document @since 0.10 (KDE 4.4)
PagesSize, ///< The size of the pages (if all pages have the same size) @since 0.10 (KDE 4.4)
CustomKeys, ///< All the custom keys the generator supports @since 0.21
Invalid ///< An invalid key @since 0.21. It will always be the last element in the enum
};
/**
* Creates a new document info.
*/
DocumentInfo();
DocumentInfo(const DocumentInfo &info);
DocumentInfo& operator=( const DocumentInfo& );
~DocumentInfo();
/**
* Returns all the keys present in this DocumentInfo
*
* @since 0.21
*/
QStringList keys() const;
/**
* Returns the value for a given key or an null string when the
* key doesn't exist.
*/
QString get( Key key ) const;
/**
* Returns the value for a given key or an null string when the
* key doesn't exist.
*/
QString get( const QString &key ) const;
/**
* Sets a value for a custom key. The title should be an i18n'ed
* string, since it's used in the document information dialog.
*/
void set( const QString &key, const QString &value,
const QString &title = QString() );
/**
* Sets a value for a special key. The title should be an i18n'ed
* string, since it's used in the document information dialog.
*/
void set( Key key, const QString &value );
/**
* Returns the user visible string for the given key
* Takes into account keys added by the set() that takes a QString
*
* @since 0.21
*/
QString getKeyTitle( const QString &key ) const;
/**
* Returns the internal string for the given key
* @since 0.10 (KDE 4.4)
*/
static QString getKeyString( Key key );
/**
* Returns the user visible string for the given key
* @since 0.10 (KDE 4.4)
*/
static QString getKeyTitle( Key key );
/**
* Returns the Key from a string key
* @since 0.21
*/
static Key getKeyFromString( const QString &key );
private:
DocumentInfoPrivate *d;
};
/**
* @short The Document. Heart of everything. Actions take place here.
......@@ -139,10 +243,15 @@ class OKULAR_EXPORT Document : public QObject
bool isOpened() const;
/**
* Returns the meta data of the document or 0 if no meta data
* are available.
* Returns the meta data of the document.
*/
const DocumentInfo * documentInfo() const;
DocumentInfo documentInfo() const;
/**
* Returns the asked set of meta data of the document. The result may contain more
* metadata than the one asked for.
*/
DocumentInfo documentInfo( const QSet<DocumentInfo::Key> &keys ) const;
/**
* Returns the table of content of the document or 0 if no
......@@ -1077,75 +1186,6 @@ class OKULAR_EXPORT DocumentViewport
} autoFit;
};
/**
* @short A DOM tree containing information about the document.
*
* The DocumentInfo structure can be filled in by generators to display
* metadata about the currently opened file.
*/
class OKULAR_EXPORT DocumentInfo : public QDomDocument
{
public:
/**
* The list of predefined keys.
*/
enum Key {
Title, ///< The title of the document
Subject, ///< The subject of the document
Description, ///< The description of the document
Author, ///< The author of the document
Creator, ///< The creator of the document (this can be different from the author)
Producer, ///< The producer of the document (e.g. some software)
Copyright, ///< The copyright of the document
Pages, ///< The number of pages of the document
CreationDate, ///< The date of creation of the document
ModificationDate, ///< The date of last modification of the document
MimeType, ///< The mime type of the document
Category, ///< The category of the document
Keywords, ///< The keywords which describe the content of the document
FilePath, ///< The path of the file @since 0.10 (KDE 4.4)
DocumentSize, ///< The size of the document @since 0.10 (KDE 4.4)
PagesSize ///< The size of the pages (if all pages have the same size) @since 0.10 (KDE 4.4)
};
/**
* Creates a new document info.
*/
DocumentInfo();
/**
* Sets a value for a special key. The title should be an i18n'ed
* string, since it's used in the document information dialog.
*/
void set( const QString &key, const QString &value,
const QString &title = QString() );
/**
* Sets the value for a predefined key. You should use this method
* whenever a predefined key exists for your value.
*/
void set( Key key, const QString &value );
/**
* Returns the value for a given key or an empty string when the
* key doesn't exist.
*/
QString get( const QString &key ) const;
/**
* Returns the internal string for the given key
* @since 0.10 (KDE 4.4)
*/
static QString getKeyString( Key key );
/**
* Returns the user visible string for the given key
* @since 0.10 (KDE 4.4)
*/
static QString getKeyTitle( Key key );
};
/**
* @short A DOM tree that describes the Table of Contents.
*
......
......@@ -96,7 +96,6 @@ class DocumentPrivate
m_scripter( 0 ),
m_archiveData( 0 ),
m_fontsCached( false ),
m_documentInfo( 0 ),
m_annotationEditingEnabled ( true ),
m_annotationBeingMoved( false )
{
......@@ -258,7 +257,8 @@ class DocumentPrivate
QPointer< FontExtractionThread > m_fontThread;
bool m_fontsCached;
DocumentInfo *m_documentInfo;
QSet<DocumentInfo::Key> m_documentInfoAskedKeys;
DocumentInfo m_documentInfo;
FontInfo::List m_fontsCache;
QSet< View * > m_views;
......@@ -272,6 +272,13 @@ class DocumentPrivate
QDomNode m_prevPropsOfAnnotBeingModified;
};
class DocumentInfoPrivate
{
public:
QMap<QString, QString> values; // key -> value
QMap<QString, QString> titles; // key -> title For the custom keys
};
}
#endif
......
......@@ -290,9 +290,9 @@ TextPage* Generator::textPage( Page* )
return 0;
}
const DocumentInfo * Generator::generateDocumentInfo()
DocumentInfo Generator::generateDocumentInfo(const QSet<DocumentInfo::Key> &keys) const
{
return 0;
return DocumentInfo();
}
const DocumentSynopsis * Generator::generateDocumentSynopsis()
......
......@@ -308,10 +308,9 @@ class OKULAR_EXPORT Generator : public QObject
virtual void generateTextPage( Page * page );
/**
* Returns the general information object of the document or 0 if
* no information are available.
* Returns the general information object of the document.
*/
virtual const DocumentInfo * generateDocumentInfo();
virtual DocumentInfo generateDocumentInfo( const QSet<DocumentInfo::Key> &keys ) const;
/**
* Returns the 'table of content' object of the document or 0 if
......
......@@ -135,12 +135,17 @@ static KJSObject docGetInfo( KJSContext *ctx, void *object )
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object );
KJSObject obj;
const DocumentInfo *docinfo = doc->m_generator->generateDocumentInfo();
if ( docinfo )
{
QSet<DocumentInfo::Key> keys;
keys << DocumentInfo::Title
<< DocumentInfo::Author
<< DocumentInfo::Subject
<< DocumentInfo::Keywords
<< DocumentInfo::Creator
<< DocumentInfo::Producer;
const DocumentInfo docinfo = doc->m_parent->documentInfo( keys );
#define KEY_GET( key, property ) \
do { \
const QString data = docinfo->get( key ); \
const QString data = docinfo.get( key ); \
if ( !data.isEmpty() ) \
{ \
const KJSString newval( data ); \
......@@ -148,14 +153,13 @@ do { \
obj.setProperty( ctx, QString( property ).toLower(), newval ); \
} \
} while ( 0 );
KEY_GET( "title", "Title" );
KEY_GET( "author", "Author" );
KEY_GET( "subject", "Subject" );
KEY_GET( "keywords", "Keywords" );
KEY_GET( "creator", "Creator" );
KEY_GET( "producer", "Producer" );
KEY_GET( DocumentInfo::Title, "Title" );
KEY_GET( DocumentInfo::Author, "Author" );
KEY_GET( DocumentInfo::Subject, "Subject" );
KEY_GET( DocumentInfo::Keywords, "Keywords" );
KEY_GET( DocumentInfo::Creator, "Creator" );
KEY_GET( DocumentInfo::Producer, "Producer" );
#undef KEY_GET
}
return obj;
}
......@@ -163,16 +167,16 @@ do { \
static KJSObject docGet ## name( KJSContext *, void *object ) \
{ \
DocumentPrivate *doc = reinterpret_cast< DocumentPrivate* >( object ); \
const DocumentInfo *docinfo = doc->m_generator->generateDocumentInfo(); \
return KJSString( docinfo->get( key ) ); \
const DocumentInfo docinfo = doc->m_parent->documentInfo(QSet<DocumentInfo::Key>() << key ); \
return KJSString( docinfo.get( key ) ); \
}
DOCINFO_GET_METHOD( "author", Author )
DOCINFO_GET_METHOD( "creator", Creator )
DOCINFO_GET_METHOD( "keywords", Keywords )
DOCINFO_GET_METHOD( "producer", Producer )
DOCINFO_GET_METHOD( "title", Title )
DOCINFO_GET_METHOD( "subject", Subject )
DOCINFO_GET_METHOD( DocumentInfo::Author, Author )
DOCINFO_GET_METHOD( DocumentInfo::Creator, Creator )
DOCINFO_GET_METHOD( DocumentInfo::Keywords, Keywords )
DOCINFO_GET_METHOD( DocumentInfo::Producer, Producer )
DOCINFO_GET_METHOD( DocumentInfo::Title, Title )
DOCINFO_GET_METHOD( DocumentInfo::Subject, Subject )
#undef DOCINFO_GET_METHOD
......
......@@ -453,10 +453,10 @@ bool TextDocumentGenerator::print( QPrinter& printer )
return true;
}
const Okular::DocumentInfo* TextDocumentGenerator::generateDocumentInfo()
Okular::DocumentInfo TextDocumentGenerator::generateDocumentInfo( const QSet<DocumentInfo::Key> & /*keys*/ ) const
{
Q_D( TextDocumentGenerator );
return &d->mDocumentInfo;
Q_D( const TextDocumentGenerator );
return d->mDocumentInfo;
}
const Okular::DocumentSynopsis* TextDocumentGenerator::generateDocumentSynopsis()
......@@ -473,7 +473,7 @@ QVariant TextDocumentGeneratorPrivate::metaData( const QString &key, const QVari
Q_UNUSED( option )
if ( key == "DocumentTitle" )
{
return mDocumentInfo.get( "title" );
return mDocumentInfo.get( DocumentInfo::Title );
}
return QVariant();
}
......
......@@ -211,7 +211,7 @@ class OKULAR_EXPORT TextDocumentGenerator : public Generator, public Okular::Con
*/
TextDocumentSettings* generalSettings();
const Okular::DocumentInfo* generateDocumentInfo();
Okular::DocumentInfo generateDocumentInfo( const QSet<DocumentInfo::Key> &keys ) const;
const Okular::DocumentSynopsis* generateDocumentSynopsis();
protected:
......
......@@ -71,7 +71,6 @@ CHMGenerator::CHMGenerator( QObject *parent, const QVariantList &args )
m_syncGen=0;
m_file=0;
m_docInfo=0;
m_pixmapRequestZoom=1;
m_request = 0;
}
......@@ -163,8 +162,6 @@ bool CHMGenerator::loadDocument( const QString & fileName, QVector< Okular::Page
bool CHMGenerator::doCloseDocument()
{
// delete the document information of the old document
delete m_docInfo;
m_docInfo=0;
delete m_file;
m_file=0;
m_textpageAddedList.clear();
......@@ -234,16 +231,14 @@ void CHMGenerator::slotCompleted()
signalPixmapRequestDone( req );
}
const Okular::DocumentInfo * CHMGenerator::generateDocumentInfo()
Okular::DocumentInfo CHMGenerator::generateDocumentInfo( const QSet<Okular::DocumentInfo::Key> &keys ) const
{
if (!m_docInfo)
{
m_docInfo=new Okular::DocumentInfo();
m_docInfo->set( Okular::DocumentInfo::MimeType, "application/x-chm" );
m_docInfo->set( Okular::DocumentInfo::Title, m_file->title() );
}
return m_docInfo;
Okular::DocumentInfo docInfo;
if ( keys.contains( Okular::DocumentInfo::MimeType ) )
docInfo.set( Okular::DocumentInfo::MimeType, "application/x-chm" );