[poppler] 3 commits - poppler/Annot.cc qt5/src qt5/tests qt6/src qt6/tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Aug 24 21:21:47 UTC 2020


 poppler/Annot.cc                |   22 ++++++-----
 qt5/src/poppler-annotation.cc   |   55 ++++++++++++++++++-----------
 qt5/tests/check_annotations.cpp |   75 ++++++++++++++++++++++++++++++++++++++++
 qt6/src/poppler-annotation.cc   |   37 ++++++++++---------
 qt6/tests/check_annotations.cpp |   75 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 216 insertions(+), 48 deletions(-)

New commits:
commit 4febe9d3ba3359005098b134e5bbe2ec434c87fd
Author: Albert Astals Cid <aacid at kde.org>
Date:   Tue Aug 18 22:51:22 2020 +0200

    qt5: Be a bit more stubborn converting dates that come from xml

diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc
index c9af2210..afc6c879 100644
--- a/qt5/src/poppler-annotation.cc
+++ b/qt5/src/poppler-annotation.cc
@@ -1015,10 +1015,20 @@ Annotation::Annotation(AnnotationPrivate &dd, const QDomNode &annNode) : d_ptr(&
         setContents(e.attribute(QStringLiteral("contents")));
     if (e.hasAttribute(QStringLiteral("uniqueName")))
         setUniqueName(e.attribute(QStringLiteral("uniqueName")));
-    if (e.hasAttribute(QStringLiteral("modifyDate")))
-        setModificationDate(QDateTime::fromString(e.attribute(QStringLiteral("modifyDate"))));
-    if (e.hasAttribute(QStringLiteral("creationDate")))
-        setCreationDate(QDateTime::fromString(e.attribute(QStringLiteral("creationDate"))));
+    if (e.hasAttribute(QStringLiteral("modifyDate"))) {
+        QDateTime dt = QDateTime::fromString(e.attribute(QStringLiteral("modifyDate")));
+        if (!dt.isValid()) {
+            dt = QDateTime::fromString(e.attribute(QStringLiteral("modifyDate")), Qt::ISODate);
+        }
+        setModificationDate(dt);
+    }
+    if (e.hasAttribute(QStringLiteral("creationDate"))) {
+        QDateTime dt = QDateTime::fromString(e.attribute(QStringLiteral("creationDate")));
+        if (!dt.isValid()) {
+            dt = QDateTime::fromString(e.attribute(QStringLiteral("creationDate")), Qt::ISODate);
+        }
+        setCreationDate(dt);
+    }
 
     // parse -other- attributes
     if (e.hasAttribute(QStringLiteral("flags")))
commit 3023066f19509a8e5ced403d5afc804c4d6af238
Author: Albert Astals Cid <aacid at kde.org>
Date:   Tue Aug 18 22:38:43 2020 +0200

    qt5/6: Make Annotation::setModification/CreationDate work on existing annots
    
    With an autotest
    
    and bonus memory leak fixes for existing tests

diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc
index 79280023..c9af2210 100644
--- a/qt5/src/poppler-annotation.cc
+++ b/qt5/src/poppler-annotation.cc
@@ -52,6 +52,7 @@
 #include <Error.h>
 #include <FileSpec.h>
 #include <Link.h>
+#include <DateInfo.h>
 
 /* Almost all getters directly query the underlying poppler annotation, with
  * the exceptions of link, file attachment, sound, movie and screen annotations,
@@ -1342,15 +1343,16 @@ void Annotation::setModificationDate(const QDateTime &date)
         return;
     }
 
-#if 0 // TODO: Conversion routine is broken
-    if (d->pdfAnnot)
-    {
-        time_t t = date.toTime_t();
-        GooString *s = timeToDateString(&t);
-        d->pdfAnnot->setModified(s);
-        delete s;
+    if (d->pdfAnnot) {
+        if (date.isValid()) {
+            const time_t t = date.toTime_t();
+            GooString *s = timeToDateString(&t);
+            d->pdfAnnot->setModified(s);
+            delete s;
+        } else {
+            d->pdfAnnot->setModified(nullptr);
+        }
     }
-#endif
 }
 
 QDateTime Annotation::creationDate() const
@@ -1377,16 +1379,17 @@ void Annotation::setCreationDate(const QDateTime &date)
         return;
     }
 
-#if 0 // TODO: Conversion routine is broken
-    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
-    if (markupann)
-    {
-        time_t t = date.toTime_t();
-        GooString *s = timeToDateString(&t);
-        markupann->setDate(s);
-        delete s;
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup *>(d->pdfAnnot);
+    if (markupann) {
+        if (date.isValid()) {
+            const time_t t = date.toTime_t();
+            GooString *s = timeToDateString(&t);
+            markupann->setDate(s);
+            delete s;
+        } else {
+            markupann->setDate(nullptr);
+        }
     }
-#endif
 }
 
 static int fromPdfFlags(int flags)
diff --git a/qt5/tests/check_annotations.cpp b/qt5/tests/check_annotations.cpp
index c76e745c..266b8d57 100644
--- a/qt5/tests/check_annotations.cpp
+++ b/qt5/tests/check_annotations.cpp
@@ -16,11 +16,15 @@ class TestAnnotations : public QObject
     Q_OBJECT
 public:
     TestAnnotations(QObject *parent = nullptr) : QObject(parent) { }
+
+    void saveAndCheck(const std::unique_ptr<Poppler::Document> &doc, const std::function<void(Poppler::Annotation *a)> &checkFunction);
+
 private slots:
     void checkQColorPrecision();
     void checkFontSizeAndColor();
     void checkHighlightFromAndToQuads();
     void checkUTF16LEAnnot();
+    void checkModificationCreationDate();
     void checkNonMarkupAnnotations();
     void checkDefaultAppearance();
 };
@@ -137,6 +141,76 @@ void TestAnnotations::checkUTF16LEAnnot()
 
     auto annot = annots[1];
     QCOMPARE(annot->contents(), QString::fromUtf8("Únîcödé豰")); // clazy:exclude=qstring-allocations
+
+    qDeleteAll(annots);
+}
+
+void TestAnnotations::saveAndCheck(const std::unique_ptr<Poppler::Document> &doc, const std::function<void(Poppler::Annotation *a)> &checkFunction)
+{
+    // also check that saving yields the same output
+    QTemporaryFile tempFile;
+    QVERIFY(tempFile.open());
+    tempFile.close();
+
+    std::unique_ptr<Poppler::PDFConverter> conv(doc->pdfConverter());
+    conv->setOutputFileName(tempFile.fileName());
+    conv->setPDFOptions(Poppler::PDFConverter::WithChanges);
+    conv->convert();
+
+    std::unique_ptr<Poppler::Document> savedDoc { Poppler::Document::load(tempFile.fileName()) };
+    std::unique_ptr<Poppler::Page> page { doc->page(0) };
+    auto annots = page->annotations();
+    checkFunction(annots.at(1));
+    qDeleteAll(annots);
+}
+
+void TestAnnotations::checkModificationCreationDate()
+{
+    std::unique_ptr<Poppler::Document> doc { Poppler::Document::load(TESTDATADIR "/unittestcases/utf16le-annot.pdf") };
+    QVERIFY(doc.get());
+
+    std::unique_ptr<Poppler::Page> page { doc->page(0) };
+
+    auto annots = page->annotations();
+    auto annot = annots.at(1);
+    QCOMPARE(annot->creationDate(), QDateTime());
+    QCOMPARE(annot->modificationDate(), QDateTime());
+
+    const QDateTime dt1(QDate(2020, 8, 7), QTime(18, 34, 56));
+    annot->setCreationDate(dt1);
+    auto checkFunction1 = [dt1](Poppler::Annotation *a) {
+        QCOMPARE(a->creationDate(), dt1);
+        // setting the creation date updates the modification date
+        QVERIFY(std::abs(a->modificationDate().secsTo(QDateTime::currentDateTime())) < 2);
+    };
+    checkFunction1(annot);
+    saveAndCheck(doc, checkFunction1);
+
+    const QDateTime dt2(QDate(2020, 8, 30), QTime(8, 14, 52));
+    annot->setModificationDate(dt2);
+    auto checkFunction2 = [dt2](Poppler::Annotation *a) { QCOMPARE(a->modificationDate(), dt2); };
+    checkFunction2(annot);
+    saveAndCheck(doc, checkFunction2);
+
+    // setting the creation date to empty means "use the modification date" and also updates the modification date
+    // so both creation date and modification date are the same and are now
+    annot->setCreationDate(QDateTime());
+    auto checkFunction3 = [](Poppler::Annotation *a) {
+        QVERIFY(std::abs(a->creationDate().secsTo(QDateTime::currentDateTime())) < 2);
+        QCOMPARE(a->creationDate(), a->modificationDate());
+    };
+    checkFunction3(annot);
+    saveAndCheck(doc, checkFunction3);
+
+    annot->setModificationDate(QDateTime());
+    auto checkFunction4 = [](Poppler::Annotation *a) {
+        QCOMPARE(a->creationDate(), QDateTime());
+        QCOMPARE(a->modificationDate(), QDateTime());
+    };
+    checkFunction4(annot);
+    saveAndCheck(doc, checkFunction4);
+
+    qDeleteAll(annots);
 }
 
 void TestAnnotations::checkNonMarkupAnnotations()
@@ -149,6 +223,7 @@ void TestAnnotations::checkNonMarkupAnnotations()
 
     auto annots = page->annotations();
     QCOMPARE(annots.size(), 17);
+    qDeleteAll(annots);
 }
 
 void TestAnnotations::checkDefaultAppearance()
diff --git a/qt6/src/poppler-annotation.cc b/qt6/src/poppler-annotation.cc
index fd77a651..f12a9181 100644
--- a/qt6/src/poppler-annotation.cc
+++ b/qt6/src/poppler-annotation.cc
@@ -51,6 +51,7 @@
 #include <Error.h>
 #include <FileSpec.h>
 #include <Link.h>
+#include <DateInfo.h>
 
 /* Almost all getters directly query the underlying poppler annotation, with
  * the exceptions of link, file attachment, sound, movie and screen annotations,
@@ -1030,15 +1031,16 @@ void Annotation::setModificationDate(const QDateTime &date)
         return;
     }
 
-#if 0 // TODO: Conversion routine is broken
-    if (d->pdfAnnot)
-    {
-        time_t t = date.toTime_t();
-        GooString *s = timeToDateString(&t);
-        d->pdfAnnot->setModified(s);
-        delete s;
+    if (d->pdfAnnot) {
+        if (date.isValid()) {
+            const time_t t = date.toSecsSinceEpoch();
+            GooString *s = timeToDateString(&t);
+            d->pdfAnnot->setModified(s);
+            delete s;
+        } else {
+            d->pdfAnnot->setModified(nullptr);
+        }
     }
-#endif
 }
 
 QDateTime Annotation::creationDate() const
@@ -1065,16 +1067,17 @@ void Annotation::setCreationDate(const QDateTime &date)
         return;
     }
 
-#if 0 // TODO: Conversion routine is broken
-    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
-    if (markupann)
-    {
-        time_t t = date.toTime_t();
-        GooString *s = timeToDateString(&t);
-        markupann->setDate(s);
-        delete s;
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup *>(d->pdfAnnot);
+    if (markupann) {
+        if (date.isValid()) {
+            const time_t t = date.toSecsSinceEpoch();
+            GooString *s = timeToDateString(&t);
+            markupann->setDate(s);
+            delete s;
+        } else {
+            markupann->setDate(nullptr);
+        }
     }
-#endif
 }
 
 static Annotation::Flags fromPdfFlags(int flags)
diff --git a/qt6/tests/check_annotations.cpp b/qt6/tests/check_annotations.cpp
index 68e35a3d..c8f38044 100644
--- a/qt6/tests/check_annotations.cpp
+++ b/qt6/tests/check_annotations.cpp
@@ -16,11 +16,15 @@ class TestAnnotations : public QObject
     Q_OBJECT
 public:
     TestAnnotations(QObject *parent = nullptr) : QObject(parent) { }
+
+    void saveAndCheck(const std::unique_ptr<Poppler::Document> &doc, const std::function<void(Poppler::Annotation *a)> &checkFunction);
+
 private slots:
     void checkQColorPrecision();
     void checkFontSizeAndColor();
     void checkHighlightFromAndToQuads();
     void checkUTF16LEAnnot();
+    void checkModificationCreationDate();
     void checkNonMarkupAnnotations();
     void checkDefaultAppearance();
 };
@@ -137,6 +141,76 @@ void TestAnnotations::checkUTF16LEAnnot()
 
     auto annot = annots[1];
     QCOMPARE(annot->contents(), QString::fromUtf8("Únîcödé豰")); // clazy:exclude=qstring-allocations
+
+    qDeleteAll(annots);
+}
+
+void TestAnnotations::saveAndCheck(const std::unique_ptr<Poppler::Document> &doc, const std::function<void(Poppler::Annotation *a)> &checkFunction)
+{
+    // also check that saving yields the same output
+    QTemporaryFile tempFile;
+    QVERIFY(tempFile.open());
+    tempFile.close();
+
+    std::unique_ptr<Poppler::PDFConverter> conv(doc->pdfConverter());
+    conv->setOutputFileName(tempFile.fileName());
+    conv->setPDFOptions(Poppler::PDFConverter::WithChanges);
+    conv->convert();
+
+    std::unique_ptr<Poppler::Document> savedDoc { Poppler::Document::load(tempFile.fileName()) };
+    std::unique_ptr<Poppler::Page> page { doc->page(0) };
+    auto annots = page->annotations();
+    checkFunction(annots.at(1));
+    qDeleteAll(annots);
+}
+
+void TestAnnotations::checkModificationCreationDate()
+{
+    std::unique_ptr<Poppler::Document> doc { Poppler::Document::load(TESTDATADIR "/unittestcases/utf16le-annot.pdf") };
+    QVERIFY(doc.get());
+
+    std::unique_ptr<Poppler::Page> page { doc->page(0) };
+
+    auto annots = page->annotations();
+    auto annot = annots.at(1);
+    QCOMPARE(annot->creationDate(), QDateTime());
+    QCOMPARE(annot->modificationDate(), QDateTime());
+
+    const QDateTime dt1(QDate(2020, 8, 7), QTime(18, 34, 56));
+    annot->setCreationDate(dt1);
+    auto checkFunction1 = [dt1](Poppler::Annotation *a) {
+        QCOMPARE(a->creationDate(), dt1);
+        // setting the creation date updates the modification date
+        QVERIFY(std::abs(a->modificationDate().secsTo(QDateTime::currentDateTime())) < 2);
+    };
+    checkFunction1(annot);
+    saveAndCheck(doc, checkFunction1);
+
+    const QDateTime dt2(QDate(2020, 8, 30), QTime(8, 14, 52));
+    annot->setModificationDate(dt2);
+    auto checkFunction2 = [dt2](Poppler::Annotation *a) { QCOMPARE(a->modificationDate(), dt2); };
+    checkFunction2(annot);
+    saveAndCheck(doc, checkFunction2);
+
+    // setting the creation date to empty means "use the modification date" and also updates the modification date
+    // so both creation date and modification date are the same and are now
+    annot->setCreationDate(QDateTime());
+    auto checkFunction3 = [](Poppler::Annotation *a) {
+        QVERIFY(std::abs(a->creationDate().secsTo(QDateTime::currentDateTime())) < 2);
+        QCOMPARE(a->creationDate(), a->modificationDate());
+    };
+    checkFunction3(annot);
+    saveAndCheck(doc, checkFunction3);
+
+    annot->setModificationDate(QDateTime());
+    auto checkFunction4 = [](Poppler::Annotation *a) {
+        QCOMPARE(a->creationDate(), QDateTime());
+        QCOMPARE(a->modificationDate(), QDateTime());
+    };
+    checkFunction4(annot);
+    saveAndCheck(doc, checkFunction4);
+
+    qDeleteAll(annots);
 }
 
 void TestAnnotations::checkNonMarkupAnnotations()
@@ -149,6 +223,7 @@ void TestAnnotations::checkNonMarkupAnnotations()
 
     auto annots = page->annotations();
     QCOMPARE(annots.size(), 17);
+    qDeleteAll(annots);
 }
 
 void TestAnnotations::checkDefaultAppearance()
commit 7064bb38e918edd71d72cba5544b3f3ed73253cf
Author: Albert Astals Cid <aacid at kde.org>
Date:   Tue Aug 18 21:50:18 2020 +0200

    Fix clearing date in Annot setModified/setDate
    
    nullptr means nullptr not null string

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 9dad9808..9459e1aa 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1421,12 +1421,13 @@ void Annot::setModified(GooString *new_modified)
 {
     annotLocker();
 
-    if (new_modified)
+    if (new_modified) {
         modified = std::make_unique<GooString>(new_modified);
-    else
-        modified = std::make_unique<GooString>();
-
-    update("M", Object(modified->copy()));
+        update("M", Object(modified->copy()));
+    } else {
+        modified.reset(nullptr);
+        update("M", Object(objNull));
+    }
 }
 
 void Annot::setFlags(unsigned int new_flags)
@@ -2094,12 +2095,13 @@ void AnnotMarkup::setOpacity(double opacityA)
 
 void AnnotMarkup::setDate(GooString *new_date)
 {
-    if (new_date)
+    if (new_date) {
         date = std::make_unique<GooString>(new_date);
-    else
-        date = std::make_unique<GooString>();
-
-    update("CreationDate", Object(date->copy()));
+        update("CreationDate", Object(date->copy()));
+    } else {
+        date.reset(nullptr);
+        update("CreationDate", Object(objNull));
+    }
 }
 
 void AnnotMarkup::removeReferencedObjects()


More information about the poppler mailing list