From e047e1b44de1dadcf017b74e88118c2721919660 Mon Sep 17 00:00:00 2001
From: Syping <schiedelrafael@keppe.org>
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 \<travisci@syping.de\>"  --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 \<travisci@syping.de\>"  --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<QVariant> activitiesList = crewMap["activities"].toList();
+//                     foreach (const QVariant &activitiesVariant, activitiesList)
+//                     {
+//                         QMap<QString, QVariant> activityRootMap = activitiesVariant.toMap();
+//                         foreach(const QVariant &activityRootVariant, activityRootMap)
+//                         {
+//                             QMap<QString, QVariant> activityMap = activityRootVariant.toMap();
+//                             foreach(const QVariant &activityVariant, activityMap)
+//                             {
+//                                 QMap<QString, QVariant> 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("<title>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("</title>");
+                    if (crewHtmlSplit2.length() >= 1)
                     {
-                        QMap<QString, QVariant> activityRootMap = activitiesVariant.toMap();
-                        foreach(const QVariant &activityRootVariant, activityRootMap)
-                        {
-                            QMap<QString, QVariant> activityMap = activityRootVariant.toMap();
-                            foreach(const QVariant &activityVariant, activityMap)
-                            {
-                                QMap<QString, QVariant> 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 @@
      <layout class="QHBoxLayout" name="hlSavegame">
       <item>
        <widget class="QCheckBox" name="cbSelected">
+        <property name="focusPolicy">
+         <enum>Qt::NoFocus</enum>
+        </property>
         <property name="text">
          <string/>
         </property>
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 <QStringBuilder>
 #include <QTextDocument>
 #include <QInputDialog>
 #include <QMessageBox>
@@ -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 <QStringBuilder>
 #include <QJsonDocument>
 #include <QJsonObject>
 #include <QStringList>
@@ -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 @@
      <layout class="QHBoxLayout" name="hlSnapmatic">
       <item>
        <widget class="QCheckBox" name="cbSelected">
+        <property name="focusPolicy">
+         <enum>Qt::NoFocus</enum>
+        </property>
         <property name="text">
          <string/>
         </property>
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{<E8)r

literal 0
HcmV?d00001

diff --git a/res/app.qrc b/res/app.qrc
index 2439a2f..8ae92ac 100755
--- a/res/app.qrc
+++ b/res/app.qrc
@@ -31,10 +31,11 @@
     <qresource prefix="/global">
         <file>global.de.ini</file>
         <file>global.en.ini</file>
-        <file>global.ja.ini</file>
-        <file>global.fr.ini</file>
-        <file>global.zh.ini</file>
         <file>global.es.ini</file>
+        <file>global.fr.ini</file>
+        <file>global.ja.ini</file>
+        <file>global.ru.ini</file>
+        <file>global.zh.ini</file>
     </qresource>
     <qresource prefix="/template">
         <file>template.g5e</file>
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#&
zX9MY<K>9q8{?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<vNRdtdHTpo+KLN9<lQFzBA)K3`G?<SR`UWmjkP+ic73!^r5gxr@Uqm05&AZF0Y;
K^yXK&Z`c6puuND0

delta 227
zcmccjlJVM0#tAiyr#IHRGcwjrKFV0fl<|AAD^tH?Gt26}FANN6+kx~~28MK1ApIRk
zPX^LIf%I`8{U1pGW?9|Oz`&5952P7^bTW`;2GY|fi!zrp8gK4p{?EwRIk}frp0kqk
z{k5eG4A~ndZ)LR?yvpVK(vyL~H-RhsJs$%@R^wz=HhaeBlU>>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</source>
     <message>
         <location filename="../UserInterface.ui" line="247"/>
         <source>&amp;Settings</source>
-        <translation>Оп&amp;ции</translation>
+        <translation>&amp;Настройки</translation>
     </message>
     <message>
         <location filename="../UserInterface.ui" line="282"/>