diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2014-12-16 00:51:08 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2014-12-16 00:51:38 +0100 |
commit | c5c391e87636e5c4dbc3022b9d58626c1533f226 (patch) | |
tree | 679a8bbbc63395be30ebf5f6c80c1136f74a971f | |
parent | 86b7ed4df30f57fb994e5d032070ed118a9a7afa (diff) |
Clean up the loading
Unify the load API and implementation to always go through FPDFAvail.
-rw-r--r-- | src/pdf/qpdfdocument.cpp | 111 | ||||
-rw-r--r-- | src/pdf/qpdfdocument.h | 12 | ||||
-rw-r--r-- | src/pdf/qpdfdocument_p.h | 9 | ||||
-rw-r--r-- | tests/auto/qpdfdocument/tst_qpdfdocument.cpp | 15 |
4 files changed, 85 insertions, 62 deletions
diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp index b6c04e9..b48bbda 100644 --- a/src/pdf/qpdfdocument.cpp +++ b/src/pdf/qpdfdocument.cpp @@ -61,6 +61,9 @@ void QPdfDocumentPrivate::clear() asyncBuffer.close(); asyncBuffer.setData(QByteArray()); asyncBuffer.open(QIODevice::ReadWrite); + + if (sequentialSourceDevice) + sequentialSourceDevice->disconnect(q); } void QPdfDocumentPrivate::updateLastError() @@ -81,7 +84,7 @@ void QPdfDocumentPrivate::updateLastError() } } -QPdfDocument::Error QPdfDocumentPrivate::load(QIODevice *newDevice, bool transferDeviceOwnership, const QString &documentPassword) +void QPdfDocumentPrivate::load(QIODevice *newDevice, bool transferDeviceOwnership) { clear(); @@ -89,57 +92,69 @@ QPdfDocument::Error QPdfDocumentPrivate::load(QIODevice *newDevice, bool transfe ownDevice.reset(newDevice); else ownDevice.reset(); - device = newDevice; - - if (!device->isOpen() && !device->open(QIODevice::ReadOnly)) - return QPdfDocument::FileNotFoundError; - - // FPDF_FILEACCESS setup - m_FileLen = device->size(); - - password = documentPassword.toUtf8(); - doc = FPDF_LoadCustomDocument(this, password.constData()); - updateLastError(); - return lastError; + if (newDevice->isSequential()) { + sequentialSourceDevice = newDevice; + device = &asyncBuffer; + QNetworkReply *reply = qobject_cast<QNetworkReply*>(sequentialSourceDevice); + if (!reply) { + qWarning() << "QPdfDocument: Loading from sequential devices only supported with QNetworkAccessManager."; + return; + } + + if (reply->header(QNetworkRequest::ContentLengthHeader).isValid()) + _q_tryLoadingWithSizeFromContentHeader(); + else + QObject::connect(reply, SIGNAL(metaDataChanged()), q, SLOT(_q_tryLoadingWithSizeFromContentHeader())); + } else { + device = newDevice; + initiateAsyncLoadWithTotalSizeKnown(device->size()); + checkComplete(); + } } -void QPdfDocumentPrivate::_q_initiateAsyncLoad() +void QPdfDocumentPrivate::_q_tryLoadingWithSizeFromContentHeader() { QMutexLocker lock(pdfMutex()); if (avail) return; - QVariant contentLength = remoteDevice->header(QNetworkRequest::ContentLengthHeader); + QNetworkReply *networkReply = qobject_cast<QNetworkReply*>(sequentialSourceDevice); + if(!networkReply) + return; + + QVariant contentLength = networkReply->header(QNetworkRequest::ContentLengthHeader); if (!contentLength.isValid()) return; - // FPDF_FILEACCESS setup - m_FileLen = contentLength.toULongLong(); + QObject::connect(sequentialSourceDevice, SIGNAL(readyRead()), q, SLOT(_q_copyFromSequentialSourceDevice())); - QObject::connect(remoteDevice, SIGNAL(readyRead()), q, SLOT(_q_readFromDevice())); + initiateAsyncLoadWithTotalSizeKnown(contentLength.toULongLong()); - avail = FPDFAvail_Create(this, this); + if (sequentialSourceDevice->bytesAvailable()) + _q_copyFromSequentialSourceDevice(); +} - if (remoteDevice->bytesAvailable()) - _q_readFromDevice(); +void QPdfDocumentPrivate::initiateAsyncLoadWithTotalSizeKnown(quint64 totalSize) +{ + // FPDF_FILEACCESS setup + m_FileLen = totalSize; + + avail = FPDFAvail_Create(this, this); } -void QPdfDocumentPrivate::_q_readFromDevice() +void QPdfDocumentPrivate::_q_copyFromSequentialSourceDevice() { QMutexLocker lock(pdfMutex()); if (loadComplete) return; - QByteArray data = remoteDevice->read(remoteDevice->bytesAvailable()); + QByteArray data = sequentialSourceDevice->read(sequentialSourceDevice->bytesAvailable()); if (data.isEmpty()) return; asyncBuffer.seek(asyncBuffer.size()); asyncBuffer.write(data); - if (!doc) - tryLoadDocument(); - if (doc) - checkComplete(); + checkComplete(); } void QPdfDocumentPrivate::tryLoadDocument() @@ -161,7 +176,13 @@ void QPdfDocumentPrivate::tryLoadDocument() void QPdfDocumentPrivate::checkComplete() { QMutexLocker lock(pdfMutex()); - if (!doc || !avail) + if (!avail || loadComplete) + return; + + if (!doc) + tryLoadDocument(); + + if (!doc) return; loadComplete = true; @@ -175,7 +196,7 @@ void QPdfDocumentPrivate::checkComplete() bool QPdfDocumentPrivate::fpdf_IsDataAvail(_FX_FILEAVAIL *pThis, size_t offset, size_t size) { QPdfDocumentPrivate *d = static_cast<QPdfDocumentPrivate*>(pThis); - return offset + size <= static_cast<quint64>(d->asyncBuffer.size()); + return offset + size <= static_cast<quint64>(d->device->size()); } int QPdfDocumentPrivate::fpdf_GetBlock(void *param, unsigned long position, unsigned char *pBuf, unsigned long size) @@ -204,35 +225,27 @@ QPdfDocument::~QPdfDocument() { } -QPdfDocument::Error QPdfDocument::load(const QString &fileName, const QString &password) +QPdfDocument::Error QPdfDocument::load(const QString &fileName) { QMutexLocker lock(pdfMutex()); - return d->load(new QFile(fileName), /*transfer ownership*/true, password); + QScopedPointer<QFile> f(new QFile(fileName)); + if (!f->open(QIODevice::ReadOnly)) { + d->lastError = FileNotFoundError; + } else { + d->load(f.take(), /*transfer ownership*/true); + } + return d->lastError; } -QPdfDocument::Error QPdfDocument::load(QIODevice *device, const QString &password) +bool QPdfDocument::isLoading() const { - QMutexLocker lock(pdfMutex()); - return d->load(device, /*transfer ownership*/false, password); + return !d->loadComplete; } -void QPdfDocument::loadAsynchronously(QNetworkReply *device) +void QPdfDocument::load(QIODevice *device) { QMutexLocker lock(pdfMutex()); - d->clear(); - - d->ownDevice.reset(); - d->device = &d->asyncBuffer; - - if (d->remoteDevice) - d->remoteDevice->disconnect(this); - - d->remoteDevice = device; - - if (d->remoteDevice->header(QNetworkRequest::ContentLengthHeader).isValid()) - d->_q_initiateAsyncLoad(); - else - connect(d->remoteDevice, SIGNAL(metaDataChanged()), this, SLOT(_q_initiateAsyncLoad())); + d->load(device, /*transfer ownership*/false); } void QPdfDocument::setPassword(const QString &password) diff --git a/src/pdf/qpdfdocument.h b/src/pdf/qpdfdocument.h index ed87cac..6459f39 100644 --- a/src/pdf/qpdfdocument.h +++ b/src/pdf/qpdfdocument.h @@ -15,6 +15,7 @@ class Q_PDF_EXPORT QPdfDocument : public QObject Q_OBJECT Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged FINAL) Q_PROPERTY(QString password READ password WRITE setPassword FINAL) + Q_PROPERTY(bool loading READ isLoading FINAL) public: enum Error { @@ -29,10 +30,11 @@ public: explicit QPdfDocument(QObject *parent = 0); ~QPdfDocument(); - Error load(const QString &fileName, const QString &password = QString()); - Error load(QIODevice *device, const QString &password = QString()); + Error load(const QString &fileName); - void loadAsynchronously(QNetworkReply *device); + bool isLoading() const; + + void load(QIODevice *device); void setPassword(const QString &password); QString password() const; @@ -51,8 +53,8 @@ Q_SIGNALS: void pageCountChanged(); private: - Q_PRIVATE_SLOT(d, void _q_initiateAsyncLoad()) - Q_PRIVATE_SLOT(d, void _q_readFromDevice()) + Q_PRIVATE_SLOT(d, void _q_tryLoadingWithSizeFromContentHeader()) + Q_PRIVATE_SLOT(d, void _q_copyFromSequentialSourceDevice()) QScopedPointer<QPdfDocumentPrivate> d; }; diff --git a/src/pdf/qpdfdocument_p.h b/src/pdf/qpdfdocument_p.h index f37881d..7850c65 100644 --- a/src/pdf/qpdfdocument_p.h +++ b/src/pdf/qpdfdocument_p.h @@ -27,18 +27,19 @@ public: QPointer<QIODevice> device; QScopedPointer<QIODevice> ownDevice; QBuffer asyncBuffer; - QPointer<QNetworkReply> remoteDevice; + QPointer<QIODevice> sequentialSourceDevice; QByteArray password; QPdfDocument::Error lastError; void clear(); - QPdfDocument::Error load(QIODevice *device, bool ownDevice, const QString &documentPassword); + void load(QIODevice *device, bool ownDevice); void loadAsync(QIODevice *device); - void _q_initiateAsyncLoad(); - void _q_readFromDevice(); + void _q_tryLoadingWithSizeFromContentHeader(); + void initiateAsyncLoadWithTotalSizeKnown(quint64 totalSize); + void _q_copyFromSequentialSourceDevice(); void tryLoadDocument(); void checkComplete(); diff --git a/tests/auto/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/qpdfdocument/tst_qpdfdocument.cpp index 6ebd197..336c6e8 100644 --- a/tests/auto/qpdfdocument/tst_qpdfdocument.cpp +++ b/tests/auto/qpdfdocument/tst_qpdfdocument.cpp @@ -66,7 +66,12 @@ void tst_QPdfDocument::loadFromIODevice() { TemporaryPdf tempPdf; QPdfDocument doc; - QCOMPARE(doc.load(&tempPdf), QPdfDocument::NoError); + QSignalSpy startedSpy(&doc, SIGNAL(documentLoadStarted())); + QSignalSpy finishedSpy(&doc, SIGNAL(documentLoadFinished())); + doc.load(&tempPdf); + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(doc.error(), QPdfDocument::NoError); QCOMPARE(doc.pageCount(), 2); } @@ -83,7 +88,7 @@ void tst_QPdfDocument::loadAsync() QSignalSpy startedSpy(&doc, SIGNAL(documentLoadStarted())); QSignalSpy finishedSpy(&doc, SIGNAL(documentLoadFinished())); - doc.loadAsynchronously(reply.data()); + doc.load(reply.data()); QCOMPARE(startedSpy.count(), 1); QCOMPARE(finishedSpy.count(), 1); @@ -95,8 +100,10 @@ void tst_QPdfDocument::password() QPdfDocument doc; QCOMPARE(doc.pageCount(), 0); QCOMPARE(doc.load(QFINDTESTDATA("pdf-sample.protected.pdf")), QPdfDocument::IncorrectPasswordError); - QCOMPARE(doc.load(QFINDTESTDATA("pdf-sample.protected.pdf"), QStringLiteral("WrongPassword")), QPdfDocument::IncorrectPasswordError); - QCOMPARE(doc.load(QFINDTESTDATA("pdf-sample.protected.pdf"), QStringLiteral("Qt")), QPdfDocument::NoError); + doc.setPassword(QStringLiteral("WrongPassword")); + QCOMPARE(doc.load(QFINDTESTDATA("pdf-sample.protected.pdf")), QPdfDocument::IncorrectPasswordError); + doc.setPassword(QStringLiteral("Qt")); + QCOMPARE(doc.load(QFINDTESTDATA("pdf-sample.protected.pdf")), QPdfDocument::NoError); QCOMPARE(doc.pageCount(), 1); } |