From 8dddbb9d4b5ec2d742984814c9483a95d8c773ac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 17 Sep 2014 14:07:10 -0700 Subject: [PATCH] make snapshots uploaded for locations temp files that will be cleared --- interface/src/location/LocationManager.cpp | 75 +++++++++++----------- interface/src/ui/Snapshot.cpp | 60 ++++++++++++++--- interface/src/ui/Snapshot.h | 4 ++ 3 files changed, 93 insertions(+), 46 deletions(-) diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 866e92be98..ed27d9e49d 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -104,47 +104,48 @@ void LocationManager::updateSnapshotForExistingLocation(const QString& locationI // first create a snapshot and save it Application* application = Application::getInstance(); - QString filename = Snapshot::saveSnapshot(application->getGLWidget(), application->getAvatar()); + QTemporaryFile* tempImageFile = Snapshot::saveTempSnapshot(application->getGLWidget(), application->getAvatar()); - AccountManager& accountManager = AccountManager::getInstance(); - - // setup a multipart that is in the AccountManager thread - we need this so it can be cleaned up after the QNetworkReply - QHttpMultiPart* imageFileMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); - imageFileMultiPart->moveToThread(accountManager.thread()); - - // load the file at that filename, parent the mile to the QHttpMultipart - QFile* locationImageFile = new QFile(filename, imageFileMultiPart); - - if (!locationImageFile->open(QIODevice::ReadOnly)) { + if (tempImageFile && tempImageFile->open()) { + AccountManager& accountManager = AccountManager::getInstance(); + + // setup a multipart that is in the AccountManager thread - we need this so it can be cleaned up after the QNetworkReply + QHttpMultiPart* imageFileMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + imageFileMultiPart->moveToThread(accountManager.thread()); + + // parent the temp file to the QHttpMultipart after moving it to account manager thread + tempImageFile->moveToThread(accountManager.thread()); + tempImageFile->setParent(imageFileMultiPart); + + qDebug() << "Uploading a snapshot from" << QFileInfo(*tempImageFile).absoluteFilePath() + << "as location image for" << locationID; + + const QString LOCATION_IMAGE_NAME = "location[image]"; + + QHttpPart imagePart; + imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, + QVariant("form-data; name=\"" + LOCATION_IMAGE_NAME + "\";" + " filename=\"" + QFileInfo(tempImageFile->fileName()).fileName().toUtf8() + "\"")); + imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream")); + imagePart.setBodyDevice(tempImageFile); + + imageFileMultiPart->append(imagePart); + + const QString LOCATION_IMAGE_PUT_PATH = "api/v1/locations/%1/image"; + + JSONCallbackParameters imageCallbackParams; + imageCallbackParams.jsonCallbackReceiver = this; + imageCallbackParams.jsonCallbackMethod = "locationImageUpdateSuccess"; + + // make an authenticated request via account manager to upload the image + // don't do anything with error or success for now + AccountManager::getInstance().authenticatedRequest(LOCATION_IMAGE_PUT_PATH.arg(locationID), + QNetworkAccessManager::PutOperation, + JSONCallbackParameters(), QByteArray(), imageFileMultiPart); + } else { qDebug() << "Couldn't open snapshot file to upload as location image. No location image will be stored."; return; } - - qDebug() << "Uploading a snapshot from" << filename << "as location image for" << locationID; - - - - const QString LOCATION_IMAGE_NAME = "location[image]"; - - QHttpPart imagePart; - imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, - QVariant("form-data; name=\"" + LOCATION_IMAGE_NAME + "\";")); - imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream")); - imagePart.setBodyDevice(locationImageFile); - - imageFileMultiPart->append(imagePart); - - const QString LOCATION_IMAGE_PUT_PATH = "api/v1/locations/%1/image"; - - JSONCallbackParameters imageCallbackParams; - imageCallbackParams.jsonCallbackReceiver = this; - imageCallbackParams.jsonCallbackMethod = "locationImageUpdateSuccess"; - - // make an authenticated request via account manager to upload the image - // don't do anything with error or success for now - AccountManager::getInstance().authenticatedRequest(LOCATION_IMAGE_PUT_PATH.arg(locationID), - QNetworkAccessManager::PutOperation, - JSONCallbackParameters(), QByteArray(), imageFileMultiPart); } diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index d530be57d2..9fe1c332be 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -65,6 +65,24 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { } QString Snapshot::saveSnapshot(QGLWidget* widget, Avatar* avatar) { + QFile* snapshotFile = savedFileForSnapshot(widget, avatar, false); + + // we don't need the snapshot file, so close it, grab its filename and delete it + snapshotFile->close(); + + QString snapshotPath = QFileInfo(*snapshotFile).absoluteFilePath(); + + delete snapshotFile; + + return snapshotPath; +} + +QTemporaryFile* Snapshot::saveTempSnapshot(QGLWidget* widget, Avatar* avatar) { + // return whatever we get back from saved file for snapshot + return static_cast(savedFileForSnapshot(widget, avatar, true));; +} + +QFile* Snapshot::savedFileForSnapshot(QGLWidget* widget, Avatar* avatar, bool isTemporary) { QImage shot = widget->grabFrameBuffer(); glm::vec3 location = avatar->getPosition(); @@ -91,16 +109,40 @@ QString Snapshot::saveSnapshot(QGLWidget* widget, Avatar* avatar) { username.replace(QRegExp("[^A-Za-z0-9_]"), "-"); QDateTime now = QDateTime::currentDateTime(); - QString fileName = Menu::getInstance()->getSnapshotsLocation(); - - if (!fileName.endsWith(QDir::separator())) { - fileName.append(QDir::separator()); - } - - fileName.append(QString(FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT), formattedLocation))); - shot.save(fileName, 0, 100); - return fileName; + QString filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT), formattedLocation); + + const int IMAGE_QUALITY = 100; + + if (!isTemporary) { + QString snapshotFullPath = Menu::getInstance()->getSnapshotsLocation(); + + if (!snapshotFullPath.endsWith(QDir::separator())) { + snapshotFullPath.append(QDir::separator()); + } + + snapshotFullPath.append(filename); + + QFile* imageFile = new QFile(snapshotFullPath); + imageFile->open(QIODevice::WriteOnly); + + shot.save(imageFile, 0, IMAGE_QUALITY); + imageFile->close(); + + return imageFile; + } else { + QTemporaryFile* imageTempFile = new QTemporaryFile(QDir::tempPath() + "/XXXXXX-" + filename); + + if (!imageTempFile->open()) { + qDebug() << "Unable to open QTemporaryFile for temp snapshot. Will not save."; + return NULL; + } + + shot.save(imageTempFile, 0, IMAGE_QUALITY); + imageTempFile->close(); + + return imageTempFile; + } } diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 2872b3fdcb..8f15532cb5 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -42,7 +42,11 @@ class Snapshot { public: static QString saveSnapshot(QGLWidget* widget, Avatar* avatar); + static QTemporaryFile* saveTempSnapshot(QGLWidget* widget, Avatar* avatar); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); + +private: + static QFile* savedFileForSnapshot(QGLWidget* widget, Avatar* avatar, bool isTemporary); }; #endif // hifi_Snapshot_h