Spaces:
Running
Running
/* poppler-document.cc: qt interface to poppler | |
* Copyright (C) 2005, Net Integration Technologies, Inc. | |
* Copyright (C) 2005, 2008, Brad Hards <[email protected]> | |
* Copyright (C) 2005-2010, 2012, 2013, 2015, 2017-2022, Albert Astals Cid <[email protected]> | |
* Copyright (C) 2006-2010, Pino Toscano <[email protected]> | |
* Copyright (C) 2010, 2011 Hib Eris <[email protected]> | |
* Copyright (C) 2012 Koji Otani <[email protected]> | |
* Copyright (C) 2012, 2013 Thomas Freitag <[email protected]> | |
* Copyright (C) 2012 Fabio D'Urso <[email protected]> | |
* Copyright (C) 2014, 2018, 2020 Adam Reichold <[email protected]> | |
* Copyright (C) 2015 William Bader <[email protected]> | |
* Copyright (C) 2016 Jakub Alba <[email protected]> | |
* Copyright (C) 2017, 2021 Adrian Johnson <[email protected]> | |
* Copyright (C) 2017 Suzuki Toshiya <[email protected]> | |
* Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <[email protected]>. Work sponsored by the LiMux project of the city of Munich | |
* Copyright (C) 2019-2021 Oliver Sander <[email protected]> | |
* Copyright (C) 2019 Alexander Volkov <[email protected]> | |
* Copyright (C) 2020 Philipp Knechtges <[email protected]> | |
* Copyright (C) 2020 Katarina Behrens <[email protected]> | |
* Copyright (C) 2020 Thorsten Behrens <[email protected]> | |
* Copyright (C) 2021 Mahmoud Khalil <[email protected]> | |
* Copyright (C) 2021 Hubert Figuiere <[email protected]> | |
* | |
* 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 | |
* the Free Software Foundation; either version 2, or (at your option) | |
* any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. | |
*/ | |
namespace Poppler { | |
std::unique_ptr<Document> Document::load(const QString &filePath, const QByteArray &ownerPassword, const QByteArray &userPassword) | |
{ | |
DocumentData *doc = new DocumentData(filePath, GooString(ownerPassword.data()), GooString(userPassword.data())); | |
return DocumentData::checkDocument(doc); | |
} | |
std::unique_ptr<Document> Document::load(QIODevice *device, const QByteArray &ownerPassword, const QByteArray &userPassword) | |
{ | |
DocumentData *doc = new DocumentData(device, GooString(ownerPassword.data()), GooString(userPassword.data())); | |
return DocumentData::checkDocument(doc); | |
} | |
std::unique_ptr<Document> Document::loadFromData(const QByteArray &fileContents, const QByteArray &ownerPassword, const QByteArray &userPassword) | |
{ | |
// create stream | |
DocumentData *doc = new DocumentData(fileContents, GooString(ownerPassword.data()), GooString(userPassword.data())); | |
return DocumentData::checkDocument(doc); | |
} | |
std::unique_ptr<Document> DocumentData::checkDocument(DocumentData *doc) | |
{ | |
if (doc->doc->isOk() || doc->doc->getErrorCode() == errEncrypted) { | |
auto pdoc = std::unique_ptr<Document>(new Document(doc)); | |
if (doc->doc->getErrorCode() == errEncrypted) { | |
pdoc->m_doc->locked = true; | |
} else { | |
pdoc->m_doc->locked = false; | |
pdoc->m_doc->fillMembers(); | |
} | |
return pdoc; | |
} else { | |
delete doc; | |
} | |
return nullptr; | |
} | |
Document::Document(DocumentData *dataA) | |
{ | |
m_doc = dataA; | |
} | |
Document::~Document() | |
{ | |
delete m_doc; | |
} | |
std::unique_ptr<Page> Document::page(int index) const | |
{ | |
// Cannot call std::make_unique, because the constructor of Page is private | |
auto page = std::unique_ptr<Page>(new Page(m_doc, index)); | |
if (page->m_page->page == nullptr) { | |
page.reset(); | |
} | |
return page; | |
} | |
bool Document::isLocked() const | |
{ | |
return m_doc->locked; | |
} | |
bool Document::unlock(const QByteArray &ownerPassword, const QByteArray &userPassword) | |
{ | |
if (m_doc->locked) { | |
/* racier then it needs to be */ | |
DocumentData *doc2; | |
if (!m_doc->fileContents.isEmpty()) { | |
doc2 = new DocumentData(m_doc->fileContents, GooString(ownerPassword.data()), GooString(userPassword.data())); | |
} else if (m_doc->m_device) { | |
doc2 = new DocumentData(m_doc->m_device, GooString(ownerPassword.data()), GooString(userPassword.data())); | |
} else { | |
doc2 = new DocumentData(m_doc->m_filePath, GooString(ownerPassword.data()), GooString(userPassword.data())); | |
} | |
if (!doc2->doc->isOk()) { | |
delete doc2; | |
} else { | |
delete m_doc; | |
m_doc = doc2; | |
m_doc->locked = false; | |
m_doc->fillMembers(); | |
} | |
} | |
return m_doc->locked; | |
} | |
Document::PageMode Document::pageMode() const | |
{ | |
switch (m_doc->doc->getCatalog()->getPageMode()) { | |
case Catalog::pageModeNone: | |
return UseNone; | |
case Catalog::pageModeOutlines: | |
return UseOutlines; | |
case Catalog::pageModeThumbs: | |
return UseThumbs; | |
case Catalog::pageModeFullScreen: | |
return FullScreen; | |
case Catalog::pageModeOC: | |
return UseOC; | |
case Catalog::pageModeAttach: | |
return UseAttach; | |
default: | |
return UseNone; | |
} | |
} | |
Document::PageLayout Document::pageLayout() const | |
{ | |
switch (m_doc->doc->getCatalog()->getPageLayout()) { | |
case Catalog::pageLayoutNone: | |
return NoLayout; | |
case Catalog::pageLayoutSinglePage: | |
return SinglePage; | |
case Catalog::pageLayoutOneColumn: | |
return OneColumn; | |
case Catalog::pageLayoutTwoColumnLeft: | |
return TwoColumnLeft; | |
case Catalog::pageLayoutTwoColumnRight: | |
return TwoColumnRight; | |
case Catalog::pageLayoutTwoPageLeft: | |
return TwoPageLeft; | |
case Catalog::pageLayoutTwoPageRight: | |
return TwoPageRight; | |
default: | |
return NoLayout; | |
} | |
} | |
Qt::LayoutDirection Document::textDirection() const | |
{ | |
if (!m_doc->doc->getCatalog()->getViewerPreferences()) { | |
return Qt::LayoutDirectionAuto; | |
} | |
switch (m_doc->doc->getCatalog()->getViewerPreferences()->getDirection()) { | |
case ViewerPreferences::directionL2R: | |
return Qt::LeftToRight; | |
case ViewerPreferences::directionR2L: | |
return Qt::RightToLeft; | |
default: | |
return Qt::LayoutDirectionAuto; | |
} | |
} | |
int Document::numPages() const | |
{ | |
return m_doc->doc->getNumPages(); | |
} | |
QList<FontInfo> Document::fonts() const | |
{ | |
QList<FontInfo> ourList; | |
FontIterator it(0, m_doc); | |
while (it.hasNext()) { | |
ourList += it.next(); | |
} | |
return ourList; | |
} | |
QList<EmbeddedFile *> Document::embeddedFiles() const | |
{ | |
return m_doc->m_embeddedFiles; | |
} | |
std::unique_ptr<FontIterator> Document::newFontIterator(int startPage) const | |
{ | |
// Cannot use std::make_unique, because the FontIterator constructor is private | |
return std::unique_ptr<FontIterator>(new FontIterator(startPage, m_doc)); | |
} | |
QByteArray Document::fontData(const FontInfo &fi) const | |
{ | |
QByteArray result; | |
if (fi.isEmbedded()) { | |
XRef *xref = m_doc->doc->getXRef()->copy(); | |
Object refObj(fi.m_data->embRef); | |
Object strObj = refObj.fetch(xref); | |
if (strObj.isStream()) { | |
int c; | |
strObj.streamReset(); | |
while ((c = strObj.streamGetChar()) != EOF) { | |
result.append((char)c); | |
} | |
strObj.streamClose(); | |
} | |
delete xref; | |
} | |
return result; | |
} | |
QString Document::info(const QString &type) const | |
{ | |
if (m_doc->locked) { | |
return QString(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData())); | |
return UnicodeParsedString(goo.get()); | |
} | |
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(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoTitle()); | |
return UnicodeParsedString(goo.get()); | |
} | |
bool Document::setTitle(const QString &val) | |
{ | |
if (m_doc->locked) { | |
return false; | |
} | |
m_doc->doc->setDocInfoTitle(QStringToUnicodeGooString(val)); | |
return true; | |
} | |
QString Document::author() const | |
{ | |
if (m_doc->locked) { | |
return QString(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoAuthor()); | |
return UnicodeParsedString(goo.get()); | |
} | |
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(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoSubject()); | |
return UnicodeParsedString(goo.get()); | |
} | |
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(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoKeywords()); | |
return UnicodeParsedString(goo.get()); | |
} | |
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(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoCreator()); | |
return UnicodeParsedString(goo.get()); | |
} | |
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(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoProducer()); | |
return UnicodeParsedString(goo.get()); | |
} | |
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 | |
{ | |
QStringList keys; | |
if (m_doc->locked) { | |
return QStringList(); | |
} | |
QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy()); | |
if (!xref) { | |
return QStringList(); | |
} | |
Object info = xref->getDocInfo(); | |
if (!info.isDict()) { | |
return QStringList(); | |
} | |
Dict *infoDict = info.getDict(); | |
// somehow iterate over keys in infoDict | |
keys.reserve(infoDict->getLength()); | |
for (int i = 0; i < infoDict->getLength(); ++i) { | |
keys.append(QString::fromLatin1(infoDict->getKey(i))); | |
} | |
return keys; | |
} | |
QDateTime Document::date(const QString &type) const | |
{ | |
if (m_doc->locked) { | |
return QDateTime(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData())); | |
QString str = UnicodeParsedString(goo.get()); | |
return Poppler::convertDate(str.toLatin1().constData()); | |
} | |
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(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoCreatDate()); | |
QString str = UnicodeParsedString(goo.get()); | |
return Poppler::convertDate(str.toLatin1().constData()); | |
} | |
bool Document::setCreationDate(const QDateTime &val) | |
{ | |
if (m_doc->locked) { | |
return false; | |
} | |
m_doc->doc->setDocInfoCreatDate(QDateTimeToUnicodeGooString(val)); | |
return true; | |
} | |
QDateTime Document::modificationDate() const | |
{ | |
if (m_doc->locked) { | |
return QDateTime(); | |
} | |
std::unique_ptr<GooString> goo(m_doc->doc->getDocInfoModDate()); | |
QString str = UnicodeParsedString(goo.get()); | |
return Poppler::convertDate(str.toLatin1().constData()); | |
} | |
bool Document::setModificationDate(const QDateTime &val) | |
{ | |
if (m_doc->locked) { | |
return false; | |
} | |
m_doc->doc->setDocInfoModDate(QDateTimeToUnicodeGooString(val)); | |
return true; | |
} | |
bool Document::isEncrypted() const | |
{ | |
return m_doc->doc->isEncrypted(); | |
} | |
bool Document::isLinearized() const | |
{ | |
return m_doc->doc->isLinearized(); | |
} | |
bool Document::okToPrint() const | |
{ | |
return m_doc->doc->okToPrint(); | |
} | |
bool Document::okToPrintHighRes() const | |
{ | |
return m_doc->doc->okToPrintHighRes(); | |
} | |
bool Document::okToChange() const | |
{ | |
return m_doc->doc->okToChange(); | |
} | |
bool Document::okToCopy() const | |
{ | |
return m_doc->doc->okToCopy(); | |
} | |
bool Document::okToAddNotes() const | |
{ | |
return m_doc->doc->okToAddNotes(); | |
} | |
bool Document::okToFillForm() const | |
{ | |
return m_doc->doc->okToFillForm(); | |
} | |
bool Document::okToCreateFormFields() const | |
{ | |
return (okToFillForm() && okToChange()); | |
} | |
bool Document::okToExtractForAccessibility() const | |
{ | |
return m_doc->doc->okToAccessibility(); | |
} | |
bool Document::okToAssemble() const | |
{ | |
return m_doc->doc->okToAssemble(); | |
} | |
Document::PdfVersion Document::getPdfVersion() const | |
{ | |
return PdfVersion { m_doc->doc->getPDFMajorVersion(), m_doc->doc->getPDFMinorVersion() }; | |
} | |
std::unique_ptr<Page> Document::page(const QString &label) const | |
{ | |
GooString label_g(label.toLatin1().data()); | |
int index; | |
if (!m_doc->doc->getCatalog()->labelToIndex(&label_g, &index)) { | |
std::unique_ptr<GooString> label_ug(QStringToUnicodeGooString(label)); | |
if (!m_doc->doc->getCatalog()->labelToIndex(label_ug.get(), &index)) { | |
return nullptr; | |
} | |
} | |
return page(index); | |
} | |
bool Document::hasEmbeddedFiles() const | |
{ | |
return (!(0 == m_doc->doc->getCatalog()->numEmbeddedFiles())); | |
} | |
QVector<OutlineItem> Document::outline() const | |
{ | |
QVector<OutlineItem> result; | |
if (::Outline *outline = m_doc->doc->getOutline()) { | |
if (const std::vector<::OutlineItem *> *items = outline->getItems()) { | |
for (void *item : *items) { | |
result.push_back(OutlineItem { new OutlineItemData { static_cast<::OutlineItem *>(item), m_doc } }); | |
} | |
} | |
} | |
return result; | |
} | |
std::unique_ptr<LinkDestination> Document::linkDestination(const QString &name) | |
{ | |
GooString *namedDest = QStringToGooString(name); | |
LinkDestinationData ldd(nullptr, namedDest, m_doc, false); | |
auto ld = std::make_unique<LinkDestination>(ldd); | |
delete namedDest; | |
return ld; | |
} | |
void Document::setPaperColor(const QColor &color) | |
{ | |
m_doc->setPaperColor(color); | |
} | |
void Document::setColorDisplayProfile(void *outputProfileA) | |
{ | |
if (m_doc->m_sRGBProfile && m_doc->m_sRGBProfile.get() == outputProfileA) { | |
// Catch the special case that the user passes the sRGB profile | |
m_doc->m_displayProfile = m_doc->m_sRGBProfile; | |
return; | |
} | |
if (m_doc->m_displayProfile && m_doc->m_displayProfile.get() == outputProfileA) { | |
// Catch the special case that the user passes the display profile | |
return; | |
} | |
m_doc->m_displayProfile = make_GfxLCMSProfilePtr(outputProfileA); | |
Q_UNUSED(outputProfileA); | |
} | |
void Document::setColorDisplayProfileName(const QString &name) | |
{ | |
void *rawprofile = cmsOpenProfileFromFile(name.toLocal8Bit().constData(), "r"); | |
m_doc->m_displayProfile = make_GfxLCMSProfilePtr(rawprofile); | |
Q_UNUSED(name); | |
} | |
void *Document::colorRgbProfile() const | |
{ | |
if (!m_doc->m_sRGBProfile) { | |
m_doc->m_sRGBProfile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile()); | |
} | |
return m_doc->m_sRGBProfile.get(); | |
return nullptr; | |
} | |
void *Document::colorDisplayProfile() const | |
{ | |
return m_doc->m_displayProfile.get(); | |
return nullptr; | |
} | |
QColor Document::paperColor() const | |
{ | |
return m_doc->paperColor; | |
} | |
void Document::setRenderBackend(Document::RenderBackend backend) | |
{ | |
// no need to delete the outputdev as for the moment we always create a splash one | |
// as the QPainter one does not allow "precaching" due to its signature | |
// delete m_doc->m_outputDev; | |
// m_doc->m_outputDev = NULL; | |
m_doc->m_backend = backend; | |
} | |
Document::RenderBackend Document::renderBackend() const | |
{ | |
return m_doc->m_backend; | |
} | |
QSet<Document::RenderBackend> Document::availableRenderBackends() | |
{ | |
QSet<Document::RenderBackend> ret; | |
ret << Document::SplashBackend; | |
ret << Document::QPainterBackend; | |
return ret; | |
} | |
void Document::setRenderHint(Document::RenderHint hint, bool on) | |
{ | |
const bool touchesOverprinting = hint & Document::OverprintPreview; | |
int hintForOperation = hint; | |
if (touchesOverprinting && !isOverprintPreviewAvailable()) { | |
hintForOperation = hintForOperation & ~(int)Document::OverprintPreview; | |
} | |
if (on) { | |
m_doc->m_hints |= hintForOperation; | |
} else { | |
m_doc->m_hints &= ~hintForOperation; | |
} | |
} | |
Document::RenderHints Document::renderHints() const | |
{ | |
return Document::RenderHints(m_doc->m_hints); | |
} | |
std::unique_ptr<PSConverter> Document::psConverter() const | |
{ | |
// Cannot use std::make_unique, because the PSConverter constructor is private | |
return std::unique_ptr<PSConverter>(new PSConverter(m_doc)); | |
} | |
std::unique_ptr<PDFConverter> Document::pdfConverter() const | |
{ | |
// Cannot use std::make_unique, because the PDFConverter constructor is private | |
return std::unique_ptr<PDFConverter>(new PDFConverter(m_doc)); | |
} | |
QString Document::metadata() const | |
{ | |
QString result; | |
Catalog *catalog = m_doc->doc->getCatalog(); | |
if (catalog && catalog->isOk()) { | |
std::unique_ptr<GooString> s = catalog->readMetadata(); | |
if (s) { | |
result = UnicodeParsedString(s.get()); | |
} | |
} | |
return result; | |
} | |
bool Document::hasOptionalContent() const | |
{ | |
return (m_doc->doc->getOptContentConfig() && m_doc->doc->getOptContentConfig()->hasOCGs()); | |
} | |
OptContentModel *Document::optionalContentModel() | |
{ | |
if (m_doc->m_optContentModel.isNull()) { | |
m_doc->m_optContentModel = new OptContentModel(m_doc->doc->getOptContentConfig(), nullptr); | |
} | |
return (OptContentModel *)m_doc->m_optContentModel; | |
} | |
QStringList Document::scripts() const | |
{ | |
Catalog *catalog = m_doc->doc->getCatalog(); | |
const int numScripts = catalog->numJS(); | |
QStringList scripts; | |
for (int i = 0; i < numScripts; ++i) { | |
GooString *s = catalog->getJS(i); | |
if (s) { | |
scripts.append(UnicodeParsedString(s)); | |
delete s; | |
} | |
} | |
return scripts; | |
} | |
bool Document::getPdfId(QByteArray *permanentId, QByteArray *updateId) const | |
{ | |
GooString gooPermanentId; | |
GooString gooUpdateId; | |
if (!m_doc->doc->getID(permanentId ? &gooPermanentId : nullptr, updateId ? &gooUpdateId : nullptr)) { | |
return false; | |
} | |
if (permanentId) { | |
*permanentId = gooPermanentId.c_str(); | |
} | |
if (updateId) { | |
*updateId = gooUpdateId.c_str(); | |
} | |
return true; | |
} | |
Document::FormType Document::formType() const | |
{ | |
switch (m_doc->doc->getCatalog()->getFormType()) { | |
case Catalog::NoForm: | |
return Document::NoForm; | |
case Catalog::AcroForm: | |
return Document::AcroForm; | |
case Catalog::XfaForm: | |
return Document::XfaForm; | |
} | |
return Document::NoForm; // make gcc happy | |
} | |
QVector<int> Document::formCalculateOrder() const | |
{ | |
Form *form = m_doc->doc->getCatalog()->getForm(); | |
if (!form) { | |
return {}; | |
} | |
QVector<int> result; | |
const std::vector<Ref> &calculateOrder = form->getCalculateOrder(); | |
for (Ref r : calculateOrder) { | |
FormWidget *w = form->findWidgetByRef(r); | |
if (w) { | |
result << w->getID(); | |
} | |
} | |
return result; | |
} | |
std::vector<std::unique_ptr<FormFieldSignature>> Document::signatures() const | |
{ | |
std::vector<std::unique_ptr<FormFieldSignature>> result; | |
const std::vector<::FormFieldSignature *> pSignatures = m_doc->doc->getSignatureFields(); | |
for (::FormFieldSignature *pSignature : pSignatures) { | |
::FormWidget *fw = pSignature->getCreateWidget(); | |
::Page *p = m_doc->doc->getPage(fw->getWidgetAnnotation()->getPageNum()); | |
result.push_back(std::make_unique<FormFieldSignature>(m_doc, p, static_cast<FormWidgetSignature *>(fw))); | |
} | |
return result; | |
} | |
bool Document::xrefWasReconstructed() const | |
{ | |
return m_doc->xrefReconstructed; | |
} | |
void Document::setXRefReconstructedCallback(const std::function<void()> &callback) | |
{ | |
m_doc->xrefReconstructedCallback = callback; | |
} | |
QDateTime convertDate(const char *dateString) | |
{ | |
int year, mon, day, hour, min, sec, tzHours, tzMins; | |
char tz; | |
GooString date(dateString); | |
if (parseDateString(&date, &year, &mon, &day, &hour, &min, &sec, &tz, &tzHours, &tzMins)) { | |
QDate d(year, mon, day); | |
QTime t(hour, min, sec); | |
if (d.isValid() && t.isValid()) { | |
QDateTime dt(d, t, Qt::UTC); | |
if (tz) { | |
// then we have some form of timezone | |
if ('Z' == tz) { | |
// We are already at UTC | |
} else if ('+' == tz) { | |
// local time is ahead of UTC | |
dt = dt.addSecs(-1 * ((tzHours * 60) + tzMins) * 60); | |
} else if ('-' == tz) { | |
// local time is behind UTC | |
dt = dt.addSecs(((tzHours * 60) + tzMins) * 60); | |
} else { | |
qWarning("unexpected tz val"); | |
} | |
} | |
return dt; | |
} | |
} | |
return QDateTime(); | |
} | |
bool isCmsAvailable() | |
{ | |
return true; | |
return false; | |
} | |
bool isOverprintPreviewAvailable() | |
{ | |
return true; | |
} | |
} | |