From e047e1b44de1dadcf017b74e88118c2721919660 Mon Sep 17 00:00:00 2001 From: Syping Date: Sat, 26 Aug 2017 14:13:35 +0200 Subject: [PATCH] finishing up gta5view 1.4.0 --- .travis.yml | 8 +-- AppEnv.cpp | 17 +++-- DatabaseThread.cpp | 114 ++++++++++++++++++++++++++-------- ProfileLoader.cpp | 10 +++ ProfileLoader.h | 4 ++ SavegameWidget.ui | 3 + SnapmaticEditor.cpp | 7 ++- SnapmaticPicture.cpp | 144 ++++++++++++++++++++++++------------------- SnapmaticPicture.h | 4 ++ SnapmaticWidget.ui | 3 + StringParser.cpp | 2 +- UserInterface.cpp | 12 +++- config.h | 4 +- gta5view.pro | 3 + res/5sync.icns | Bin 0 -> 45948 bytes res/app.qrc | 7 ++- res/global.ru.ini | 106 +++++++++++++++++++++++++++++++ res/gta5sync_ru.qm | Bin 29910 -> 29918 bytes res/gta5sync_ru.ts | 2 +- 19 files changed, 340 insertions(+), 110 deletions(-) create mode 100644 res/5sync.icns create mode 100644 res/global.ru.ini diff --git a/.travis.yml b/.travis.yml index 7c7976a..5ea857e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,22 +17,22 @@ install: before_script: - export INSTALL_ROOT=/usr - if [ `git name-rev --tags --name-only $(git rev-parse HEAD)` == "undefined" ]; then export APPLICATION_VERSION="$PACKAGE_VERSION.$TRAVIS_BUILD_NUMBER"; else export APPLICATION_VERSION=`git name-rev --tags --name-only $(git rev-parse HEAD)`; fi - - echo "gta5view build version is $PACKAGE_VERSION" + - echo "gta5view build version is $APPLICATION_VERSION" - mkdir build - mkdir package - cd build - echo "Grand Theft Auto V Snapmatic and Savegame viewer" > ./description-pak script: - - qmake -qt=5 "DEFINES+=GTA5SYNC_DAILYB=\\\\\\\"$PACKAGE_VERSION-rc2\\\\\\\"" ../gta5view.pro + - qmake -qt=5 "DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release\\\\\\\"" "DEFINES+=GTA5SYNC_DAILYB=\\\\\\\"$APPLICATION_VERSION\\\\\\\"" ../gta5view.pro - make -j 4 - - sudo checkinstall -D --default --nodoc --pkgname=gta5view --pkgversion=$PACKAGE_VERSION --pkgrelease=rc2 --pkggroup=utility --maintainer="Syping on Travis \" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5 --pakdir=../package + - sudo checkinstall -D --default --nodoc --pkgname=gta5view --pkgversion=$APPLICATION_VERSION --pkgrelease=travis1 --pkggroup=utility --maintainer="Syping on Travis \" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5 --pakdir=../package deploy: provider: releases api_key: secure: "o7VneEz1aHfdVwZvOZLfopf6uJWNrFsZaBvunTmXFzpmNFhlNS1qwqgMUkIA2yBRbZ3wIzVs4vfwIHv7W9yE/PqK+AYL+R8+AwKGrwlgT4HqJNuk6VM/LNJ6GwT/qkQuaoOVw29bUjmzzgIRdHmw53SlJv6Hh1VE8HphlTT//aex6nCfcFhUZ0BETdZDWz5FSHwL3NalUoqfKfQrJeky5RXzCyCANQC2tKt0bV46GaWIgWrDo2KCTNqPtRWWf5GDmnkXE5IYRMQ3mXvO9iYh0v5Y2jo4PiXGUiFUU6Z3aAWFAiPdGclrBO697cf3lCTzDMhuCETR153qFYsLShUlFf61ITAmCeHAWETjZDri0lmPONo3GoNB6alGfYEA51qw14kXakrTpICtTJj7gw/gtUYOabW6hrzmieNzMBIy62RikDPjyakFnuwW2qNHRlD65e0jYv+6nCpb6E+OV16Ysh1zhV2vTfpfzVmSuyu2J+ELqXD3OZCXRSPpDIih9UQ8335p8FBji6jHORcgym/TRgdgRmENibh8tLzWp+UjpWHuWfcpvZgOskjfwU0iDMCayMJ7tDpOhXHcAhDRnd6XRIiOJ5YZCzflj2nEwmt3YUd7DwXS/AU+WHOmcNQBjXBxF/FJa35XXcy3HKJM5TTKqtph3medo30us5yXHeG6NNg=" - file: "../package/gta5view_$PACKAGE_VERSION-rc2_amd64.deb" + file: "../package/gta5view_$APPLICATION_VERSION-travis1_amd64.deb" skip_cleanup: true on: tags: true diff --git a/AppEnv.cpp b/AppEnv.cpp index aad4f73..c1449f8 100755 --- a/AppEnv.cpp +++ b/AppEnv.cpp @@ -56,11 +56,11 @@ QString AppEnv::getGameFolder(bool *ok) QString GTAV_defaultFolder = StandardPaths::documentsLocation() + QDir::separator() + "Rockstar Games" + QDir::separator() + "GTA V"; QString GTAV_returnFolder = GTAV_defaultFolder; - QSettings SyncSettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); - SyncSettings.beginGroup("dir"); - bool forceDir = SyncSettings.value("force", false).toBool(); - GTAV_returnFolder = SyncSettings.value("dir", GTAV_defaultFolder).toString(); - SyncSettings.endGroup(); + QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); + settings.beginGroup("dir"); + bool forceDir = settings.value("force", false).toBool(); + GTAV_returnFolder = settings.value("dir", GTAV_defaultFolder).toString(); + settings.endGroup(); if (forceDir) { @@ -125,9 +125,14 @@ QByteArray AppEnv::getUserAgent() return QString("Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 %1/%2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8(); } +// QUrl AppEnv::getCrewFetchingUrl(QString crewID) +// { +// return QUrl(QString("https://socialclub.rockstargames.com/reference/crewfeed/%1").arg(crewID)); +// } + QUrl AppEnv::getCrewFetchingUrl(QString crewID) { - return QUrl(QString("https://socialclub.rockstargames.com/reference/crewfeed/%1").arg(crewID)); + return QUrl(QString("https://socialclub.rockstargames.com/crew/%1/%1").arg(crewID)); } QUrl AppEnv::getPlayerFetchingUrl(QString crewID, QString pageNumber) diff --git a/DatabaseThread.cpp b/DatabaseThread.cpp index 4273b0d..0b090d0 100755 --- a/DatabaseThread.cpp +++ b/DatabaseThread.cpp @@ -82,6 +82,80 @@ void DatabaseThread::run() } } +// void DatabaseThread::scanCrewReference(QStringList crewList, int requestDelay) +// { +// foreach (const QString &crewID, crewList) +// { +// if (threadRunning && crewID != "0") +// { +// QNetworkAccessManager *netManager = new QNetworkAccessManager(); + +// QNetworkRequest netRequest(AppEnv::getCrewFetchingUrl(crewID)); +// netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent()); +// netRequest.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); +// netRequest.setRawHeader("Accept-Language", "en-US;q=0.5,en;q=0.3"); +// netRequest.setRawHeader("Connection", "keep-alive"); + +// QNetworkReply *netReply = netManager->get(netRequest); + +// QEventLoop *downloadLoop = new QEventLoop(); +// QObject::connect(netReply, SIGNAL(finished()), downloadLoop, SLOT(quit())); +// QObject::connect(this, SIGNAL(threadEndCommited()), downloadLoop, SLOT(quit())); +// QTimer::singleShot(30000, downloadLoop, SLOT(quit())); +// downloadLoop->exec(); +// delete downloadLoop; + +// if (netReply->isFinished()) +// { +// QByteArray crewJson = netReply->readAll(); +// QJsonDocument crewDocument = QJsonDocument::fromJson(crewJson); +// QJsonObject crewObject = crewDocument.object(); +// QVariantMap crewMap = crewObject.toVariantMap(); +// QString crewName; +// bool isFound = false; + +// if (crewMap.contains("activities")) +// { +// QList activitiesList = crewMap["activities"].toList(); +// foreach (const QVariant &activitiesVariant, activitiesList) +// { +// QMap activityRootMap = activitiesVariant.toMap(); +// foreach(const QVariant &activityRootVariant, activityRootMap) +// { +// QMap activityMap = activityRootVariant.toMap(); +// foreach(const QVariant &activityVariant, activityMap) +// { +// QMap activityFinalMap = activityVariant.toMap(); +// if (activityFinalMap.contains("id") && activityFinalMap["id"] == crewID) +// { +// if (activityFinalMap.contains("name") && isFound == false) +// { +// isFound = true; +// crewName = activityFinalMap["name"].toString(); +// } +// } +// } +// } +// } +// } +// if (!crewName.isNull()) +// { +// crewDB->setCrewName(crewID.toInt(), crewName); +// } +// } + +// QEventLoop *waitingLoop = new QEventLoop(); +// QTimer::singleShot(requestDelay, waitingLoop, SLOT(quit())); +// QObject::connect(this, SIGNAL(threadEndCommited()), waitingLoop, SLOT(quit())); +// waitingLoop->exec(); +// delete waitingLoop; + +// delete netReply; +// delete netManager; +// } +// } +// } + void DatabaseThread::scanCrewReference(QStringList crewList, int requestDelay) { foreach (const QString &crewID, crewList) @@ -91,6 +165,9 @@ void DatabaseThread::scanCrewReference(QStringList crewList, int requestDelay) QNetworkAccessManager *netManager = new QNetworkAccessManager(); QNetworkRequest netRequest(AppEnv::getCrewFetchingUrl(crewID)); +#if QT_VERSION >= 0x050600 + netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); +#endif netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent()); netRequest.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); netRequest.setRawHeader("Accept-Language", "en-US;q=0.5,en;q=0.3"); @@ -107,38 +184,18 @@ void DatabaseThread::scanCrewReference(QStringList crewList, int requestDelay) if (netReply->isFinished()) { - QByteArray crewJson = netReply->readAll(); - QJsonDocument crewDocument = QJsonDocument::fromJson(crewJson); - QJsonObject crewObject = crewDocument.object(); - QVariantMap crewMap = crewObject.toVariantMap(); QString crewName; - bool isFound = false; - - if (crewMap.contains("activities")) + QByteArray crewHtml = netReply->readAll(); + QStringList crewHtmlSplit1 = QString::fromUtf8(crewHtml).split("Rockstar Games Social Club - Crew : "); + if (crewHtmlSplit1.length() >= 2) { - QList<QVariant> activitiesList = crewMap["activities"].toList(); - foreach (const QVariant &activitiesVariant, activitiesList) + QStringList crewHtmlSplit2 = QString(crewHtmlSplit1.at(1)).split(""); + if (crewHtmlSplit2.length() >= 1) { - QMap activityRootMap = activitiesVariant.toMap(); - foreach(const QVariant &activityRootVariant, activityRootMap) - { - QMap activityMap = activityRootVariant.toMap(); - foreach(const QVariant &activityVariant, activityMap) - { - QMap activityFinalMap = activityVariant.toMap(); - if (activityFinalMap.contains("id") && activityFinalMap["id"] == crewID) - { - if (activityFinalMap.contains("name") && isFound == false) - { - isFound = true; - crewName = activityFinalMap["name"].toString(); - } - } - } - } + crewName = crewHtmlSplit2.at(0); } } - if (!crewName.isNull()) + if (!crewName.isEmpty()) { crewDB->setCrewName(crewID.toInt(), crewName); } @@ -171,6 +228,9 @@ void DatabaseThread::scanCrewMembersList(QStringList crewList, int maxPages, int QNetworkAccessManager *netManager = new QNetworkAccessManager(); QNetworkRequest netRequest(AppEnv::getPlayerFetchingUrl(crewID, QString::number(currentPage))); +#if QT_VERSION >= 0x050600 + netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); +#endif netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent()); netRequest.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); netRequest.setRawHeader("Accept-Language", "en-US;q=0.5,en;q=0.3"); diff --git a/ProfileLoader.cpp b/ProfileLoader.cpp index 66f48b2..73e3941 100755 --- a/ProfileLoader.cpp +++ b/ProfileLoader.cpp @@ -91,3 +91,13 @@ void ProfileLoader::run() crewDB->addCrew(crewID); } } + +void ProfileLoader::preloaded() +{ + +} + +void ProfileLoader::loaded() +{ + +} diff --git a/ProfileLoader.h b/ProfileLoader.h index 6b5bac2..23c4d77 100755 --- a/ProfileLoader.h +++ b/ProfileLoader.h @@ -39,6 +39,10 @@ private: CrewDatabase *crewDB; ProfileLoader *profileLoader; +private slots: + void preloaded(); + void loaded(); + signals: void pictureLoaded(SnapmaticPicture *picture); void savegameLoaded(SavegameData *savegame, QString savegamePath); diff --git a/SavegameWidget.ui b/SavegameWidget.ui index 81ea544..2f857c7 100755 --- a/SavegameWidget.ui +++ b/SavegameWidget.ui @@ -40,6 +40,9 @@ + + Qt::NoFocus + diff --git a/SnapmaticEditor.cpp b/SnapmaticEditor.cpp index 046ce8e..c4ce38f 100644 --- a/SnapmaticEditor.cpp +++ b/SnapmaticEditor.cpp @@ -21,6 +21,7 @@ #include "SnapmaticPicture.h" #include "StringParser.h" #include "AppEnv.h" +#include #include #include #include @@ -230,7 +231,7 @@ void SnapmaticEditor::on_cmdApply_clicked() { adjustedFileName.remove(adjustedFileName.length() - 7, 7); } - QString backupFileName = adjustedFileName + ".bak"; + QString backupFileName = adjustedFileName % ".bak"; if (!QFile::exists(backupFileName)) { QFile::copy(adjustedFileName, backupFileName); @@ -307,6 +308,10 @@ void SnapmaticEditor::on_labCrew_linkActivated(const QString &link) int indexNum = 0; QStringList itemList; QStringList crewList = crewDB->getCrews(); + if (!crewList.contains(QLatin1String("0"))) + { + crewList.append(QLatin1String("0")); + } crewList.sort(); foreach(const QString &crew, crewList) { diff --git a/SnapmaticPicture.cpp b/SnapmaticPicture.cpp index 0fa91dd..1ded9ad 100755 --- a/SnapmaticPicture.cpp +++ b/SnapmaticPicture.cpp @@ -18,6 +18,7 @@ #include "SnapmaticPicture.h" #include "StringParser.h" +#include #include #include #include @@ -73,6 +74,7 @@ void SnapmaticPicture::reset() jpegRawContentSize = 0; picExportFileName = ""; isCustomFormat = 0; + isLoadedInRAM = 0; pictureHead = ""; pictureStr = ""; lowRamMode = 0; @@ -90,37 +92,26 @@ void SnapmaticPicture::reset() localSpJson = {}; } -bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bool fastLoad, bool lowRamMode_) +bool SnapmaticPicture::preloadFile() { - // 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 - QFile *picFile = new QFile(picFilePath); picFileName = QFileInfo(picFilePath).fileName(); - QIODevice *picStream; - if (!picFile->open(QFile::ReadOnly)) { - lastStep = "1;/1,OpenFile," + StringParser::convertDrawStringForLog(picFilePath); + lastStep = "1;/1,OpenFile," % StringParser::convertDrawStringForLog(picFilePath); delete picFile; return false; } - - if (picFilePath.right(4) != ".g5e") + if (picFilePath.right(4) != QLatin1String(".g5e")) { rawPicContent = picFile->read(snapmaticFileMaxSize); picFile->close(); delete picFile; - // Set Custom Format + // Setting is values isCustomFormat = false; + isLoadedInRAM = true; } else { @@ -133,57 +124,78 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo // Reading g5e Content g5eContent.remove(0, 1); - if (g5eContent.left(3) == "G5E") + if (g5eContent.left(3) == QByteArray("G5E")) { g5eContent.remove(0, 3); - if (g5eContent.left(2).toHex() == "1000") + if (g5eContent.left(2).toHex() == QByteArray("1000")) { g5eContent.remove(0, 2); - if (g5eContent.left(3) == "LEN") + 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) == "FIL") + if (g5eContent.left(3) == QByteArray("FIL")) { g5eContent.remove(0, 3); picFileName = g5eContent.left(fileNameLength); g5eContent.remove(0, fileNameLength); - if (g5eContent.left(3) == "COM") + if (g5eContent.left(3) == QByteArray("COM")) { g5eContent.remove(0, 3); rawPicContent = qUncompress(g5eContent); + + // Setting is values + isLoadedInRAM = true; } else { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",4,G5E_FORMATERROR"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",4,G5E_FORMATERROR"; return false; } } else { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",3,G5E_FORMATERROR"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",3,G5E_FORMATERROR"; return false; } } else { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",2,G5E_FORMATERROR"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",2,G5E_FORMATERROR"; return false; } } else { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",1,G5E_NOTCOMPATIBLE"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",1,G5E_NOTCOMPATIBLE"; return false; } } else { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",1,G5E_FORMATERROR"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",1,G5E_FORMATERROR"; return false; } } + emit preloaded(); + return true; +} + +bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bool fastLoad, bool lowRamMode_) +{ + // 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; + + if (!isLoadedInRAM) { preloadFile(); } picStream = new QBuffer(&rawPicContent); picStream->open(QIODevice::ReadWrite); @@ -191,7 +203,7 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo // Reading Snapmatic Header if (!picStream->isReadable()) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",1,NOHEADER"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",1,NOHEADER"; picStream->close(); delete picStream; return false; @@ -202,7 +214,7 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo // Reading JPEG Header Line if (!picStream->isReadable()) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",2,NOHEADER"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",2,NOHEADER"; picStream->close(); delete picStream; return false; @@ -211,9 +223,9 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo // Checking for JPEG jpegHeaderLine.remove(0, jpegHeaderLineDifStr); - if (jpegHeaderLine.left(4) != "JPEG") + if (jpegHeaderLine.left(4) != QByteArray("JPEG")) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",2,NOJPEG"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",2,NOJPEG"; picStream->close(); delete picStream; return false; @@ -222,7 +234,7 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo // Read JPEG Stream if (!picStream->isReadable()) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",2,NOPIC"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",2,NOPIC"; picStream->close(); delete picStream; return false; @@ -265,14 +277,14 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo // Read JSON Stream if (!picStream->isReadable()) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",3,NOJSON"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",3,NOJSON"; picStream->close(); delete picStream; return false; } - else if (picStream->read(4) != "JSON") + else if (picStream->read(4) != QByteArray("JSON")) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",3,CTJSON"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",3,CTJSON"; picStream->close(); delete picStream; return false; @@ -283,14 +295,14 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo if (!picStream->isReadable()) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",4,NOTITL"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",4,NOTITL"; picStream->close(); delete picStream; return false; } - else if (picStream->read(4) != "TITL") + else if (picStream->read(4) != QByteArray("TITL")) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",4,CTTITL"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",4,CTTITL"; picStream->close(); delete picStream; return false; @@ -300,14 +312,14 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo if (!picStream->isReadable()) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",5,NODESC"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",5,NODESC"; picStream->close(); delete picStream; return picOk; } - else if (picStream->read(4) != "DESC") + else if (picStream->read(4) != QByteArray("DESC")) { - lastStep = "2;/3,ReadingFile," + StringParser::convertDrawStringForLog(picFilePath) + ",5,CTDESC"; + lastStep = "2;/3,ReadingFile," % StringParser::convertDrawStringForLog(picFilePath) % ",5,CTDESC"; picStream->close(); delete picStream; return false; @@ -319,8 +331,11 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo picStream->close(); delete picStream; + if (!writeEnabled) { rawPicContent.clear(); } else if (lowRamMode) { rawPicContent = qCompress(rawPicContent, 9); } + + emit loaded(); return picOk; } @@ -352,26 +367,26 @@ QString SnapmaticPicture::getSnapmaticTIDEString(const QByteArray &tideBytes) void SnapmaticPicture::updateStrings() { QString cmpPicTitl = titlStr; - cmpPicTitl.replace("\"", "''"); - cmpPicTitl.replace(" ", "_"); - cmpPicTitl.replace(":", "-"); - cmpPicTitl.replace("\\", ""); - cmpPicTitl.replace("{", ""); - cmpPicTitl.replace("}", ""); - cmpPicTitl.replace("/", ""); - cmpPicTitl.replace("<", ""); - cmpPicTitl.replace(">", ""); - cmpPicTitl.replace("*", ""); - cmpPicTitl.replace("?", ""); - cmpPicTitl.replace(".", ""); + cmpPicTitl.replace('\"', "''"); + cmpPicTitl.replace(' ', '_'); + cmpPicTitl.replace(':', '-'); + cmpPicTitl.remove('\\'); + cmpPicTitl.remove('{'); + cmpPicTitl.remove('}'); + cmpPicTitl.remove('/'); + cmpPicTitl.remove('<'); + cmpPicTitl.remove('>'); + cmpPicTitl.remove('*'); + cmpPicTitl.remove('?'); + cmpPicTitl.remove('.'); pictureStr = tr("PHOTO - %1").arg(localSpJson.createdDateTime.toString("MM/dd/yy HH:mm:ss")); - sortStr = localSpJson.createdDateTime.toString("yyMMddHHmmss") + QString::number(localSpJson.uid); - picExportFileName = sortStr + "_" + cmpPicTitl; + sortStr = localSpJson.createdDateTime.toString("yyMMddHHmmss") % QString::number(localSpJson.uid); + picExportFileName = sortStr % "_" % cmpPicTitl; } bool SnapmaticPicture::readingPictureFromFile(const QString &fileName, bool writeEnabled_, bool cacheEnabled_, bool fastLoad, bool lowRamMode_) { - if (fileName != "") + if (!fileName.isEmpty()) { picFilePath = fileName; return readingPicture(writeEnabled_, cacheEnabled_, fastLoad, lowRamMode_); @@ -580,7 +595,7 @@ QImage SnapmaticPicture::getImage() QFile *picFile = new QFile(picFilePath); if (!picFile->open(QFile::ReadOnly)) { - lastStep = "1;/1,OpenFile," + StringParser::convertDrawStringForLog(picFilePath); + lastStep = "1;/1,OpenFile," % StringParser::convertDrawStringForLog(picFilePath); delete picFile; return QImage(0, 0, QImage::Format_RGB888); } @@ -781,7 +796,7 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, const QString form QFile *picFile = new QFile(fileName); if (picFile->open(QIODevice::WriteOnly)) { - if (format == "G5E") + if (format == QLatin1String("G5E")) { // Modern compressed export QByteArray stockFileNameUTF8 = picFileName.toUtf8(); @@ -795,14 +810,15 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, const QString form numberLength = "00"; } QByteArray g5eHeader; + g5eHeader.reserve(stockFileNameUTF8.length() + 16); g5eHeader += '\x00'; // First Null Byte - g5eHeader += "G5E"; // GTA 5 Export + g5eHeader += QByteArray("G5E"); // GTA 5 Export g5eHeader += '\x10'; g5eHeader += '\x00'; // 2 byte GTA 5 Export Version - g5eHeader += "LEN"; // Before Length + g5eHeader += QByteArray("LEN"); // Before Length g5eHeader += QByteArray::fromHex(numberLength); // Length in HEX before Compressed - g5eHeader += "FIL"; // Before File Name + g5eHeader += QByteArray("FIL"); // Before File Name g5eHeader += stockFileNameUTF8; // File Name - g5eHeader += "COM"; // Before Compressed + g5eHeader += QByteArray("COM"); // Before Compressed picFile->write(g5eHeader); if (!lowRamMode) { @@ -815,7 +831,7 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, const QString form picFile->close(); delete picFile; } - else if (format == "JPG") + else if (format == QLatin1String("JPG")) { // JPEG export QBuffer snapmaticStream(&rawPicContent); @@ -876,7 +892,7 @@ bool SnapmaticPicture::deletePicFile() bool SnapmaticPicture::isHidden() { - if (picFilePath.right(7) == ".hidden") + if (picFilePath.right(7) == QLatin1String(".hidden")) { return true; } @@ -891,7 +907,7 @@ bool SnapmaticPicture::setPictureHidden() } if (!isHidden()) { - QString newPicFilePath = QString(picFilePath + ".hidden"); + QString newPicFilePath = QString(picFilePath % ".hidden"); if (QFile::rename(picFilePath, newPicFilePath)) { picFilePath = newPicFilePath; diff --git a/SnapmaticPicture.h b/SnapmaticPicture.h index 2b16c66..ab0ba00 100755 --- a/SnapmaticPicture.h +++ b/SnapmaticPicture.h @@ -53,6 +53,7 @@ public: explicit SnapmaticPicture(const QString &fileName = "", QObject *parent = 0); ~SnapmaticPicture(); void reset(); + bool preloadFile(); bool readingPictureFromFile(const QString &fileName, bool writeEnabled = true, bool cacheEnabled = false, bool fastLoad = true, bool lowRamMode = false); bool readingPicture(bool writeEnabled = true, bool cacheEnabled = false, bool fastLoad = true, bool lowRamMode = false); bool isPicOk(); @@ -121,6 +122,7 @@ private: bool lowRamMode; bool writeEnabled; bool cacheEnabled; + bool isLoadedInRAM; bool isCustomFormat; int jpegRawContentSize; int jpegRawContentSizeE; @@ -138,7 +140,9 @@ private: static bool verifyTitleChar(const QChar &titleChar); signals: + void preloaded(); void updated(); + void loaded(); public slots: }; diff --git a/SnapmaticWidget.ui b/SnapmaticWidget.ui index 1a6f42f..5c720c8 100755 --- a/SnapmaticWidget.ui +++ b/SnapmaticWidget.ui @@ -40,6 +40,9 @@ + + Qt::NoFocus + diff --git a/StringParser.cpp b/StringParser.cpp index ec55853..6addd10 100755 --- a/StringParser.cpp +++ b/StringParser.cpp @@ -38,7 +38,7 @@ QString StringParser::parseTitleString(const QByteArray &commitBytes, int maxLen { Q_UNUSED(maxLength) QString retStr = QTextCodec::codecForName("UTF-16LE")->toUnicode(commitBytes).trimmed(); - retStr.remove(QChar((char)0x00)); + retStr.remove(QChar('\x00')); return retStr; } diff --git a/UserInterface.cpp b/UserInterface.cpp index 60e7afb..b029c6e 100755 --- a/UserInterface.cpp +++ b/UserInterface.cpp @@ -88,6 +88,9 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D void UserInterface::setupDirEnv() { + // settings init + QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); + bool folderExists; GTAV_Folder = AppEnv::getGameFolder(&folderExists); if (folderExists) @@ -102,11 +105,18 @@ void UserInterface::setupDirEnv() folderExists = true; QDir::setCurrent(GTAV_Folder); AppEnv::setGameFolder(GTAV_Folder); + + // First time folder selection save + settings.beginGroup("dir"); + if (settings.value("dir", "").toString().isEmpty()) + { + settings.setValue("dir", GTAV_Folder); + } + settings.endGroup(); } } // profiles init - QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); settings.beginGroup("Profile"); QString defaultProfile = settings.value("Default", "").toString(); diff --git a/config.h b/config.h index ff4e316..c855265 100755 --- a/config.h +++ b/config.h @@ -50,14 +50,14 @@ #ifndef GTA5SYNC_APPVER #ifndef GTA5SYNC_DAILYB -#define GTA5SYNC_APPVER "1.4.0-rc2" +#define GTA5SYNC_APPVER "1.4.0" #else #define GTA5SYNC_APPVER QString("%1").arg(GTA5SYNC_DAILYB) #endif #endif #ifndef GTA5SYNC_BUILDTYPE -#define GTA5SYNC_BUILDTYPE "Release Candidate" +#define GTA5SYNC_BUILDTYPE "Custom" #endif #ifndef GTA5SYNC_SHARE diff --git a/gta5view.pro b/gta5view.pro index 76c40f3..13e3a9e 100755 --- a/gta5view.pro +++ b/gta5view.pro @@ -132,6 +132,9 @@ win32: RC_FILE += res/app.rc win32: LIBS += -luser32 win32: CONFIG -= embed_manifest_exe +# MAC OS X ONLY +macx: ICON = res/5sync.icns + # QT4 ONLY STUFF isEqual(QT_MAJOR_VERSION, 4): INCLUDEPATH += ./qjson4 diff --git a/res/5sync.icns b/res/5sync.icns new file mode 100644 index 0000000000000000000000000000000000000000..12f8c6f26f292315fb61ca6384a82d2d8a46f472 GIT binary patch literal 45948 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 Vo6Wo2*0QXiRpGS*^E8-~{~L7{ global.de.ini global.en.ini - global.ja.ini - global.fr.ini - global.zh.ini global.es.ini + global.fr.ini + global.ja.ini + global.ru.ini + global.zh.ini template.g5e diff --git a/res/global.ru.ini b/res/global.ru.ini new file mode 100644 index 0000000..e53f2c9 --- /dev/null +++ b/res/global.ru.ini @@ -0,0 +1,106 @@ +[Global] +AIRP="Международный аэропорт Лос-Сантос" +ALAMO="Аламо-Си" +ALTA="Альта" +ARMYB="Форт-Занкудо" +BANNING="Бэннинг" +BAYTRE="Каньон Бэйтри" +BEACH="Веспуччи-Бич" +BHAMCA="Каньон Бэнхэм" +BRADP="Перевал Брэддока" +BRADT="Тоннель Брэддока" +BURTON="Бертон" +CALAFB="Калафиа-Бридж" +CANNY="Каньон Ратон" +CCREAK="Кэссиди-Крик" +CHAMH="Чемберлен-Хиллз" +CHIL="Вайнвуд-Хиллз" +CHU="Чумаш" +CMSW="Заповедник горы Чилиад" +COSI="Загород" +CYPRE="Сайпрес-Флэтс" +DAVIS="Дэвис" +DELBE="Дель-Перро-Бич" +DELPE="Дель-Перро" +DELSOL="Ла-Пуэрта" +DESRT="Пустыня Гранд-Сенора" +DOWNT="Центр" +DTVINE="Центр Вайнвуда" +EAST_V="Восточный Вайнвуд" +EBURO="Эль-Бурро-Хайтс" +ECLIPS="Эклипс" +ELGORL="Маяк Эль-Гордо" +ELSANT="Восточный Лос-Сантос" +ELYSIAN="Элизиан-Айленд" +GALFISH="Галили" +GALLI="Галилео-Парк" +GOLF="Гольф-клуб" +GRAPES="Грейпсид" +GREATC="Грейт-Чапаррал" +HARMO="Хармони" +HAWICK="Хавик" +HEART="Харт-Аттакс-Бич" +HORS="Гоночная трасса Вайнвуда" +HUD_MG_TRI_ALA="Аламо-Си" +HUD_MG_TRI_VES="Веспуччи" +HUMLAB="Лаборатория Humane Labs and Research" +JAIL="Тюрьма Болингброук" +KOREAT="Маленький Сеул" +LACT="Лэнд-экт-резервуар" +LAGO="Лаго-Занкудо" +LDAM="Лэнд-экт-дэм" +LMESA="Ла-Меса" +LOSPFY="Шоссе Ла-Пуэрта" +LOSPUER="Ла-Пуэрта" +LOSSF="Шоссе Лос-Сантоса" +MGCR_1="Южный Лос-Сантос" +MGCR_6="Каналы Веспуччи" +MGSR_3="Каньон Ратон" +MIRR="Миррор-Парк" +MORN="Морнингвуд" +MOVIE="Richards Majestic" +MTCHIL="Гора Чилиад" +MTGORDO="Гора Гордо" +MTJOSE="Гора Джосайя" +MURRI="Мурьета-Хайтс" +NCHU="Северный Чумаш" +OBSERV="Обсерватория Галилео" +OCEANA="Тихий океан" +PALCOV="Бухта Палето" +PALETO="Палето-Бэй" +PALFOR="Лес Палето" +PALHIGH="Нагорья Паломино" +PALMPOW="Электростанция Палмер-Тэйлор" +PBLUFF="Пасифик-Блаффс" +PBOX="Пиллбокс-Хилл" +PROCOB="Прокопио-Бич" +PROL="Северный Янктон" +RANCHO="Ранчо" +RGLEN="Ричман-Глен" +RICHM="Ричман" +ROCKF="Рокфорд-Хиллз" +RTRAK="Трасса Redwood Lights" +SANAND="Сан-Андреас" +SANCHIA="Сан-Шаньский горный хребет" +SANDY="Сэнди-Шорс" +SENORA="Шоссе Сенора" +SKID="Мишн-Роу" +SLAB="Стэб-Сити" +SLSANT="Южный Лос-Сантос" +STAD="Арена Maze Bank" +STRAW="Строберри" +TATAMO="Татавиамские горы" +TERMINA="Терминал" +TEXTI="Текстайл-Сити" +TONGVAH="Тонгва-Хиллз" +TONGVAV="Долина Тонгва" +UTOPIAG="Утопия-Гарденс" +VCANA="Каналы Веспуччи" +VESP="Веспуччи" +VINE="Вайнвуд" +WINDF="Ветряная ферма Ron Alternates" +WMIRROR="Вест-Миррор-драйв" +WVINE="Западный Вайнвуд" +ZANCUDO="Река Занкудо" +ZENORA="Шоссе Сенора" +ZP_ORT="Порт Южного Лос-Сантоса" diff --git a/res/gta5sync_ru.qm b/res/gta5sync_ru.qm index a9d9ff463bcba95b2147bfb30fbcf779f2553e14..6a271c0e64bef67eda16b519391756c41112d962 100644 GIT binary patch delta 223 zcmccilJVY4#tAiymp9hBGcvYLKFV0fl*v5Vm8svcn`L$17Y2s3{XqIF14Ftlkp2#& zX9MY9q8{?EXW!OXI{p8-gl18GJeoeiX!f%N>zqRi!t)|-2o|1&a9oZQPQ&)LZN z{@PLohU^`ax3by`-sSRr>B+$0o4^(Ro{xbct8+3dn?2+E$*yeuoS(V-8J++wNt}F_ zO>RIbU=4Gduwr9y$3g zo4lkx_rBbxKow89kJ!CrV9-6oeZHg)$d{Td%C64nw%L~5hmp~0a~FqKDmM>{9E&}J O8jBl?#pdU^-`M~TX-y{p diff --git a/res/gta5sync_ru.ts b/res/gta5sync_ru.ts index bafc054..3a3e584 100644 --- a/res/gta5sync_ru.ts +++ b/res/gta5sync_ru.ts @@ -1496,7 +1496,7 @@ Press 1 for Default View &Settings - Оп&ции + &Настройки