[poppler] 6 commits - cpp/poppler-document.cpp cpp/poppler-document.h qt4/src qt5/src

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Jul 24 10:48:40 UTC 2016


 cpp/poppler-document.cpp    |  475 +++++++++++++++++++++++++++++++++++++++++---
 cpp/poppler-document.h      |   28 ++
 qt4/src/poppler-document.cc |  237 +++++++++++++++++----
 qt4/src/poppler-private.cc  |    9 
 qt4/src/poppler-private.h   |    3 
 qt4/src/poppler-qt4.h       |  118 ++++++++++
 qt5/src/poppler-document.cc |  235 +++++++++++++++++----
 qt5/src/poppler-private.cc  |    9 
 qt5/src/poppler-private.h   |    3 
 qt5/src/poppler-qt5.h       |  118 ++++++++++
 10 files changed, 1126 insertions(+), 109 deletions(-)

New commits:
commit 844ede567f188997bb49ab1fc435797b4f31f5e9
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Jul 24 12:47:21 2016 +0200

    qt5: Fix memory leak in new implementation of ::date

diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc
index 8f5199f..651f510 100644
--- a/qt5/src/poppler-document.cc
+++ b/qt5/src/poppler-document.cc
@@ -448,7 +448,8 @@ namespace Poppler {
 	    return QDateTime();
 	}
 
-	QString str = UnicodeParsedString(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	QString str = UnicodeParsedString(goo.data());
 	return Poppler::convertDate(str.toLatin1().data());
     }
 
commit d34ac7cedf4213020f5a4c05e09aa8d781bc6e43
Author: Jakub Kucharski <jakubkucharski97 at gmail.com>
Date:   Sun Jul 24 12:43:41 2016 +0200

    qt5: Added document property setters & getters
    
    Part of Bug #36653

diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc
index 537dca3..8f5199f 100644
--- a/qt5/src/poppler-document.cc
+++ b/qt5/src/poppler-document.cc
@@ -9,6 +9,7 @@
  * Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2014 Adam Reichold <adamreichold at myopera.com>
  * Copyright (C) 2015 William Bader <williambader at hotmail.com>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  *
  * 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
@@ -264,37 +265,155 @@ namespace Poppler {
 	return result;
     }
 
-    /* borrowed from kpdf */
     QString Document::info( const QString & type ) const
     {
-	// [Albert] Code adapted from pdfinfo.cc on xpdf
-	Object info;
-	if ( m_doc->locked )
+	if (m_doc->locked) {
 	    return QString();
+	}
 
-	QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
-	if (!xref)
-		return QString();
-	xref->getDocInfo(&info);
-	if ( !info.isDict() )
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setInfo( const QString & key, const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	GooString *goo = QStringToUnicodeGooString(val);
+	m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), goo);
+	return true;
+    }
+
+    QString Document::title() const
+    {
+	if (m_doc->locked) {
 	    return QString();
+	}
 
-	QString result;
-	Object obj;
-	GooString *s1;
-	Dict *infoDict = info.getDict();
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoTitle());
+	return UnicodeParsedString(goo.data());
+    }
 
-	if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
-	{
-	    s1 = obj.getString();
-	    result = UnicodeParsedString(s1);
-	    obj.free();
-	    info.free();
-	    return result;
+    bool Document::setTitle( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
 	}
-	obj.free();
-	info.free();
-	return QString();
+
+	m_doc->doc->setDocInfoTitle(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::author() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoAuthor());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setAuthor( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoAuthor(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::subject() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoSubject());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setSubject( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoSubject(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::keywords() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoKeywords());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setKeywords( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoKeywords(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::creator() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoCreator());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setCreator( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoCreator(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::producer() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoProducer());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setProducer( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoProducer(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    bool Document::removeInfo()
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->removeDocInfo();
+	return true;
     }
 
     QStringList Document::infoKeys() const
@@ -323,35 +442,64 @@ namespace Poppler {
 	return keys;
     }
 
-    /* borrowed from kpdf */
     QDateTime Document::date( const QString & type ) const
     {
-	// [Albert] Code adapted from pdfinfo.cc on xpdf
-	if ( m_doc->locked )
+	if (m_doc->locked) {
 	    return QDateTime();
+	}
 
-	Object info;
-	QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
-	if (!xref)
-		return QDateTime();
-	xref->getDocInfo(&info);
-	if ( !info.isDict() ) {
-	    info.free();
+	QString str = UnicodeParsedString(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	return Poppler::convertDate(str.toLatin1().data());
+    }
+
+    bool Document::setDate( const QString & key, const QDateTime & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), QDateTimeToUnicodeGooString(val));
+	return true;
+    }
+
+    QDateTime Document::creationDate() const
+    {
+	if (m_doc->locked) {
 	    return QDateTime();
 	}
 
-	Object obj;
-	Dict *infoDict = info.getDict();
-	QDateTime result;
+	QString str = UnicodeParsedString(m_doc->doc->getDocInfoCreatDate());
+	return Poppler::convertDate(str.toLatin1().data());
+    }
 
-	if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
-	{
-	    char *aux = obj.getString()->getCString();
-	    result = Poppler::convertDate(aux);
+    bool Document::setCreationDate( const QDateTime & val )
+    {
+	if (m_doc->locked) {
+	    return false;
 	}
-	obj.free();
-	info.free();
-	return result;
+
+	m_doc->doc->setDocInfoCreatDate(QDateTimeToUnicodeGooString(val));
+	return true;
+    }
+
+    QDateTime Document::modificationDate() const
+    {
+	if (m_doc->locked) {
+	    return QDateTime();
+	}
+
+	QString str = UnicodeParsedString(m_doc->doc->getDocInfoModDate());
+	return Poppler::convertDate(str.toLatin1().data());
+    }
+
+    bool Document::setModificationDate( const QDateTime & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoModDate(QDateTimeToUnicodeGooString(val));
+	return true;
     }
 
     bool Document::isEncrypted() const
diff --git a/qt5/src/poppler-private.cc b/qt5/src/poppler-private.cc
index 86855fd..55d8972 100644
--- a/qt5/src/poppler-private.cc
+++ b/qt5/src/poppler-private.cc
@@ -4,6 +4,7 @@
  * Copyright (C) 2008, 2010, 2011, 2014 by Pino Toscano <pino at kde.org>
  * Copyright (C) 2013 by Thomas Freitag <Thomas.Freitag at alfa.de>
  * Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -153,6 +154,14 @@ namespace Debug {
         return ret;
     }
 
+    GooString *QDateTimeToUnicodeGooString(const QDateTime &dt) {
+        if (!dt.isValid()) {
+            return NULL;
+        }
+
+        return QStringToUnicodeGooString(dt.toUTC().toString("yyyyMMddhhmmss+00'00'"));
+    }
+
     void linkActionToTocItem( ::LinkAction * a, DocumentData * doc, QDomElement * e )
     {
         if ( !a || !e )
diff --git a/qt5/src/poppler-private.h b/qt5/src/poppler-private.h
index df6290b..1a83bb6 100644
--- a/qt5/src/poppler-private.h
+++ b/qt5/src/poppler-private.h
@@ -9,6 +9,7 @@
  * Copyright (C) 2013 Anthony Granger <grangeranthony at gmail.com>
  * Copyright (C) 2014 Bogdan Cristea <cristeab at gmail.com>
  * Copyright (C) 2014 Aki Koskinen <freedesktop at akikoskinen.info>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -63,6 +64,8 @@ namespace Poppler {
 
     GooString *QStringToGooString(const QString &s);
 
+    GooString *QDateTimeToUnicodeGooString(const QDateTime &dt);
+
     void qt5ErrorFunction(int pos, char *msg, va_list args);
 
     class LinkDestinationData
diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h
index b159477..ef313e6 100644
--- a/qt5/src/poppler-qt5.h
+++ b/qt5/src/poppler-qt5.h
@@ -15,6 +15,7 @@
  * Copyright (C) 2012, 2014, 2015 Adam Reichold <adamreichold at myopera.com>
  * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
  * Copyright (C) 2013 Anthony Granger <grangeranthony at gmail.com>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  *
  * 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
@@ -1072,6 +1073,37 @@ QDateTime modified = m_doc->date("ModDate");
 	QDateTime date( const QString & data ) const;
 
 	/**
+	   Set the Info dict date entry specified by \param key to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setDate( const QString & key, const QDateTime & val );
+
+	/**
+	   The date of the creation of the document
+	*/
+	QDateTime creationDate() const;
+
+	/**
+	   Set the creation date of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setCreationDate( const QDateTime & val );
+
+	/**
+	   The date of the last change in the document
+	*/
+	QDateTime modificationDate() const;
+
+	/**
+	   Set the modification date of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setModificationDate( const QDateTime & val );
+
+	/**
 	   Get specified information associated with the document
 
 	   You would use this method with something like:
@@ -1090,6 +1122,92 @@ QString subject = m_doc->info("Subject");
 	QString info( const QString & data ) const;
 
 	/**
+	   Set the value of the document's Info dictionary entry specified by \param key to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setInfo( const QString & key, const QString & val );
+
+	/**
+	   The title of the document
+	*/
+	QString title() const;
+
+	/**
+	   Set the title of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setTitle( const QString & val );
+
+	/**
+	   The author of the document
+	*/
+	QString author() const;
+
+	/**
+	   Set the author of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setAuthor( const QString & val );
+
+	/**
+	   The subject of the document
+	*/
+	QString subject() const;
+
+	/**
+	   Set the subject of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setSubject( const QString & val );
+
+	/**
+	   The keywords of the document
+	*/
+	QString keywords() const;
+
+	/**
+	   Set the keywords of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setKeywords( const QString & val );
+
+	/**
+	   The creator of the document
+	*/
+	QString creator() const;
+
+	/**
+	   Set the creator of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setCreator( const QString & val );
+
+	/**
+	   The producer of the document
+	*/
+	QString producer() const;
+
+	/**
+	   Set the producer of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setProducer( const QString & val );
+
+	/**
+	   Remove the document's Info dictionary
+
+	   \returns true on success, false on failure
+	*/
+	bool removeInfo();
+
+	/**
 	   Obtain a list of the available string information keys.
 	*/
 	QStringList infoKeys() const;
commit 720718739c8002304e8da33d9ca87bc0c1511425
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Jul 24 12:40:04 2016 +0200

    qt4: Fix memory leak in new implementation of ::date

diff --git a/qt4/src/poppler-document.cc b/qt4/src/poppler-document.cc
index 7bde1d6..2893625 100644
--- a/qt4/src/poppler-document.cc
+++ b/qt4/src/poppler-document.cc
@@ -1,7 +1,7 @@
 /* poppler-document.cc: qt interface to poppler
  * Copyright (C) 2005, Net Integration Technologies, Inc.
  * Copyright (C) 2005, 2008, Brad Hards <bradh at frogmouth.net>
- * Copyright (C) 2005-2010, 2012, 2013, 2015, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2005-2010, 2012, 2013, 2015, 2016, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2006-2010, Pino Toscano <pino at kde.org>
  * Copyright (C) 2010, 2011 Hib Eris <hib at hiberis.nl>
  * Copyright (C) 2012 Koji Otani <sho at bbr.jp>
@@ -462,7 +462,8 @@ namespace Poppler {
 	    return QDateTime();
 	}
 
-	QString str = UnicodeParsedString(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	QString str = UnicodeParsedString(goo.data());
 	return Poppler::convertDate(str.toLatin1().data());
     }
 
commit e7cbc36467dfac9415d7d1cac70b77e04566e75d
Author: Jakub Kucharski <jakubkucharski97 at gmail.com>
Date:   Sun Jul 24 12:39:34 2016 +0200

    qt4: Added document property setters & getters
    
    Part of Bug #36653

diff --git a/qt4/src/poppler-document.cc b/qt4/src/poppler-document.cc
index 94f997d..7bde1d6 100644
--- a/qt4/src/poppler-document.cc
+++ b/qt4/src/poppler-document.cc
@@ -9,6 +9,7 @@
  * Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2014 Adam Reichold <adamreichold at myopera.com>
  * Copyright (C) 2015 William Bader <williambader at hotmail.com>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  *
  * 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
@@ -278,37 +279,155 @@ namespace Poppler {
 	return result;
     }
 
-    /* borrowed from kpdf */
     QString Document::info( const QString & type ) const
     {
-	// [Albert] Code adapted from pdfinfo.cc on xpdf
-	Object info;
-	if ( m_doc->locked )
+	if (m_doc->locked) {
 	    return QString();
+	}
 
-	QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
-	if (!xref)
-		return QString();
-	xref->getDocInfo(&info);
-	if ( !info.isDict() )
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setInfo( const QString & key, const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	GooString *goo = QStringToUnicodeGooString(val);
+	m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), goo);
+	return true;
+    }
+
+    QString Document::title() const
+    {
+	if (m_doc->locked) {
 	    return QString();
+	}
 
-	QString result;
-	Object obj;
-	GooString *s1;
-	Dict *infoDict = info.getDict();
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoTitle());
+	return UnicodeParsedString(goo.data());
+    }
 
-	if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
-	{
-	    s1 = obj.getString();
-	    result = UnicodeParsedString(s1);
-	    obj.free();
-	    info.free();
-	    return result;
+    bool Document::setTitle( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
 	}
-	obj.free();
-	info.free();
-	return QString();
+
+	m_doc->doc->setDocInfoTitle(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::author() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoAuthor());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setAuthor( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoAuthor(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::subject() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoSubject());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setSubject( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoSubject(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::keywords() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoKeywords());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setKeywords( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoKeywords(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::creator() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoCreator());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setCreator( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoCreator(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    QString Document::producer() const
+    {
+	if (m_doc->locked) {
+	    return QString();
+	}
+
+	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoProducer());
+	return UnicodeParsedString(goo.data());
+    }
+
+    bool Document::setProducer( const QString & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoProducer(QStringToUnicodeGooString(val));
+	return true;
+    }
+
+    bool Document::removeInfo()
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->removeDocInfo();
+	return true;
     }
 
     QStringList Document::infoKeys() const
@@ -337,35 +456,64 @@ namespace Poppler {
 	return keys;
     }
 
-    /* borrowed from kpdf */
     QDateTime Document::date( const QString & type ) const
     {
-	// [Albert] Code adapted from pdfinfo.cc on xpdf
-	if ( m_doc->locked )
+	if (m_doc->locked) {
 	    return QDateTime();
+	}
 
-	Object info;
-	QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
-	if (!xref)
-		return QDateTime();
-	xref->getDocInfo(&info);
-	if ( !info.isDict() ) {
-	    info.free();
+	QString str = UnicodeParsedString(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
+	return Poppler::convertDate(str.toLatin1().data());
+    }
+
+    bool Document::setDate( const QString & key, const QDateTime & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), QDateTimeToUnicodeGooString(val));
+	return true;
+    }
+
+    QDateTime Document::creationDate() const
+    {
+	if (m_doc->locked) {
 	    return QDateTime();
 	}
 
-	Object obj;
-	Dict *infoDict = info.getDict();
-	QDateTime result;
+	QString str = UnicodeParsedString(m_doc->doc->getDocInfoCreatDate());
+	return Poppler::convertDate(str.toLatin1().data());
+    }
 
-	if ( infoDict->lookup( type.toLatin1().data(), &obj )->isString() )
-	{
-	    char *aux = obj.getString()->getCString();
-	    result = Poppler::convertDate(aux);
+    bool Document::setCreationDate( const QDateTime & val )
+    {
+	if (m_doc->locked) {
+	    return false;
 	}
-	obj.free();
-	info.free();
-	return result;
+
+	m_doc->doc->setDocInfoCreatDate(QDateTimeToUnicodeGooString(val));
+	return true;
+    }
+
+    QDateTime Document::modificationDate() const
+    {
+	if (m_doc->locked) {
+	    return QDateTime();
+	}
+
+	QString str = UnicodeParsedString(m_doc->doc->getDocInfoModDate());
+	return Poppler::convertDate(str.toLatin1().data());
+    }
+
+    bool Document::setModificationDate( const QDateTime & val )
+    {
+	if (m_doc->locked) {
+	    return false;
+	}
+
+	m_doc->doc->setDocInfoModDate(QDateTimeToUnicodeGooString(val));
+	return true;
     }
 
     bool Document::isEncrypted() const
diff --git a/qt4/src/poppler-private.cc b/qt4/src/poppler-private.cc
index cbf21b1..d64dca6 100644
--- a/qt4/src/poppler-private.cc
+++ b/qt4/src/poppler-private.cc
@@ -4,6 +4,7 @@
  * Copyright (C) 2008, 2010, 2011 by Pino Toscano <pino at kde.org>
  * Copyright (C) 2013 by Thomas Freitag <Thomas.Freitag at alfa.de>
  * Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -153,6 +154,14 @@ namespace Debug {
         return ret;
     }
 
+    GooString *QDateTimeToUnicodeGooString(const QDateTime &dt) {
+        if (!dt.isValid()) {
+            return NULL;
+        }
+
+        return QStringToUnicodeGooString(dt.toUTC().toString("yyyyMMddhhmmss+00'00'"));
+    }
+
     void linkActionToTocItem( ::LinkAction * a, DocumentData * doc, QDomElement * e )
     {
         if ( !a || !e )
diff --git a/qt4/src/poppler-private.h b/qt4/src/poppler-private.h
index 0d11e83..015f18e 100644
--- a/qt4/src/poppler-private.h
+++ b/qt4/src/poppler-private.h
@@ -7,6 +7,7 @@
  * Copyright (C) 2011 Hib Eris <hib at hiberis.nl>
  * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
  * Copyright (C) 2013 Julien Nabet <serval2412 at yahoo.fr>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  * Inspired on code by
  * Copyright (C) 2004 by Albert Astals Cid <tsdgeos at terra.es>
  * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -61,6 +62,8 @@ namespace Poppler {
 
     GooString *QStringToGooString(const QString &s);
 
+    GooString *QDateTimeToUnicodeGooString(const QDateTime &dt);
+
     void qt4ErrorFunction(int pos, char *msg, va_list args);
 
     class LinkDestinationData
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index c0340a4..2b518c1 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -14,6 +14,7 @@
  * Copyright (C) 2012, Tobias Koenig <tobias.koenig at kdab.com>
  * Copyright (C) 2012, 2014, 2015 Adam Reichold <adamreichold at myopera.com>
  * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  *
  * 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
@@ -1082,6 +1083,37 @@ QDateTime modified = m_doc->date("ModDate");
 	QDateTime date( const QString & data ) const;
 
 	/**
+	   Set the Info dict date entry specified by \param key to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setDate( const QString & key, const QDateTime & val );
+
+	/**
+	   The date of the creation of the document
+	*/
+	QDateTime creationDate() const;
+
+	/**
+	   Set the creation date of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setCreationDate( const QDateTime & val );
+
+	/**
+	   The date of the last change in the document
+	*/
+	QDateTime modificationDate() const;
+
+	/**
+	   Set the modification date of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setModificationDate( const QDateTime & val );
+
+	/**
 	   Get specified information associated with the document
 
 	   You would use this method with something like:
@@ -1100,6 +1132,92 @@ QString subject = m_doc->info("Subject");
 	QString info( const QString & data ) const;
 
 	/**
+	   Set the value of the document's Info dictionary entry specified by \param key to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setInfo( const QString & key, const QString & val );
+
+	/**
+	   The title of the document
+	*/
+	QString title() const;
+
+	/**
+	   Set the title of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setTitle( const QString & val );
+
+	/**
+	   The author of the document
+	*/
+	QString author() const;
+
+	/**
+	   Set the author of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setAuthor( const QString & val );
+
+	/**
+	   The subject of the document
+	*/
+	QString subject() const;
+
+	/**
+	   Set the subject of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setSubject( const QString & val );
+
+	/**
+	   The keywords of the document
+	*/
+	QString keywords() const;
+
+	/**
+	   Set the keywords of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setKeywords( const QString & val );
+
+	/**
+	   The creator of the document
+	*/
+	QString creator() const;
+
+	/**
+	   Set the creator of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setCreator( const QString & val );
+
+	/**
+	   The producer of the document
+	*/
+	QString producer() const;
+
+	/**
+	   Set the producer of the document to \param val
+
+	   \returns true on success, false on failure
+	*/
+	bool setProducer( const QString & val );
+
+	/**
+	   Remove the document's Info dictionary
+
+	   \returns true on success, false on failure
+	*/
+	bool removeInfo();
+
+	/**
 	   Obtain a list of the available string information keys.
 	*/
 	QStringList infoKeys() const;
commit 977669048b93e0561fc86e15b42ac69884e36fab
Author: Jakub Kucharski <jakubkucharski97 at gmail.com>
Date:   Sun Jul 24 12:20:58 2016 +0200

    cpp: Added document property setters & getters
    
    Part of Bug #36653

diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp
index ead6a30..c0be271 100644
--- a/cpp/poppler-document.cpp
+++ b/cpp/poppler-document.cpp
@@ -341,21 +341,36 @@ ustring document::info_key(const std::string &key) const
         return ustring();
     }
 
-    Object info;
-    if (!d->doc->getDocInfo(&info)->isDict()) {
-        info.free();
+    std::auto_ptr<GooString> goo_value(d->doc->getDocInfoStringEntry(key.c_str()));
+    if (!goo_value.get()) {
         return ustring();
     }
 
-    Dict *info_dict = info.getDict();
-    Object obj;
-    ustring result;
-    if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) {
-        result = detail::unicode_GooString_to_ustring(obj.getString());
+    return detail::unicode_GooString_to_ustring(goo_value.get());
+}
+
+/**
+ Sets the value of the specified \p key of the %document information to \p val.
+ If \p val is empty, the entry specified by \p key is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_info_key(const std::string &key, const ustring &val)
+{
+    if (d->is_locked) {
+        return false;
     }
-    obj.free();
-    info.free();
-    return result;
+
+    GooString *goo_val;
+
+    if (val.empty()) {
+        goo_val = NULL;
+    } else {
+        goo_val = detail::ustring_to_unicode_GooString(val);
+    }
+
+    d->doc->setDocInfoStringEntry(key.c_str(), goo_val);
+    return true;
 }
 
 /**
@@ -371,21 +386,407 @@ time_type document::info_date(const std::string &key) const
         return time_type(-1);
     }
 
-    Object info;
-    if (!d->doc->getDocInfo(&info)->isDict()) {
-        info.free();
+    std::auto_ptr<GooString> goo_date(d->doc->getDocInfoStringEntry(key.c_str()));
+    if (!goo_date.get()) {
         return time_type(-1);
     }
 
-    Dict *info_dict = info.getDict();
-    Object obj;
-    time_type result = time_type(-1);
-    if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) {
-        result = dateStringToTime(obj.getString());
+    return dateStringToTime(goo_date.get());
+}
+
+/**
+ Sets the time_type value of the specified \p key of the %document information
+ to \p val.
+ If \p val == time_type(-1), the entry specified by \p key is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_info_date(const std::string &key, time_type val)
+{
+    if (d->is_locked) {
+        return false;
     }
-    obj.free();
-    info.free();
-    return result;
+
+    GooString *goo_date;
+
+    if (val == time_type(-1)) {
+        goo_date = NULL;
+    } else {
+        time_t t = static_cast<time_t> (val);
+        goo_date = timeToDateString(&t);
+    }
+
+    d->doc->setDocInfoStringEntry(key.c_str(), goo_date);
+    return true;
+}
+
+/**
+ Gets the %document's title.
+
+ \returns the document's title, or an empty string if not available
+ \see set_title, info_key
+ */
+ustring document::get_title() const
+{
+    if (d->is_locked) {
+        return ustring();
+    }
+
+    std::auto_ptr<GooString> goo_title(d->doc->getDocInfoTitle());
+    if (!goo_title.get()) {
+        return ustring();
+    }
+
+    return detail::unicode_GooString_to_ustring(goo_title.get());
+}
+
+/**
+ Sets the %document's title to \p title.
+ If \p title is empty, the %document's title is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_title(const ustring &title)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_title;
+
+    if (title.empty()) {
+        goo_title = NULL;
+    } else {
+        goo_title = detail::ustring_to_unicode_GooString(title);
+    }
+
+    d->doc->setDocInfoTitle(goo_title);
+    return true;
+}
+
+/**
+ Gets the document's author.
+
+ \returns the document's author, or an empty string if not available
+ \see set_author, info_key
+ */
+ustring document::get_author() const
+{
+    if (d->is_locked) {
+        return ustring();
+    }
+
+    std::auto_ptr<GooString> goo_author(d->doc->getDocInfoAuthor());
+    if (!goo_author.get()) {
+        return ustring();
+    }
+
+    return detail::unicode_GooString_to_ustring(goo_author.get());
+}
+
+/**
+ Sets the %document's author to \p author.
+ If \p author is empty, the %document's author is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_author(const ustring &author)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_author;
+
+    if (author.empty()) {
+        goo_author = NULL;
+    } else {
+        goo_author = detail::ustring_to_unicode_GooString(author);
+    }
+
+    d->doc->setDocInfoAuthor(goo_author);
+    return true;
+}
+
+/**
+ Gets the document's subject.
+
+ \returns the document's subject, or an empty string if not available
+ \see set_subject, info_key
+ */
+ustring document::get_subject() const
+{
+    if (d->is_locked) {
+        return ustring();
+    }
+
+    std::auto_ptr<GooString> goo_subject(d->doc->getDocInfoSubject());
+    if (!goo_subject.get()) {
+        return ustring();
+    }
+
+    return detail::unicode_GooString_to_ustring(goo_subject.get());
+}
+
+/**
+ Sets the %document's subject to \p subject.
+ If \p subject is empty, the %document's subject is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_subject(const ustring &subject)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_subject;
+
+    if (subject.empty()) {
+        goo_subject = NULL;
+    } else {
+        goo_subject = detail::ustring_to_unicode_GooString(subject);
+    }
+
+    d->doc->setDocInfoSubject(goo_subject);
+    return true;
+}
+
+/**
+ Gets the document's keywords.
+
+ \returns the document's keywords, or an empty string if not available
+ \see set_keywords, info_key
+ */
+ustring document::get_keywords() const
+{
+    if (d->is_locked) {
+        return ustring();
+    }
+
+    std::auto_ptr<GooString> goo_keywords(d->doc->getDocInfoKeywords());
+    if (!goo_keywords.get()) {
+        return ustring();
+    }
+
+    return detail::unicode_GooString_to_ustring(goo_keywords.get());
+}
+
+/**
+ Sets the %document's keywords to \p keywords.
+ If \p keywords is empty, the %document's keywords are removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_keywords(const ustring &keywords)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_keywords;
+
+    if (keywords.empty()) {
+        goo_keywords = NULL;
+    } else {
+        goo_keywords = detail::ustring_to_unicode_GooString(keywords);
+    }
+
+    d->doc->setDocInfoKeywords(goo_keywords);
+    return true;
+}
+
+/**
+ Gets the document's creator.
+
+ \returns the document's creator, or an empty string if not available
+ \see set_creator, info_key
+ */
+ustring document::get_creator() const
+{
+    if (d->is_locked) {
+        return ustring();
+    }
+
+    std::auto_ptr<GooString> goo_creator(d->doc->getDocInfoCreator());
+    if (!goo_creator.get()) {
+        return ustring();
+    }
+
+    return detail::unicode_GooString_to_ustring(goo_creator.get());
+}
+
+/**
+ Sets the %document's creator to \p creator.
+ If \p creator is empty, the %document's creator is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_creator(const ustring &creator)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_creator;
+
+    if (creator.empty()) {
+        goo_creator = NULL;
+    } else {
+        goo_creator = detail::ustring_to_unicode_GooString(creator);
+    }
+
+    d->doc->setDocInfoCreator(goo_creator);
+    return true;
+}
+
+/**
+ Gets the document's producer.
+
+ \returns the document's producer, or an empty string if not available
+ \see set_producer, info_key
+ */
+ustring document::get_producer() const
+{
+    if (d->is_locked) {
+        return ustring();
+    }
+
+    std::auto_ptr<GooString> goo_producer(d->doc->getDocInfoProducer());
+    if (!goo_producer.get()) {
+        return ustring();
+    }
+
+    return detail::unicode_GooString_to_ustring(goo_producer.get());
+}
+
+/**
+ Sets the %document's producer to \p producer.
+ If \p producer is empty, the %document's producer is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_producer(const ustring &producer)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_producer;
+
+    if (producer.empty()) {
+        goo_producer = NULL;
+    } else {
+        goo_producer = detail::ustring_to_unicode_GooString(producer);
+    }
+
+    d->doc->setDocInfoProducer(goo_producer);
+    return true;
+}
+
+/**
+ Gets the document's creation date as a time_type value.
+
+ \returns the document's creation date as a time_type value
+ \see set_creation_date, info_date
+ */
+time_type document::get_creation_date() const
+{
+    if (d->is_locked) {
+        return time_type(-1);
+    }
+
+    std::auto_ptr<GooString> goo_creation_date(d->doc->getDocInfoCreatDate());
+    if (!goo_creation_date.get()) {
+        return time_type(-1);
+    }
+
+    return dateStringToTime(goo_creation_date.get());
+}
+
+/**
+ Sets the %document's creation date to \p creation_date.
+ If \p creation_date == time_type(-1), the %document's creation date is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_creation_date(time_type creation_date)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_creation_date;
+
+    if (creation_date == time_type(-1)) {
+        goo_creation_date = NULL;
+    } else {
+        time_t t = static_cast<time_t> (creation_date);
+        goo_creation_date = timeToDateString(&t);
+    }
+
+    d->doc->setDocInfoCreatDate(goo_creation_date);
+    return true;
+}
+
+/**
+ Gets the document's modification date as a time_type value.
+
+ \returns the document's modification date as a time_type value
+ \see set_modification_date, info_date
+ */
+time_type document::get_modification_date() const
+{
+    if (d->is_locked) {
+        return time_type(-1);
+    }
+
+    std::auto_ptr<GooString> goo_modification_date(d->doc->getDocInfoModDate());
+    if (!goo_modification_date.get()) {
+        return time_type(-1);
+    }
+
+    return dateStringToTime(goo_modification_date.get());
+}
+
+/**
+ Sets the %document's modification date to \p mod_date.
+ If \p mod_date == time_type(-1), the %document's modification date is removed.
+
+ \returns true on success, false on failure
+ */
+bool document::set_modification_date(time_type mod_date)
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString *goo_mod_date;
+
+    if (mod_date == time_type(-1)) {
+        goo_mod_date = NULL;
+    } else {
+        time_t t = static_cast<time_t> (mod_date);
+        goo_mod_date = timeToDateString(&t);
+    }
+
+    d->doc->setDocInfoModDate(goo_mod_date);
+    return true;
+}
+
+/**
+ Removes the %document's Info dictionary.
+
+ \returns true on success, false on failure
+ */
+bool document::remove_info()
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    d->doc->removeDocInfo();
+    return true;
 }
 
 /**
diff --git a/cpp/poppler-document.h b/cpp/poppler-document.h
index cd0d3bd..f62f3b1 100644
--- a/cpp/poppler-document.h
+++ b/cpp/poppler-document.h
@@ -62,8 +62,32 @@ public:
     page_layout_enum page_layout() const;
     void get_pdf_version(int *major, int *minor) const;
     std::vector<std::string> info_keys() const;
+
     ustring info_key(const std::string &key) const;
+    bool set_info_key(const std::string &key, const ustring &val);
+
     time_type info_date(const std::string &key) const;
+    bool set_info_date(const std::string &key, time_type val);
+
+    ustring get_title() const;
+    bool set_title(const ustring &title);
+    ustring get_author() const;
+    bool set_author(const ustring &author);
+    ustring get_subject() const;
+    bool set_subject(const ustring &subject);
+    ustring get_keywords() const;
+    bool set_keywords(const ustring &keywords);
+    ustring get_creator() const;
+    bool set_creator(const ustring &creator);
+    ustring get_producer() const;
+    bool set_producer(const ustring &producer);
+    time_type get_creation_date() const;
+    bool set_creation_date(time_type creation_date);
+    time_type get_modification_date() const;
+    bool set_modification_date(time_type mod_date);
+
+    bool remove_info();
+
     bool is_encrypted() const;
     bool is_linearized() const;
     bool has_permission(permission_enum which) const;
commit 7f4a201226bc1112a121c749eb73f2a78e5149e3
Author: Jakub Kucharski <jakubkucharski97 at gmail.com>
Date:   Sun Jul 24 12:19:52 2016 +0200

    cpp: Added functions to save a document
    
    Part of Bug #36653

diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp
index 3b2c066..ead6a30 100644
--- a/cpp/poppler-document.cpp
+++ b/cpp/poppler-document.cpp
@@ -597,6 +597,36 @@ std::vector<embedded_file *> document::embedded_files() const
 }
 
 /**
+ Saves the %document to file \p file_name.
+
+ \returns true on success, false on failure
+ */
+bool document::save(const std::string &file_name) const
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString fname(file_name.c_str());
+    return d->doc->saveAs(&fname) == errNone;
+}
+
+/**
+ Saves the original version of the %document to file \p file_name.
+
+ \returns true on success, false on failure
+ */
+bool document::save_a_copy(const std::string &file_name) const
+{
+    if (d->is_locked) {
+        return false;
+    }
+
+    GooString fname(file_name.c_str());
+    return d->doc->saveWithoutChangesAs(&fname) == errNone;
+}
+
+/**
  Tries to load a PDF %document from the specified file.
 
  \param file_name the file to open
diff --git a/cpp/poppler-document.h b/cpp/poppler-document.h
index dfae398..cd0d3bd 100644
--- a/cpp/poppler-document.h
+++ b/cpp/poppler-document.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009-2010, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2016 Jakub Kucharski <jakubkucharski97 at gmail.com>
  *
  * 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
@@ -81,6 +82,9 @@ public:
     bool has_embedded_files() const;
     std::vector<embedded_file *> embedded_files() const;
 
+    bool save(const std::string &filename) const;
+    bool save_a_copy(const std::string &filename) const;
+
     static document* load_from_file(const std::string &file_name,
                                     const std::string &owner_password = std::string(),
                                     const std::string &user_password = std::string());


More information about the poppler mailing list