From 186df05cea770491a7ce436a1bc793c58d53f7d1 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 9 Nov 2020 01:08:51 +0100 Subject: [PATCH] WIP: SnapmaticPicture using RagePhoto now --- RagePhoto.cpp | 95 ++++- RagePhoto.h | 19 +- SnapmaticPicture.cpp | 930 +++++++++---------------------------------- SnapmaticPicture.h | 30 +- gta5view.pro | 2 + 5 files changed, 285 insertions(+), 791 deletions(-) diff --git a/RagePhoto.cpp b/RagePhoto.cpp index 6144acc..55645dd 100644 --- a/RagePhoto.cpp +++ b/RagePhoto.cpp @@ -24,20 +24,23 @@ RagePhoto::RagePhoto(const QByteArray &data) : p_fileData(data) { - p_inputMode = 0; + p_photoFormat = PhotoFormat::Undefined; p_isLoaded = false; + p_inputMode = 0; } RagePhoto::RagePhoto(const QString &filePath) : p_filePath(filePath) { - p_inputMode = 1; + p_photoFormat = PhotoFormat::Undefined; p_isLoaded = false; + p_inputMode = 1; } RagePhoto::RagePhoto(QIODevice *ioDevice) : p_ioDevice(ioDevice) { - p_inputMode = 2; + p_photoFormat = PhotoFormat::Undefined; p_isLoaded = false; + p_inputMode = 2; } bool RagePhoto::isLoaded() @@ -74,7 +77,7 @@ bool RagePhoto::load() return false; quint32 format = charToUInt32LE(formatHeader); - if (format == PhotoFormat::GTA5) { + if (format == static_cast(PhotoFormat::GTA5)) { char photoHeader[256]; size = dataBuffer.read(photoHeader, 256); if (size != 256) @@ -138,7 +141,7 @@ bool RagePhoto::load() size = dataBuffer.read(photoData, p_photoSize); if (size != p_photoSize) return false; - p_photoData = QByteArray::fromRawData(photoData, p_photoSize); + p_photoData = QByteArray(photoData, p_photoSize); dataBuffer.seek(p_jsonOffset + 264); char jsonMarker[4]; @@ -158,13 +161,12 @@ bool RagePhoto::load() size = dataBuffer.read(jsonBytes, i_jsonSize); if (size != i_jsonSize) return false; - QByteArray t_jsonBytes; for (quint32 i = 0; i != i_jsonSize; i++) { if (jsonBytes[i] == '\x00') break; - t_jsonBytes += jsonBytes[i]; + p_jsonData += jsonBytes[i]; } - QJsonDocument t_jsonDocument = QJsonDocument::fromJson(t_jsonBytes); + QJsonDocument t_jsonDocument = QJsonDocument::fromJson(p_jsonData); if (t_jsonDocument.isNull()) return false; p_jsonObject = t_jsonDocument.object(); @@ -225,17 +227,20 @@ bool RagePhoto::load() if (strncmp(jendMarker, "JEND", 4) != 0) return false; + if (p_photoFormat != PhotoFormat::G5EX) + p_photoFormat = PhotoFormat::GTA5; + p_fileData.clear(); p_isLoaded = true; return true; } - else if (format == PhotoFormat::G5EX) { + else if (format == static_cast(PhotoFormat::G5EX)) { char formatHeader[4]; size = dataBuffer.read(formatHeader, 4); if (size != 4) return false; quint32 format = charToUInt32LE(formatHeader); - if (format == ExportFormat::G5E3P) { + if (format == static_cast(ExportFormat::G5E3P)) { char photoHeaderSize[4]; size = dataBuffer.peek(photoHeaderSize, 4); if (size != 4) @@ -293,8 +298,8 @@ bool RagePhoto::load() if (size != i_jsonSize) return false; QByteArray t_jsonBytes = QByteArray::fromRawData(compressedJson, i_jsonSize); - t_jsonBytes = qUncompress(t_jsonBytes); - QJsonDocument t_jsonDocument = QJsonDocument::fromJson(t_jsonBytes); + p_jsonData = qUncompress(t_jsonBytes); + QJsonDocument t_jsonDocument = QJsonDocument::fromJson(p_jsonData); if (t_jsonDocument.isNull()) return false; p_jsonObject = t_jsonDocument.object(); @@ -345,11 +350,14 @@ bool RagePhoto::load() return false; p_endOfFile = charToUInt32LE(endOfFile); + p_photoFormat = PhotoFormat::G5EX; + p_fileData.clear(); p_isLoaded = true; return true; } - else if (format == ExportFormat::G5E2P) { + else if (format == static_cast(ExportFormat::G5E2P)) { + p_photoFormat = PhotoFormat::G5EX; p_fileData = dataBuffer.readAll(); p_inputMode = 0; return load(); @@ -365,8 +373,10 @@ bool RagePhoto::load() void RagePhoto::clear() { + p_photoFormat = PhotoFormat::Undefined; p_jsonObject = QJsonObject(); p_descriptionString.clear(); + p_jsonData.clear(); p_photoData.clear(); p_photoString.clear(); p_titleString.clear(); @@ -379,20 +389,47 @@ void RagePhoto::setDescription(const QString &description) p_descriptionString = description; } -void RagePhoto::setFilePath(const QString &filePath) +void RagePhoto::setFileData(const QByteArray &data) { - p_filePath = filePath; + p_fileData = data; p_inputMode = 0; } -void RagePhoto::setPhotoData(const QByteArray &data) +void RagePhoto::setFilePath(const QString &filePath) { - p_photoData = data; + p_filePath = filePath; + p_inputMode = 1; } -void RagePhoto::setPhotoData(const char *data, int size) +bool RagePhoto::setJsonData(const QByteArray &data) { - p_photoData = QByteArray::fromRawData(data, size); + QJsonDocument t_jsonDocument = QJsonDocument::fromJson(data); + if (t_jsonDocument.isNull()) + return false; + p_jsonObject = t_jsonDocument.object(); + p_jsonData = data; + return true; +} + +bool RagePhoto::setPhotoData(const QByteArray &data) +{ + if ((quint32)data.size() > p_photoSize) + return false; + p_photoData = data; + return true; +} + +bool RagePhoto::setPhotoData(const char *data, int size) +{ + if ((quint32)size > p_photoSize) + return false; + p_photoData = QByteArray(data, size); + return true; +} + +void RagePhoto::setPhotoFormat(PhotoFormat photoFormat) +{ + p_photoFormat = photoFormat; } void RagePhoto::setTitle(const QString &title) @@ -400,6 +437,16 @@ void RagePhoto::setTitle(const QString &title) p_titleString = title; } +const QByteArray RagePhoto::jsonData() +{ + return p_jsonData; +} + +const QJsonObject RagePhoto::jsonObject() +{ + return p_jsonObject; +} + const QByteArray RagePhoto::photoData() { return p_photoData; @@ -420,6 +467,16 @@ const QString RagePhoto::title() return p_titleString; } +quint32 RagePhoto::photoBuffer() +{ + return p_jpegBuffer; +} + +RagePhoto::PhotoFormat RagePhoto::photoFormat() +{ + return p_photoFormat; +} + RagePhoto* RagePhoto::loadFile(const QString &filePath) { RagePhoto *ragePhoto = new RagePhoto(filePath); diff --git a/RagePhoto.h b/RagePhoto.h index 922a757..a63881b 100644 --- a/RagePhoto.h +++ b/RagePhoto.h @@ -27,16 +27,18 @@ class RagePhoto : public QObject { Q_OBJECT public: - enum ExportFormat { + enum class ExportFormat : quint32 { G5E2P = 0x01000032U, G5E2S = 0x02000032U, G5E3P = 0x01000033U, G5E3S = 0x02000033U, + Undefined = 0, }; - enum PhotoFormat { + enum class PhotoFormat : quint32 { G5EX = 0x45354700U, GTA5 = 0x01000000U, RDR2 = 0x04000000U, + Undefined = 0, }; explicit RagePhoto(const QByteArray &data); explicit RagePhoto(const QString &filePath = QString()); @@ -45,14 +47,21 @@ public: bool load(); void clear(); void setDescription(const QString &description); + void setFileData(const QByteArray &data); void setFilePath(const QString &filePath); - void setPhotoData(const QByteArray &data); - void setPhotoData(const char *data, int size); + bool setJsonData(const QByteArray &data); + bool setPhotoData(const QByteArray &data); + bool setPhotoData(const char *data, int size); + void setPhotoFormat(PhotoFormat photoFormat); void setTitle(const QString &title); + const QJsonObject jsonObject(); + const QByteArray jsonData(); const QByteArray photoData(); const QString description(); const QString photoString(); const QString title(); + quint32 photoBuffer(); + PhotoFormat photoFormat(); static RagePhoto* loadFile(const QString &filePath); private: @@ -60,8 +69,10 @@ private: inline quint32 charToUInt32LE(char *x); inline void uInt32ToCharBE(quint32 *x, char *y); inline void uInt32ToCharLE(quint32 *x, char *y); + PhotoFormat p_photoFormat; QJsonObject p_jsonObject; QByteArray p_fileData; + QByteArray p_jsonData; QByteArray p_photoData; QIODevice *p_ioDevice; QString p_descriptionString; diff --git a/SnapmaticPicture.cpp b/SnapmaticPicture.cpp index ed5046b..290e591 100644 --- a/SnapmaticPicture.cpp +++ b/SnapmaticPicture.cpp @@ -42,28 +42,6 @@ #include "StandardPaths.h" #endif -// PARSER ALLOCATIONS -#define snapmaticHeaderLength 278 -#define snapmaticUsefulLength 260 -#define snapmaticFileMaxSize 528192 -#define jpegHeaderLineDifStr 2 -#define jpegHeaderLineDifLim 8 -#define jpegPreHeaderLength 14 -#define jpegPicStreamLength 524288 -#define jsonStreamLength 3076 -#define tideStreamLength 260 - -// EDITOR ALLOCATIONS -#define jpegStreamEditorBegin 292 -#define jsonStreamEditorBegin 524588 -#define jsonStreamEditorLength 3072 -#define titlStreamEditorBegin 527668 -#define titlStreamEditorLength 256 -#define titlStreamCharacterMax 39 - -// LIMIT ALLOCATIONS -#define jpegStreamLimitBegin 288 - // IMAGES VALUES #define snapmaticResolutionW 960 #define snapmaticResolutionH 536 @@ -72,6 +50,7 @@ SnapmaticPicture::SnapmaticPicture(const QString &fileName, QObject *parent) : QObject(parent), picFilePath(fileName) { reset(); + ragePhoto.setFilePath(fileName); } SnapmaticPicture::~SnapmaticPicture() @@ -81,39 +60,19 @@ SnapmaticPicture::~SnapmaticPicture() void SnapmaticPicture::reset() { // INIT PIC - rawPicContent.clear(); - rawPicContent.squeeze(); + ragePhoto.clear(); cachePicture = QImage(); picExportFileName = QString(); - pictureHead = QString(); pictureStr = QString(); lastStep = QString(); sortStr = QString(); - titlStr = QString(); - descStr = QString(); - - // INIT PIC INTS - jpegRawContentSizeE = 0; - jpegRawContentSize = 0; // INIT PIC BOOLS - isCustomFormat = false; - isModernFormat = false; isFormatSwitch = false; - isLoadedInRAM = false; - lowRamMode = false; picOk = false; // INIT JSON jsonOk = false; - jsonStr = QString(); - - // SNAPMATIC DEFAULTS -#ifdef SNAPMATIC_NODEFAULT - careSnapDefault = false; -#else - careSnapDefault = true; -#endif // SNAPMATIC PROPERTIES localProperties = {}; @@ -133,325 +92,59 @@ bool SnapmaticPicture::preloadFile() delete picFile; return false; } + + bool ok = ragePhoto.load(); + if (!ok) + return false; + if (picFilePath.right(4) != QLatin1String(".g5e")) { - rawPicContent = picFile->read(snapmaticFileMaxSize + 1024); - picFile->close(); - delete picFile; - - if (rawPicContent.mid(1, 3) == QByteArray("G5E")) - { + if (ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) isFormatSwitch = true; - } - else - { - isCustomFormat = false; - isModernFormat = false; - isLoadedInRAM = true; - } } else { g5eMode = true; } - if (g5eMode || isFormatSwitch) - { - QByteArray g5eContent; - if (!isFormatSwitch) - { - g5eContent = picFile->read(snapmaticFileMaxSize + 1024); - picFile->close(); - delete picFile; - } - else - { - g5eContent = rawPicContent; - rawPicContent.clear(); - } - - // Set Custom Format - isCustomFormat = true; - - // Reading g5e Content - g5eContent.remove(0, 1); - if (g5eContent.left(3) == QByteArray("G5E")) - { - g5eContent.remove(0, 3); - if (g5eContent.left(2).toHex() == QByteArray("1000")) - { - g5eContent.remove(0, 2); - if (g5eContent.left(3) == QByteArray("LEN")) - { - g5eContent.remove(0, 3); - int fileNameLength = g5eContent.left(1).toHex().toInt(); - g5eContent.remove(0, 1); - if (g5eContent.left(3) == QByteArray("FIL")) - { - g5eContent.remove(0, 3); - picFileName = g5eContent.left(fileNameLength); - g5eContent.remove(0, fileNameLength); - if (g5eContent.left(3) == QByteArray("COM")) - { - g5eContent.remove(0, 3); - rawPicContent = qUncompress(g5eContent); - - // Setting is values - isModernFormat = false; - isLoadedInRAM = true; - } - else - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",4,G5E_FORMATERROR"; - return false; - } - } - else - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",3,G5E_FORMATERROR"; - return false; - } - } - else - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",2,G5E_FORMATERROR"; - return false; - } - } - else if (g5eContent.left(2).toHex() == QByteArray("3200")) - { - g5eContent.remove(0, 2); - if (g5eContent.left(2).toHex() == QByteArray("0001")) - { - g5eContent.remove(0, 2); - rawPicContent = qUncompress(g5eContent); - - // Setting is values - isModernFormat = true; - isLoadedInRAM = true; - } - else if (g5eContent.left(2).toHex() == QByteArray("0002")) - { - lastStep = "2;/4,ReadingFile," % convertDrawStringForLog(picFilePath) % ",2,G5E2_FORMATWRONG,G5E2_SGD"; - return false; - } - else - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",2,G5E2_MISSINGEXTENSION"; - return false; - } - } - else - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",1,G5E_NOTCOMPATIBLE"; - return false; - } - } - else - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",1,G5E_FORMATERROR"; - return false; - } - } emit preloaded(); - return true; + return ok; } bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bool fastLoad, bool lowRamMode_) { + Q_UNUSED(fastLoad) + Q_UNUSED(lowRamMode_) + Q_UNUSED(writeEnabled_) // Start opening file // lastStep is like currentStep // Set boolean values - writeEnabled = writeEnabled_; cacheEnabled = cacheEnabled_; - lowRamMode = lowRamMode_; - if (!writeEnabled) { lowRamMode = false; } // Low RAM Mode only works when writeEnabled is true - QIODevice *picStream; + bool ok = true; + if (!ragePhoto.isLoaded()) + ok = preloadFile(); - if (!isLoadedInRAM) { preloadFile(); } - - picStream = new QBuffer(&rawPicContent); - picStream->open(QIODevice::ReadWrite); - - // Reading Snapmatic Header - if (!picStream->isReadable()) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",1,NOHEADER"; - picStream->close(); - delete picStream; + if (!ok) return false; - } - QByteArray snapmaticHeaderLine = picStream->read(snapmaticHeaderLength); - pictureHead = getSnapmaticHeaderString(snapmaticHeaderLine); - if (pictureHead == QLatin1String("MALFORMED")) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",1,MALFORMEDHEADER"; - picStream->close(); - delete picStream; - return false; - } - // Reading JPEG Header Line - if (!picStream->isReadable()) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",2,NOHEADER"; - picStream->close(); - delete picStream; - return false; - } - QByteArray jpegHeaderLine = picStream->read(jpegPreHeaderLength); - - // Checking for JPEG - jpegHeaderLine.remove(0, jpegHeaderLineDifStr); - if (jpegHeaderLine.left(4) != QByteArray("JPEG")) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",2,NOJPEG"; - picStream->close(); - delete picStream; - return false; - } - - // Get JPEG Size Limit - jpegHeaderLine.remove(0, jpegHeaderLineDifLim); - QString jpegHeaderLineStr = QString::fromUtf8(jpegHeaderLine.toHex().remove(8 - 2, 2)); - QString hexadecimalStr = jpegHeaderLineStr.mid(4, 2) % jpegHeaderLineStr.mid(2, 2) % jpegHeaderLineStr.mid(0, 2); - jpegRawContentSize = hexadecimalStr.toInt(0, 16); - - // Read JPEG Stream - if (!picStream->isReadable()) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",2,NOPIC"; - picStream->close(); - delete picStream; - return false; - } - QByteArray jpegRawContent = picStream->read(jpegPicStreamLength); - if (cacheEnabled) picOk = cachePicture.loadFromData(jpegRawContent, "JPEG"); + if (cacheEnabled) picOk = cachePicture.loadFromData(ragePhoto.photoData(), "JPEG"); if (!cacheEnabled) { QImage tempPicture; - picOk = tempPicture.loadFromData(jpegRawContent, "JPEG"); - } - else if (!fastLoad) - { - if (careSnapDefault) - { - QImage tempPicture = QImage(snapmaticResolution, QImage::Format_RGB888); - QPainter tempPainter(&tempPicture); - if (cachePicture.size() != snapmaticResolution) - { - tempPainter.drawImage(0, 0, cachePicture.scaled(snapmaticResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - } - else - { - tempPainter.drawImage(0, 0, cachePicture); - } - tempPainter.end(); - cachePicture = tempPicture; - } - else - { - QImage tempPicture = QImage(cachePicture.size(), QImage::Format_RGB888); - QPainter tempPainter(&tempPicture); - tempPainter.drawImage(0, 0, cachePicture); - tempPainter.end(); - cachePicture = tempPicture; - } + picOk = tempPicture.loadFromData(ragePhoto.photoData(), "JPEG"); } - // Read JSON Stream - if (!picStream->isReadable()) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",3,NOJSON"; - picStream->close(); - delete picStream; - return false; - } - else if (picStream->read(4) != QByteArray("JSON")) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",3,CTJSON"; - picStream->close(); - delete picStream; - return false; - } - QByteArray jsonRawContent = picStream->read(jsonStreamLength); - jsonStr = getSnapmaticJSONString(jsonRawContent); parseJsonContent(); // JSON parsing is own function - - if (!picStream->isReadable()) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",4,NOTITL"; - picStream->close(); - delete picStream; - return false; - } - else if (picStream->read(4) != QByteArray("TITL")) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",4,CTTITL"; - picStream->close(); - delete picStream; - return false; - } - QByteArray titlRawContent = picStream->read(tideStreamLength); - titlStr = getSnapmaticTIDEString(titlRawContent); - - if (!picStream->isReadable()) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",5,NODESC"; - picStream->close(); - delete picStream; - return picOk; - } - else if (picStream->read(4) != QByteArray("DESC")) - { - lastStep = "2;/3,ReadingFile," % convertDrawStringForLog(picFilePath) % ",5,CTDESC"; - picStream->close(); - delete picStream; - return false; - } - QByteArray descRawContent = picStream->read(tideStreamLength); - descStr = getSnapmaticTIDEString(descRawContent); - updateStrings(); - picStream->close(); - delete picStream; - - if (!writeEnabled) { rawPicContent.clear(); } - else if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - emit loaded(); return picOk; } -QString SnapmaticPicture::getSnapmaticHeaderString(const QByteArray &snapmaticHeader) -{ - QList snapmaticBytesList = snapmaticHeader.left(snapmaticUsefulLength).split('\x01'); - if (snapmaticBytesList.length() < 2) { return QLatin1String("MALFORMED"); } - QByteArray snapmaticBytes = snapmaticBytesList.at(1); - return parseTitleString(snapmaticBytes, snapmaticBytes.length()); -} - -QString SnapmaticPicture::getSnapmaticJSONString(const QByteArray &jsonBytes) -{ - QByteArray jsonUsefulBytes = jsonBytes; - jsonUsefulBytes.replace('\x00', ""); - jsonUsefulBytes.replace('\x0c', ""); - return QString::fromUtf8(jsonUsefulBytes.trimmed()); -} - -QString SnapmaticPicture::getSnapmaticTIDEString(const QByteArray &tideBytes) -{ - QByteArray tideUsefulBytes = tideBytes; - tideUsefulBytes.remove(0,4); - QList tideUsefulBytesList = tideUsefulBytes.split('\x00'); - return QString::fromUtf8(tideUsefulBytesList.at(0).trimmed()); -} - void SnapmaticPicture::updateStrings() { - QString cmpPicTitl = titlStr; + QString cmpPicTitl = ragePhoto.title(); cmpPicTitl.replace('\"', "''"); cmpPicTitl.replace(' ', '_'); cmpPicTitl.replace(':', '-'); @@ -467,7 +160,7 @@ void SnapmaticPicture::updateStrings() pictureStr = tr("PHOTO - %1").arg(localProperties.createdDateTime.toString("MM/dd/yy HH:mm:ss")); sortStr = localProperties.createdDateTime.toString("yyMMddHHmmss") % QString::number(localProperties.uid); QString exportStr = localProperties.createdDateTime.toString("yyyyMMdd") % "-" % QString::number(localProperties.uid); - if (isModernFormat) { picFileName = "PGTA5" % QString::number(localProperties.uid); } + if (getSnapmaticFormat() == SnapmaticFormat::G5E_Format) picFileName = "PGTA5" % QString::number(localProperties.uid); picExportFileName = exportStr % "_" % cmpPicTitl; } @@ -486,120 +179,43 @@ bool SnapmaticPicture::readingPictureFromFile(const QString &fileName, bool writ bool SnapmaticPicture::setImage(const QImage &picture) { - if (writeEnabled) - { - QImage altPicture; - bool useAltPicture = false; - if (picture.size() != snapmaticResolution && careSnapDefault) + quint32 jpegPicStreamLength = ragePhoto.photoBuffer(); + QByteArray picByteArray; + int comLvl = 100; + bool saveSuccess = false; + while (comLvl != 0 && !saveSuccess) { + QByteArray picByteArrayT; + QBuffer picStreamT(&picByteArrayT); + picStreamT.open(QIODevice::WriteOnly); + saveSuccess = picture.save(&picStreamT, "JPEG", comLvl); + picStreamT.close(); + if (saveSuccess) { - altPicture = picture.scaled(snapmaticResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - useAltPicture = true; - } - QByteArray picByteArray; - int comLvl = 100; - bool saveSuccess = false; - while (comLvl != 0 && !saveSuccess) - { - QByteArray picByteArrayT; - QBuffer picStreamT(&picByteArrayT); - picStreamT.open(QIODevice::WriteOnly); - if (useAltPicture) { saveSuccess = altPicture.save(&picStreamT, "JPEG", comLvl); } - else { saveSuccess = picture.save(&picStreamT, "JPEG", comLvl); } - picStreamT.close(); - if (saveSuccess) - { - if (picByteArrayT.length() > jpegPicStreamLength) - { - comLvl--; - saveSuccess = false; - } - else - { - picByteArray = picByteArrayT; - } + if ((quint32)picByteArrayT.length() > jpegPicStreamLength) { + comLvl--; + saveSuccess = false; + } + else { + picByteArray = picByteArrayT; } } - if (saveSuccess) { return setPictureStream(picByteArray); } } + if (saveSuccess) + return setPictureStream(picByteArray); return false; } bool SnapmaticPicture::setPictureStream(const QByteArray &streamArray) // clean method { - if (writeEnabled) - { - QByteArray picByteArray = streamArray; - if (lowRamMode) { rawPicContent = qUncompress(rawPicContent); } - QBuffer snapmaticStream(&rawPicContent); - snapmaticStream.open(QIODevice::ReadWrite); - if (!snapmaticStream.seek(jpegStreamEditorBegin)) return false; - if (picByteArray.length() > jpegPicStreamLength) return false; - while (picByteArray.length() != jpegPicStreamLength) - { - picByteArray += '\x00'; - } - int result = snapmaticStream.write(picByteArray); - QString hexadecimalStr; - hexadecimalStr.setNum(streamArray.length(), 16); - while (hexadecimalStr.length() != 6) - { - hexadecimalStr.prepend('0'); - } - hexadecimalStr = hexadecimalStr.mid(4, 2) % hexadecimalStr.mid(2, 2) % hexadecimalStr.mid(0, 2); - bool updatedRawContentSize = false; - if (snapmaticStream.seek(jpegStreamLimitBegin)) - { - snapmaticStream.write(QByteArray::fromHex(hexadecimalStr.toUtf8())); - updatedRawContentSize = true; - } - snapmaticStream.close(); - if (result != 0) - { - if (updatedRawContentSize) { jpegRawContentSize = streamArray.length(); } - if (cacheEnabled) - { - QImage replacedPicture; - replacedPicture.loadFromData(picByteArray); - cachePicture = replacedPicture; - } - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - return true; - } - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - return false; - } + bool success = ragePhoto.setPhotoData(streamArray); + // SAVE HERE return false; } bool SnapmaticPicture::setPictureTitl(const QString &newTitle_) { - if (writeEnabled) - { - QString newTitle = newTitle_; - if (lowRamMode) { rawPicContent = qUncompress(rawPicContent); } - QBuffer snapmaticStream(&rawPicContent); - snapmaticStream.open(QIODevice::ReadWrite); - if (!snapmaticStream.seek(titlStreamEditorBegin)) return false; - if (newTitle.length() > titlStreamCharacterMax) - { - newTitle = newTitle.left(titlStreamCharacterMax); - } - QByteArray newTitleArray = newTitle.toUtf8(); - while (newTitleArray.length() != titlStreamEditorLength) - { - newTitleArray += '\x00'; - } - int result = snapmaticStream.write(newTitleArray); - snapmaticStream.close(); - if (result != 0) - { - titlStr = newTitle; - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - return true; - } - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - return false; - } + ragePhoto.setTitle(newTitle_); + // SAVE HERE return false; } @@ -651,19 +267,9 @@ QString SnapmaticPicture::getPictureSortStr() return sortStr; } -QString SnapmaticPicture::getPictureDesc() -{ - return descStr; -} - QString SnapmaticPicture::getPictureTitl() { - return titlStr; -} - -QString SnapmaticPicture::getPictureHead() -{ - return pictureHead; + return ragePhoto.title(); } QString SnapmaticPicture::getPictureStr() @@ -758,138 +364,21 @@ QString SnapmaticPicture::getLastStep(bool readable) QImage SnapmaticPicture::getImage(bool fastLoad) { + Q_UNUSED(fastLoad) if (cacheEnabled) { return cachePicture; } - else if (writeEnabled) - { - bool fastLoadU = fastLoad; - if (!careSnapDefault) { fastLoadU = true; } - - bool returnOk = false; - QImage tempPicture; - QImage returnPicture; - if (!fastLoadU) - { - returnPicture = QImage(snapmaticResolution, QImage::Format_RGB888); - } - - if (lowRamMode) { rawPicContent = qUncompress(rawPicContent); } - QBuffer snapmaticStream(&rawPicContent); - snapmaticStream.open(QIODevice::ReadOnly); - if (snapmaticStream.seek(jpegStreamEditorBegin)) - { - QByteArray jpegRawContent = snapmaticStream.read(jpegPicStreamLength); - returnOk = tempPicture.loadFromData(jpegRawContent, "JPEG"); - } - snapmaticStream.close(); - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - - if (returnOk) - { - if (!fastLoadU) - { - QPainter returnPainter(&returnPicture); - if (tempPicture.size() != snapmaticResolution) - { - returnPainter.drawImage(0, 0, tempPicture.scaled(snapmaticResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - } - else - { - returnPainter.drawImage(0, 0, tempPicture); - } - returnPainter.end(); - return returnPicture; - } - else - { - return tempPicture; - } - } - } else { - bool fastLoadU = fastLoad; - if (!careSnapDefault) { fastLoadU = true; } - - bool returnOk = false; - QImage tempPicture; - QImage returnPicture; - if (!fastLoadU) - { - returnPicture = QImage(snapmaticResolution, QImage::Format_RGB888); - } - QIODevice *picStream; - - QFile *picFile = new QFile(picFilePath); - if (!picFile->open(QFile::ReadOnly)) - { - lastStep = "1;/1,OpenFile," % convertDrawStringForLog(picFilePath); - delete picFile; - return QImage(); - } - rawPicContent = picFile->read(snapmaticFileMaxSize); - picFile->close(); - delete picFile; - - picStream = new QBuffer(&rawPicContent); - picStream->open(QIODevice::ReadWrite); - if (picStream->seek(jpegStreamEditorBegin)) - { - QByteArray jpegRawContent = picStream->read(jpegPicStreamLength); - returnOk = tempPicture.loadFromData(jpegRawContent, "JPEG"); - } - picStream->close(); - delete picStream; - - rawPicContent.clear(); - rawPicContent.squeeze(); - - if (returnOk) - { - if (!fastLoadU) - { - QPainter returnPainter(&returnPicture); - if (tempPicture.size() != snapmaticResolution) - { - returnPainter.drawImage(0, 0, tempPicture.scaled(snapmaticResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - } - else - { - returnPainter.drawImage(0, 0, tempPicture); - } - returnPainter.end(); - return returnPicture; - } - else - { - return tempPicture; - } - } + return QImage::fromData(ragePhoto.photoData(), "JPEG"); } return QImage(); } -QByteArray SnapmaticPicture::getPictureStream() // Incomplete because it just work in writeEnabled mode +QByteArray SnapmaticPicture::getPictureStream() { - QByteArray jpegRawContent; - if (writeEnabled) - { - QBuffer *picStream = new QBuffer(&rawPicContent); - picStream->open(QIODevice::ReadWrite); - if (picStream->seek(jpegStreamEditorBegin)) - { - jpegRawContent = picStream->read(jpegPicStreamLength); - } - delete picStream; - } - return jpegRawContent; -} - -int SnapmaticPicture::getContentMaxLength() -{ - return jpegRawContentSize; + return ragePhoto.photoData(); } bool SnapmaticPicture::isPicOk() @@ -922,7 +411,7 @@ bool SnapmaticPicture::isJsonOk() QString SnapmaticPicture::getJsonStr() { - return jsonStr; + return QString::fromUtf8(ragePhoto.jsonData()); } SnapmaticProperties SnapmaticPicture::getSnapmaticProperties() @@ -932,8 +421,7 @@ SnapmaticProperties SnapmaticPicture::getSnapmaticProperties() void SnapmaticPicture::parseJsonContent() { - QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonStr.toUtf8()); - QJsonObject jsonObject = jsonDocument.object(); + QJsonObject jsonObject = ragePhoto.jsonObject(); QVariantMap jsonMap = jsonObject.toVariantMap(); bool jsonIncomplete = false; @@ -1067,8 +555,7 @@ void SnapmaticPicture::parseJsonContent() bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties) { - QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonStr.toUtf8()); - QJsonObject jsonObject = jsonDocument.object(); + QJsonObject jsonObject = ragePhoto.jsonObject(); QJsonObject locObject; locObject["x"] = properties.location.x; @@ -1088,8 +575,7 @@ bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties) jsonObject["drctr"] = properties.isFromDirector; jsonObject["rsedtr"] = properties.isFromRSEditor; - jsonDocument.setObject(jsonObject); - + QJsonDocument jsonDocument(jsonObject); if (setJsonStr(QString::fromUtf8(jsonDocument.toJson(QJsonDocument::Compact)))) { localProperties = properties; @@ -1100,172 +586,144 @@ bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties) bool SnapmaticPicture::setJsonStr(const QString &newJsonStr, bool updateProperties) { - if (newJsonStr.length() < jsonStreamEditorLength) - { - if (writeEnabled) - { - QByteArray jsonByteArray = newJsonStr.toUtf8(); - while (jsonByteArray.length() != jsonStreamEditorLength) - { - jsonByteArray += '\x00'; - } - if (lowRamMode) { rawPicContent = qUncompress(rawPicContent); } - QBuffer snapmaticStream(&rawPicContent); - snapmaticStream.open(QIODevice::ReadWrite); - if (!snapmaticStream.seek(jsonStreamEditorBegin)) - { - snapmaticStream.close(); - return false; - } - int result = snapmaticStream.write(jsonByteArray); - snapmaticStream.close(); - if (result != 0) - { - jsonStr = newJsonStr; - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - if (updateProperties) { parseJsonContent(); } - return true; - } - else - { - if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } - return false; - } - } - else - { - return false; - } + if (ragePhoto.setJsonData(newJsonStr.toUtf8())) { + // SAVE HERE + if (updateProperties) + parseJsonContent(); + return true; + } + else { + return false; } - return false; } // FILE MANAGEMENT bool SnapmaticPicture::exportPicture(const QString &fileName, SnapmaticFormat format_) { - // Keep current format when Auto_Format is used - SnapmaticFormat format = format_; - if (format_ == SnapmaticFormat::Auto_Format) - { - if (isCustomFormat) - { - format = SnapmaticFormat::G5E_Format; - } - else - { - format = SnapmaticFormat::PGTA_Format; - } - } + // // Keep current format when Auto_Format is used + // SnapmaticFormat format = format_; + // if (format_ == SnapmaticFormat::Auto_Format) + // { + // if (ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) + // { + // format = SnapmaticFormat::G5E_Format; + // } + // else + // { + // format = SnapmaticFormat::PGTA_Format; + // } + // } - bool saveSuccess = false; - bool writeFailure = false; -#if QT_VERSION >= 0x050000 - QSaveFile *picFile = new QSaveFile(fileName); -#else - QFile *picFile = new QFile(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); -#endif - if (picFile->open(QIODevice::WriteOnly)) - { - if (format == SnapmaticFormat::G5E_Format) - { - // Modern compressed export (v2) - QByteArray g5eHeader; - g5eHeader.reserve(10); - g5eHeader += '\x00'; // First Null Byte - g5eHeader += QByteArray("G5E"); // GTA 5 Export - g5eHeader += '\x32'; g5eHeader += '\x00'; // 2 byte GTA 5 Export Version - g5eHeader += '\x00'; g5eHeader += '\x01'; // 2 byte GTA 5 Export Type - if (picFile->write(g5eHeader) == -1) { writeFailure = true; } - if (!lowRamMode) - { - if (picFile->write(qCompress(rawPicContent, 9)) == -1) { writeFailure = true; } // Compressed Snapmatic - } - else - { - if (picFile->write(rawPicContent) == -1) { writeFailure = true; } - } -#if QT_VERSION >= 0x050000 - if (writeFailure) { picFile->cancelWriting(); } - else { saveSuccess = picFile->commit(); } -#else - if (!writeFailure) { saveSuccess = true; } - picFile->close(); -#endif - delete picFile; - } - else if (format == SnapmaticFormat::JPEG_Format) - { - // JPEG export - QBuffer snapmaticStream(&rawPicContent); - snapmaticStream.open(QIODevice::ReadOnly); - if (snapmaticStream.seek(jpegStreamEditorBegin)) - { - QByteArray jpegRawContent = snapmaticStream.read(jpegPicStreamLength); - if (jpegRawContentSizeE != 0) - { - jpegRawContent = jpegRawContent.left(jpegRawContentSizeE); - } - if (picFile->write(jpegRawContent) == -1) { writeFailure = true; } -#if QT_VERSION >= 0x050000 - if (writeFailure) { picFile->cancelWriting(); } - else { saveSuccess = picFile->commit(); } -#else - if (!writeFailure) { saveSuccess = true; } - picFile->close(); -#endif - } - delete picFile; - } - else - { - // Classic straight export - if (!lowRamMode) - { - if (picFile->write(rawPicContent) == -1) { writeFailure = true; } - } - else - { - if (picFile->write(qUncompress(rawPicContent)) == -1) { writeFailure = true; } - } -#if QT_VERSION >= 0x050000 - if (writeFailure) { picFile->cancelWriting(); } - else { saveSuccess = picFile->commit(); } -#else - if (!writeFailure) { saveSuccess = true; } - picFile->close(); -#endif - delete picFile; - } -#if QT_VERSION <= 0x050000 - if (saveSuccess) - { - bool tempBakCreated = false; - if (QFile::exists(fileName)) - { - if (!QFile::rename(fileName, fileName % ".tmp")) - { - QFile::remove(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); - return false; - } - tempBakCreated = true; - } - if (!QFile::rename(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp", fileName)) - { - QFile::remove(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); - if (tempBakCreated) { QFile::rename(fileName % ".tmp", fileName); } - return false; - } - if (tempBakCreated) { QFile::remove(fileName % ".tmp"); } - } -#endif - return saveSuccess; - } - else - { - delete picFile; - return saveSuccess; - } + // bool saveSuccess = false; + // bool writeFailure = false; + //#if QT_VERSION >= 0x050000 + // QSaveFile *picFile = new QSaveFile(fileName); + //#else + // QFile *picFile = new QFile(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); + //#endif + // if (picFile->open(QIODevice::WriteOnly)) + // { + // if (format == SnapmaticFormat::G5E_Format) + // { + // // Modern compressed export (v2) + // QByteArray g5eHeader; + // g5eHeader.reserve(10); + // g5eHeader += '\x00'; // First Null Byte + // g5eHeader += QByteArray("G5E"); // GTA 5 Export + // g5eHeader += '\x32'; g5eHeader += '\x00'; // 2 byte GTA 5 Export Version + // g5eHeader += '\x00'; g5eHeader += '\x01'; // 2 byte GTA 5 Export Type + // if (picFile->write(g5eHeader) == -1) { writeFailure = true; } + // if (!lowRamMode) + // { + // if (picFile->write(qCompress(rawPicContent, 9)) == -1) { writeFailure = true; } // Compressed Snapmatic + // } + // else + // { + // if (picFile->write(rawPicContent) == -1) { writeFailure = true; } + // } + //#if QT_VERSION >= 0x050000 + // if (writeFailure) { picFile->cancelWriting(); } + // else { saveSuccess = picFile->commit(); } + //#else + // if (!writeFailure) { saveSuccess = true; } + // picFile->close(); + //#endif + // delete picFile; + // } + // else if (format == SnapmaticFormat::JPEG_Format) + // { + // // JPEG export + // QBuffer snapmaticStream(&rawPicContent); + // snapmaticStream.open(QIODevice::ReadOnly); + // if (snapmaticStream.seek(jpegStreamEditorBegin)) + // { + // QByteArray jpegRawContent = snapmaticStream.read(jpegPicStreamLength); + // if (jpegRawContentSizeE != 0) + // { + // jpegRawContent = jpegRawContent.left(jpegRawContentSizeE); + // } + // if (picFile->write(jpegRawContent) == -1) { writeFailure = true; } + //#if QT_VERSION >= 0x050000 + // if (writeFailure) { picFile->cancelWriting(); } + // else { saveSuccess = picFile->commit(); } + //#else + // if (!writeFailure) { saveSuccess = true; } + // picFile->close(); + //#endif + // } + // delete picFile; + // } + // else + // { + // // Classic straight export + // if (!lowRamMode) + // { + // if (picFile->write(rawPicContent) == -1) { writeFailure = true; } + // } + // else + // { + // if (picFile->write(qUncompress(rawPicContent)) == -1) { writeFailure = true; } + // } + //#if QT_VERSION >= 0x050000 + // if (writeFailure) { picFile->cancelWriting(); } + // else { saveSuccess = picFile->commit(); } + //#else + // if (!writeFailure) { saveSuccess = true; } + // picFile->close(); + //#endif + // delete picFile; + // } + //#if QT_VERSION <= 0x050000 + // if (saveSuccess) + // { + // bool tempBakCreated = false; + // if (QFile::exists(fileName)) + // { + // if (!QFile::rename(fileName, fileName % ".tmp")) + // { + // QFile::remove(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); + // return false; + // } + // tempBakCreated = true; + // } + // if (!QFile::rename(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp", fileName)) + // { + // QFile::remove(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); + // if (tempBakCreated) { QFile::rename(fileName % ".tmp", fileName); } + // return false; + // } + // if (tempBakCreated) { QFile::remove(fileName % ".tmp"); } + // } + //#endif + // return saveSuccess; + // } + // else + // { + // delete picFile; + // return saveSuccess; + // } + return false; } void SnapmaticPicture::setPicFileName(const QString &picFileName_) @@ -1323,7 +781,7 @@ bool SnapmaticPicture::isVisible() bool SnapmaticPicture::setPictureHidden() { - if (isCustomFormat) + if (ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { return false; } @@ -1342,7 +800,7 @@ bool SnapmaticPicture::setPictureHidden() bool SnapmaticPicture::setPictureVisible() { - if (isCustomFormat) + if (ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { return false; } @@ -1366,23 +824,11 @@ QSize SnapmaticPicture::getSnapmaticResolution() return snapmaticResolution; } -// SNAPMATIC DEFAULTS - -bool SnapmaticPicture::isSnapmaticDefaultsEnforced() -{ - return careSnapDefault; -} - -void SnapmaticPicture::setSnapmaticDefaultsEnforced(bool enforced) -{ - careSnapDefault = enforced; -} - // SNAPMATIC FORMAT SnapmaticFormat SnapmaticPicture::getSnapmaticFormat() { - if (isCustomFormat) + if (ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { return SnapmaticFormat::G5E_Format; } @@ -1393,12 +839,12 @@ void SnapmaticPicture::setSnapmaticFormat(SnapmaticFormat format) { if (format == SnapmaticFormat::G5E_Format) { - isCustomFormat = true; + ragePhoto.setPhotoFormat(RagePhoto::PhotoFormat::G5EX); return; } else if (format == SnapmaticFormat::PGTA_Format) { - isCustomFormat = false; + ragePhoto.setPhotoFormat(RagePhoto::PhotoFormat::GTA5); return; } qDebug() << "setSnapmaticFormat: Invalid SnapmaticFormat defined, valid SnapmaticFormats are G5E_Format and PGTA_Format"; @@ -1414,7 +860,7 @@ bool SnapmaticPicture::isFormatSwitched() bool SnapmaticPicture::verifyTitle(const QString &title) { // VERIFY TITLE FOR BE A VALID SNAPMATIC TITLE - if (title.length() <= titlStreamCharacterMax && title.length() > 0) + if (title.length() <= 39 && title.length() > 0) { for (const QChar &titleChar : title) { diff --git a/SnapmaticPicture.h b/SnapmaticPicture.h index d882ade..06eb934 100644 --- a/SnapmaticPicture.h +++ b/SnapmaticPicture.h @@ -19,6 +19,7 @@ #ifndef SNAPMATICPICTURE_H #define SNAPMATICPICTURE_H +#include "RagePhoto.h" #include #include #include @@ -65,16 +66,13 @@ public: QByteArray getPictureStream(); QString getLastStep(bool readable = true); QString getPictureStr(); - QString getPictureHead(); QString getPictureTitl(); - QString getPictureDesc(); QString getPictureSortStr(); QString getPictureFileName(); QString getPictureFilePath(); QString getExportPictureFileName(); QString getOriginalPictureFileName(); QString getOriginalPictureFilePath(); - int getContentMaxLength(); bool setImage(const QImage &picture); bool setPictureTitl(const QString &newTitle); // Please use setPictureTitle instead bool setPictureStream(const QByteArray &streamArray); @@ -106,7 +104,6 @@ public: QString getPictureJson() { return getJsonStr(); } QString getPictureTitle() { return getPictureTitl(); } QString getPictureString() { return getPictureStr(); } - QString getPictureDescription() { return getPictureDesc(); } bool setJsonString(const QString &jsonString, bool updateProperties = false) { return setJsonStr(jsonString, updateProperties); } // Please use setPictureJson instead bool setPictureJson(const QString &json, bool updateProperties = false) { return setJsonStr(json, updateProperties); } bool setPictureTitle(const QString &title) { return setPictureTitl(title); } @@ -122,10 +119,6 @@ public: // PREDEFINED PROPERTIES static QSize getSnapmaticResolution(); - // SNAPMATIC DEFAULTS - bool isSnapmaticDefaultsEnforced(); - void setSnapmaticDefaultsEnforced(bool enforced); - // SNAPMATIC FORMAT SnapmaticFormat getSnapmaticFormat(); void setSnapmaticFormat(SnapmaticFormat format); @@ -140,43 +133,28 @@ public: static QString convertLogStringForDraw(const QString &inputStr); private: - QString getSnapmaticHeaderString(const QByteArray &snapmaticHeader); - QString getSnapmaticJSONString(const QByteArray &jsonBytes); - QString getSnapmaticTIDEString(const QByteArray &tideBytes); QImage cachePicture; QString picExportFileName; QString picFileName; QString picFilePath; - QString pictureHead; QString pictureStr; QString lastStep; QString sortStr; - QString titlStr; - QString descStr; bool picOk; - bool lowRamMode; - bool writeEnabled; bool cacheEnabled; - bool isLoadedInRAM; - bool isCustomFormat; bool isFormatSwitch; - bool isModernFormat; - bool careSnapDefault; - int jpegRawContentSize; - int jpegRawContentSizeE; - - // PICTURE STREAM - QByteArray rawPicContent; // JSON void parseJsonContent(); bool jsonOk; - QString jsonStr; SnapmaticProperties localProperties; // VERIFY CONTENT static bool verifyTitleChar(const QChar &titleChar); + // RAGEPHOTO + RagePhoto ragePhoto; + signals: void customSignal(QString signal); void preloaded(); diff --git a/gta5view.pro b/gta5view.pro index 537835c..cacdc53 100644 --- a/gta5view.pro +++ b/gta5view.pro @@ -50,6 +50,7 @@ SOURCES += main.cpp \ ProfileInterface.cpp \ ProfileLoader.cpp \ ProfileWidget.cpp \ + RagePhoto.cpp \ SavegameCopy.cpp \ SavegameData.cpp \ SavegameDialog.cpp \ @@ -92,6 +93,7 @@ HEADERS += \ ProfileInterface.h \ ProfileLoader.h \ ProfileWidget.h \ + RagePhoto.h \ SavegameCopy.h \ SavegameData.h \ SavegameDialog.h \