Compare commits
182 Commits
Author | SHA1 | Date |
---|---|---|
Syping | fcbe264d63 | |
Syping | f8049c8178 | |
Syping | d0899623ad | |
Syping | 547922329a | |
Syping | 1fbe4d9e67 | |
Syping | 678425a7c5 | |
Syping | f9129f8364 | |
Syping | 4e5592566a | |
Syping | 39436a6dbf | |
Syping | 15dfc2c84b | |
Syping | 57c32eea58 | |
Syping | 90744ced60 | |
Syping | 90846e6fb6 | |
Syping | 2735325f4c | |
Syping | 8b8e22c958 | |
Syping | 91ccdca77a | |
Syping | ae0c7c2905 | |
Syping | 4a026640e3 | |
Syping | 8be9fd6d5e | |
Syping | 8295e38ab4 | |
Syping | 24cd9a16f9 | |
Syping | aa142c9ec9 | |
Syping | 4c42f06b39 | |
Syping | 94fb78c59a | |
Syping | 3f910c16b0 | |
Syping | bbf7f08980 | |
Syping | ec93fa8ce0 | |
Syping | d37fbdf055 | |
Syping | 1c00871e80 | |
Syping | a74e7847b2 | |
Syping | e41d4946f8 | |
Syping | 28fedfdd0b | |
Syping | a882738735 | |
Syping | 23245a3324 | |
Syping | af86e70f4b | |
Syping | 2bf6bb5630 | |
Syping | 6b2b18ed16 | |
Syping | c936fed2f8 | |
Syping | cb8793f3b3 | |
Syping | 1038f000f7 | |
Syping | 3c124f9f27 | |
Syping | 27075778c6 | |
Syping | 2b0455e2ff | |
Syping | ab248413ea | |
Syping | 279cd5ac3b | |
Syping | 1f62f6fe48 | |
Syping | c8a955e8de | |
Syping | 5250bad4b6 | |
Syping | 9121987142 | |
Syping | cabd44f066 | |
Syping | 01fb80fdd1 | |
Syping | f63645a1fb | |
Syping | 8732b9d64d | |
Syping | bb4a9b484c | |
Syping | c79c8dbe6e | |
Syping | 4e31d159fa | |
Syping | 0633d14d6b | |
Syping | c6b39546ba | |
Syping | eac9caa2c6 | |
Syping | a80b5843a7 | |
Syping | 07797f6e60 | |
Syping | 55186e8b88 | |
Syping | eee9100d8b | |
Syping | b73719ed4e | |
Syping | a143b43d15 | |
Syping | 032475ddfd | |
Syping | bdde72573b | |
Syping | 827676768a | |
Syping | 0c02c3ce98 | |
Syping | 6063803d5e | |
Syping | 1f3c036b47 | |
Syping | ea0526ae9d | |
Syping | aeae6c9311 | |
Syping | c39c3a3e9f | |
Syping | 9989d9d869 | |
Syping | fa86e8f8a7 | |
Syping | f9880fff70 | |
Syping | 7ba5322643 | |
Syping | 1f409b0f25 | |
Syping | dea33f8ab0 | |
Syping | 6b54b2e6ae | |
VADemon | 38f2877ea3 | |
Syping | c67a0a0fc9 | |
Syping | 7a15c3e56b | |
Syping | feabaac48e | |
Jean | 6ab75420ec | |
Syping | cda974d5df | |
VenJam1n | 36677ed07a | |
Syping | 17014925c5 | |
Syping | f151035574 | |
Syping | 53ef2bdb54 | |
Syping | 2606cd8965 | |
Syping | 973fb58a5d | |
Syping | 39f20aca9d | |
Syping | c29cc44717 | |
Syping | 9ced2253fc | |
Syping | 778abdd36a | |
Syping | 30a6b55c9e | |
Syping | b02f06ae97 | |
Syping | 193bb60caa | |
Syping | 414867f13e | |
Syping | 7b68bb10b5 | |
Syping | 2487a188d5 | |
Syping | c34d3331fb | |
Syping | afeab6120d | |
Syping | 4c6962ab23 | |
Syping | 08ecd5ca61 | |
Syping | 5f35428cd0 | |
Syping | 714be43280 | |
Syping | 1165c3b536 | |
Syping | 06eb2e4277 | |
Syping | 00db9ecab2 | |
Syping | dc101a66da | |
Syping | 541a7d18bd | |
Syping | f932a8d5ee | |
Syping | 81ea0490cf | |
Syping | a8db3985a2 | |
Syping | 0127bc61e6 | |
Syping | 25c64b7f5d | |
Syping | c3d684436b | |
Syping | 4135b1f588 | |
Syping | 7c08e1486e | |
Syping | d61cbd4743 | |
Syping | efa88cc46e | |
Syping | f1cfbbf573 | |
Syping | ca8003c2e8 | |
Syping | 69a7ec8dbe | |
Syping | 0321d79136 | |
Syping | e2b7062e26 | |
Syping | 99f3c22ab0 | |
Syping | 9b5cb46c35 | |
Syping | c909e20178 | |
Syping | 0e337b4dec | |
Syping | 3b305fb809 | |
Syping | 06a8657423 | |
Syping | caffd9f246 | |
Syping | caaa6a1d85 | |
Syping | 196cb8bc55 | |
Syping | 2d62bbb97e | |
Syping | c3e030e827 | |
Syping | 291236ff2c | |
Syping | c7ec038e26 | |
Syping | cde4b380f8 | |
Syping | bcd7e3cd15 | |
Syping | 1f1025787e | |
Syping | fd5ce958bd | |
Syping | 681e76737e | |
Syping | 24ca667537 | |
Syping | e6c8a48e12 | |
Syping | 867281f80a | |
Syping | a33bc8145b | |
Syping | e3a8edae2d | |
Syping | 609efb7fba | |
Syping | 29f883555d | |
Syping | 8fc3dc6c7c | |
Syping | 72377e49eb | |
Syping | 5840d8e8e9 | |
Syping | d0e157bf1c | |
Syping | 9b41d80d9a | |
Syping | 06ada3d770 | |
Syping | cd20e0b512 | |
Syping | bd97ee86ba | |
Syping | 7b98e75f8d | |
Syping | 99ffbf4178 | |
Syping | 108f1725f6 | |
Syping | 5c7cb24c36 | |
Syping | 6e335638a3 | |
Syping | 5a4b2f1d67 | |
Syping | d91b9f5f43 | |
Syping | 3dfc2e001b | |
Syping | 1b54c8c456 | |
Syping | 979747b8f5 | |
Syping | e74b19fed0 | |
Syping | d94a3712be | |
Syping | e765511614 | |
Syping | 61864c65eb | |
Syping | bf81aea0c9 | |
Syping | 48650633a5 | |
Syping | 2b3a22b893 | |
Syping | 9b373669b2 | |
Syping | 55a01e7fe4 | |
Syping | fdf07dd681 |
|
@ -0,0 +1,33 @@
|
|||
IDI_ICON1 ICON DISCARDABLE "5sync.ico"
|
||||
#define RT_MANIFEST 24
|
||||
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gta5view.exe.manifest"
|
||||
#include <windows.h>
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION MAJOR_VER, MINOR_VER, PATCH_VER, INT_BUILD_VER
|
||||
PRODUCTVERSION MAJOR_VER, MINOR_VER, PATCH_VER, INT_BUILD_VER
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0809, 1200
|
||||
END
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Syping"
|
||||
VALUE "FileDescription", "gta5view"
|
||||
VALUE "FileVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER"
|
||||
VALUE "InternalName", "gta5view"
|
||||
VALUE "LegalCopyright", "Copyright © 2016-2020 Syping"
|
||||
VALUE "OriginalFilename", "gta5view.exe"
|
||||
VALUE "ProductName", "gta5view"
|
||||
VALUE "ProductVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER"
|
||||
END
|
||||
END
|
||||
END
|
|
@ -0,0 +1,72 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ $(git name-rev --tags --name-only $(git rev-parse HEAD)) == "undefined" ]; then
|
||||
export APPLICATION_VERSION=$(lua -e 'for line in io.lines("config.h") do local m = string.match(line, "#define GTA5SYNC_APPVER \"(.+)\"$"); if m then print(m); os.exit(0) end end')
|
||||
else
|
||||
export APPLICATION_VERSION=$(git name-rev --tags --name-only $(git rev-parse HEAD))
|
||||
fi
|
||||
export PACKAGE_VERSION=$(grep -oE '^[^\-]*' <<< $APPLICATION_VERSION)
|
||||
export PACKAGE_BUILD=$(grep -oP '\-\K.+' <<< $APPLICATION_VERSION)
|
||||
export EXECUTABLE_VERSION=${PACKAGE_VERSION}${PACKAGE_BUILD}${EXECUTABLE_TAG}
|
||||
|
||||
export APPLICATION_MAJOR_VERSION=$(cut -d. -f1 <<< $APPLICATION_VERSION)
|
||||
export APPLICATION_MINOR_VERSION=$(cut -d. -f2 <<< $APPLICATION_VERSION)
|
||||
export APPLICATION_PATCH_VERSION=$(cut -d. -f3 <<< $APPLICATION_VERSION)
|
||||
|
||||
if [ "${PACKAGE_BUILD}" == "" ]; then
|
||||
export PACKAGE_BUILD=1
|
||||
else
|
||||
export APPLICATION_BUILD_INT_VERSION=$(grep -oE "[1-9]*$" <<< $PACKAGE_BUILD)
|
||||
export APPLICATION_BUILD_STR_VERSION=-${PACKAGE_BUILD}
|
||||
fi
|
||||
|
||||
cat ".ci/app.rc" | sed \
|
||||
-e "s/MAJOR_VER/$APPLICATION_MAJOR_VERSION/g" \
|
||||
-e "s/MINOR_VER/$APPLICATION_MINOR_VERSION/g" \
|
||||
-e "s/PATCH_VER/$APPLICATION_PATCH_VERSION/g" \
|
||||
-e "s/INT_BUILD_VER/0/g" \
|
||||
-e "s/STR_BUILD_VER/$APPLICATION_BUILD_STR_VERSION/g" \
|
||||
-e "s/STR_BUILD_VER/$APPLICATION_BUILD_STR_VERSION/g" \
|
||||
> "res/app.rc"
|
||||
|
||||
if [ "${BUILD_TYPE}" == "ALPHA" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_ALPHA=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_ALPHA"
|
||||
elif [ "${BUILD_TYPE}" == "Alpha" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_ALPHA=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_ALPHA"
|
||||
elif [ "${BUILD_TYPE}" == "BETA" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_BETA=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_BETA"
|
||||
elif [ "${BUILD_TYPE}" == "Beta" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_BETA=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_BETA"
|
||||
elif [ "${BUILD_TYPE}" == "DEV" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DEV=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DEV"
|
||||
elif [ "${BUILD_TYPE}" == "Development" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DEV=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DEV"
|
||||
elif [ "${BUILD_TYPE}" == "DAILY" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DAILY=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DAILY"
|
||||
elif [ "${BUILD_TYPE}" == "Daily" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DAILY=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DAILY"
|
||||
elif [ "${BUILD_TYPE}" == "RC" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_RC=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_RC"
|
||||
elif [ "${BUILD_TYPE}" == "Release Candidate" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_RC=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_RC"
|
||||
elif [ "${BUILD_TYPE}" == "REL" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_REL=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_REL"
|
||||
elif [ "${BUILD_TYPE}" == "Release" ]; then
|
||||
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_REL=TRUE"
|
||||
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_REL"
|
||||
fi
|
||||
|
||||
export PROJECT_DIR=$(pwd)
|
||||
|
||||
.ci/${BUILD_SCRIPT}
|
|
@ -0,0 +1,44 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
chmod -x res/gta5sync_*.qm res/*.desktop res/*gta5view*.png && \
|
||||
cd build && \
|
||||
mkdir -p qt4 && \
|
||||
cd qt4 && \
|
||||
echo "Grand Theft Auto V Snapmatic and Savegame viewer/editor" > ./description-pak && \
|
||||
cd .. && \
|
||||
mkdir -p qt5 && \
|
||||
cd qt5 && \
|
||||
echo "Grand Theft Auto V Snapmatic and Savegame viewer/editor" > ./description-pak && \
|
||||
cd .. && \
|
||||
|
||||
# Set compiler
|
||||
export CC=clang && \
|
||||
export CXX=clang++ && \
|
||||
|
||||
# Prepare checkinstall step
|
||||
mkdir -p /usr/share/gta5view && \
|
||||
|
||||
# Starting build
|
||||
cd qt5 && \
|
||||
cmake \
|
||||
"-DCMAKE_INSTALL_PREFIX=/usr" \
|
||||
${CMAKE_BUILD_TYPE} \
|
||||
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
|
||||
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
|
||||
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
|
||||
"-DWITH_TELEMETRY=ON" \
|
||||
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
|
||||
"-DQCONF_BUILD=ON" \
|
||||
../../ && \
|
||||
make -j 4 && \
|
||||
checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt5 --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5svg5,libqt5widgets5,qttranslations5-l10n --conflicts=gta5view,gta5view-qt4 --replaces=gta5view,gta5view-qt4 --pakdir=${PROJECT_DIR}/assets && \
|
||||
cd .. && \
|
||||
cd qt4 && \
|
||||
qmake -qt=4 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=gnu++11 ${QMAKE_FLAGS_QT4} ${QMAKE_BUILD_TYPE} "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt4 --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqtcore4,libqtgui4,libqt4-network,libqt4-svg,qtcore4-l10n --conflicts=gta5view,gta5view-qt5 --replaces=gta5view,gta5view-qt5 --pakdir=${PROJECT_DIR}/assets
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install packages
|
||||
.travis/osx_install.sh && \
|
||||
.ci/debian_install.sh && \
|
||||
|
||||
# Build gta5view
|
||||
.travis/osx_build.sh && \
|
||||
.ci/debian_build.sh && \
|
||||
cd ${PROJECT_DIR}
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ "${DOCKER_USER}" != "" ]; then
|
||||
DOCKER_IMAGE=${DOCKER_USER}/debian:${DEBIAN_VERSION}
|
||||
else
|
||||
DOCKER_IMAGE=debian:${DEBIAN_VERSION}
|
||||
fi
|
||||
PROJECT_DIR_DOCKER=/gta5view
|
||||
|
||||
cd ${PROJECT_DIR} && \
|
||||
docker pull ${DOCKER_IMAGE} && \
|
||||
docker run --rm \
|
||||
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
|
||||
${DOCKER_IMAGE} \
|
||||
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APPLICATION_COMMIT=${APPLICATION_COMMIT} && export BUILD_TYPE=${BUILD_TYPE} && export APT_INSTALL=${APT_INSTALL} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && export QMAKE_BUILD_TYPE=${QMAKE_BUILD_TYPE} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .ci/debian_install.sh && .ci/debian_build.sh"
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install packages
|
||||
apt-get update -qq && \
|
||||
apt-get install -qq ${APT_INSTALL} checkinstall cmake dpkg-dev fakeroot g++ gcc qtbase5-dev qt5-qmake qttranslations5-l10n libqt4-dev libqt5svg5-dev
|
|
@ -3,8 +3,8 @@
|
|||
!define APP_NAME "gta5view"
|
||||
!define COMP_NAME "Syping"
|
||||
!define WEB_SITE "https://gta5view.syping.de/"
|
||||
!define VERSION "1.5.5.0"
|
||||
!define COPYRIGHT "Copyright © 2016-2018 Syping"
|
||||
!define VERSION "1.8.0.0"
|
||||
!define COPYRIGHT "Copyright © 2016-2020 Syping"
|
||||
!define DESCRIPTION "Grand Theft Auto V Savegame and Snapmatic Viewer/Editor"
|
||||
!define INSTALLER_NAME "gta5view_setup.exe"
|
||||
!define MAIN_APP_EXE "gta5view.exe"
|
||||
|
@ -33,6 +33,7 @@ Caption "${APP_NAME}"
|
|||
OutFile "${INSTALLER_NAME}"
|
||||
#BrandingText "${APP_NAME}"
|
||||
XPStyle on
|
||||
Unicode true
|
||||
InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" ""
|
||||
InstallDir "$PROGRAMFILES64\Syping\gta5view"
|
||||
|
||||
|
@ -78,6 +79,7 @@ InstallDir "$PROGRAMFILES64\Syping\gta5view"
|
|||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "German"
|
||||
!insertmacro MUI_LANGUAGE "Korean"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "Ukrainian"
|
||||
!insertmacro MUI_LANGUAGE "TradChinese"
|
||||
|
@ -89,7 +91,7 @@ InstallDir "$PROGRAMFILES64\Syping\gta5view"
|
|||
Function .onInit
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
!ifdef WIN32
|
||||
MessageBox MB_OK|MB_ICONSTOP "Can't install the 64bit version on a 32bit system, please download the 32bit version!"
|
||||
MessageBox MB_OK|MB_ICONSTOP "Windows 32-Bit is not supported anymore!"
|
||||
Quit
|
||||
!endif
|
||||
SetRegView 64
|
||||
|
@ -101,45 +103,48 @@ Section -MainProgram
|
|||
${INSTALL_TYPE}
|
||||
SetOverwrite ifnewer
|
||||
SetOutPath "$INSTDIR"
|
||||
File "../build/release/gta5view.exe"
|
||||
File "/usr/lib/gcc/x86_64-w64-mingw32/6.3-win32/libgcc_s_seh-1.dll"
|
||||
File "/usr/lib/gcc/x86_64-w64-mingw32/6.3-win32/libstdc++-6.dll"
|
||||
File "/opt/windev/libressl-latest_qt64d/bin/libcrypto-43.dll"
|
||||
File "/opt/windev/libressl-latest_qt64d/bin/libssl-45.dll"
|
||||
File "/opt/windev/libjpeg-turbo-latest_qt64d/bin/libjpeg-62.dll"
|
||||
File "/opt/windev/qt64d-latest/bin/Qt5Core.dll"
|
||||
File "/opt/windev/qt64d-latest/bin/Qt5Gui.dll"
|
||||
File "/opt/windev/qt64d-latest/bin/Qt5Network.dll"
|
||||
File "/opt/windev/qt64d-latest/bin/Qt5Svg.dll"
|
||||
File "/opt/windev/qt64d-latest/bin/Qt5Widgets.dll"
|
||||
File "/opt/windev/qt64d-latest/bin/Qt5WinExtras.dll"
|
||||
File "../build/gta5view.exe"
|
||||
File "/opt/llvm-mingw/x86_64-w64-mingw32/bin/libc++.dll"
|
||||
File "/opt/llvm-mingw/x86_64-w64-mingw32/bin/libunwind.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/openssl/bin/libcrypto-1_1-x64.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/openssl/bin/libssl-1_1-x64.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Core.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Gui.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Network.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Svg.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Widgets.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5WinExtras.dll"
|
||||
SetOutPath "$INSTDIR\lang"
|
||||
File "../res/gta5sync_en_US.qm"
|
||||
File "../res/gta5sync_de.qm"
|
||||
File "../res/gta5sync_fr.qm"
|
||||
File "../res/gta5sync_ru.qm"
|
||||
File "../res/gta5sync_uk.qm"
|
||||
File "../res/gta5sync_zh_TW.qm"
|
||||
File "../res/qtbase_en_GB.qm"
|
||||
File "../build/gta5sync_en_US.qm"
|
||||
File "../build/gta5sync_de.qm"
|
||||
File "../build/gta5sync_fr.qm"
|
||||
File "../build/gta5sync_ko.qm"
|
||||
File "../build/gta5sync_ru.qm"
|
||||
File "../build/gta5sync_uk.qm"
|
||||
File "../build/gta5sync_zh_TW.qm"
|
||||
File "../build/qtbase_en_GB.qm"
|
||||
File "../res/qtbase_de.qm"
|
||||
File "../res/qtbase_fr.qm"
|
||||
File "../res/qtbase_ko.qm"
|
||||
File "../res/qtbase_ru.qm"
|
||||
File "../res/qtbase_uk.qm"
|
||||
File "../res/qtbase_zh_TW.qm"
|
||||
SetOutPath "$INSTDIR\audio"
|
||||
File "/opt/windev/qt64d-latest/plugins/audio/qtaudio_windows.dll"
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qgif.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qicns.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qico.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qjpeg.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qsvg.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qtga.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qtiff.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qwbmp.dll"
|
||||
File "/opt/windev/qt64d-latest/plugins/imageformats/qwebp.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qgif.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qicns.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qico.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qjpeg.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qsvg.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qtga.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qtiff.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qwbmp.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qwebp.dll"
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "/opt/windev/qt64d-latest/plugins/platforms/qwindows.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/platforms/qwindows.dll"
|
||||
SetOutPath "$INSTDIR\styles"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/styles/qcleanlooksstyle.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/styles/qplastiquestyle.dll"
|
||||
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/styles/qwindowsvistastyle.dll"
|
||||
SectionEnd
|
||||
|
||||
######################################################################
|
||||
|
@ -189,11 +194,10 @@ SectionEnd
|
|||
Section Uninstall
|
||||
${INSTALL_TYPE}
|
||||
Delete "$INSTDIR\gta5view.exe"
|
||||
Delete "$INSTDIR\libgcc_s_seh-1.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libcrypto-43.dll"
|
||||
Delete "$INSTDIR\libssl-45.dll"
|
||||
Delete "$INSTDIR\libjpeg-62.dll"
|
||||
Delete "$INSTDIR\libc++.dll"
|
||||
Delete "$INSTDIR\libunwind.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1-x64.dll"
|
||||
Delete "$INSTDIR\libssl-1_1-x64.dll"
|
||||
Delete "$INSTDIR\Qt5Core.dll"
|
||||
Delete "$INSTDIR\Qt5Gui.dll"
|
||||
Delete "$INSTDIR\Qt5Network.dll"
|
||||
|
@ -203,16 +207,17 @@ Delete "$INSTDIR\Qt5WinExtras.dll"
|
|||
Delete "$INSTDIR\lang\gta5sync_en_US.qm"
|
||||
Delete "$INSTDIR\lang\gta5sync_de.qm"
|
||||
Delete "$INSTDIR\lang\gta5sync_fr.qm"
|
||||
Delete "$INSTDIR\lang\gta5sync_ko.qm"
|
||||
Delete "$INSTDIR\lang\gta5sync_ru.qm"
|
||||
Delete "$INSTDIR\lang\gta5sync_uk.qm"
|
||||
Delete "$INSTDIR\lang\gta5sync_zh_TW.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_en_GB.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_de.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_fr.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_ko.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_ru.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_uk.qm"
|
||||
Delete "$INSTDIR\lang\qtbase_zh_TW.qm"
|
||||
Delete "$INSTDIR\audio\qtaudio_windows.dll"
|
||||
Delete "$INSTDIR\imageformats\qgif.dll"
|
||||
Delete "$INSTDIR\imageformats\qicns.dll"
|
||||
Delete "$INSTDIR\imageformats\qico.dll"
|
||||
|
@ -223,10 +228,13 @@ Delete "$INSTDIR\imageformats\qtiff.dll"
|
|||
Delete "$INSTDIR\imageformats\qwbmp.dll"
|
||||
Delete "$INSTDIR\imageformats\qwebp.dll"
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
|
||||
Delete "$INSTDIR\styles\qcleanlooksstyle.dll"
|
||||
Delete "$INSTDIR\styles\qplastiquestyle.dll"
|
||||
Delete "$INSTDIR\styles\qwindowsvistastyle.dll"
|
||||
RmDir "$INSTDIR\lang"
|
||||
RmDir "$INSTDIR\platforms"
|
||||
RmDir "$INSTDIR\imageformats"
|
||||
RmDir "$INSTDIR\platforms"
|
||||
RmDir "$INSTDIR\styles"
|
||||
|
||||
Delete "$INSTDIR\uninstall.exe"
|
||||
!ifdef WEB_SITE
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
echo "gta5view image name is gta5view-osx_${APPLICATION_VERSION}.dmg" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
cd build && \
|
||||
|
||||
/usr/local/opt/qt/bin/qmake ${QMAKE_FLAGS_QT5} ${QMAKE_BUILD_TYPE} "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" "DEFINES+=GTA5SYNC_COMMIT=\\\\\\\"${APPLICATION_COMMIT}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
/usr/local/opt/qt/bin/macdeployqt gta5view.app -dmg && \
|
||||
cp -Rf gta5view.dmg ../assets/gta5view-osx_${APPLICATION_VERSION}.dmg
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install packages
|
||||
.ci/osx_install.sh && \
|
||||
|
||||
# Build gta5view
|
||||
.ci/osx_build.sh && \
|
||||
cd ${PROJECT_DIR}
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install packages
|
||||
brew install qt
|
||||
brew upgrade qt
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Prepare environment variable
|
||||
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
echo "gta5view executable is ${GTA5VIEW_EXECUTABLE}" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
|
||||
# Starting build
|
||||
cd build && \
|
||||
mingw64-qt-cmake \
|
||||
${CMAKE_BUILD_TYPE} \
|
||||
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
|
||||
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
|
||||
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
|
||||
"-DWITH_TELEMETRY=ON" \
|
||||
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
|
||||
.. && \
|
||||
make -j 4 && \
|
||||
x86_64-w64-mingw32-strip -s gta5view.exe && \
|
||||
cp -Rf *.exe ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} && \
|
||||
cd ${PROJECT_DIR}/assets
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
DOCKER_IMAGE=sypingauto/gta5view-build:1.8-static
|
||||
PROJECT_DIR_DOCKER=/gta5view
|
||||
|
||||
cd ${PROJECT_DIR} && \
|
||||
docker pull ${DOCKER_IMAGE} && \
|
||||
docker run --rm \
|
||||
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
|
||||
${DOCKER_IMAGE} \
|
||||
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APPLICATION_COMMIT=${APPLICATION_COMMIT} && export BUILD_TYPE=${BUILD_TYPE} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && export QMAKE_BUILD_TYPE=${QMAKE_BUILD_TYPE} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .ci/windows_build.sh" && \
|
||||
|
||||
# Prepare environment variable
|
||||
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
|
||||
|
||||
# Upload Assets to Dropbox
|
||||
if [ "${PACKAGE_CODE}" == "gta5-mods" ]; then
|
||||
${PROJECT_DIR}/.ci/dropbox_uploader.sh mkdir gta5-mods/${PACKAGE_VERSION}
|
||||
${PROJECT_DIR}/.ci/dropbox_uploader.sh upload ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} gta5-mods/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
|
||||
rm -rf ${GTA5VIEW_EXECUTABLE}
|
||||
elif [ "${PACKAGE_CODE}" == "gtainside" ]; then
|
||||
${PROJECT_DIR}/.ci/dropbox_uploader.sh mkdir gtainside/${PACKAGE_VERSION}
|
||||
${PROJECT_DIR}/.ci/dropbox_uploader.sh upload ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} gtainside/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
|
||||
rm -rf ${GTA5VIEW_EXECUTABLE}
|
||||
fi
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
|
||||
# Starting build
|
||||
cd build && \
|
||||
mingw64-qt-cmake \
|
||||
${CMAKE_BUILD_TYPE} \
|
||||
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
|
||||
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
|
||||
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
|
||||
"-DWITH_TELEMETRY=ON" \
|
||||
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
|
||||
"-DQCONF_BUILD=ON" \
|
||||
"-DGTA5VIEW_INLANG=RUNDIR:SEPARATOR:lang" \
|
||||
"-DGTA5VIEW_LANG=RUNDIR:SEPARATOR:lang" \
|
||||
"-DGTA5VIEW_PLUG=RUNDIR:SEPARATOR:plugins" \
|
||||
.. && \
|
||||
make -j 4 && \
|
||||
x86_64-w64-mingw32-strip -s gta5view.exe && \
|
||||
cd ${PROJECT_DIR}/assets && \
|
||||
makensis -NOCD ${PROJECT_DIR}/.ci/gta5view.nsi && \
|
||||
mv -f gta5view_setup.exe gta5view-${EXECUTABLE_VERSION}_setup.exe
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
DOCKER_IMAGE=sypingauto/gta5view-build:1.8-shared
|
||||
PROJECT_DIR_DOCKER=/gta5view
|
||||
|
||||
cd ${PROJECT_DIR} && \
|
||||
docker pull ${DOCKER_IMAGE} && \
|
||||
docker run --rm \
|
||||
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
|
||||
${DOCKER_IMAGE} \
|
||||
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APPLICATION_COMMIT=${APPLICATION_COMMIT} && export BUILD_TYPE=${BUILD_TYPE} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && export QMAKE_BUILD_TYPE=${QMAKE_BUILD_TYPE} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .ci/wininstall_build.sh"
|
|
@ -0,0 +1,36 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
|
||||
environment:
|
||||
BUILD_TYPE: "REL"
|
||||
|
||||
steps:
|
||||
- name: Windows Installer
|
||||
image: sypingauto/gta5view-build:1.8-shared
|
||||
environment:
|
||||
BUILD_SCRIPT: "wininstall_build.sh"
|
||||
QT_SELECT: "qt5-x86_64-w64-mingw32"
|
||||
TCA_PASS:
|
||||
from_secret: tca_pass
|
||||
commands:
|
||||
- .drone/drone.sh
|
||||
volumes:
|
||||
- name: gta5view
|
||||
path: /srv/gta5view
|
||||
- name: Windows Portable
|
||||
image: sypingauto/gta5view-build:1.8-static
|
||||
environment:
|
||||
BUILD_SCRIPT: "windows_build.sh"
|
||||
QT_SELECT: "qt5-x86_64-w64-mingw32"
|
||||
TCA_PASS:
|
||||
from_secret: tca_pass
|
||||
commands:
|
||||
- .drone/drone.sh
|
||||
volumes:
|
||||
- name: gta5view
|
||||
path: /srv/gta5view
|
||||
|
||||
volumes:
|
||||
- name: gta5view
|
||||
host:
|
||||
path: /srv/gta5view
|
Binary file not shown.
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Cleanup previous Drone build
|
||||
if [ -d "assets" ]; then
|
||||
rm -rf assets
|
||||
fi
|
||||
if [ -d "build" ]; then
|
||||
rm -rf build
|
||||
fi
|
||||
|
||||
# Decrypt Telemetry Authenticator
|
||||
rm -rf tmext/TelemetryClassAuthenticator.cpp && \
|
||||
openssl aes-256-cbc -k ${TCA_PASS} -in .drone/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d -pbkdf2
|
||||
|
||||
# Check if build is not tagged
|
||||
if [ "${DRONE_TAG}" == "" ]; then
|
||||
export EXECUTABLE_TAG=-$(git rev-parse --short HEAD)
|
||||
else
|
||||
export EXECUTABLE_TAG=
|
||||
fi
|
||||
|
||||
# Check if package code is not set
|
||||
if [ "${PACKAGE_CODE}" == "" ]; then
|
||||
export PACKAGE_CODE=Drone
|
||||
fi
|
||||
|
||||
# Init Application Commit Hash
|
||||
export APPLICATION_COMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
# Start CI script and copying assets into gta5view directory
|
||||
.ci/ci.sh && \
|
||||
mkdir -p /srv/gta5view/${APPLICATION_COMMIT} && \
|
||||
cp -Rf assets/* /srv/gta5view/${APPLICATION_COMMIT}/
|
|
@ -0,0 +1,20 @@
|
|||
app-id: de.syping.gta5view
|
||||
runtime: org.kde.Platform
|
||||
runtime-version: '5.15'
|
||||
sdk: org.kde.Sdk
|
||||
command: gta5view
|
||||
finish-args:
|
||||
- --share=network
|
||||
- --share=ipc
|
||||
- --socket=fallback-x11
|
||||
- --socket=wayland
|
||||
- --device=dri
|
||||
modules:
|
||||
- name: gta5view
|
||||
buildsystem: cmake-ninja
|
||||
config-opts:
|
||||
- -DFLATPAK_BUILD=ON
|
||||
- -DQCONF_BUILD=ON
|
||||
sources:
|
||||
- type: dir
|
||||
path: ../
|
|
@ -29,3 +29,7 @@
|
|||
|
||||
# Qt project user file
|
||||
*.pro.user
|
||||
|
||||
# Gettext translation files
|
||||
*.po
|
||||
*.pot
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
stages:
|
||||
- build
|
||||
|
||||
variables:
|
||||
BUILD_TYPE: "REL"
|
||||
|
||||
Windows Installer:
|
||||
stage: build
|
||||
image: sypingauto/gta5view-build:1.8-shared
|
||||
variables:
|
||||
BUILD_SCRIPT: "wininstall_build.sh"
|
||||
QT_SELECT: "qt5-x86_64-w64-mingw32"
|
||||
script:
|
||||
- .gitlab/gitlab.sh
|
||||
artifacts:
|
||||
name: "gta5view-$CI_COMMIT_REF_NAME-${CI_COMMIT_SHA:0:8}_setup"
|
||||
paths:
|
||||
- "gta5view-*.exe"
|
||||
|
||||
Windows Portable:
|
||||
stage: build
|
||||
image: sypingauto/gta5view-build:1.8-static
|
||||
variables:
|
||||
BUILD_SCRIPT: "windows_build.sh"
|
||||
QT_SELECT: "qt5-x86_64-w64-mingw32"
|
||||
script:
|
||||
- .gitlab/gitlab.sh
|
||||
artifacts:
|
||||
name: "gta5view-$CI_COMMIT_REF_NAME-${CI_COMMIT_SHA:0:8}_portable"
|
||||
paths:
|
||||
- "gta5view-*.exe"
|
Binary file not shown.
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Decrypt Telemetry Authenticator
|
||||
rm -rf tmext/TelemetryClassAuthenticator.cpp && \
|
||||
openssl aes-256-cbc -k ${tca_pass} -in .gitlab/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d
|
||||
|
||||
# Check if build is not tagged
|
||||
if [ "${CI_COMMIT_TAG}" == "" ]; then
|
||||
export EXECUTABLE_TAG=-$(git rev-parse --short HEAD)
|
||||
else
|
||||
export EXECUTABLE_TAG=
|
||||
fi
|
||||
|
||||
# Check if package code is not set
|
||||
if [ "${PACKAGE_CODE}" == "" ]; then
|
||||
export PACKAGE_CODE=GitLab
|
||||
fi
|
||||
|
||||
# Init Application Commit Hash
|
||||
export APPLICATION_COMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
# Start CI script and copying assets into base directory
|
||||
.ci/ci.sh && \
|
||||
cp -Rf assets/* ./
|
45
.travis.yml
45
.travis.yml
|
@ -1,45 +1,45 @@
|
|||
dist: trusty
|
||||
dist: bionic
|
||||
sudo: required
|
||||
|
||||
language: cpp
|
||||
|
||||
service:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
- BUILD_TYPE=REL
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env:
|
||||
- BUILD_SCRIPT=debian_travis.sh
|
||||
- QMAKE_FLAGS_QT4=QMAKE_CXXFLAGS+=-Wno-missing-field-initializers
|
||||
- DEBIAN_VERSION=jessie
|
||||
- DOCKER_USER=i386
|
||||
- APT_INSTALL=clang
|
||||
- env:
|
||||
- BUILD_SCRIPT=debian_travis.sh
|
||||
- QMAKE_FLAGS_QT4=QMAKE_CXXFLAGS+=-Wno-missing-field-initializers
|
||||
- DEBIAN_VERSION=jessie
|
||||
- BUILD_SCRIPT=debian_docker.sh
|
||||
- RELEASE_LABEL="Debian 64-Bit Package"
|
||||
- DEBIAN_VERSION=stretch
|
||||
- DOCKER_USER=amd64
|
||||
- APT_INSTALL=clang
|
||||
- env:
|
||||
- BUILD_SCRIPT=windows_travis.sh
|
||||
- QT_SELECT=qt5-i686-w64-mingw32
|
||||
- env:
|
||||
- BUILD_SCRIPT=windows_travis.sh
|
||||
- BUILD_SCRIPT=windows_docker.sh
|
||||
- QT_SELECT=qt5-x86_64-w64-mingw32
|
||||
- EXECUTABLE_ARCH=_x64
|
||||
- RELEASE_LABEL="Windows 64-Bit Portable"
|
||||
- env:
|
||||
- BUILD_SCRIPT=windows_travis.sh
|
||||
- QT_SELECT=qt5-x86_64-w64-mingw32
|
||||
- PACKAGE_CODE=Dropbox
|
||||
- env:
|
||||
- BUILD_SCRIPT=windows_travis.sh
|
||||
- BUILD_SCRIPT=windows_docker.sh
|
||||
- QT_SELECT=qt5-x86_64-w64-mingw32
|
||||
- RELEASE_LABEL="Windows 64-Bit Portable for gta5-mods"
|
||||
- PACKAGE_CODE=gta5-mods
|
||||
- env:
|
||||
- BUILD_SCRIPT=wininstall_travis.sh
|
||||
- BUILD_SCRIPT=windows_docker.sh
|
||||
- QT_SELECT=qt5-x86_64-w64-mingw32
|
||||
- RELEASE_LABEL="Windows 64-Bit Portable for gtainside"
|
||||
- PACKAGE_CODE=gtainside
|
||||
- env:
|
||||
- BUILD_SCRIPT=wininstall_docker.sh
|
||||
- QT_SELECT=qt5-x86_64-w64-mingw32
|
||||
- RELEASE_LABEL="Windows 64-Bit Installer"
|
||||
- os: osx
|
||||
env: BUILD_SCRIPT=osx_travis.sh
|
||||
env:
|
||||
- BUILD_SCRIPT=osx_ci.sh
|
||||
- RELEASE_LABEL="Mac OS X 64-Bit Disk Image"
|
||||
|
||||
before_install:
|
||||
- ".travis/source.sh"
|
||||
|
@ -51,6 +51,7 @@ deploy:
|
|||
provider: releases
|
||||
api_key:
|
||||
secure: o7VneEz1aHfdVwZvOZLfopf6uJWNrFsZaBvunTmXFzpmNFhlNS1qwqgMUkIA2yBRbZ3wIzVs4vfwIHv7W9yE/PqK+AYL+R8+AwKGrwlgT4HqJNuk6VM/LNJ6GwT/qkQuaoOVw29bUjmzzgIRdHmw53SlJv6Hh1VE8HphlTT//aex6nCfcFhUZ0BETdZDWz5FSHwL3NalUoqfKfQrJeky5RXzCyCANQC2tKt0bV46GaWIgWrDo2KCTNqPtRWWf5GDmnkXE5IYRMQ3mXvO9iYh0v5Y2jo4PiXGUiFUU6Z3aAWFAiPdGclrBO697cf3lCTzDMhuCETR153qFYsLShUlFf61ITAmCeHAWETjZDri0lmPONo3GoNB6alGfYEA51qw14kXakrTpICtTJj7gw/gtUYOabW6hrzmieNzMBIy62RikDPjyakFnuwW2qNHRlD65e0jYv+6nCpb6E+OV16Ysh1zhV2vTfpfzVmSuyu2J+ELqXD3OZCXRSPpDIih9UQ8335p8FBji6jHORcgym/TRgdgRmENibh8tLzWp+UjpWHuWfcpvZgOskjfwU0iDMCayMJ7tDpOhXHcAhDRnd6XRIiOJ5YZCzflj2nEwmt3YUd7DwXS/AU+WHOmcNQBjXBxF/FJa35XXcy3HKJM5TTKqtph3medo30us5yXHeG6NNg=
|
||||
label: ${RELEASE_LABEL}
|
||||
file_glob: true
|
||||
file: assets/*
|
||||
skip_cleanup: true
|
||||
|
|
Binary file not shown.
|
@ -1,31 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
chmod -x res/gta5sync_*.qm res/gta5view.desktop res/gta5view.png && \
|
||||
cd build && \
|
||||
mkdir -p qt4 && \
|
||||
cd qt4 && \
|
||||
echo "Grand Theft Auto V Snapmatic and Savegame viewer/manager" > ./description-pak && \
|
||||
cd .. && \
|
||||
mkdir -p qt5 && \
|
||||
cd qt5 && \
|
||||
echo "Grand Theft Auto V Snapmatic and Savegame viewer/manager" > ./description-pak && \
|
||||
cd .. && \
|
||||
|
||||
# Prepare checkinstall step
|
||||
mkdir -p /usr/share/gta5view && \
|
||||
|
||||
# Starting build
|
||||
cd qt5 && \
|
||||
qmake -qt=5 -spec linux-clang GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=gnu++11 ${QMAKE_FLAGS_QT5} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_QCONF DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt5 --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5,qttranslations5-l10n --conflicts=gta5view,gta5view-qt4 --replaces=gta5view,gta5view-qt4 --pakdir=${PROJECT_DIR}/assets && \
|
||||
cd .. && \
|
||||
cd qt4 && \
|
||||
qmake -qt=4 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=gnu++11 ${QMAKE_FLAGS_QT4} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt4 --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqtcore4,libqtgui4,libqt4-network,qtcore4-l10n --conflicts=gta5view,gta5view-qt5 --replaces=gta5view,gta5view-qt5 --pakdir=${PROJECT_DIR}/assets
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install packages
|
||||
apt-get update -qq && \
|
||||
apt-get install -qq ${APT_INSTALL} checkinstall dpkg-dev fakeroot g++ gcc qtbase5-dev qt5-qmake qttranslations5-l10n libqt4-dev
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ ${DOCKER_USER} ]]; then
|
||||
DOCKER_IMAGE=${DOCKER_USER}/debian:${DEBIAN_VERSION}
|
||||
else
|
||||
DOCKER_IMAGE=debian:${DEBIAN_VERSION}
|
||||
fi
|
||||
PROJECT_DIR_DOCKER=/gta5view
|
||||
|
||||
cd ${PROJECT_DIR} && \
|
||||
docker pull ${DOCKER_IMAGE} && \
|
||||
docker run --rm \
|
||||
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
|
||||
${DOCKER_IMAGE} \
|
||||
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APT_INSTALL=${APT_INSTALL} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .travis/debian_install.sh && .travis/debian_build.sh"
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
echo "gta5view image name is gta5view-osx_${APPLICATION_VERSION}.dmg" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
cd build && \
|
||||
|
||||
/usr/local/opt/qt/bin/qmake ${QMAKE_FLAGS_QT5} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
/usr/local/opt/qt/bin/macdeployqt gta5view.app -dmg && \
|
||||
cp -Rf gta5view.dmg ../assets/gta5view-osx_${APPLICATION_VERSION}.dmg
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -rf tmext/TelemetryClassAuthenticator.cpp && \
|
||||
openssl aes-256-cbc -K $encrypted_55502862a724_key -iv $encrypted_55502862a724_iv -in tmext/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d && \
|
||||
openssl aes-256-cbc -K $encrypted_db000a5d87d6_key -iv $encrypted_db000a5d87d6_iv -in .travis/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d && \
|
||||
openssl aes-256-cbc -K $encrypted_d57e7d2f8877_key -iv $encrypted_d57e7d2f8877_iv -in .travis/dropbox_uploader.enc -out ~/.dropbox_uploader -d
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install lua
|
||||
if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
|
||||
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
|
||||
brew install lua
|
||||
else
|
||||
sudo apt-get update -qq && \
|
||||
sudo apt-get install -qq lua5.2
|
||||
elif [ "${TRAVIS_OS_NAME}" == "osx" ]; then
|
||||
brew install lua
|
||||
fi
|
||||
|
||||
# Check if build is not tagged
|
||||
|
@ -20,11 +20,8 @@ if [ "${PACKAGE_CODE}" == "" ]; then
|
|||
export PACKAGE_CODE=GitHub
|
||||
fi
|
||||
|
||||
if [ `git name-rev --tags --name-only $(git rev-parse HEAD)` == "undefined" ]; then export APPLICATION_VERSION=`lua -e 'for line in io.lines("config.h") do local m = string.match(line, "#define GTA5SYNC_APPVER \"(.+)\"$"); if m then print(m); os.exit(0) end end'`; else export APPLICATION_VERSION=`git name-rev --tags --name-only $(git rev-parse HEAD)`; fi
|
||||
export PACKAGE_VERSION=$(grep -oE '^[^\-]*' <<< $APPLICATION_VERSION)
|
||||
export PACKAGE_BUILD=$(grep -oP '\-\K.+' <<< $APPLICATION_VERSION)
|
||||
export EXECUTABLE_VERSION=${PACKAGE_VERSION}${PACKAGE_BUILD}${EXECUTABLE_TAG}
|
||||
if [[ ! ${PACKAGE_BUILD} ]]; then export PACKAGE_BUILD=1; fi
|
||||
export PROJECT_DIR=$(pwd)
|
||||
# Init Application Commit Hash
|
||||
export APPLICATION_COMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
.travis/${BUILD_SCRIPT}
|
||||
# Start CI script
|
||||
.ci/ci.sh
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Install packages
|
||||
sudo .travis/debian_install.sh && \
|
||||
sudo .ci/debian_install.sh && \
|
||||
|
||||
# Build gta5view
|
||||
sudo .travis/debian_build.sh && \
|
||||
sudo .ci/debian_build.sh && \
|
||||
cd ${PROJECT_DIR}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
apt-get update -qq && \
|
||||
apt-get install -qq curl && \
|
||||
|
||||
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
echo "gta5view executable is ${GTA5VIEW_EXECUTABLE}" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
|
||||
# Starting build
|
||||
cd build && \
|
||||
qmake-static ${QMAKE_FLAGS} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
cp -Rf release/*.exe ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} && \
|
||||
cd ${PROJECT_DIR}/assets && \
|
||||
upx --best ${GTA5VIEW_EXECUTABLE} && \
|
||||
|
||||
if [ "${PACKAGE_CODE}" == "Dropbox" ]; then
|
||||
${PROJECT_DIR}/.travis/dropbox_uploader.sh mkdir gta5view-builds/${PACKAGE_VERSION}
|
||||
${PROJECT_DIR}/.travis/dropbox_uploader.sh upload ${GTA5VIEW_EXECUTABLE} gta5view-builds/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
|
||||
rm -rf ${GTA5VIEW_EXECUTABLE}
|
||||
elif [ "${PACKAGE_CODE}" == "gta5-mods" ]; then
|
||||
${PROJECT_DIR}/.travis/dropbox_uploader.sh mkdir gta5-mods/${PACKAGE_VERSION}
|
||||
${PROJECT_DIR}/.travis/dropbox_uploader.sh upload ${GTA5VIEW_EXECUTABLE} gta5-mods/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
|
||||
rm -rf ${GTA5VIEW_EXECUTABLE}
|
||||
fi
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
QT_VERSION=5.6.3
|
||||
DOCKER_IMAGE=syping/qt5-static-mingw:${QT_VERSION}
|
||||
PROJECT_DIR_DOCKER=/gta5view
|
||||
|
||||
cd ${PROJECT_DIR} && \
|
||||
docker pull ${DOCKER_IMAGE} && \
|
||||
docker run --rm \
|
||||
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
|
||||
-v "${HOME}/.dropbox_uploader:/root/.dropbox_uploader" \
|
||||
${DOCKER_IMAGE} \
|
||||
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .travis/windows_build.sh"
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
apt-get update -qq && \
|
||||
apt-get install -qq nsis && \
|
||||
|
||||
# Creating folders
|
||||
cd ${PROJECT_DIR} && \
|
||||
echo "gta5view build version is ${APPLICATION_VERSION}" && \
|
||||
mkdir -p build && \
|
||||
mkdir -p assets && \
|
||||
|
||||
# Starting build
|
||||
cd build && \
|
||||
qmake ${QMAKE_FLAGS} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" DEFINES+=GTA5SYNC_QCONF DEFINES+=GTA5SYNC_INLANG='\\\"RUNDIR:SEPARATOR:lang\\\"' DEFINES+=GTA5SYNC_LANG='\\\"RUNDIR:SEPARATOR:lang\\\"' DEFINES+=GTA5SYNC_PLUG='\\\"RUNDIR:SEPARATOR:plugins\\\"' ../gta5view.pro && \
|
||||
make -j 4 && \
|
||||
cd ${PROJECT_DIR}/assets && \
|
||||
makensis -NOCD ${PROJECT_DIR}/.travis/gta5view.nsi && \
|
||||
mv -f gta5view_setup.exe gta5view-${EXECUTABLE_VERSION}_setup.exe
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
QT_VERSION=5.6.3
|
||||
DOCKER_IMAGE=syping/qt5-shared-mingw:${QT_VERSION}
|
||||
PROJECT_DIR_DOCKER=/gta5view
|
||||
|
||||
cd ${PROJECT_DIR} && \
|
||||
docker pull ${DOCKER_IMAGE} && \
|
||||
docker run --rm \
|
||||
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
|
||||
${DOCKER_IMAGE} \
|
||||
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .travis/wininstall_build.sh"
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2019 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -37,6 +37,11 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
|||
buildType.replace("_", " ");
|
||||
QString projectBuild = AppEnv::getBuildDateTime();
|
||||
QString buildStr = GTA5SYNC_BUILDSTRING;
|
||||
#ifndef GTA5SYNC_BUILDTYPE_REL
|
||||
#ifdef GTA5SYNC_COMMIT
|
||||
if (!appVersion.contains("-")) { appVersion = appVersion % "-" % GTA5SYNC_COMMIT; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Translator Comments
|
||||
//: Translated by translator, example Translated by Syping
|
||||
|
|
346
AppEnv.cpp
346
AppEnv.cpp
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,13 +22,17 @@
|
|||
#include "StandardPaths.h"
|
||||
#include <QtGlobal>
|
||||
#include <QStringBuilder>
|
||||
#include <QDesktopWidget>
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
#include <QScreen>
|
||||
#include <QDebug>
|
||||
#include <QRect>
|
||||
#include <QDir>
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
|
@ -152,7 +156,38 @@ QString AppEnv::getPluginsFolder()
|
|||
|
||||
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();
|
||||
#if QT_VERSION >= 0x050400
|
||||
#ifdef Q_OS_WIN
|
||||
QString kernelVersion = QSysInfo::kernelVersion();
|
||||
const QStringList &kernelVersionList = kernelVersion.split(".");
|
||||
if (kernelVersionList.length() > 2)
|
||||
{
|
||||
kernelVersion = kernelVersionList.at(0) % "." % kernelVersionList.at(1);
|
||||
}
|
||||
QString runArch = QSysInfo::buildCpuArchitecture();
|
||||
if (runArch == "x86_64")
|
||||
{
|
||||
runArch = "Win64; x64";
|
||||
}
|
||||
else if (runArch == "i686")
|
||||
{
|
||||
const QString &curArch = QSysInfo::currentCpuArchitecture();
|
||||
if (curArch == "x86_64")
|
||||
{
|
||||
runArch = "WOW64";
|
||||
}
|
||||
else if (curArch == "i686")
|
||||
{
|
||||
runArch = "Win32; x86";
|
||||
}
|
||||
}
|
||||
return QString("Mozilla/5.0 (Windows NT %1; %2) %3/%4").arg(kernelVersion, runArch, GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
|
||||
#else
|
||||
return QString("Mozilla/5.0 (%1; %2) %3/%4").arg(QSysInfo::kernelType(), QSysInfo::kernelVersion(), GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
|
||||
#endif
|
||||
#else
|
||||
return QString("Mozilla/5.0 %1/%2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
|
||||
#endif
|
||||
}
|
||||
|
||||
// QUrl AppEnv::getCrewFetchingUrl(QString crewID)
|
||||
|
@ -167,7 +202,7 @@ QUrl AppEnv::getCrewFetchingUrl(QString crewID)
|
|||
|
||||
QUrl AppEnv::getPlayerFetchingUrl(QString crewID, QString pageNumber)
|
||||
{
|
||||
return QUrl(QString("https://socialclub.rockstargames.com/crewsapi/GetMembersList?crewId=%1&pageNumber=%2").arg(crewID, pageNumber));
|
||||
return QUrl(QString("https://socialclub.rockstargames.com/crewsapi/GetMembersList?crewId=%1&pageNumber=%2&pageSize=5000").arg(crewID, pageNumber));
|
||||
}
|
||||
|
||||
QUrl AppEnv::getPlayerFetchingUrl(QString crewID, int pageNumber)
|
||||
|
@ -175,12 +210,302 @@ QUrl AppEnv::getPlayerFetchingUrl(QString crewID, int pageNumber)
|
|||
return getPlayerFetchingUrl(crewID, QString::number(pageNumber));
|
||||
}
|
||||
|
||||
// Game Stuff
|
||||
|
||||
GameVersion AppEnv::getGameVersion()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QString argumentValue;
|
||||
#ifdef _WIN64
|
||||
argumentValue = "\\WOW6432Node";
|
||||
#endif
|
||||
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
|
||||
QString installFolderSc = registrySettingsSc.value("InstallFolder", "").toString();
|
||||
QDir installFolderScDir(installFolderSc);
|
||||
bool scVersionInstalled = false;
|
||||
if (!installFolderSc.isEmpty() && installFolderScDir.exists())
|
||||
{
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "gameVersionFoundSocialClubVersion";
|
||||
#endif
|
||||
scVersionInstalled = true;
|
||||
}
|
||||
|
||||
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\GTAV").arg(argumentValue), QSettings::NativeFormat);
|
||||
QString installFolderSteam = registrySettingsSteam.value("installfoldersteam", "").toString();
|
||||
if (installFolderSteam.right(5) == "\\GTAV")
|
||||
{
|
||||
installFolderSteam = installFolderSteam.remove(installFolderSteam.length() - 5, 5);
|
||||
}
|
||||
QDir installFolderSteamDir(installFolderSteam);
|
||||
bool steamVersionInstalled = false;
|
||||
if (!installFolderSteam.isEmpty() && installFolderSteamDir.exists())
|
||||
{
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "gameVersionFoundSteamVersion";
|
||||
#endif
|
||||
steamVersionInstalled = true;
|
||||
}
|
||||
|
||||
if (scVersionInstalled && steamVersionInstalled)
|
||||
{
|
||||
return GameVersion::BothVersions;
|
||||
}
|
||||
else if (scVersionInstalled)
|
||||
{
|
||||
return GameVersion::SocialClubVersion;
|
||||
}
|
||||
else if (steamVersionInstalled)
|
||||
{
|
||||
return GameVersion::SteamVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GameVersion::NoVersion;
|
||||
}
|
||||
#else
|
||||
return GameVersion::NoVersion;
|
||||
#endif
|
||||
}
|
||||
|
||||
GameLanguage AppEnv::getGameLanguage(GameVersion gameVersion)
|
||||
{
|
||||
if (gameVersion == GameVersion::SocialClubVersion)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QString argumentValue;
|
||||
#ifdef _WIN64
|
||||
argumentValue = "\\WOW6432Node";
|
||||
#endif
|
||||
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
|
||||
QString languageSc = registrySettingsSc.value("Language", "").toString();
|
||||
return gameLanguageFromString(languageSc);
|
||||
#else
|
||||
return GameLanguage::Undefined;
|
||||
#endif
|
||||
}
|
||||
else if (gameVersion == GameVersion::SteamVersion)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QString argumentValue;
|
||||
#ifdef _WIN64
|
||||
argumentValue = "\\WOW6432Node";
|
||||
#endif
|
||||
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V Steam").arg(argumentValue), QSettings::NativeFormat);
|
||||
QString languageSteam = registrySettingsSteam.value("Language", "").toString();
|
||||
return gameLanguageFromString(languageSteam);
|
||||
#else
|
||||
return GameLanguage::Undefined;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return GameLanguage::Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
GameLanguage AppEnv::gameLanguageFromString(QString gameLanguage)
|
||||
{
|
||||
if (gameLanguage == "en-US")
|
||||
{
|
||||
return GameLanguage::English;
|
||||
}
|
||||
else if (gameLanguage == "fr-FR")
|
||||
{
|
||||
return GameLanguage::French;
|
||||
}
|
||||
else if (gameLanguage == "it-IT")
|
||||
{
|
||||
return GameLanguage::Italian;
|
||||
}
|
||||
else if (gameLanguage == "de-DE")
|
||||
{
|
||||
return GameLanguage::German;
|
||||
}
|
||||
else if (gameLanguage == "es-ES")
|
||||
{
|
||||
return GameLanguage::Spanish;
|
||||
}
|
||||
else if (gameLanguage == "es-MX")
|
||||
{
|
||||
return GameLanguage::Mexican;
|
||||
}
|
||||
else if (gameLanguage == "pt-BR")
|
||||
{
|
||||
return GameLanguage::Brasilian;
|
||||
}
|
||||
else if (gameLanguage == "ru-RU")
|
||||
{
|
||||
return GameLanguage::Russian;
|
||||
}
|
||||
else if (gameLanguage == "pl-PL")
|
||||
{
|
||||
return GameLanguage::Polish;
|
||||
}
|
||||
else if (gameLanguage == "ja-JP")
|
||||
{
|
||||
return GameLanguage::Japanese;
|
||||
}
|
||||
else if (gameLanguage == "zh-CHS")
|
||||
{
|
||||
return GameLanguage::SChinese;
|
||||
}
|
||||
else if (gameLanguage == "zh-CHT")
|
||||
{
|
||||
return GameLanguage::TChinese;
|
||||
}
|
||||
else if (gameLanguage == "ko-KR")
|
||||
{
|
||||
return GameLanguage::Koreana;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GameLanguage::Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
QString AppEnv::gameLanguageToString(GameLanguage gameLanguage)
|
||||
{
|
||||
if (gameLanguage == GameLanguage::English)
|
||||
{
|
||||
return "en-US";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::French)
|
||||
{
|
||||
return "fr-FR";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Italian)
|
||||
{
|
||||
return "it-IT";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::German)
|
||||
{
|
||||
return "de-DE";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Spanish)
|
||||
{
|
||||
return "es-ES";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Mexican)
|
||||
{
|
||||
return "es-MX";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Brasilian)
|
||||
{
|
||||
return "pt-BR";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Russian)
|
||||
{
|
||||
return "ru-RU";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Polish)
|
||||
{
|
||||
return "pl-PL";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Japanese)
|
||||
{
|
||||
return "ja-JP";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::SChinese)
|
||||
{
|
||||
return "zh-CHS";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::TChinese)
|
||||
{
|
||||
return "zh-CHT";
|
||||
}
|
||||
else if (gameLanguage == GameLanguage::Koreana)
|
||||
{
|
||||
return "ko-KR";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Undefinied";
|
||||
}
|
||||
}
|
||||
|
||||
bool AppEnv::setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage)
|
||||
{
|
||||
bool socialClubVersion = false;
|
||||
bool steamVersion = false;
|
||||
if (gameVersion == GameVersion::SocialClubVersion)
|
||||
{
|
||||
socialClubVersion = true;
|
||||
}
|
||||
else if (gameVersion == GameVersion::SteamVersion)
|
||||
{
|
||||
steamVersion = true;
|
||||
}
|
||||
else if (gameVersion == GameVersion::BothVersions)
|
||||
{
|
||||
socialClubVersion = true;
|
||||
steamVersion = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (socialClubVersion)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QString argumentValue;
|
||||
#ifdef _WIN64
|
||||
argumentValue = "\\WOW6432Node";
|
||||
#endif
|
||||
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
|
||||
if (gameLanguage != GameLanguage::Undefined)
|
||||
{
|
||||
registrySettingsSc.setValue("Language", gameLanguageToString(gameLanguage));
|
||||
}
|
||||
else
|
||||
{
|
||||
registrySettingsSc.remove("Language");
|
||||
}
|
||||
registrySettingsSc.sync();
|
||||
if (registrySettingsSc.status() != QSettings::NoError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(gameLanguage)
|
||||
#endif
|
||||
}
|
||||
if (steamVersion)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QString argumentValue;
|
||||
#ifdef _WIN64
|
||||
argumentValue = "\\WOW6432Node";
|
||||
#endif
|
||||
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V Steam").arg(argumentValue), QSettings::NativeFormat);
|
||||
if (gameLanguage != GameLanguage::Undefined)
|
||||
{
|
||||
registrySettingsSteam.setValue("Language", gameLanguageToString(gameLanguage));
|
||||
}
|
||||
else
|
||||
{
|
||||
registrySettingsSteam.remove("Language");
|
||||
}
|
||||
registrySettingsSteam.sync();
|
||||
if (registrySettingsSteam.status() != QSettings::NoError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(gameLanguage)
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Screen Stuff
|
||||
|
||||
qreal AppEnv::screenRatio()
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
qreal dpi = QGuiApplication::primaryScreen()->logicalDotsPerInch();
|
||||
qreal dpi = QApplication::primaryScreen()->logicalDotsPerInch();
|
||||
#else
|
||||
qreal dpi = qApp->desktop()->logicalDpiX();
|
||||
qreal dpi = QApplication::desktop()->logicalDpiX();
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
return (dpi / 72);
|
||||
|
@ -188,3 +513,12 @@ qreal AppEnv::screenRatio()
|
|||
return (dpi / 96);
|
||||
#endif
|
||||
}
|
||||
|
||||
qreal AppEnv::screenRatioPR()
|
||||
{
|
||||
#if QT_VERSION >= 0x050600
|
||||
return QApplication::primaryScreen()->devicePixelRatio();
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
|
11
AppEnv.h
11
AppEnv.h
|
@ -22,6 +22,9 @@
|
|||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
enum class GameVersion : int { NoVersion = 0, SocialClubVersion = 1, SteamVersion = 2, BothVersions = 3 };
|
||||
enum class GameLanguage : int { Undefined = 0, English = 1, French = 2, Italian = 3, German = 4, Spanish = 5, Mexican = 6, Brasilian = 7, Russian = 8, Polish = 9, Japanese = 10, SChinese = 11, TChinese = 12, Koreana = 13 };
|
||||
|
||||
class AppEnv
|
||||
{
|
||||
public:
|
||||
|
@ -44,8 +47,16 @@ public:
|
|||
static QUrl getPlayerFetchingUrl(QString crewID, QString pageNumber);
|
||||
static QUrl getPlayerFetchingUrl(QString crewID, int pageNumber);
|
||||
|
||||
// Game Stuff
|
||||
static GameVersion getGameVersion();
|
||||
static GameLanguage getGameLanguage(GameVersion gameVersion);
|
||||
static GameLanguage gameLanguageFromString(QString gameLanguage);
|
||||
static QString gameLanguageToString(GameLanguage gameLanguage);
|
||||
static bool setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage);
|
||||
|
||||
// Screen Stuff
|
||||
static qreal screenRatio();
|
||||
static qreal screenRatioPR();
|
||||
};
|
||||
|
||||
#endif // APPENV_H
|
||||
|
|
|
@ -0,0 +1,356 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(gta5view LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt5 COMPONENTS Network Svg Widgets REQUIRED)
|
||||
find_package(Qt5 COMPONENTS LinguistTools QUIET)
|
||||
|
||||
if(WIN32)
|
||||
find_package(Qt5 COMPONENTS WinExtras REQUIRED)
|
||||
list(APPEND GTA5VIEW_LIBS
|
||||
Qt5::WinExtras
|
||||
)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DUNICODE
|
||||
-D_UNICODE
|
||||
-DWIN32
|
||||
)
|
||||
list(APPEND GTA5VIEW_RESOURCES
|
||||
res/app.rc
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_CMAKE
|
||||
-DGTA5SYNC_PROJECT
|
||||
-DSNAPMATIC_NODEFAULT
|
||||
)
|
||||
|
||||
set(GTA5VIEW_SOURCES
|
||||
main.cpp
|
||||
AboutDialog.cpp
|
||||
AppEnv.cpp
|
||||
CrewDatabase.cpp
|
||||
DatabaseThread.cpp
|
||||
ExportDialog.cpp
|
||||
ExportThread.cpp
|
||||
GlobalString.cpp
|
||||
IconLoader.cpp
|
||||
ImportDialog.cpp
|
||||
JsonEditorDialog.cpp
|
||||
MapLocationDialog.cpp
|
||||
OptionsDialog.cpp
|
||||
PictureDialog.cpp
|
||||
PictureExport.cpp
|
||||
PictureWidget.cpp
|
||||
PlayerListDialog.cpp
|
||||
ProfileDatabase.cpp
|
||||
ProfileInterface.cpp
|
||||
ProfileLoader.cpp
|
||||
ProfileWidget.cpp
|
||||
SavegameCopy.cpp
|
||||
SavegameData.cpp
|
||||
SavegameDialog.cpp
|
||||
SavegameWidget.cpp
|
||||
SidebarGenerator.cpp
|
||||
SnapmaticEditor.cpp
|
||||
SnapmaticPicture.cpp
|
||||
SnapmaticWidget.cpp
|
||||
StandardPaths.cpp
|
||||
StringParser.cpp
|
||||
TranslationClass.cpp
|
||||
UserInterface.cpp
|
||||
anpro/imagecropper.cpp
|
||||
pcg/pcg_basic.c
|
||||
uimod/JSHighlighter.cpp
|
||||
uimod/UiModLabel.cpp
|
||||
uimod/UiModWidget.cpp
|
||||
)
|
||||
|
||||
set(GTA5VIEW_HEADERS
|
||||
config.h
|
||||
AboutDialog.h
|
||||
AppEnv.h
|
||||
CrewDatabase.h
|
||||
DatabaseThread.h
|
||||
ExportDialog.h
|
||||
ExportThread.h
|
||||
GlobalString.h
|
||||
IconLoader.h
|
||||
ImportDialog.h
|
||||
JsonEditorDialog.h
|
||||
MapLocationDialog.h
|
||||
OptionsDialog.h
|
||||
PictureDialog.h
|
||||
PictureExport.h
|
||||
PictureWidget.h
|
||||
PlayerListDialog.h
|
||||
ProfileDatabase.h
|
||||
ProfileInterface.h
|
||||
ProfileLoader.h
|
||||
ProfileWidget.h
|
||||
SavegameCopy.h
|
||||
SavegameData.h
|
||||
SavegameDialog.h
|
||||
SavegameWidget.h
|
||||
SidebarGenerator.h
|
||||
SnapmaticEditor.h
|
||||
SnapmaticPicture.h
|
||||
SnapmaticWidget.h
|
||||
StandardPaths.h
|
||||
StringParser.h
|
||||
TranslationClass.h
|
||||
UserInterface.h
|
||||
anpro/imagecropper.h
|
||||
pcg/pcg_basic.h
|
||||
uimod/JSHighlighter.h
|
||||
uimod/UiModLabel.h
|
||||
uimod/UiModWidget.h
|
||||
)
|
||||
|
||||
set(GTA5VIEW_INCLUDEDIR
|
||||
anpro
|
||||
pcg
|
||||
uimod
|
||||
)
|
||||
|
||||
set(GTA5VIEW_FORMS
|
||||
AboutDialog.ui
|
||||
ExportDialog.ui
|
||||
ImportDialog.ui
|
||||
JsonEditorDialog.ui
|
||||
MapLocationDialog.ui
|
||||
OptionsDialog.ui
|
||||
PictureDialog.ui
|
||||
PlayerListDialog.ui
|
||||
ProfileInterface.ui
|
||||
SavegameDialog.ui
|
||||
SavegameWidget.ui
|
||||
SnapmaticEditor.ui
|
||||
SnapmaticWidget.ui
|
||||
UserInterface.ui
|
||||
)
|
||||
|
||||
list(APPEND GTA5VIEW_RESOURCES
|
||||
res/app.qrc
|
||||
res/global.qrc
|
||||
)
|
||||
set_property(SOURCE res/global.qrc PROPERTY AUTORCC_OPTIONS "-threshold;0;-compress;9")
|
||||
|
||||
if(Qt5LinguistTools_FOUND)
|
||||
qt5_add_translation(GTA5VIEW_TRANSLATIONS
|
||||
res/gta5sync_de.ts
|
||||
res/gta5sync_en_US.ts
|
||||
res/gta5sync_fr.ts
|
||||
res/gta5sync_ko.ts
|
||||
res/gta5sync_ru.ts
|
||||
res/gta5sync_uk.ts
|
||||
res/gta5sync_zh_TW.ts
|
||||
res/qtbase_en_GB.ts
|
||||
)
|
||||
add_custom_target(translations DEPENDS ${GTA5VIEW_TRANSLATIONS})
|
||||
else()
|
||||
set(GTA5VIEW_TRANSLATIONS
|
||||
res/gta5sync_de.qm
|
||||
res/gta5sync_en_US.qm
|
||||
res/gta5sync_fr.qm
|
||||
res/gta5sync_ko.qm
|
||||
res/gta5sync_ru.qm
|
||||
res/gta5sync_uk.qm
|
||||
res/gta5sync_zh_TW.qm
|
||||
res/qtbase_en_GB.qm
|
||||
)
|
||||
endif()
|
||||
|
||||
option(QCONF_BUILD "System installation intended Qconf build" OFF)
|
||||
if(QCONF_BUILD)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_QCONF
|
||||
)
|
||||
else()
|
||||
list(APPEND GTA5VIEW_RESOURCES
|
||||
res/tr_g5p.qrc
|
||||
res/tr_qt5.qrc
|
||||
)
|
||||
endif()
|
||||
|
||||
option(FLATPAK_BUILD "Flatpak modifications and identifications" OFF)
|
||||
if(FLATPAK_BUILD)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_BUILDCODE=\"Flatpak\""
|
||||
"-DGTA5SYNC_BUILDTYPE=\"Flatpak\""
|
||||
-DGTA5SYNC_FLATPAK
|
||||
)
|
||||
endif()
|
||||
|
||||
option(WITH_MOTD "Developer message system directed to users" OFF)
|
||||
if(WITH_MOTD)
|
||||
list(APPEND GTA5VIEW_HEADERS
|
||||
MessageThread.h
|
||||
)
|
||||
list(APPEND GTA5VIEW_SOURCES
|
||||
MessageThread.cpp
|
||||
)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_MOTD
|
||||
)
|
||||
if(MOTD_WEBURL)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_MOTD_WEBURL=\"${MOTD_WEBURL}\""
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(WITH_TELEMETRY "Hardware survey and basic telemetry system" OFF)
|
||||
if(WITH_TELEMETRY)
|
||||
list(APPEND GTA5VIEW_HEADERS
|
||||
TelemetryClass.h
|
||||
tmext/TelemetryClassAuthenticator.h
|
||||
)
|
||||
list(APPEND GTA5VIEW_SOURCES
|
||||
TelemetryClass.cpp
|
||||
tmext/TelemetryClassAuthenticator.cpp
|
||||
)
|
||||
list(APPEND GTA5VIEW_INCLUDEDIR
|
||||
tmext
|
||||
)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_TELEMETRY
|
||||
)
|
||||
if(TELEMETRY_AUTHID AND TELEMETRY_AUTHPW AND TELEMETRY_PUSHURL AND TELEMETRY_REGURL)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_TELEMETRY_AUTHID=\"${TELEMETRY_AUTHID}\""
|
||||
"-DGTA5SYNC_TELEMETRY_AUTHPW=\"${TELEMETRY_AUTHPW}\""
|
||||
"-DGTA5SYNC_TELEMETRY_PUSHURL=\"${TELEMETRY_PUSHURL}\""
|
||||
"-DGTA5SYNC_TELEMETRY_REGURL=\"${TELEMETRY_REGURL}\""
|
||||
)
|
||||
endif()
|
||||
if(TELEMETRY_WEBURL)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_TELEMETRY_WEBURL=\"${TELEMETRY_WEBURL}\""
|
||||
)
|
||||
endif()
|
||||
if(WIN32)
|
||||
list(APPEND GTA5VIEW_LIBS
|
||||
d3d9
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GTA5VIEW_APPVER)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_APPVER=\"${GTA5VIEW_APPVER}\""
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDCODE)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_BUILDCODE=\"${GTA5VIEW_BUILDCODE}\""
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDTYPE)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_BUILDTYPE=\"${GTA5VIEW_BUILDTYPE}\""
|
||||
)
|
||||
else()
|
||||
if(GTA5VIEW_BUILDTYPE_ALPHA)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_BUILDTYPE_ALPHA
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDTYPE_BETA)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_BUILDTYPE_BETA
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDTYPE_DEV)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_BUILDTYPE_DEV
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDTYPE_DAILY)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_BUILDTYPE_DAILY
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDTYPE_RC)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_BUILDTYPE_RC
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_BUILDTYPE_REL)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
-DGTA5SYNC_BUILDTYPE_REL
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(GTA5VIEW_COMMIT)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_COMMIT=\"${GTA5VIEW_COMMIT}\""
|
||||
)
|
||||
endif()
|
||||
|
||||
if(GTA5VIEW_INLANG)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_INLANG=\"${GTA5VIEW_INLANG}\""
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_LANG)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_LANG=\"${GTA5VIEW_LANG}\""
|
||||
)
|
||||
endif()
|
||||
if(GTA5VIEW_PLUG)
|
||||
list(APPEND GTA5VIEW_DEFINES
|
||||
"-DGTA5SYNC_PLUG=\"${GTA5VIEW_PLUG}\""
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(gta5view
|
||||
WIN32 MACOSX_BUNDLE
|
||||
${GTA5VIEW_HEADERS}
|
||||
${GTA5VIEW_SOURCES}
|
||||
${GTA5VIEW_FORMS}
|
||||
${GTA5VIEW_RESOURCES}
|
||||
)
|
||||
|
||||
if(Qt5LinguistTools_FOUND AND QCONF_BUILD)
|
||||
add_dependencies(gta5view translations)
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16.0")
|
||||
target_precompile_headers(gta5view PRIVATE config.h)
|
||||
endif()
|
||||
|
||||
if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.14.0")
|
||||
qt5_import_plugins(gta5view INCLUDE Qt5::QSvgPlugin)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(gta5view PRIVATE ${GTA5VIEW_DEFINES})
|
||||
target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR})
|
||||
target_link_libraries(gta5view PRIVATE Qt5::Network Qt5::Svg Qt5::Widgets ${GTA5VIEW_LIBS})
|
||||
|
||||
install(TARGETS gta5view DESTINATION bin)
|
||||
install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications)
|
||||
install(FILES res/de.syping.gta5view.metainfo.xml DESTINATION share/metainfo)
|
||||
install(FILES res/gta5view-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-32.png DESTINATION share/icons/hicolor/32x32/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-48.png DESTINATION share/icons/hicolor/48x48/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-64.png DESTINATION share/icons/hicolor/64x64/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-96.png DESTINATION share/icons/hicolor/96x96/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-128.png DESTINATION share/icons/hicolor/128x128/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-256.png DESTINATION share/icons/hicolor/256x256/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/gta5view-512.png DESTINATION share/icons/hicolor/512x512/apps RENAME de.syping.gta5view.png)
|
||||
install(FILES res/de.syping.gta5view.png DESTINATION share/pixmaps)
|
||||
if(QCONF_BUILD)
|
||||
install(FILES ${GTA5VIEW_TRANSLATIONS} DESTINATION share/gta5view/translations)
|
||||
endif()
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -44,84 +44,12 @@ void DatabaseThread::run()
|
|||
{
|
||||
QEventLoop threadLoop;
|
||||
|
||||
QStringList crewList;
|
||||
QStringList crewListR;
|
||||
|
||||
// Register thread loop end signal
|
||||
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
|
||||
|
||||
// Setup crewList for Quick time scan
|
||||
crewList = crewDB->getCrews();
|
||||
if (!crewList.isEmpty())
|
||||
{
|
||||
crewListR = deleteCompatibleCrews(crewList);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (crewList.isEmpty() && threadRunning)
|
||||
{
|
||||
QTimer::singleShot(1000, &threadLoop, SLOT(quit()));
|
||||
threadLoop.exec();
|
||||
if (!crewDB->isAddingCrews())
|
||||
{
|
||||
crewList = crewDB->getCrews();
|
||||
}
|
||||
}
|
||||
if (threadRunning)
|
||||
{
|
||||
crewListR = deleteCompatibleCrews(crewList);
|
||||
}
|
||||
}
|
||||
|
||||
// Only do QTS when Thread should be run
|
||||
if (threadRunning)
|
||||
{
|
||||
// Quick time scan
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "Start QTS";
|
||||
#endif
|
||||
if (crewListR.length() <= 5)
|
||||
{
|
||||
scanCrewReference(crewListR, 2500);
|
||||
emit crewNameUpdated();
|
||||
}
|
||||
if (crewList.length() <= 3)
|
||||
{
|
||||
scanCrewMembersList(crewList, 3, 2500);
|
||||
emit playerNameUpdated();
|
||||
}
|
||||
else if (crewList.length() <= 5)
|
||||
{
|
||||
scanCrewMembersList(crewList, 2, 2500);
|
||||
emit playerNameUpdated();
|
||||
}
|
||||
|
||||
if (threadRunning)
|
||||
{
|
||||
QTimer::singleShot(10000, &threadLoop, SLOT(quit()));
|
||||
threadLoop.exec();
|
||||
}
|
||||
}
|
||||
|
||||
while (threadRunning)
|
||||
{
|
||||
crewList = crewDB->getCrews();
|
||||
crewListR = deleteCompatibleCrews(crewList);
|
||||
|
||||
// Long time scan
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "Start LTS";
|
||||
#endif
|
||||
scanCrewReference(crewListR, 10000);
|
||||
emit crewNameUpdated();
|
||||
scanCrewMembersList(crewList, crewMaxPages, 10000);
|
||||
emit playerNameUpdated();
|
||||
|
||||
if (threadRunning)
|
||||
{
|
||||
QTimer::singleShot(300000, &threadLoop, SLOT(quit()));
|
||||
threadLoop.exec();
|
||||
}
|
||||
QTimer::singleShot(300000, &threadLoop, SLOT(quit()));
|
||||
threadLoop.exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,11 +62,14 @@ void DatabaseThread::scanCrewReference(const QStringList &crewList, const int &r
|
|||
QNetworkAccessManager *netManager = new QNetworkAccessManager();
|
||||
QNetworkRequest netRequest(AppEnv::getCrewFetchingUrl(crewID));
|
||||
#if QT_VERSION >= 0x050600
|
||||
#if QT_VERSION < 0x060000
|
||||
netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
#endif
|
||||
#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");
|
||||
netRequest.setRawHeader("Accept", "text/html");
|
||||
netRequest.setRawHeader("Accept-Charset", "utf-8");
|
||||
netRequest.setRawHeader("Accept-Language", "en-US,en;q=0.9");
|
||||
netRequest.setRawHeader("Connection", "keep-alive");
|
||||
|
||||
QNetworkReply *netReply = netManager->get(netRequest);
|
||||
|
@ -169,6 +100,10 @@ void DatabaseThread::scanCrewReference(const QStringList &crewList, const int &r
|
|||
emit crewNameFound(crewID.toInt(), crewName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
netReply->abort();
|
||||
}
|
||||
|
||||
if (threadRunning)
|
||||
{
|
||||
|
@ -202,11 +137,14 @@ void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int
|
|||
QNetworkAccessManager *netManager = new QNetworkAccessManager();
|
||||
QNetworkRequest netRequest(AppEnv::getPlayerFetchingUrl(crewID, currentPage));
|
||||
#if QT_VERSION >= 0x050600
|
||||
#if QT_VERSION < 0x060000
|
||||
netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
#endif
|
||||
#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");
|
||||
netRequest.setRawHeader("Accept", "application/json");
|
||||
netRequest.setRawHeader("Accept-Charset", "utf-8");
|
||||
netRequest.setRawHeader("Accept-Language", "en-US,en;q=0.9");
|
||||
netRequest.setRawHeader("Connection", "keep-alive");
|
||||
|
||||
QNetworkReply *netReply = netManager->get(netRequest);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,14 +22,19 @@
|
|||
#include "ProfileWidget.h"
|
||||
#include "ExportThread.h"
|
||||
#include "SavegameData.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QDesktopWidget>
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QScreen>
|
||||
#else
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
ExportThread::ExportThread(QMap<ProfileWidget*,QString> profileMap, QString exportDirectory, bool pictureCopyEnabled, bool pictureExportEnabled, int exportCount, QObject *parent) : QThread(parent),
|
||||
profileMap(profileMap), exportDirectory(exportDirectory), pictureCopyEnabled(pictureCopyEnabled), pictureExportEnabled(pictureExportEnabled), exportCount(exportCount)
|
||||
{
|
||||
|
@ -101,8 +106,17 @@ void ExportThread::run()
|
|||
QImage exportPicture = picture->getImage();
|
||||
if (sizeMode == "Desktop")
|
||||
{
|
||||
QRect desktopResolution = qApp->desktop()->screenGeometry();
|
||||
exportPicture = exportPicture.scaled(desktopResolution.width(), desktopResolution.height(), aspectRatio, Qt::SmoothTransformation);
|
||||
#if QT_VERSION >= 0x050000
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
QRect desktopResolution = QApplication::primaryScreen()->geometry();
|
||||
int desktopSizeWidth = qRound((double)desktopResolution.width() * screenRatioPR);
|
||||
int desktopSizeHeight = qRound((double)desktopResolution.height() * screenRatioPR);
|
||||
#else
|
||||
QRect desktopResolution = QApplication::desktop()->screenGeometry();
|
||||
int desktopSizeWidth = desktopResolution.width();
|
||||
int desktopSizeHeight = desktopResolution.height();
|
||||
#endif
|
||||
exportPicture = exportPicture.scaled(desktopSizeWidth, desktopSizeHeight, aspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
else if (sizeMode == "Custom")
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -35,9 +35,11 @@ QMap<QString, QString> GlobalString::getGlobalMap()
|
|||
{
|
||||
QMap<QString, QString> globalMap;
|
||||
QSettings globalFile(getLanguageFile(), QSettings::IniFormat);
|
||||
#if QT_VERSION < 0x060000
|
||||
globalFile.setIniCodec("UTF-8");
|
||||
#endif
|
||||
globalFile.beginGroup("Global");
|
||||
for (QString globalStr : globalFile.childKeys())
|
||||
for (const QString &globalStr : globalFile.childKeys())
|
||||
{
|
||||
globalMap[globalStr] = globalFile.value(globalStr, globalStr).toString();
|
||||
}
|
||||
|
@ -49,7 +51,9 @@ QString GlobalString::getString(QString valueStr, bool *ok)
|
|||
{
|
||||
QString globalString = valueStr;
|
||||
QSettings globalFile(getLanguageFile(), QSettings::IniFormat);
|
||||
#if QT_VERSION < 0x060000
|
||||
globalFile.setIniCodec("UTF-8");
|
||||
#endif
|
||||
globalFile.beginGroup("Global");
|
||||
QStringList globalStrList = globalFile.childKeys();
|
||||
if (globalStrList.contains(valueStr))
|
||||
|
|
|
@ -27,15 +27,15 @@ IconLoader::IconLoader()
|
|||
QIcon IconLoader::loadingAppIcon()
|
||||
{
|
||||
QIcon appIcon;
|
||||
appIcon.addFile(":/img/5sync-16.png", QSize(16, 16));
|
||||
appIcon.addFile(":/img/5sync-24.png", QSize(24, 24));
|
||||
appIcon.addFile(":/img/5sync-32.png", QSize(32, 32));
|
||||
appIcon.addFile(":/img/5sync-40.png", QSize(40, 40));
|
||||
appIcon.addFile(":/img/5sync-48.png", QSize(48, 48));
|
||||
appIcon.addFile(":/img/5sync-64.png", QSize(64, 64));
|
||||
appIcon.addFile(":/img/5sync-96.png", QSize(96, 96));
|
||||
appIcon.addFile(":/img/5sync-128.png", QSize(128, 128));
|
||||
appIcon.addFile(":/img/5sync-256.png", QSize(256, 256));
|
||||
appIcon.addFile(":/img/gta5view-16.png", QSize(16, 16));
|
||||
appIcon.addFile(":/img/gta5view-24.png", QSize(24, 24));
|
||||
appIcon.addFile(":/img/gta5view-32.png", QSize(32, 32));
|
||||
appIcon.addFile(":/img/gta5view-40.png", QSize(40, 40));
|
||||
appIcon.addFile(":/img/gta5view-48.png", QSize(48, 48));
|
||||
appIcon.addFile(":/img/gta5view-64.png", QSize(64, 64));
|
||||
appIcon.addFile(":/img/gta5view-96.png", QSize(96, 96));
|
||||
appIcon.addFile(":/img/gta5view-128.png", QSize(128, 128));
|
||||
appIcon.addFile(":/img/gta5view-256.png", QSize(256, 256));
|
||||
return appIcon;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2017-2018 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ImageEditorDialog.h"
|
||||
#include "ui_ImageEditorDialog.h"
|
||||
#include "ProfileInterface.h"
|
||||
#include "SidebarGenerator.h"
|
||||
#include "StandardPaths.h"
|
||||
#include "ImportDialog.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QImageReader>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
ImageEditorDialog::ImageEditorDialog(SnapmaticPicture *picture, QString profileName, QWidget *parent) :
|
||||
QDialog(parent), smpic(picture), profileName(profileName),
|
||||
ui(new Ui::ImageEditorDialog)
|
||||
{
|
||||
// Set Window Flags
|
||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->cmdClose->setFocus();
|
||||
|
||||
// Set Icon for Close Button
|
||||
if (QIcon::hasThemeIcon("dialog-close"))
|
||||
{
|
||||
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
|
||||
}
|
||||
else if (QIcon::hasThemeIcon("gtk-close"))
|
||||
{
|
||||
ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close"));
|
||||
}
|
||||
|
||||
// Set Icon for Import Button
|
||||
if (QIcon::hasThemeIcon("document-import"))
|
||||
{
|
||||
ui->cmdReplace->setIcon(QIcon::fromTheme("document-import"));
|
||||
}
|
||||
|
||||
// Set Icon for Overwrite Button
|
||||
if (QIcon::hasThemeIcon("document-save"))
|
||||
{
|
||||
ui->cmdSave->setIcon(QIcon::fromTheme("document-save"));
|
||||
}
|
||||
else if (QIcon::hasThemeIcon("gtk-save"))
|
||||
{
|
||||
ui->cmdSave->setIcon(QIcon::fromTheme("gtk-save"));
|
||||
}
|
||||
|
||||
// DPI calculation
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
|
||||
snapmaticResolutionLW = 516 * screenRatio; // 430
|
||||
snapmaticResolutionLH = 288 * screenRatio; // 240
|
||||
ui->labPicture->setMinimumSize(snapmaticResolutionLW, snapmaticResolutionLH);
|
||||
ui->labCapacity->setText(tr("Capacity: %1").arg(QString::number(qRound((double)picture->getContentMaxLength() / 1024)) % " KB"));
|
||||
|
||||
imageIsChanged = false;
|
||||
pictureCache = picture->getImage();
|
||||
ui->labPicture->setPixmap(QPixmap::fromImage(pictureCache).scaled(snapmaticResolutionLW, snapmaticResolutionLH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
|
||||
setMaximumSize(sizeHint());
|
||||
setMinimumSize(sizeHint());
|
||||
setFixedSize(sizeHint());
|
||||
}
|
||||
|
||||
ImageEditorDialog::~ImageEditorDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ImageEditorDialog::on_cmdClose_clicked()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ImageEditorDialog::on_cmdReplace_clicked()
|
||||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("FileDialogs");
|
||||
bool dontUseNativeDialog = settings.value("DontUseNativeDialog", false).toBool();
|
||||
settings.beginGroup("ImportReplace");
|
||||
|
||||
fileDialogPreOpen: //Work?
|
||||
QFileDialog fileDialog(this);
|
||||
fileDialog.setFileMode(QFileDialog::ExistingFile);
|
||||
fileDialog.setViewMode(QFileDialog::Detail);
|
||||
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
|
||||
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
fileDialog.setWindowTitle(ProfileInterface::tr("Import..."));
|
||||
fileDialog.setLabelText(QFileDialog::Accept, ProfileInterface::tr("Import"));
|
||||
|
||||
// Getting readable Image formats
|
||||
QString imageFormatsStr = " ";
|
||||
for (QByteArray imageFormat : QImageReader::supportedImageFormats())
|
||||
{
|
||||
imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
filters << ProfileInterface::tr("All image files (%1)").arg(imageFormatsStr.trimmed());
|
||||
filters << ProfileInterface::tr("All files (**)");
|
||||
fileDialog.setNameFilters(filters);
|
||||
|
||||
QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
|
||||
|
||||
fileDialog.setSidebarUrls(sidebarUrls);
|
||||
fileDialog.setDirectory(settings.value(profileName % "+Directory", StandardPaths::documentsLocation()).toString());
|
||||
fileDialog.restoreGeometry(settings.value(profileName % "+Geometry", "").toByteArray());
|
||||
|
||||
if (fileDialog.exec())
|
||||
{
|
||||
QStringList selectedFiles = fileDialog.selectedFiles();
|
||||
if (selectedFiles.length() == 1)
|
||||
{
|
||||
QString selectedFile = selectedFiles.at(0);
|
||||
QString selectedFileName = QFileInfo(selectedFile).fileName();
|
||||
|
||||
QFile snapmaticFile(selectedFile);
|
||||
if (!snapmaticFile.open(QFile::ReadOnly))
|
||||
{
|
||||
QMessageBox::warning(this, ProfileInterface::tr("Import"), ProfileInterface::tr("Can't import %1 because file can't be open").arg("\""+selectedFileName+"\""));
|
||||
goto fileDialogPreOpen;
|
||||
}
|
||||
QImage *importImage = new QImage();
|
||||
QImageReader snapmaticImageReader;
|
||||
snapmaticImageReader.setDecideFormatFromContent(true);
|
||||
snapmaticImageReader.setDevice(&snapmaticFile);
|
||||
if (!snapmaticImageReader.read(importImage))
|
||||
{
|
||||
QMessageBox::warning(this, ProfileInterface::tr("Import"), ProfileInterface::tr("Can't import %1 because file can't be parsed properly").arg("\""+selectedFileName+"\""));
|
||||
delete importImage;
|
||||
goto fileDialogPreOpen;
|
||||
}
|
||||
ImportDialog *importDialog = new ImportDialog(this);
|
||||
importDialog->setImage(importImage);
|
||||
importDialog->setModal(true);
|
||||
importDialog->show();
|
||||
importDialog->exec();
|
||||
if (importDialog->isImportAgreed())
|
||||
{
|
||||
pictureCache = importDialog->image();
|
||||
ui->labPicture->setPixmap(QPixmap::fromImage(pictureCache).scaled(snapmaticResolutionLW, snapmaticResolutionLH, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
imageIsChanged = true;
|
||||
}
|
||||
delete importDialog;
|
||||
}
|
||||
}
|
||||
|
||||
settings.setValue(profileName % "+Geometry", fileDialog.saveGeometry());
|
||||
settings.setValue(profileName % "+Directory", fileDialog.directory().absolutePath());
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void ImageEditorDialog::on_cmdSave_clicked()
|
||||
{
|
||||
if (imageIsChanged)
|
||||
{
|
||||
const QByteArray previousPicture = smpic->getPictureStream();
|
||||
bool success = smpic->setImage(pictureCache);
|
||||
if (success)
|
||||
{
|
||||
QString currentFilePath = smpic->getPictureFilePath();
|
||||
QString originalFilePath = smpic->getOriginalPictureFilePath();
|
||||
QString backupFileName = originalFilePath % ".bak";
|
||||
if (!QFile::exists(backupFileName))
|
||||
{
|
||||
QFile::copy(currentFilePath, backupFileName);
|
||||
}
|
||||
if (!smpic->exportPicture(currentFilePath))
|
||||
{
|
||||
smpic->setPictureStream(previousPicture);
|
||||
QMessageBox::warning(this, tr("Snapmatic Image Editor"), tr("Patching of Snapmatic Image failed because of I/O Error"));
|
||||
return;
|
||||
}
|
||||
smpic->emitCustomSignal("PictureUpdated");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Snapmatic Image Editor"), tr("Patching of Snapmatic Image failed because of Image Error"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
void ImageEditorDialog::on_cmdQuestion_clicked()
|
||||
{
|
||||
QMessageBox::information(this, tr("Snapmatic Image Editor"), tr("Every taken Snapmatic have a different Capacity, a Snapmatic with higher Capacity can store a picture with better quality."));
|
||||
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ImageEditorDialog</class>
|
||||
<widget class="QDialog" name="ImageEditorDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>516</width>
|
||||
<height>335</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Overwrite Image...</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlInterface">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labPicture">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>516</width>
|
||||
<height>288</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="buttomFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlButtons">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlCapacity">
|
||||
<item>
|
||||
<widget class="QLabel" name="labCapacity">
|
||||
<property name="text">
|
||||
<string>Capacity: %1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="cmdQuestion">
|
||||
<property name="text">
|
||||
<string>?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="hsCapacity">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlButtons">
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdReplace">
|
||||
<property name="text">
|
||||
<string>&Import...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="hsButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdSave">
|
||||
<property name="text">
|
||||
<string>&Overwrite</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdClose">
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
445
ImportDialog.cpp
445
ImportDialog.cpp
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2017-2018 Syping
|
||||
* Copyright (C) 2017-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,9 +20,11 @@
|
|||
#include "ui_ImportDialog.h"
|
||||
#include "SidebarGenerator.h"
|
||||
#include "StandardPaths.h"
|
||||
#include "imagecropper.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QInputDialog>
|
||||
#include <QImageReader>
|
||||
#include <QColorDialog>
|
||||
#include <QFileDialog>
|
||||
|
@ -43,15 +45,20 @@
|
|||
#define snapmaticAvatarPlacementW 145
|
||||
#define snapmaticAvatarPlacementH 66
|
||||
|
||||
ImportDialog::ImportDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
|
||||
QDialog(parent), profileName(profileName),
|
||||
ui(new Ui::ImportDialog)
|
||||
{
|
||||
// Set Window Flags
|
||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->cmdOK->setDefault(true);
|
||||
ui->cmdOK->setFocus();
|
||||
importAgreed = false;
|
||||
settingsLocked = false;
|
||||
watermarkAvatar = true;
|
||||
watermarkPicture = false;
|
||||
insideAvatarZone = false;
|
||||
avatarAreaImage = QImage(":/img/avatarareaimport.png");
|
||||
selectedColour = QColor::fromRgb(0, 0, 0, 255);
|
||||
|
@ -81,6 +88,13 @@ ImportDialog::ImportDialog(QWidget *parent) :
|
|||
ui->labBackgroundImage->setText(tr("Background Image:"));
|
||||
ui->cmdBackgroundWipe->setVisible(false);
|
||||
|
||||
// Set Import Settings
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Import");
|
||||
QString currentProfile = settings.value("Profile", "Default").toString();
|
||||
settings.endGroup();
|
||||
processSettings(currentProfile);
|
||||
|
||||
// DPI calculation
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
snapmaticResolutionLW = 516 * screenRatio; // 430
|
||||
|
@ -101,6 +115,15 @@ ImportDialog::ImportDialog(QWidget *parent) :
|
|||
}
|
||||
#endif
|
||||
|
||||
// Options menu
|
||||
optionsMenu = new QMenu(this);
|
||||
optionsMenu->addAction(tr("&Import new Picture..."), this, SLOT(importNewPicture()));
|
||||
optionsMenu->addAction(tr("&Crop Picture..."), this, SLOT(cropPicture()));
|
||||
optionsMenu->addSeparator();
|
||||
optionsMenu->addAction(tr("&Load Settings..."), this, SLOT(loadImportSettings()));
|
||||
optionsMenu->addAction(tr("&Save Settings..."), this, SLOT(saveImportSettings()));
|
||||
ui->cmdOptions->setMenu(optionsMenu);
|
||||
|
||||
setMaximumSize(sizeHint());
|
||||
setMinimumSize(sizeHint());
|
||||
setFixedSize(sizeHint());
|
||||
|
@ -108,6 +131,7 @@ ImportDialog::ImportDialog(QWidget *parent) :
|
|||
|
||||
ImportDialog::~ImportDialog()
|
||||
{
|
||||
delete optionsMenu;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -118,6 +142,7 @@ void ImportDialog::processImage()
|
|||
QPixmap snapmaticPixmap(snapmaticResolutionW, snapmaticResolutionH);
|
||||
snapmaticPixmap.fill(selectedColour);
|
||||
QPainter snapmaticPainter(&snapmaticPixmap);
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
if (!backImage.isNull())
|
||||
{
|
||||
if (!ui->cbStretch->isChecked())
|
||||
|
@ -169,6 +194,7 @@ void ImportDialog::processImage()
|
|||
snapmaticImage = snapmaticImage.scaled(snapmaticAvatarResolution, snapmaticAvatarResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
snapmaticPainter.drawImage(snapmaticAvatarPlacementW + diffWidth, snapmaticAvatarPlacementH + diffHeight, snapmaticImage);
|
||||
if (ui->cbWatermark->isChecked()) { processWatermark(&snapmaticPainter); }
|
||||
imageTitle = tr("Custom Avatar", "Custom Avatar Description in SC, don't use Special Character!");
|
||||
}
|
||||
else
|
||||
|
@ -195,11 +221,351 @@ void ImportDialog::processImage()
|
|||
snapmaticImage = snapmaticImage.scaled(snapmaticResolutionW, snapmaticResolutionH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
snapmaticPainter.drawImage(0 + diffWidth, 0 + diffHeight, snapmaticImage);
|
||||
if (ui->cbWatermark->isChecked()) { processWatermark(&snapmaticPainter); }
|
||||
imageTitle = tr("Custom Picture", "Custom Picture Description in SC, don't use Special Character!");
|
||||
}
|
||||
snapmaticPainter.end();
|
||||
newImage = snapmaticPixmap.toImage();
|
||||
ui->labPicture->setPixmap(snapmaticPixmap.scaled(snapmaticResolutionLW, snapmaticResolutionLH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
#if QT_VERSION >= 0x050600
|
||||
snapmaticPixmap.setDevicePixelRatio(screenRatioPR);
|
||||
#endif
|
||||
ui->labPicture->setPixmap(snapmaticPixmap.scaled(snapmaticResolutionLW * screenRatioPR, snapmaticResolutionLH * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
void ImportDialog::processWatermark(QPainter *snapmaticPainter)
|
||||
{
|
||||
bool blackWatermark = false;
|
||||
bool redWatermark = false;
|
||||
if (selectedColour.red() > 127)
|
||||
{
|
||||
if (selectedColour.green() > 127 || selectedColour.blue() > 127)
|
||||
{
|
||||
redWatermark = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
redWatermark = true;
|
||||
}
|
||||
if (selectedColour.lightness() > 127)
|
||||
{
|
||||
blackWatermark = true;
|
||||
}
|
||||
// draw watermark
|
||||
if (redWatermark)
|
||||
{
|
||||
snapmaticPainter->drawImage(0, 0, QImage(":/img/watermark_2r.png"));
|
||||
}
|
||||
else
|
||||
{
|
||||
QImage viewWatermark = QImage(":/img/watermark_2b.png");
|
||||
if (!blackWatermark)
|
||||
{
|
||||
viewWatermark.invertPixels(QImage::InvertRgb);
|
||||
}
|
||||
snapmaticPainter->drawImage(0, 0, viewWatermark);
|
||||
}
|
||||
QImage textWatermark = QImage(":/img/watermark_1b.png");
|
||||
if (!blackWatermark)
|
||||
{
|
||||
textWatermark.invertPixels(QImage::InvertRgb);
|
||||
}
|
||||
snapmaticPainter->drawImage(0, 0, textWatermark);
|
||||
}
|
||||
|
||||
void ImportDialog::processSettings(QString settingsProfile, bool setDefault)
|
||||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Import");
|
||||
if (setDefault)
|
||||
{
|
||||
settings.setValue("Profile", settingsProfile);
|
||||
}
|
||||
if (settingsProfile == "Default")
|
||||
{
|
||||
watermarkAvatar = true;
|
||||
watermarkPicture = false;
|
||||
selectedColour = QColor::fromRgb(0, 0, 0, 255);
|
||||
backImage = QImage();
|
||||
ui->cbStretch->setChecked(false);
|
||||
ui->cbForceAvatarColour->setChecked(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.beginGroup(settingsProfile);
|
||||
watermarkAvatar = settings.value("WatermarkAvatar", true).toBool();
|
||||
watermarkPicture = settings.value("WatermarkPicture", false).toBool();
|
||||
backImage = qvariant_cast<QImage>(settings.value("BackgroundImage", QImage()));
|
||||
selectedColour = qvariant_cast<QColor>(settings.value("SelectedColour", QColor::fromRgb(0, 0, 0, 255)));
|
||||
ui->cbStretch->setChecked(settings.value("BackgroundStretch", false).toBool());
|
||||
ui->cbForceAvatarColour->setChecked(settings.value("ForceAvatarColour", false).toBool());
|
||||
settings.endGroup();
|
||||
}
|
||||
if (!workImage.isNull())
|
||||
{
|
||||
if (ui->cbAvatar->isChecked())
|
||||
{
|
||||
ui->cbWatermark->setChecked(watermarkAvatar);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->cbWatermark->setChecked(watermarkPicture);
|
||||
}
|
||||
}
|
||||
ui->labColour->setText(tr("Background Colour: <span style=\"color: %1\">%1</span>").arg(selectedColour.name()));
|
||||
if (!backImage.isNull())
|
||||
{
|
||||
ui->labBackgroundImage->setText(tr("Background Image: %1").arg(tr("Storage", "Background Image: Storage")));
|
||||
ui->cmdBackgroundWipe->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labBackgroundImage->setText(tr("Background Image:"));
|
||||
ui->cmdBackgroundWipe->setVisible(false);
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void ImportDialog::saveSettings(QString settingsProfile)
|
||||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Import");
|
||||
settings.beginGroup(settingsProfile);
|
||||
settings.setValue("WatermarkAvatar", watermarkAvatar);
|
||||
settings.setValue("WatermarkPicture", watermarkPicture);
|
||||
settings.setValue("BackgroundImage", backImage);
|
||||
settings.setValue("SelectedColour", selectedColour);
|
||||
settings.setValue("BackgroundStretch", ui->cbStretch->isChecked());
|
||||
settings.setValue("ForceAvatarColour", ui->cbForceAvatarColour->isChecked());
|
||||
settings.endGroup();
|
||||
settings.setValue("Profile", settingsProfile);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void ImportDialog::cropPicture()
|
||||
{
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
|
||||
QDialog cropDialog(this);
|
||||
#if QT_VERSION >= 0x050000
|
||||
cropDialog.setObjectName(QStringLiteral("CropDialog"));
|
||||
#else
|
||||
cropDialog.setObjectName(QString::fromUtf8("CropDialog"));
|
||||
#endif
|
||||
cropDialog.setWindowTitle(tr("Crop Picture..."));
|
||||
cropDialog.setWindowFlags(cropDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
cropDialog.setModal(true);
|
||||
|
||||
QVBoxLayout cropLayout;
|
||||
#if QT_VERSION >= 0x050000
|
||||
cropLayout.setObjectName(QStringLiteral("CropLayout"));
|
||||
#else
|
||||
cropLayout.setObjectName(QString::fromUtf8("CropLayout"));
|
||||
#endif
|
||||
cropLayout.setContentsMargins(0, 0, 0, 0);
|
||||
cropLayout.setSpacing(0);
|
||||
cropDialog.setLayout(&cropLayout);
|
||||
|
||||
ImageCropper imageCropper(&cropDialog);
|
||||
#if QT_VERSION >= 0x050000
|
||||
imageCropper.setObjectName(QStringLiteral("ImageCropper"));
|
||||
#else
|
||||
imageCropper.setObjectName(QString::fromUtf8("ImageCropper"));
|
||||
#endif
|
||||
imageCropper.setBackgroundColor(Qt::black);
|
||||
imageCropper.setCroppingRectBorderColor(QColor(255, 255, 255, 127));
|
||||
imageCropper.setImage(QPixmap::fromImage(origImage, Qt::AutoColor));
|
||||
imageCropper.setProportion(QSize(1, 1));
|
||||
imageCropper.setFixedSize(workImage.size());
|
||||
cropLayout.addWidget(&imageCropper);
|
||||
|
||||
QHBoxLayout buttonLayout;
|
||||
#if QT_VERSION >= 0x050000
|
||||
cropLayout.setObjectName(QStringLiteral("ButtonLayout"));
|
||||
#else
|
||||
cropLayout.setObjectName(QString::fromUtf8("ButtonLayout"));
|
||||
#endif
|
||||
cropLayout.addLayout(&buttonLayout);
|
||||
|
||||
QPushButton cropButton(&cropDialog);
|
||||
#if QT_VERSION >= 0x050000
|
||||
cropButton.setObjectName(QStringLiteral("CropButton"));
|
||||
#else
|
||||
cropButton.setObjectName(QString::fromUtf8("CropButton"));
|
||||
#endif
|
||||
cropButton.setMinimumSize(0, 40 * screenRatio);
|
||||
cropButton.setText(tr("&Crop"));
|
||||
cropButton.setToolTip(tr("Crop Picture"));
|
||||
QObject::connect(&cropButton, SIGNAL(clicked(bool)), &cropDialog, SLOT(accept()));
|
||||
|
||||
buttonLayout.addWidget(&cropButton);
|
||||
|
||||
cropDialog.show();
|
||||
cropDialog.setFixedSize(cropDialog.sizeHint());
|
||||
if (cropDialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
QImage *croppedImage = new QImage(imageCropper.cropImage().toImage());
|
||||
setImage(croppedImage);
|
||||
}
|
||||
}
|
||||
|
||||
void ImportDialog::importNewPicture()
|
||||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("FileDialogs");
|
||||
bool dontUseNativeDialog = settings.value("DontUseNativeDialog", false).toBool();
|
||||
settings.beginGroup("ImportCopy");
|
||||
|
||||
fileDialogPreOpen: //Work?
|
||||
QFileDialog fileDialog(this);
|
||||
fileDialog.setFileMode(QFileDialog::ExistingFile);
|
||||
fileDialog.setViewMode(QFileDialog::Detail);
|
||||
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
|
||||
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
fileDialog.setWindowTitle(QApplication::translate("ProfileInterface", "Import..."));
|
||||
fileDialog.setLabelText(QFileDialog::Accept, QApplication::translate("ProfileInterface", "Import"));
|
||||
|
||||
// Getting readable Image formats
|
||||
QString imageFormatsStr = " ";
|
||||
for (QByteArray imageFormat : QImageReader::supportedImageFormats())
|
||||
{
|
||||
imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
filters << QApplication::translate("ProfileInterface", "All image files (%1)").arg(imageFormatsStr.trimmed());
|
||||
filters << QApplication::translate("ProfileInterface", "All files (**)");
|
||||
fileDialog.setNameFilters(filters);
|
||||
|
||||
QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
|
||||
|
||||
fileDialog.setSidebarUrls(sidebarUrls);
|
||||
fileDialog.setDirectory(settings.value(profileName % "+Directory", StandardPaths::documentsLocation()).toString());
|
||||
fileDialog.restoreGeometry(settings.value(profileName % "+Geometry", "").toByteArray());
|
||||
|
||||
if (fileDialog.exec())
|
||||
{
|
||||
QStringList selectedFiles = fileDialog.selectedFiles();
|
||||
if (selectedFiles.length() == 1)
|
||||
{
|
||||
QString selectedFile = selectedFiles.at(0);
|
||||
QString selectedFileName = QFileInfo(selectedFile).fileName();
|
||||
|
||||
QFile snapmaticFile(selectedFile);
|
||||
if (!snapmaticFile.open(QFile::ReadOnly))
|
||||
{
|
||||
QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be open").arg("\""+selectedFileName+"\""));
|
||||
goto fileDialogPreOpen;
|
||||
}
|
||||
QImage *importImage = new QImage();
|
||||
QImageReader snapmaticImageReader;
|
||||
snapmaticImageReader.setDecideFormatFromContent(true);
|
||||
snapmaticImageReader.setDevice(&snapmaticFile);
|
||||
if (!snapmaticImageReader.read(importImage))
|
||||
{
|
||||
QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be parsed properly").arg("\""+selectedFileName+"\""));
|
||||
delete importImage;
|
||||
goto fileDialogPreOpen;
|
||||
}
|
||||
setImage(importImage);
|
||||
}
|
||||
}
|
||||
|
||||
settings.setValue(profileName % "+Geometry", fileDialog.saveGeometry());
|
||||
settings.setValue(profileName % "+Directory", fileDialog.directory().absolutePath());
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void ImportDialog::loadImportSettings()
|
||||
{
|
||||
if (settingsLocked)
|
||||
{
|
||||
QMessageBox::information(this, tr("Load Settings..."), tr("Please import a new picture first"));
|
||||
return;
|
||||
}
|
||||
bool ok;
|
||||
QStringList profileList;
|
||||
profileList << tr("Default", "Default as Default Profile")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("1")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("2")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("3")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("4")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("5");
|
||||
QString sProfile = QInputDialog::getItem(this, tr("Load Settings..."), tr("Please select your settings profile"), profileList, 0, false, &ok, windowFlags());
|
||||
if (ok)
|
||||
{
|
||||
QString pProfile;
|
||||
if (sProfile == tr("Default", "Default as Default Profile"))
|
||||
{
|
||||
pProfile = "Default";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1"))
|
||||
{
|
||||
pProfile = "Profile 1";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2"))
|
||||
{
|
||||
pProfile = "Profile 2";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3"))
|
||||
{
|
||||
pProfile = "Profile 3";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4"))
|
||||
{
|
||||
pProfile = "Profile 4";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5"))
|
||||
{
|
||||
pProfile = "Profile 5";
|
||||
}
|
||||
processSettings(pProfile, true);
|
||||
processImage();
|
||||
}
|
||||
}
|
||||
|
||||
void ImportDialog::saveImportSettings()
|
||||
{
|
||||
if (settingsLocked)
|
||||
{
|
||||
QMessageBox::information(this, tr("Save Settings..."), tr("Please import a new picture first"));
|
||||
return;
|
||||
}
|
||||
bool ok;
|
||||
QStringList profileList;
|
||||
profileList << tr("Profile %1", "Profile %1 as Profile 1").arg("1")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("2")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("3")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("4")
|
||||
<< tr("Profile %1", "Profile %1 as Profile 1").arg("5");
|
||||
QString sProfile = QInputDialog::getItem(this, tr("Save Settings..."), tr("Please select your settings profile"), profileList, 0, false, &ok, windowFlags());
|
||||
if (ok)
|
||||
{
|
||||
QString pProfile;
|
||||
if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1"))
|
||||
{
|
||||
pProfile = "Profile 1";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2"))
|
||||
{
|
||||
pProfile = "Profile 2";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3"))
|
||||
{
|
||||
pProfile = "Profile 3";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4"))
|
||||
{
|
||||
pProfile = "Profile 4";
|
||||
}
|
||||
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5"))
|
||||
{
|
||||
pProfile = "Profile 5";
|
||||
}
|
||||
saveSettings(pProfile);
|
||||
}
|
||||
}
|
||||
|
||||
QImage ImportDialog::image()
|
||||
|
@ -209,6 +575,7 @@ QImage ImportDialog::image()
|
|||
|
||||
void ImportDialog::setImage(QImage *image_)
|
||||
{
|
||||
origImage = *image_;
|
||||
workImage = QImage();
|
||||
if (image_->width() == image_->height())
|
||||
{
|
||||
|
@ -227,20 +594,57 @@ void ImportDialog::setImage(QImage *image_)
|
|||
}
|
||||
else if (image_->width() > snapmaticResolutionW && image_->width() > image_->height())
|
||||
{
|
||||
insideAvatarZone = false;
|
||||
ui->cbAvatar->setChecked(false);
|
||||
workImage = image_->scaledToWidth(snapmaticResolutionW, Qt::SmoothTransformation);
|
||||
delete image_;
|
||||
}
|
||||
else if (image_->height() > snapmaticResolutionH && image_->height() > image_->width())
|
||||
{
|
||||
insideAvatarZone = false;
|
||||
ui->cbAvatar->setChecked(false);
|
||||
workImage = image_->scaledToHeight(snapmaticResolutionH, Qt::SmoothTransformation);
|
||||
delete image_;
|
||||
}
|
||||
else
|
||||
{
|
||||
insideAvatarZone = false;
|
||||
ui->cbAvatar->setChecked(false);
|
||||
workImage = *image_;
|
||||
delete image_;
|
||||
}
|
||||
processImage();
|
||||
lockSettings(false);
|
||||
}
|
||||
|
||||
void ImportDialog::lockSettings(bool lock)
|
||||
{
|
||||
ui->cbAvatar->setDisabled(lock);
|
||||
ui->cbForceAvatarColour->setDisabled(lock);
|
||||
ui->cbIgnore->setDisabled(lock);
|
||||
ui->cbStretch->setDisabled(lock);
|
||||
ui->cbWatermark->setDisabled(lock);
|
||||
ui->cmdBackgroundChange->setDisabled(lock);
|
||||
ui->cmdBackgroundWipe->setDisabled(lock);
|
||||
ui->cmdColourChange->setDisabled(lock);
|
||||
ui->labBackgroundImage->setDisabled(lock);
|
||||
ui->labColour->setDisabled(lock);
|
||||
ui->gbSettings->setDisabled(lock);
|
||||
ui->gbBackground->setDisabled(lock);
|
||||
ui->cmdOK->setDisabled(lock);
|
||||
settingsLocked = lock;
|
||||
}
|
||||
|
||||
void ImportDialog::enableOverwriteMode()
|
||||
{
|
||||
setWindowTitle(QApplication::translate("ImageEditorDialog", "Overwrite Image..."));
|
||||
ui->cmdOK->setText(QApplication::translate("ImageEditorDialog", "&Overwrite"));
|
||||
ui->cmdOK->setToolTip(QApplication::translate("ImageEditorDialog", "Apply changes"));
|
||||
ui->cmdCancel->setText(QApplication::translate("ImageEditorDialog", "&Close"));
|
||||
ui->cmdCancel->setToolTip(QApplication::translate("ImageEditorDialog", "Discard changes"));
|
||||
ui->cmdCancel->setDefault(true);
|
||||
ui->cmdCancel->setFocus();
|
||||
lockSettings(true);
|
||||
}
|
||||
|
||||
bool ImportDialog::isImportAgreed()
|
||||
|
@ -248,6 +652,11 @@ bool ImportDialog::isImportAgreed()
|
|||
return importAgreed;
|
||||
}
|
||||
|
||||
bool ImportDialog::areSettingsLocked()
|
||||
{
|
||||
return settingsLocked;
|
||||
}
|
||||
|
||||
QString ImportDialog::getImageTitle()
|
||||
{
|
||||
return imageTitle;
|
||||
|
@ -261,7 +670,7 @@ void ImportDialog::on_cbIgnore_toggled(bool checked)
|
|||
|
||||
void ImportDialog::on_cbAvatar_toggled(bool checked)
|
||||
{
|
||||
if (workImage.width() == workImage.height() && !checked)
|
||||
if (!workImage.isNull() && workImage.width() == workImage.height() && !checked)
|
||||
{
|
||||
if (QMessageBox::No == QMessageBox::warning(this, tr("Snapmatic Avatar Zone"), tr("Are you sure to use a square image outside of the Avatar Zone?\nWhen you want to use it as Avatar the image will be detached!"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No))
|
||||
{
|
||||
|
@ -271,6 +680,16 @@ void ImportDialog::on_cbAvatar_toggled(bool checked)
|
|||
}
|
||||
}
|
||||
insideAvatarZone = ui->cbAvatar->isChecked();
|
||||
watermarkBlock = true;
|
||||
if (insideAvatarZone)
|
||||
{
|
||||
ui->cbWatermark->setChecked(watermarkAvatar);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->cbWatermark->setChecked(watermarkPicture);
|
||||
}
|
||||
watermarkBlock = false;
|
||||
processImage();
|
||||
}
|
||||
|
||||
|
@ -402,3 +821,19 @@ void ImportDialog::on_cbForceAvatarColour_toggled(bool checked)
|
|||
Q_UNUSED(checked)
|
||||
processImage();
|
||||
}
|
||||
|
||||
void ImportDialog::on_cbWatermark_toggled(bool checked)
|
||||
{
|
||||
if (!watermarkBlock)
|
||||
{
|
||||
if (insideAvatarZone)
|
||||
{
|
||||
watermarkAvatar = checked;
|
||||
}
|
||||
else
|
||||
{
|
||||
watermarkPicture = checked;
|
||||
}
|
||||
processImage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2017 Syping
|
||||
* Copyright (C) 2017-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,6 +20,7 @@
|
|||
#define IMPORTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMenu>
|
||||
|
||||
namespace Ui {
|
||||
class ImportDialog;
|
||||
|
@ -30,15 +31,22 @@ class ImportDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImportDialog(QWidget *parent = 0);
|
||||
explicit ImportDialog(QString profileName, QWidget *parent = 0);
|
||||
~ImportDialog();
|
||||
QImage image();
|
||||
QString getImageTitle();
|
||||
void setImage(QImage *image);
|
||||
void lockSettings(bool lock);
|
||||
void enableOverwriteMode();
|
||||
bool isImportAgreed();
|
||||
bool areSettingsLocked();
|
||||
|
||||
private slots:
|
||||
void processImage();
|
||||
void cropPicture();
|
||||
void importNewPicture();
|
||||
void loadImportSettings();
|
||||
void saveImportSettings();
|
||||
void on_cbIgnore_toggled(bool checked);
|
||||
void on_cbAvatar_toggled(bool checked);
|
||||
void on_cmdCancel_clicked();
|
||||
|
@ -49,20 +57,31 @@ private slots:
|
|||
void on_cmdBackgroundWipe_clicked();
|
||||
void on_cbStretch_toggled(bool checked);
|
||||
void on_cbForceAvatarColour_toggled(bool checked);
|
||||
void on_cbWatermark_toggled(bool checked);
|
||||
|
||||
private:
|
||||
QString profileName;
|
||||
Ui::ImportDialog *ui;
|
||||
QImage avatarAreaImage;
|
||||
QString backgroundPath;
|
||||
QString imageTitle;
|
||||
QImage backImage;
|
||||
QImage workImage;
|
||||
QImage origImage;
|
||||
QImage newImage;
|
||||
QColor selectedColour;
|
||||
QMenu *optionsMenu;
|
||||
bool insideAvatarZone;
|
||||
bool watermarkPicture;
|
||||
bool watermarkAvatar;
|
||||
bool watermarkBlock;
|
||||
bool settingsLocked;
|
||||
bool importAgreed;
|
||||
int snapmaticResolutionLW;
|
||||
int snapmaticResolutionLH;
|
||||
void processWatermark(QPainter *snapmaticPainter);
|
||||
void processSettings(QString settingsProfile, bool setDefault = false);
|
||||
void saveSettings(QString settingsProfile);
|
||||
};
|
||||
|
||||
#endif // IMPORTDIALOG_H
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>516</width>
|
||||
<height>425</height>
|
||||
<height>512</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>516</width>
|
||||
<height>425</height>
|
||||
<height>512</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -85,7 +85,7 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="vlSettings">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlCheckboxes">
|
||||
<layout class="QHBoxLayout" name="hlCheckboxesTop">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbAvatar">
|
||||
<property name="sizePolicy">
|
||||
|
@ -114,6 +114,23 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlCheckboxesButtom">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbWatermark">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Watermark</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -124,7 +141,7 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="vlBackground">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlColor">
|
||||
<layout class="QHBoxLayout" name="hlColour">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlColourManage">
|
||||
<item>
|
||||
|
@ -153,6 +170,9 @@
|
|||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="cmdColourChange">
|
||||
<property name="toolTip">
|
||||
<string>Select background colour</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
@ -203,6 +223,9 @@
|
|||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="cmdBackgroundChange">
|
||||
<property name="toolTip">
|
||||
<string>Select background image</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
@ -210,6 +233,9 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="cmdBackgroundWipe">
|
||||
<property name="toolTip">
|
||||
<string>Remove background image</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
|
@ -273,6 +299,19 @@
|
|||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlButtons">
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdOptions">
|
||||
<property name="toolTip">
|
||||
<string>Import options</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Options</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="hsButtons">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
#include "ui_JsonEditorDialog.h"
|
||||
#include "SnapmaticEditor.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
|
||||
#if QT_VERSION >= 0x050200
|
||||
|
@ -29,6 +31,10 @@
|
|||
#include <QDebug>
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#endif
|
||||
|
||||
JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
|
||||
QDialog(parent), smpic(picture),
|
||||
ui(new Ui::JsonEditorDialog)
|
||||
|
@ -37,6 +43,7 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
|
|||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowMinMaxButtonsHint);
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->cmdClose->setDefault(true);
|
||||
ui->cmdClose->setFocus();
|
||||
|
||||
// Set Icon for Close Button
|
||||
|
@ -63,9 +70,18 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
|
|||
|
||||
#if QT_VERSION >= 0x050200
|
||||
ui->txtJSON->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
#else
|
||||
QFont jsonFont = ui->txtJSON->font();
|
||||
jsonFont.setStyleHint(QFont::Monospace);
|
||||
jsonFont.setFixedPitch(true);
|
||||
ui->txtJSON->setFont(jsonFont);
|
||||
#endif
|
||||
QFontMetrics fontMetrics(ui->txtJSON->font());
|
||||
#if QT_VERSION >= 0x050B00
|
||||
ui->txtJSON->setTabStopDistance(fontMetrics.horizontalAdvance(" "));
|
||||
#else
|
||||
ui->txtJSON->setTabStopWidth(fontMetrics.width(" "));
|
||||
#endif
|
||||
|
||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonCode.toUtf8());
|
||||
ui->txtJSON->setStyleSheet("QPlainTextEdit{background-color: rgb(46, 47, 48); color: rgb(238, 231, 172);}");
|
||||
|
@ -87,6 +103,7 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
|
|||
{
|
||||
ui->lineJSON->setMinimumHeight(qRound(1 * screenRatio));
|
||||
ui->lineJSON->setMaximumHeight(qRound(1 * screenRatio));
|
||||
ui->lineJSON->setLineWidth(qRound(1 * screenRatio));
|
||||
}
|
||||
resize(450 * screenRatio, 550 * screenRatio);
|
||||
}
|
||||
|
@ -182,7 +199,24 @@ bool JsonEditorDialog::saveJsonContent()
|
|||
return false;
|
||||
}
|
||||
jsonCode = newCode;
|
||||
smpic->updateStrings();
|
||||
smpic->emitUpdate();
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "JSONEdited";
|
||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
@ -196,13 +230,13 @@ bool JsonEditorDialog::saveJsonContent()
|
|||
|
||||
void JsonEditorDialog::on_cmdClose_clicked()
|
||||
{
|
||||
this->close();
|
||||
close();
|
||||
}
|
||||
|
||||
void JsonEditorDialog::on_cmdSave_clicked()
|
||||
{
|
||||
if (saveJsonContent())
|
||||
{
|
||||
this->close();
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,9 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Apply changes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Save</string>
|
||||
</property>
|
||||
|
@ -125,6 +128,9 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Discard changes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2017 Syping
|
||||
* Copyright (C) 2017-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -60,36 +60,10 @@ MapLocationDialog::~MapLocationDialog()
|
|||
|
||||
void MapLocationDialog::drawPointOnMap(double xpos_d, double ypos_d)
|
||||
{
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
int pointMakerSize = 8 * screenRatio;
|
||||
QPixmap pointMakerPixmap = IconLoader::loadingPointmakerIcon().pixmap(QSize(pointMakerSize, pointMakerSize));
|
||||
QSize mapPixelSize = size();
|
||||
|
||||
int pointMakerHalfSize = pointMakerSize / 2;
|
||||
long xpos_ms = qRound(xpos_d);
|
||||
long ypos_ms = qRound(ypos_d);
|
||||
double xpos_ma = xpos_ms + 4000;
|
||||
double ypos_ma = ypos_ms + 4000;
|
||||
double xrat = (double)mapPixelSize.width() / 10000;
|
||||
double yrat = (double)mapPixelSize.height() / 12000;
|
||||
long xpos_mp = qRound(xpos_ma * xrat);
|
||||
long ypos_mp = qRound(ypos_ma * yrat);
|
||||
long xpos_pr = xpos_mp - pointMakerHalfSize;
|
||||
long ypos_pr = ypos_mp + pointMakerHalfSize;
|
||||
|
||||
QPixmap mapPixmap(mapPixelSize);
|
||||
QPainter mapPainter(&mapPixmap);
|
||||
mapPainter.drawPixmap(0, 0, mapPixelSize.width(), mapPixelSize.height(), QPixmap(":/img/mappreview.jpg").scaled(mapPixelSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
mapPainter.drawPixmap(xpos_pr, mapPixelSize.height() - ypos_pr, pointMakerSize, pointMakerSize, pointMakerPixmap);
|
||||
mapPainter.end();
|
||||
|
||||
QPalette backgroundPalette;
|
||||
backgroundPalette.setBrush(backgroundRole(), QBrush(mapPixmap));
|
||||
setPalette(backgroundPalette);
|
||||
|
||||
ui->labPos->setText(tr("X: %1\nY: %2", "X and Y position").arg(QString::number(xpos_d), QString::number(ypos_d)));
|
||||
xpos_new = xpos_d;
|
||||
ypos_new = ypos_d;
|
||||
ui->labPos->setText(tr("X: %1\nY: %2", "X and Y position").arg(QString::number(xpos_d), QString::number(ypos_d)));
|
||||
repaint();
|
||||
}
|
||||
|
||||
void MapLocationDialog::on_cmdChange_clicked()
|
||||
|
@ -121,6 +95,21 @@ void MapLocationDialog::on_cmdDone_clicked()
|
|||
changeMode = false;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x060000
|
||||
void MapLocationDialog::updatePosFromEvent(double x, double y)
|
||||
{
|
||||
QSize mapPixelSize = size();
|
||||
double xpos_ad = x;
|
||||
double ypos_ad = mapPixelSize.height() - y;
|
||||
double xrat = 10000 / (double)mapPixelSize.width();
|
||||
double yrat = 12000 / (double)mapPixelSize.height();
|
||||
double xpos_rv = xrat * xpos_ad;
|
||||
double ypos_rv = yrat * ypos_ad;
|
||||
double xpos_fp = xpos_rv - 4000;
|
||||
double ypos_fp = ypos_rv - 4000;
|
||||
drawPointOnMap(xpos_fp, ypos_fp);
|
||||
}
|
||||
#else
|
||||
void MapLocationDialog::updatePosFromEvent(int x, int y)
|
||||
{
|
||||
QSize mapPixelSize = size();
|
||||
|
@ -134,13 +123,60 @@ void MapLocationDialog::updatePosFromEvent(int x, int y)
|
|||
double ypos_fp = ypos_rv - 4000;
|
||||
drawPointOnMap(xpos_fp, ypos_fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MapLocationDialog::paintEvent(QPaintEvent *ev)
|
||||
{
|
||||
QPainter painter(this);
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
|
||||
// Paint Map
|
||||
QSize mapPixelSize = QSize(width() * screenRatioPR, height() * screenRatioPR);
|
||||
painter.drawPixmap(0, 0, width(), height(), QPixmap(":/img/mappreview.jpg").scaled(mapPixelSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
|
||||
// Paint Marker
|
||||
int pointMarkerSize = 8 * screenRatio;
|
||||
int pointMarkerHalfSize = pointMarkerSize / 2;
|
||||
long xpos_ms = qRound(xpos_new);
|
||||
long ypos_ms = qRound(ypos_new);
|
||||
double xpos_ma = xpos_ms + 4000;
|
||||
double ypos_ma = ypos_ms + 4000;
|
||||
double xrat = (double)width() / 10000;
|
||||
double yrat = (double)height() / 12000;
|
||||
long xpos_mp = qRound(xpos_ma * xrat);
|
||||
long ypos_mp = qRound(ypos_ma * yrat);
|
||||
long xpos_pr;
|
||||
long ypos_pr;
|
||||
if (screenRatioPR != 1) {
|
||||
#ifdef Q_OS_WIN
|
||||
xpos_pr = xpos_mp - pointMarkerHalfSize;
|
||||
ypos_pr = ypos_mp + pointMarkerHalfSize;
|
||||
#else
|
||||
xpos_pr = xpos_mp - pointMarkerHalfSize + screenRatioPR;
|
||||
ypos_pr = ypos_mp + pointMarkerHalfSize - screenRatioPR;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
xpos_pr = xpos_mp - pointMarkerHalfSize;
|
||||
ypos_pr = ypos_mp + pointMarkerHalfSize;
|
||||
}
|
||||
QPixmap mapMarkerPixmap = IconLoader::loadingPointmakerIcon().pixmap(QSize(pointMarkerSize, pointMarkerSize));
|
||||
painter.drawPixmap(xpos_pr, height() - ypos_pr, pointMarkerSize, pointMarkerSize, mapMarkerPixmap);
|
||||
|
||||
QDialog::paintEvent(ev);
|
||||
}
|
||||
|
||||
void MapLocationDialog::mouseMoveEvent(QMouseEvent *ev)
|
||||
{
|
||||
if (!changeMode) { ev->ignore(); }
|
||||
else if (ev->buttons() & Qt::LeftButton)
|
||||
{
|
||||
#if QT_VERSION >= 0x060000
|
||||
updatePosFromEvent(ev->position().x(), ev->position().y());
|
||||
#else
|
||||
updatePosFromEvent(ev->x(), ev->y());
|
||||
#endif
|
||||
ev->accept();
|
||||
}
|
||||
else
|
||||
|
@ -154,7 +190,11 @@ void MapLocationDialog::mouseReleaseEvent(QMouseEvent *ev)
|
|||
if (!changeMode) { ev->ignore(); }
|
||||
else if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
#if QT_VERSION >= 0x060000
|
||||
updatePosFromEvent(ev->position().x(), ev->position().y());
|
||||
#else
|
||||
updatePosFromEvent(ev->x(), ev->y());
|
||||
#endif
|
||||
ev->accept();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
~MapLocationDialog();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *ev);
|
||||
void mouseMoveEvent(QMouseEvent *ev);
|
||||
void mouseReleaseEvent(QMouseEvent *ev);
|
||||
|
||||
|
@ -47,7 +48,11 @@ private slots:
|
|||
void on_cmdApply_clicked();
|
||||
void on_cmdChange_clicked();
|
||||
void on_cmdRevert_clicked();
|
||||
#if QT_VERSION >= 0x060000
|
||||
void updatePosFromEvent(double x, double y);
|
||||
#else
|
||||
void updatePosFromEvent(int x, int y);
|
||||
#endif
|
||||
void on_cmdClose_clicked();
|
||||
|
||||
private:
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
<property name="windowTitle">
|
||||
<string>Snapmatic Map Viewer</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QDialog#MapLocationDialog {
|
||||
background-color: transparent;
|
||||
}</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlMapPreview">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
|
@ -134,6 +139,9 @@ color: rgb(255, 255, 255);
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Close viewer</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
|
@ -160,6 +168,9 @@ color: rgb(255, 255, 255);
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Apply new position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Apply</string>
|
||||
</property>
|
||||
|
@ -173,6 +184,9 @@ color: rgb(255, 255, 255);
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Revert old position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Revert</string>
|
||||
</property>
|
||||
|
@ -186,8 +200,11 @@ color: rgb(255, 255, 255);
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select new position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Set</string>
|
||||
<string>&Select</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
|
@ -199,6 +216,9 @@ color: rgb(255, 255, 255);
|
|||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Quit select position</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Done</string>
|
||||
</property>
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "TranslationClass.h"
|
||||
#include "MessageThread.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonDocument>
|
||||
#include <QEventLoop>
|
||||
#include <QUrlQuery>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
|
||||
MessageThread::MessageThread(uint cacheId, QObject *parent) : QThread(parent), cacheId(cacheId)
|
||||
{
|
||||
threadRunning = true;
|
||||
}
|
||||
|
||||
void MessageThread::run()
|
||||
{
|
||||
QEventLoop threadLoop;
|
||||
|
||||
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
|
||||
|
||||
while (threadRunning) {
|
||||
{
|
||||
#ifdef GTA5SYNC_MOTD_WEBURL
|
||||
QUrl motdWebUrl = QUrl(GTA5SYNC_MOTD_WEBURL);
|
||||
#else
|
||||
QUrl motdWebUrl = QUrl("https://motd.syping.de/gta5view-dev/");
|
||||
#endif
|
||||
QUrlQuery urlQuery(motdWebUrl);
|
||||
urlQuery.addQueryItem("code", GTA5SYNC_BUILDCODE);
|
||||
urlQuery.addQueryItem("cacheid", QString::number(cacheId));
|
||||
urlQuery.addQueryItem("lang", Translator->getCurrentLanguage());
|
||||
urlQuery.addQueryItem("version", GTA5SYNC_APPVER);
|
||||
motdWebUrl.setQuery(urlQuery);
|
||||
|
||||
QNetworkAccessManager *netManager = new QNetworkAccessManager();
|
||||
QNetworkRequest netRequest(motdWebUrl);
|
||||
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
|
||||
QNetworkReply *netReply = netManager->get(netRequest);
|
||||
|
||||
QEventLoop downloadLoop;
|
||||
QObject::connect(netManager, SIGNAL(finished(QNetworkReply*)), &downloadLoop, SLOT(quit()));
|
||||
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
|
||||
QTimer::singleShot(60000, &downloadLoop, SLOT(quit()));
|
||||
downloadLoop.exec();
|
||||
|
||||
if (netReply->isFinished()) {
|
||||
QByteArray jsonContent = netReply->readAll();
|
||||
QString headerData = QString::fromUtf8(netReply->rawHeader("gta5view"));
|
||||
if (!headerData.isEmpty()) {
|
||||
QMap<QString,QString> headerMap;
|
||||
const QStringList headerVarList = headerData.split(';');
|
||||
for (QString headerVar : headerVarList) {
|
||||
QStringList varValueList = headerVar.split('=');
|
||||
if (varValueList.length() >= 2) {
|
||||
const QString variable = varValueList.at(0).trimmed();
|
||||
varValueList.removeFirst();
|
||||
const QString value = varValueList.join('=');
|
||||
headerMap.insert(variable, value);
|
||||
}
|
||||
}
|
||||
if (headerMap.value("update", "false") == "true") {
|
||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonContent);
|
||||
emit messagesArrived(jsonDocument.object());
|
||||
}
|
||||
if (headerMap.contains("cache")) {
|
||||
bool uintOk;
|
||||
uint cacheVal = headerMap.value("cache").toUInt(&uintOk);
|
||||
if (uintOk) {
|
||||
cacheId = cacheVal;
|
||||
emit updateCacheId(cacheId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete netReply;
|
||||
delete netManager;
|
||||
}
|
||||
|
||||
QTimer::singleShot(300000, &threadLoop, SLOT(quit()));
|
||||
threadLoop.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void MessageThread::terminateThread()
|
||||
{
|
||||
threadRunning = false;
|
||||
emit threadTerminated();
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,38 +16,33 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef IMAGEEDITORDIALOG_H
|
||||
#define IMAGEEDITORDIALOG_H
|
||||
#ifndef MESSAGETHREAD_H
|
||||
#define MESSAGETHREAD_H
|
||||
|
||||
#include "SnapmaticPicture.h"
|
||||
#include <QDialog>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
namespace Ui {
|
||||
class ImageEditorDialog;
|
||||
}
|
||||
|
||||
class ImageEditorDialog : public QDialog
|
||||
class MessageThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImageEditorDialog(SnapmaticPicture *picture, QString profileName, QWidget *parent = 0);
|
||||
~ImageEditorDialog();
|
||||
explicit MessageThread(uint cacheId, QObject *parent = 0);
|
||||
|
||||
private slots:
|
||||
void on_cmdClose_clicked();
|
||||
void on_cmdReplace_clicked();
|
||||
void on_cmdSave_clicked();
|
||||
void on_cmdQuestion_clicked();
|
||||
public slots:
|
||||
void terminateThread();
|
||||
|
||||
private:
|
||||
SnapmaticPicture *smpic;
|
||||
QString profileName;
|
||||
Ui::ImageEditorDialog *ui;
|
||||
int snapmaticResolutionLW;
|
||||
int snapmaticResolutionLH;
|
||||
bool imageIsChanged;
|
||||
QImage pictureCache;
|
||||
bool threadRunning;
|
||||
uint cacheId;
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void messagesArrived(const QJsonObject &messageObject);
|
||||
void updateCacheId(uint cacheId);
|
||||
void threadTerminated();
|
||||
};
|
||||
|
||||
#endif // IMAGEEDITORDIALOG_H
|
||||
#endif // MESSAGETHREAD_H
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -24,7 +24,6 @@
|
|||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QDesktopWidget>
|
||||
#include <QJsonDocument>
|
||||
#include <QStyleFactory>
|
||||
#include <QApplication>
|
||||
|
@ -40,6 +39,12 @@
|
|||
#include <QList>
|
||||
#include <QDir>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QScreen>
|
||||
#else
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#endif
|
||||
|
@ -55,11 +60,19 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
|
|||
ui->setupUi(this);
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
ui->labPicCustomRes->setVisible(false);
|
||||
ui->cmdCancel->setDefault(true);
|
||||
ui->cmdCancel->setFocus();
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
QRect desktopResolution = QApplication::primaryScreen()->geometry();
|
||||
int desktopSizeWidth = qRound((double)desktopResolution.width() * screenRatioPR);
|
||||
int desktopSizeHeight = qRound((double)desktopResolution.height() * screenRatioPR);
|
||||
#else
|
||||
QRect desktopResolution = QApplication::desktop()->screenGeometry(this);
|
||||
int desktopSizeWidth = desktopResolution.width();
|
||||
int desktopSizeHeight = desktopResolution.height();
|
||||
#endif
|
||||
aspectRatio = Qt::KeepAspectRatio;
|
||||
defExportSize = QSize(960, 536);
|
||||
cusExportSize = defExportSize;
|
||||
|
@ -102,6 +115,7 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
|
|||
setupInterfaceSettings();
|
||||
setupStatisticsSettings();
|
||||
setupSnapmaticPictureViewer();
|
||||
setupWindowsGameSettings();
|
||||
|
||||
#ifndef Q_QS_ANDROID
|
||||
// DPI calculation
|
||||
|
@ -109,7 +123,7 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
|
|||
resize(435 * screenRatio, 405 * screenRatio);
|
||||
#endif
|
||||
|
||||
this->setWindowTitle(windowTitle().arg(GTA5SYNC_APPSTR));
|
||||
setWindowTitle(windowTitle().arg(GTA5SYNC_APPSTR));
|
||||
}
|
||||
|
||||
OptionsDialog::~OptionsDialog()
|
||||
|
@ -122,24 +136,33 @@ OptionsDialog::~OptionsDialog()
|
|||
|
||||
void OptionsDialog::setupTreeWidget()
|
||||
{
|
||||
for (QString playerIDStr : profileDB->getPlayers())
|
||||
{
|
||||
bool ok;
|
||||
int playerID = playerIDStr.toInt(&ok);
|
||||
if (ok)
|
||||
const QStringList players = profileDB->getPlayers();
|
||||
if (players.length() != 0) {
|
||||
QStringList::const_iterator it = players.constBegin();
|
||||
QStringList::const_iterator end = players.constEnd();
|
||||
while (it != end)
|
||||
{
|
||||
QString playerName = profileDB->getPlayerName(playerID);
|
||||
bool ok;
|
||||
int playerID = it->toInt(&ok);
|
||||
if (ok)
|
||||
{
|
||||
QString playerName = profileDB->getPlayerName(playerID);
|
||||
|
||||
QStringList playerTreeViewList;
|
||||
playerTreeViewList += playerIDStr;
|
||||
playerTreeViewList += playerName;
|
||||
QStringList playerTreeViewList;
|
||||
playerTreeViewList += *it;
|
||||
playerTreeViewList += playerName;
|
||||
|
||||
QTreeWidgetItem *playerItem = new QTreeWidgetItem(playerTreeViewList);
|
||||
ui->twPlayers->addTopLevelItem(playerItem);
|
||||
playerItems += playerItem;
|
||||
QTreeWidgetItem *playerItem = new QTreeWidgetItem(playerTreeViewList);
|
||||
ui->twPlayers->addTopLevelItem(playerItem);
|
||||
playerItems += playerItem;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
ui->twPlayers->sortItems(1, Qt::AscendingOrder);
|
||||
}
|
||||
else {
|
||||
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabPlayers));
|
||||
}
|
||||
ui->twPlayers->sortItems(1, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void OptionsDialog::setupLanguageBox()
|
||||
|
@ -149,9 +172,21 @@ void OptionsDialog::setupLanguageBox()
|
|||
currentAreaLanguage = settings->value("AreaLanguage", "Auto").toString();
|
||||
settings->endGroup();
|
||||
|
||||
QString cbSysStr = tr("%1 (Next Closest Language)", "First language a person can talk with a different person/application. \"Native\" or \"Not Native\".").arg(tr("System",
|
||||
"System in context of System default"));
|
||||
QString cbSysStr = tr("%1 (Language priority)", "First language a person can talk with a different person/application. \"Native\" or \"Not Native\".").arg(tr("System",
|
||||
"System in context of System default"));
|
||||
#ifdef Q_OS_WIN
|
||||
QString cbAutoStr;
|
||||
if (AppEnv::getGameLanguage(AppEnv::getGameVersion()) != GameLanguage::Undefined)
|
||||
{
|
||||
cbAutoStr = tr("%1 (Game language)", "Next closest language compared to the Game settings").arg(tr("Auto", "Automatic language choice."));
|
||||
}
|
||||
else
|
||||
{
|
||||
cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
|
||||
}
|
||||
#else
|
||||
QString cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
|
||||
#endif
|
||||
ui->cbLanguage->addItem(cbSysStr, "System");
|
||||
ui->cbAreaLanguage->addItem(cbAutoStr, "Auto");
|
||||
|
||||
|
@ -266,7 +301,7 @@ void OptionsDialog::setupInterfaceSettings()
|
|||
settings->beginGroup("Startup");
|
||||
bool alwaysUseMessageFont = settings->value("AlwaysUseMessageFont", false).toBool();
|
||||
ui->cbAlwaysUseMessageFont->setChecked(alwaysUseMessageFont);
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
if (QSysInfo::windowsVersion() >= 0x0080)
|
||||
{
|
||||
ui->gbFont->setVisible(false);
|
||||
|
@ -332,10 +367,12 @@ void OptionsDialog::applySettings()
|
|||
settings->setValue("Language", ui->cbLanguage->itemData(ui->cbLanguage->currentIndex()));
|
||||
settings->setValue("AreaLanguage", ui->cbAreaLanguage->itemData(ui->cbAreaLanguage->currentIndex()));
|
||||
#endif
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
settings->setValue("NavigationBar", ui->cbSnapmaticNavigationBar->isChecked());
|
||||
#endif
|
||||
#else
|
||||
settings->setValue("NavigationBar", ui->cbSnapmaticNavigationBar->isChecked());
|
||||
#endif
|
||||
settings->endGroup();
|
||||
|
||||
|
@ -406,10 +443,20 @@ void OptionsDialog::applySettings()
|
|||
#ifdef GTA5SYNC_TELEMETRY
|
||||
settings->beginGroup("Telemetry");
|
||||
settings->setValue("PushAppConf", ui->cbAppConfigStats->isChecked());
|
||||
settings->setValue("PushUsageData", ui->cbUsageData->isChecked());
|
||||
if (!Telemetry->isStateForced()) { settings->setValue("IsEnabled", ui->cbParticipateStats->isChecked()); }
|
||||
settings->endGroup();
|
||||
Telemetry->refresh();
|
||||
Telemetry->work();
|
||||
if (ui->cbUsageData->isChecked() && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "SettingsUpdated";
|
||||
jsonObject["UpdateTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
|
@ -430,6 +477,7 @@ void OptionsDialog::applySettings()
|
|||
Translator->initUserLanguage();
|
||||
}
|
||||
|
||||
settings->sync();
|
||||
emit settingsApplied(newContentMode, languageChanged);
|
||||
|
||||
if ((forceCustomFolder && ui->txtFolder->text() != currentCFolder) || (forceCustomFolder != currentFFolder && forceCustomFolder))
|
||||
|
@ -549,17 +597,10 @@ void OptionsDialog::setupStatisticsSettings()
|
|||
ui->cbParticipateStats->setText(tr("Participate in %1 User Statistics").arg(GTA5SYNC_APPSTR));
|
||||
ui->labUserStats->setText(QString("<a href=\"%2\">%1</a>").arg(tr("View %1 User Statistics Online").arg(GTA5SYNC_APPSTR), TelemetryClass::getWebURL().toString()));
|
||||
|
||||
ui->gbUserFeedback->setVisible(false);
|
||||
// settings->beginGroup("Startup");
|
||||
// if (settings->value("IsFirstStart", true).toBool() == true)
|
||||
// {
|
||||
// ui->gbUserFeedback->setVisible(false);
|
||||
// }
|
||||
// settings->endGroup();
|
||||
|
||||
settings->beginGroup("Telemetry");
|
||||
ui->cbParticipateStats->setChecked(Telemetry->isEnabled());
|
||||
ui->cbAppConfigStats->setChecked(settings->value("PushAppConf", false).toBool());
|
||||
ui->cbUsageData->setChecked(settings->value("PushUsageData", false).toBool());
|
||||
settings->endGroup();
|
||||
|
||||
if (Telemetry->isStateForced())
|
||||
|
@ -581,6 +622,77 @@ void OptionsDialog::setupStatisticsSettings()
|
|||
#endif
|
||||
}
|
||||
|
||||
void OptionsDialog::setupWindowsGameSettings()
|
||||
{
|
||||
#ifdef GTA5SYNC_GAME
|
||||
GameVersion gameVersion = AppEnv::getGameVersion();
|
||||
#ifdef Q_OS_WIN
|
||||
if (gameVersion != GameVersion::NoVersion)
|
||||
{
|
||||
if (gameVersion == GameVersion::SocialClubVersion)
|
||||
{
|
||||
ui->gbSteam->setDisabled(true);
|
||||
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
|
||||
ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No"))));
|
||||
if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined)
|
||||
{
|
||||
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined")));
|
||||
}
|
||||
ui->labSteamLanguage->setVisible(false);
|
||||
}
|
||||
else if (gameVersion == GameVersion::SteamVersion)
|
||||
{
|
||||
ui->gbSocialClub->setDisabled(true);
|
||||
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No"))));
|
||||
ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
|
||||
ui->labSocialClubLanguage->setVisible(false);
|
||||
if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined)
|
||||
{
|
||||
ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined")));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
|
||||
ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
|
||||
if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined)
|
||||
{
|
||||
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined")));
|
||||
}
|
||||
if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined)
|
||||
{
|
||||
ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined")));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
|
||||
}
|
||||
#else
|
||||
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
|
||||
#endif
|
||||
#else
|
||||
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
|
||||
#endif
|
||||
}
|
||||
|
||||
void OptionsDialog::on_cbIgnoreAspectRatio_toggled(bool checked)
|
||||
{
|
||||
if (checked)
|
||||
|
@ -611,18 +723,19 @@ void OptionsDialog::setupCustomGTAFolder()
|
|||
|
||||
void OptionsDialog::setupSnapmaticPictureViewer()
|
||||
{
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
settings->beginGroup("Interface");
|
||||
ui->cbSnapmaticNavigationBar->setChecked(settings->value("NavigationBar", false).toBool());
|
||||
ui->cbSnapmaticNavigationBar->setChecked(settings->value("NavigationBar", true).toBool());
|
||||
settings->endGroup();
|
||||
#else
|
||||
ui->cbSnapmaticNavigationBar->setVisible(false);
|
||||
ui->gbSnapmaticPictureViewer->setVisible(false);
|
||||
#endif
|
||||
#else
|
||||
ui->cbSnapmaticNavigationBar->setVisible(false);
|
||||
ui->gbSnapmaticPictureViewer->setVisible(false);
|
||||
settings->beginGroup("Interface");
|
||||
ui->cbSnapmaticNavigationBar->setChecked(settings->value("NavigationBar", true).toBool());
|
||||
settings->endGroup();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -640,25 +753,6 @@ void OptionsDialog::on_cbDefaultStyle_toggled(bool checked)
|
|||
ui->cbStyleList->setDisabled(checked);
|
||||
}
|
||||
|
||||
void OptionsDialog::on_cmdUserFeedbackSend_clicked()
|
||||
{
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
if (ui->txtUserFeedback->toPlainText().length() < 1024 && ui->txtUserFeedback->toPlainText().length() >= 3)
|
||||
{
|
||||
QJsonDocument feedback;
|
||||
QJsonObject feedbackObject;
|
||||
feedbackObject["Message"] = ui->txtUserFeedback->toPlainText();
|
||||
feedback.setObject(feedbackObject);
|
||||
Telemetry->push(TelemetryCategory::UserFeedback, feedback);
|
||||
ui->txtUserFeedback->setPlainText(QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("User Feedback"), tr("A feedback message have to between 3-1024 characters long"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OptionsDialog::on_cmdCopyStatsID_clicked()
|
||||
{
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
|
|
|
@ -47,7 +47,6 @@ private slots:
|
|||
void on_cbIgnoreAspectRatio_toggled(bool checked);
|
||||
void on_cmdExploreFolder_clicked();
|
||||
void on_cbDefaultStyle_toggled(bool checked);
|
||||
void on_cmdUserFeedbackSend_clicked();
|
||||
void on_cmdCopyStatsID_clicked();
|
||||
|
||||
signals:
|
||||
|
@ -80,6 +79,7 @@ private:
|
|||
void setupInterfaceSettings();
|
||||
void setupStatisticsSettings();
|
||||
void setupSnapmaticPictureViewer();
|
||||
void setupWindowsGameSettings();
|
||||
void applySettings();
|
||||
};
|
||||
|
||||
|
|
155
OptionsDialog.ui
155
OptionsDialog.ui
|
@ -382,6 +382,72 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabGame">
|
||||
<attribute name="title">
|
||||
<string>Game</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="vlGame">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbSocialClub">
|
||||
<property name="title">
|
||||
<string>Social Club Version</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlGameSocialClub">
|
||||
<item>
|
||||
<widget class="QLabel" name="labSocialClubFound">
|
||||
<property name="text">
|
||||
<string>Found: %1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labSocialClubLanguage">
|
||||
<property name="text">
|
||||
<string>Language: %1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbSteam">
|
||||
<property name="title">
|
||||
<string>Steam Version</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlGameSteam">
|
||||
<item>
|
||||
<widget class="QLabel" name="labSteamFound">
|
||||
<property name="text">
|
||||
<string>Found: %1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labSteamLanguage">
|
||||
<property name="text">
|
||||
<string>Language: %1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="vsGame">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabStats">
|
||||
<attribute name="title">
|
||||
<string>Feedback</string>
|
||||
|
@ -420,11 +486,11 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbCategorys">
|
||||
<widget class="QGroupBox" name="gbCategories">
|
||||
<property name="title">
|
||||
<string>Categories</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlCategorys">
|
||||
<layout class="QVBoxLayout" name="vlCategories">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbGeneralStats">
|
||||
<property name="enabled">
|
||||
|
@ -458,6 +524,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbUsageData">
|
||||
<property name="text">
|
||||
<string>Personal Usage Data</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -466,74 +539,32 @@
|
|||
<property name="title">
|
||||
<string>Other</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="hlOtherStats">
|
||||
<layout class="QVBoxLayout" name="vlFeedbackOther">
|
||||
<item>
|
||||
<widget class="QLabel" name="labParticipationID">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Participation ID: %1</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdCopyStatsID">
|
||||
<property name="text">
|
||||
<string>&Copy</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbUserFeedback">
|
||||
<property name="title">
|
||||
<string>User Feedback</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vlUserFeedback">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="txtUserFeedback"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hlUserFeedbackButtons">
|
||||
<layout class="QHBoxLayout" name="hlParticipation">
|
||||
<item>
|
||||
<widget class="QLabel" name="labUserFeedback">
|
||||
<widget class="QLabel" name="labParticipationID">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Limit: 1 message/day</string>
|
||||
<string>Participation ID: %1</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="hsUserFeedbackButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdUserFeedbackSend">
|
||||
<widget class="QPushButton" name="cmdCopyStatsID">
|
||||
<property name="text">
|
||||
<string>&Send</string>
|
||||
<string>&Copy</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,17 +22,22 @@
|
|||
#include "ui_PictureDialog.h"
|
||||
#include "SidebarGenerator.h"
|
||||
#include "MapLocationDialog.h"
|
||||
#include "ImageEditorDialog.h"
|
||||
#include "JsonEditorDialog.h"
|
||||
#include "SnapmaticEditor.h"
|
||||
#include "StandardPaths.h"
|
||||
#include "PictureExport.h"
|
||||
#include "ImportDialog.h"
|
||||
#include "StringParser.h"
|
||||
#include "GlobalString.h"
|
||||
#include "UiModLabel.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#if QT_VERSION < 0x060000
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
#include <QtWinExtras/QtWin>
|
||||
#include <QtWinExtras/QWinEvent>
|
||||
|
@ -40,10 +45,10 @@
|
|||
#endif
|
||||
|
||||
#include <QStringBuilder>
|
||||
#include <QDesktopWidget>
|
||||
#include <QJsonDocument>
|
||||
#include <QApplication>
|
||||
#include <QFontMetrics>
|
||||
#include <QJsonObject>
|
||||
#include <QSizePolicy>
|
||||
#include <QStaticText>
|
||||
#include <QFileDialog>
|
||||
|
@ -66,6 +71,10 @@
|
|||
#include <QUrl>
|
||||
#include <QDir>
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#endif
|
||||
|
||||
// Macros for better Overview + RAM
|
||||
#define locX QString::number(picture->getSnapmaticProperties().location.x)
|
||||
#define locY QString::number(picture->getSnapmaticProperties().location.y)
|
||||
|
@ -75,7 +84,11 @@
|
|||
#define picPath picture->getPictureFilePath()
|
||||
#define picTitl StringParser::escapeString(picture->getPictureTitle())
|
||||
#define plyrsList picture->getSnapmaticProperties().playersList
|
||||
#if QT_VERSION >= 0x060000
|
||||
#define created QLocale().toString(picture->getSnapmaticProperties().createdDateTime, QLocale::ShortFormat)
|
||||
#else
|
||||
#define created picture->getSnapmaticProperties().createdDateTime.toString(Qt::DefaultLocaleShortDate)
|
||||
#endif
|
||||
|
||||
PictureDialog::PictureDialog(ProfileDatabase *profileDB, CrewDatabase *crewDB, QWidget *parent) :
|
||||
QDialog(parent), profileDB(profileDB), crewDB(crewDB),
|
||||
|
@ -129,11 +142,15 @@ void PictureDialog::setupPictureDialog()
|
|||
smpic = nullptr;
|
||||
crewStr = "";
|
||||
|
||||
// Get Snapmatic Resolution
|
||||
QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
|
||||
|
||||
// Avatar area
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
if (screenRatio != 1)
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
if (screenRatio != 1 || screenRatioPR != 1)
|
||||
{
|
||||
avatarAreaPicture = QImage(":/img/avatararea.png").scaledToHeight(536 * screenRatio, Qt::FastTransformation);
|
||||
avatarAreaPicture = QImage(":/img/avatararea.png").scaledToHeight(snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::FastTransformation);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -143,6 +160,11 @@ void PictureDialog::setupPictureDialog()
|
|||
avatarLocY = 66;
|
||||
avatarSize = 470;
|
||||
|
||||
// DPI calculation (picture)
|
||||
ui->labPicture->setFixedSize(snapmaticResolution.width() * screenRatio, snapmaticResolution.height() * screenRatio);
|
||||
ui->labPicture->setFocusPolicy(Qt::StrongFocus);
|
||||
ui->labPicture->setScaledContents(true);
|
||||
|
||||
// Overlay area
|
||||
renderOverlayPicture();
|
||||
overlayEnabled = true;
|
||||
|
@ -178,17 +200,21 @@ void PictureDialog::setupPictureDialog()
|
|||
|
||||
installEventFilter(this);
|
||||
installEventFilter(ui->labPicture);
|
||||
ui->labPicture->setFixedSize(960 * screenRatio, 536 * screenRatio);
|
||||
ui->labPicture->setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
// DPI calculation
|
||||
ui->hlButtons->setSpacing(6 * screenRatio);
|
||||
ui->vlButtons->setSpacing(6 * screenRatio);
|
||||
ui->vlButtons->setContentsMargins(0, 0, 5 * screenRatio, 5 * screenRatio);
|
||||
ui->jsonLayout->setContentsMargins(4 * screenRatio, 10 * screenRatio, 4 * screenRatio, 4 * screenRatio);
|
||||
|
||||
// Pre-adapt window for DPI
|
||||
setFixedWidth(960 * screenRatio);
|
||||
setFixedHeight(536 * screenRatio);
|
||||
setFixedWidth(snapmaticResolution.width() * screenRatio);
|
||||
setFixedHeight(snapmaticResolution.height() * screenRatio);
|
||||
}
|
||||
|
||||
PictureDialog::~PictureDialog()
|
||||
{
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
if (naviEnabled)
|
||||
{
|
||||
|
@ -199,6 +225,15 @@ PictureDialog::~PictureDialog()
|
|||
delete layout()->menuBar();
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (naviEnabled)
|
||||
{
|
||||
for (QObject *obj : layout()->menuBar()->children())
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
delete layout()->menuBar();
|
||||
}
|
||||
#endif
|
||||
for (QObject *obj : manageMenu->children())
|
||||
{
|
||||
|
@ -219,139 +254,42 @@ void PictureDialog::closeEvent(QCloseEvent *ev)
|
|||
|
||||
void PictureDialog::addPreviousNextButtons()
|
||||
{
|
||||
// Windows Vista additions
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
QToolBar *uiToolbar = new QToolBar("Picture Toolbar", this);
|
||||
uiToolbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
uiToolbar->setObjectName("uiToolbar");
|
||||
uiToolbar->addAction(QIcon(":/img/back.png"), "", this, SLOT(previousPictureRequestedSlot()));
|
||||
uiToolbar->addAction(QIcon(":/img/next.png"), "", this, SLOT(nextPictureRequestedSlot()));
|
||||
uiToolbar->setObjectName("UiToolbar");
|
||||
uiToolbar->addAction(QIcon(":/img/back.svgz"), "", this, SLOT(previousPictureRequestedSlot()));
|
||||
uiToolbar->addAction(QIcon(":/img/next.svgz"), "", this, SLOT(nextPictureRequestedSlot()));
|
||||
layout()->setMenuBar(uiToolbar);
|
||||
|
||||
naviEnabled = true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
#ifdef GTA5SYNC_APV
|
||||
bool PictureDialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
*result = 0;
|
||||
MSG *msg = static_cast<MSG*>(message);
|
||||
LRESULT lRet = 0;
|
||||
|
||||
if (naviEnabled && QtWin::isCompositionEnabled())
|
||||
{
|
||||
if (msg->message == WM_NCCALCSIZE && msg->wParam == TRUE)
|
||||
{
|
||||
NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(msg->lParam);
|
||||
|
||||
int sideBorderSize = ((frameSize().width() - size().width()) / 2);
|
||||
#ifdef GTA5SYNC_APV_SIDE
|
||||
int buttomBorderSize = sideBorderSize;
|
||||
#else
|
||||
int buttomBorderSize = (frameSize().height() - size().height());
|
||||
QToolBar *uiToolbar = new QToolBar("Picture Toolbar", this);
|
||||
#if QT_VERSION < 0x050600
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
if (screenRatio != 1) {
|
||||
QSize iconSize = uiToolbar->iconSize();
|
||||
uiToolbar->setIconSize(QSize(iconSize.width() * screenRatio, iconSize.height() * screenRatio));
|
||||
}
|
||||
#endif
|
||||
uiToolbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
uiToolbar->setObjectName("UiToolbar");
|
||||
uiToolbar->addAction(QIcon(":/img/back.svgz"), "", this, SLOT(previousPictureRequestedSlot()));
|
||||
uiToolbar->addAction(QIcon(":/img/next.svgz"), "", this, SLOT(nextPictureRequestedSlot()));
|
||||
layout()->setMenuBar(uiToolbar);
|
||||
naviEnabled = true;
|
||||
#endif
|
||||
pncsp->rgrc[0].left += sideBorderSize;
|
||||
pncsp->rgrc[0].right -= sideBorderSize;
|
||||
pncsp->rgrc[0].bottom -= buttomBorderSize;
|
||||
}
|
||||
else if (msg->message == WM_NCHITTEST)
|
||||
{
|
||||
int CLOSE_BUTTON_ID = 20;
|
||||
lRet = HitTestNCA(msg->hwnd, msg->lParam);
|
||||
DwmDefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam, &lRet);
|
||||
*result = lRet;
|
||||
if (lRet != CLOSE_BUTTON_ID) { return QWidget::nativeEvent(eventType, message, result); }
|
||||
}
|
||||
else
|
||||
{
|
||||
return QWidget::nativeEvent(eventType, message, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QWidget::nativeEvent(eventType, message, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LRESULT PictureDialog::HitTestNCA(HWND hWnd, LPARAM lParam)
|
||||
{
|
||||
int LEFTEXTENDWIDTH = 0;
|
||||
int RIGHTEXTENDWIDTH = 0;
|
||||
int BOTTOMEXTENDWIDTH = 0;
|
||||
int TOPEXTENDWIDTH = layout()->menuBar()->height();
|
||||
|
||||
POINT ptMouse = {(int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)};
|
||||
|
||||
RECT rcWindow;
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
|
||||
RECT rcFrame = {};
|
||||
AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
|
||||
|
||||
USHORT uRow = 1;
|
||||
USHORT uCol = 1;
|
||||
bool fOnResizeBorder = false;
|
||||
|
||||
if (ptMouse.y >= rcWindow.top && ptMouse.y < rcWindow.top + TOPEXTENDWIDTH)
|
||||
{
|
||||
fOnResizeBorder = (ptMouse.y < (rcWindow.top - rcFrame.top));
|
||||
uRow = 0;
|
||||
}
|
||||
else if (ptMouse.y < rcWindow.bottom && ptMouse.y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
|
||||
{
|
||||
uRow = 2;
|
||||
}
|
||||
|
||||
if (ptMouse.x >= rcWindow.left && ptMouse.x < rcWindow.left + LEFTEXTENDWIDTH)
|
||||
{
|
||||
uCol = 0;
|
||||
}
|
||||
else if (ptMouse.x < rcWindow.right && ptMouse.x >= rcWindow.right - RIGHTEXTENDWIDTH)
|
||||
{
|
||||
uCol = 2;
|
||||
}
|
||||
|
||||
LRESULT hitTests[3][3] =
|
||||
{
|
||||
{ HTTOPLEFT, fOnResizeBorder ? HTTOP : HTCAPTION, HTTOPRIGHT },
|
||||
{ HTLEFT, HTNOWHERE, HTRIGHT },
|
||||
{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
|
||||
};
|
||||
|
||||
return hitTests[uRow][uCol];
|
||||
}
|
||||
|
||||
void PictureDialog::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
// int newDialogHeight = ui->labPicture->pixmap()->height();
|
||||
// newDialogHeight = newDialogHeight + ui->jsonFrame->height();
|
||||
// if (naviEnabled) newDialogHeight = newDialogHeight + layout()->menuBar()->height();
|
||||
// int buttomBorderSize = (frameSize().height() - size().height());
|
||||
// int sideBorderSize = ((frameSize().width() - size().width()) / 2);
|
||||
// int brokenDialogHeight = newDialogHeight + (buttomBorderSize - sideBorderSize);
|
||||
// if (event->size().height() == brokenDialogHeight)
|
||||
// {
|
||||
// qDebug() << "BROKEN 1";
|
||||
// setGeometry(geometry().x(), geometry().y(), width(), newDialogHeight);
|
||||
// qDebug() << "BROKEN 2";
|
||||
// event->ignore();
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void PictureDialog::adaptNewDialogSize(QSize newLabelSize)
|
||||
{
|
||||
Q_UNUSED(newLabelSize)
|
||||
int newDialogHeight = ui->labPicture->pixmap()->height();
|
||||
#if QT_VERSION >= 0x050F00
|
||||
int newDialogHeight = SnapmaticPicture::getSnapmaticResolution().height();
|
||||
#else
|
||||
int newDialogHeight = (ui->labPicture->pixmap()->height() / AppEnv::screenRatioPR());
|
||||
#endif
|
||||
newDialogHeight = newDialogHeight + ui->jsonFrame->height();
|
||||
if (naviEnabled) newDialogHeight = newDialogHeight + layout()->menuBar()->height();
|
||||
setMaximumSize(width(), newDialogHeight);
|
||||
|
@ -362,14 +300,14 @@ void PictureDialog::adaptNewDialogSize(QSize newLabelSize)
|
|||
updateGeometry();
|
||||
}
|
||||
|
||||
void PictureDialog::stylizeDialog()
|
||||
void PictureDialog::styliseDialog()
|
||||
{
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
if (QtWin::isCompositionEnabled())
|
||||
{
|
||||
QPalette palette;
|
||||
QtWin::extendFrameIntoClientArea(this, 0, this->layout()->menuBar()->height(), 0, 0);
|
||||
QtWin::extendFrameIntoClientArea(this, 0, qRound(layout()->menuBar()->height() * AppEnv::screenRatioPR()), 0, 0);
|
||||
ui->jsonFrame->setStyleSheet(QString("QFrame { background: %1; }").arg(palette.window().color().name()));
|
||||
setStyleSheet("PictureDialog { background: transparent; }");
|
||||
}
|
||||
|
@ -386,13 +324,13 @@ void PictureDialog::stylizeDialog()
|
|||
|
||||
bool PictureDialog::event(QEvent *event)
|
||||
{
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
if (naviEnabled)
|
||||
{
|
||||
if (event->type() == QWinEvent::CompositionChange || event->type() == QWinEvent::ColorizationChange)
|
||||
{
|
||||
stylizeDialog();
|
||||
styliseDialog();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -471,7 +409,7 @@ bool PictureDialog::eventFilter(QObject *obj, QEvent *ev)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
if (obj != ui->labPicture && naviEnabled)
|
||||
{
|
||||
|
@ -553,24 +491,25 @@ void PictureDialog::renderOverlayPicture()
|
|||
{
|
||||
// Generating Overlay Preview
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
QRect preferedRect = QRect(0, 0, 200 * screenRatio, 160 * screenRatio);
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
QRect preferedRect = QRect(0, 0, 200 * screenRatio * screenRatioPR, 160 * screenRatio * screenRatioPR);
|
||||
QString overlayText = tr("Key 1 - Avatar Preview Mode\nKey 2 - Toggle Overlay\nArrow Keys - Navigate");
|
||||
|
||||
QFont overlayPainterFont;
|
||||
overlayPainterFont.setPixelSize(12 * screenRatio);
|
||||
overlayPainterFont.setPixelSize(12 * screenRatio * screenRatioPR);
|
||||
QFontMetrics fontMetrics(overlayPainterFont);
|
||||
QRect overlaySpace = fontMetrics.boundingRect(preferedRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip | Qt::TextWordWrap, overlayText);
|
||||
|
||||
int hOverlay = Qt::AlignTop;
|
||||
if (overlaySpace.height() < 74 * screenRatio)
|
||||
if (overlaySpace.height() < 74 * screenRatio * screenRatioPR)
|
||||
{
|
||||
hOverlay = Qt::AlignVCenter;
|
||||
preferedRect.setHeight(71 * screenRatio);
|
||||
overlaySpace.setHeight(80 * screenRatio);
|
||||
preferedRect.setHeight(71 * screenRatio * screenRatioPR);
|
||||
overlaySpace.setHeight(80 * screenRatio * screenRatioPR);
|
||||
}
|
||||
else
|
||||
{
|
||||
overlaySpace.setHeight(overlaySpace.height() + 6 * screenRatio);
|
||||
overlaySpace.setHeight(overlaySpace.height() + 6 * screenRatio * screenRatioPR);
|
||||
}
|
||||
|
||||
QImage overlayImage(overlaySpace.size(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -582,13 +521,13 @@ void PictureDialog::renderOverlayPicture()
|
|||
overlayPainter.drawText(preferedRect, Qt::AlignLeft | hOverlay | Qt::TextDontClip | Qt::TextWordWrap, overlayText);
|
||||
overlayPainter.end();
|
||||
|
||||
if (overlaySpace.width() < 194 * screenRatio)
|
||||
if (overlaySpace.width() < 194 * screenRatio * screenRatioPR)
|
||||
{
|
||||
overlaySpace.setWidth(200 * screenRatio);
|
||||
overlaySpace.setWidth(200 * screenRatio * screenRatioPR);
|
||||
}
|
||||
else
|
||||
{
|
||||
overlaySpace.setWidth(overlaySpace.width() + 6 * screenRatio);
|
||||
overlaySpace.setWidth(overlaySpace.width() + 6 * screenRatio * screenRatioPR);
|
||||
}
|
||||
|
||||
QImage overlayBorderImage(overlaySpace.width(), overlaySpace.height(), QImage::Format_ARGB6666_Premultiplied);
|
||||
|
@ -598,7 +537,7 @@ void PictureDialog::renderOverlayPicture()
|
|||
overlayTempImage.fill(Qt::transparent);
|
||||
QPainter overlayTempPainter(&overlayTempImage);
|
||||
overlayTempPainter.drawImage(0, 0, overlayBorderImage);
|
||||
overlayTempPainter.drawImage(3 * screenRatio, 3 * screenRatio, overlayImage);
|
||||
overlayTempPainter.drawImage(3 * screenRatio * screenRatioPR, 3 * screenRatio * screenRatioPR, overlayImage);
|
||||
overlayTempPainter.end();
|
||||
}
|
||||
|
||||
|
@ -671,63 +610,54 @@ void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture)
|
|||
void PictureDialog::renderPicture()
|
||||
{
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
if (!previewMode)
|
||||
{
|
||||
if (overlayEnabled)
|
||||
{
|
||||
QPixmap shownImagePixmap(960 * screenRatio, 536 * screenRatio);
|
||||
QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
|
||||
QPixmap shownImagePixmap(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR);
|
||||
shownImagePixmap.fill(Qt::transparent);
|
||||
QPainter shownImagePainter(&shownImagePixmap);
|
||||
if (screenRatio == 1)
|
||||
{
|
||||
shownImagePainter.drawImage(0, 0, snapmaticPicture);
|
||||
shownImagePainter.drawImage(3 * screenRatio, 3 * screenRatio, overlayTempImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
shownImagePainter.drawImage(0, 0, snapmaticPicture.scaledToHeight(536 * screenRatio, Qt::SmoothTransformation));
|
||||
shownImagePainter.drawImage(3 * screenRatio, 3 * screenRatio, overlayTempImage);
|
||||
}
|
||||
shownImagePainter.drawImage(0, 0, snapmaticPicture.scaled(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
shownImagePainter.drawImage(3 * screenRatio * screenRatioPR, 3 * screenRatio * screenRatioPR, overlayTempImage);
|
||||
shownImagePainter.end();
|
||||
#if QT_VERSION >= 0x050600
|
||||
shownImagePixmap.setDevicePixelRatio(screenRatioPR);
|
||||
#endif
|
||||
ui->labPicture->setPixmap(shownImagePixmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (screenRatio != 1)
|
||||
{
|
||||
QPixmap shownImagePixmap(960 * screenRatio, 536 * screenRatio);
|
||||
shownImagePixmap.fill(Qt::transparent);
|
||||
QPainter shownImagePainter(&shownImagePixmap);
|
||||
shownImagePainter.drawImage(0, 0, snapmaticPicture.scaledToHeight(536 * screenRatio, Qt::SmoothTransformation));
|
||||
shownImagePainter.end();
|
||||
ui->labPicture->setPixmap(shownImagePixmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labPicture->setPixmap(QPixmap::fromImage(snapmaticPicture));
|
||||
}
|
||||
QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
|
||||
QPixmap shownImagePixmap(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR);
|
||||
shownImagePixmap.fill(Qt::transparent);
|
||||
QPainter shownImagePainter(&shownImagePixmap);
|
||||
shownImagePainter.drawImage(0, 0, snapmaticPicture.scaled(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
shownImagePainter.end();
|
||||
#if QT_VERSION >= 0x050600
|
||||
shownImagePixmap.setDevicePixelRatio(screenRatioPR);
|
||||
#endif
|
||||
ui->labPicture->setPixmap(shownImagePixmap);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generating Avatar Preview
|
||||
QPixmap avatarPixmap(960 * screenRatio, 536 * screenRatio);
|
||||
QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
|
||||
QPixmap avatarPixmap(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR);
|
||||
QPainter snapPainter(&avatarPixmap);
|
||||
QFont snapPainterFont;
|
||||
snapPainterFont.setPixelSize(12 * screenRatio);
|
||||
if (screenRatio == 1)
|
||||
{
|
||||
snapPainter.drawImage(0, 0, snapmaticPicture);
|
||||
}
|
||||
else
|
||||
{
|
||||
snapPainter.drawImage(0, 0, snapmaticPicture.scaledToHeight(536 * screenRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
snapPainterFont.setPixelSize(12 * screenRatio * screenRatioPR);
|
||||
snapPainter.drawImage(0, 0, snapmaticPicture.scaled(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
snapPainter.drawImage(0, 0, avatarAreaPicture);
|
||||
snapPainter.setPen(QColor::fromRgb(255, 255, 255, 255));
|
||||
snapPainter.setFont(snapPainterFont);
|
||||
snapPainter.drawText(QRect(3 * screenRatio, 3 * screenRatio, 140 * screenRatio, 536 * screenRatio), Qt::AlignLeft | Qt::TextWordWrap, tr("Avatar Preview Mode\nPress 1 for Default View"));
|
||||
snapPainter.drawText(QRect(3 * screenRatio * screenRatioPR, 3 * screenRatio * screenRatioPR, 140 * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR), Qt::AlignLeft | Qt::TextWordWrap, tr("Avatar Preview Mode\nPress 1 for Default View"));
|
||||
snapPainter.end();
|
||||
#if QT_VERSION >= 0x050600
|
||||
avatarPixmap.setDevicePixelRatio(screenRatioPR);
|
||||
#endif
|
||||
ui->labPicture->setPixmap(avatarPixmap);
|
||||
}
|
||||
}
|
||||
|
@ -755,10 +685,15 @@ void PictureDialog::playerNameUpdated()
|
|||
QString PictureDialog::generateCrewString()
|
||||
{
|
||||
SnapmaticPicture *picture = smpic; // used by macro
|
||||
QString crewIDStr = crewID; // save operation time
|
||||
const QString crewIDStr = crewID; // save operation time
|
||||
if (crewIDStr != "0" && !crewIDStr.isEmpty())
|
||||
{
|
||||
return QString("<a href=\"https://socialclub.rockstargames.com/crew/" % QString(crewStr).replace(" ", "_") % "/" % crewIDStr % "\">" % crewStr % "</a>");
|
||||
if (crewIDStr != crewStr) {
|
||||
return QString("<a href=\"https://socialclub.rockstargames.com/crew/" % QString(crewStr).replace(" ", "_") % "/" % crewIDStr % "\">" % crewStr % "</a>");
|
||||
}
|
||||
else {
|
||||
return QString(crewIDStr);
|
||||
}
|
||||
}
|
||||
return tr("No Crew");
|
||||
}
|
||||
|
@ -770,11 +705,15 @@ QString PictureDialog::generatePlayersString()
|
|||
QString plyrsStr;
|
||||
if (playersList.length() >= 1)
|
||||
{
|
||||
for (QString player : playersList)
|
||||
for (const QString &player : playersList)
|
||||
{
|
||||
QString playerName;
|
||||
playerName = profileDB->getPlayerName(player);
|
||||
plyrsStr += ", <a href=\"https://socialclub.rockstargames.com/member/" % playerName % "/" % player % "\">" % playerName % "</a>";
|
||||
const QString playerName = profileDB->getPlayerName(player);
|
||||
if (player != playerName) {
|
||||
plyrsStr += ", <a href=\"https://socialclub.rockstargames.com/member/" % playerName % "/" % player % "\">" % playerName % "</a>";
|
||||
}
|
||||
else {
|
||||
plyrsStr += ", " % player;
|
||||
}
|
||||
}
|
||||
plyrsStr.remove(0, 2);
|
||||
}
|
||||
|
@ -813,13 +752,17 @@ void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button)
|
|||
{
|
||||
if (button == Qt::LeftButton)
|
||||
{
|
||||
#if QT_VERSION >= 0x060000
|
||||
QRect desktopRect = QApplication::screenAt(pos())->geometry();
|
||||
#else
|
||||
QRect desktopRect = QApplication::desktop()->screenGeometry(this);
|
||||
#endif
|
||||
PictureWidget *pictureWidget = new PictureWidget(this); // Work!
|
||||
pictureWidget->setObjectName("PictureWidget");
|
||||
#if QT_VERSION >= 0x050600
|
||||
pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint^Qt::WindowStaysOnTopHint^Qt::MaximizeUsingFullscreenGeometryHint);
|
||||
pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint^Qt::MaximizeUsingFullscreenGeometryHint);
|
||||
#else
|
||||
pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint^Qt::WindowStaysOnTopHint);
|
||||
pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint);
|
||||
#endif
|
||||
pictureWidget->setWindowTitle(windowTitle());
|
||||
pictureWidget->setStyleSheet("QLabel#pictureLabel{background-color: black;}");
|
||||
|
@ -833,7 +776,7 @@ void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button)
|
|||
|
||||
pictureWidget->move(desktopRect.x(), desktopRect.y());
|
||||
pictureWidget->resize(desktopRect.width(), desktopRect.height());
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
QtWin::markFullscreenWindow(pictureWidget, true);
|
||||
#endif
|
||||
|
@ -909,6 +852,23 @@ void PictureDialog::openPreviewMap()
|
|||
else
|
||||
{
|
||||
updated();
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "LocationEdited";
|
||||
jsonObject["ExtraFlags"] = "Viewer";
|
||||
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
|
||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
delete mapLocDialog;
|
||||
|
@ -940,25 +900,66 @@ void PictureDialog::editSnapmaticProperties()
|
|||
|
||||
void PictureDialog::editSnapmaticImage()
|
||||
{
|
||||
SnapmaticPicture *picture = smpic;
|
||||
ImageEditorDialog *imageEditor;
|
||||
QImage *currentImage = new QImage(smpic->getImage());
|
||||
ImportDialog *importDialog;
|
||||
if (rqFullscreen && fullscreenWidget != nullptr)
|
||||
{
|
||||
imageEditor = new ImageEditorDialog(picture, profileName, fullscreenWidget);
|
||||
importDialog = new ImportDialog(profileName, fullscreenWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
imageEditor = new ImageEditorDialog(picture, profileName, this);
|
||||
importDialog = new ImportDialog(profileName, this);
|
||||
}
|
||||
imageEditor->setWindowIcon(windowIcon());
|
||||
imageEditor->setModal(true);
|
||||
#ifndef Q_OS_ANDROID
|
||||
imageEditor->show();
|
||||
#else
|
||||
snapmaticEditor->showMaximized();
|
||||
importDialog->setWindowIcon(windowIcon());
|
||||
importDialog->setImage(currentImage);
|
||||
importDialog->enableOverwriteMode();
|
||||
importDialog->setModal(true);
|
||||
importDialog->exec();
|
||||
if (importDialog->isImportAgreed())
|
||||
{
|
||||
const QByteArray previousPicture = smpic->getPictureStream();
|
||||
bool success = smpic->setImage(importDialog->image());
|
||||
if (success)
|
||||
{
|
||||
QString currentFilePath = smpic->getPictureFilePath();
|
||||
QString originalFilePath = smpic->getOriginalPictureFilePath();
|
||||
QString backupFileName = originalFilePath % ".bak";
|
||||
if (!QFile::exists(backupFileName))
|
||||
{
|
||||
QFile::copy(currentFilePath, backupFileName);
|
||||
}
|
||||
if (!smpic->exportPicture(currentFilePath))
|
||||
{
|
||||
smpic->setPictureStream(previousPicture);
|
||||
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of I/O Error"));
|
||||
return;
|
||||
}
|
||||
smpic->emitCustomSignal("PictureUpdated");
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "ImageEdited";
|
||||
jsonObject["ExtraFlags"] = "Viewer";
|
||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
imageEditor->exec();
|
||||
delete imageEditor;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
delete importDialog;
|
||||
}
|
||||
|
||||
void PictureDialog::editSnapmaticRawJson()
|
||||
|
|
|
@ -29,14 +29,6 @@
|
|||
#include <QEvent>
|
||||
#include <QMenu>
|
||||
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
#ifdef GTA5SYNC_APV
|
||||
#include <dwmapi.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Ui {
|
||||
class PictureDialog;
|
||||
}
|
||||
|
@ -56,7 +48,7 @@ public:
|
|||
void setSnapmaticPicture(SnapmaticPicture *picture, int index);
|
||||
void setSnapmaticPicture(SnapmaticPicture *picture);
|
||||
void addPreviousNextButtons();
|
||||
void stylizeDialog();
|
||||
void styliseDialog();
|
||||
bool isIndexed();
|
||||
int getIndex();
|
||||
~PictureDialog();
|
||||
|
@ -98,15 +90,6 @@ protected:
|
|||
bool eventFilter(QObject *obj, QEvent *ev);
|
||||
void mousePressEvent(QMouseEvent *ev);
|
||||
bool event(QEvent *event);
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
#ifdef GTA5SYNC_APV
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
LRESULT HitTestNCA(HWND hWnd, LPARAM lParam);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
QString generateCrewString();
|
||||
|
@ -136,7 +119,7 @@ private:
|
|||
int avatarLocY;
|
||||
int avatarSize;
|
||||
QMenu *manageMenu;
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050200
|
||||
QPoint dragPosition;
|
||||
bool dragStart;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,21 +17,25 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "AppEnv.h"
|
||||
#include "PictureExport.h"
|
||||
#include "PictureDialog.h"
|
||||
#include "StandardPaths.h"
|
||||
#include "SidebarGenerator.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QDesktopWidget>
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QSettings>
|
||||
#include <QRegExp>
|
||||
#include <QDebug>
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QSaveFile>
|
||||
#include <QScreen>
|
||||
#endif
|
||||
|
||||
PictureExport::PictureExport()
|
||||
|
@ -157,8 +161,17 @@ fileDialogPreSave: //Work?
|
|||
QImage exportPicture = picture->getImage();
|
||||
if (sizeMode == "Desktop")
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
QRect desktopResolution = QApplication::primaryScreen()->geometry();
|
||||
int desktopSizeWidth = qRound((double)desktopResolution.width() * screenRatioPR);
|
||||
int desktopSizeHeight = qRound((double)desktopResolution.height() * screenRatioPR);
|
||||
#else
|
||||
QRect desktopResolution = QApplication::desktop()->screenGeometry();
|
||||
exportPicture = exportPicture.scaled(desktopResolution.width(), desktopResolution.height(), aspectRatio, Qt::SmoothTransformation);
|
||||
int desktopSizeWidth = desktopResolution.width();
|
||||
int desktopSizeHeight = desktopResolution.height();
|
||||
#endif
|
||||
exportPicture = exportPicture.scaled(desktopSizeWidth, desktopSizeHeight, aspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
else if (sizeMode == "Custom")
|
||||
{
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "PictureDialog.h"
|
||||
#include "PictureWidget.h"
|
||||
#include "UiModLabel.h"
|
||||
#include <QDesktopWidget>
|
||||
#include <QApplication>
|
||||
#include <QHBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
|
@ -27,6 +26,10 @@
|
|||
#include <QEvent>
|
||||
#include <QDebug>
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
installEventFilter(this);
|
||||
|
@ -44,7 +47,9 @@ PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent)
|
|||
|
||||
QObject::connect(pictureLabel, SIGNAL(mouseDoubleClicked(Qt::MouseButton)), this, SLOT(pictureDoubleClicked(Qt::MouseButton)));
|
||||
QObject::connect(pictureLabel, SIGNAL(customContextMenuRequested(QPoint)), parent, SLOT(exportCustomContextMenuRequested(QPoint)));
|
||||
#if QT_VERSION < 0x060000
|
||||
QObject::connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(updateWindowSize(int)));
|
||||
#endif
|
||||
|
||||
setLayout(widgetLayout);
|
||||
}
|
||||
|
@ -98,12 +103,21 @@ void PictureWidget::setImage(QImage image_)
|
|||
|
||||
void PictureWidget::updateWindowSize(int screenID)
|
||||
{
|
||||
#if QT_VERSION >= 0x060000
|
||||
Q_UNUSED(screenID)
|
||||
QRect desktopRect = QApplication::screenAt(pos())->geometry();
|
||||
move(desktopRect.x(), desktopRect.y());
|
||||
resize(desktopRect.width(), desktopRect.height());
|
||||
showFullScreen();
|
||||
pictureLabel->setPixmap(QPixmap::fromImage(image.scaled(desktopRect.width(), desktopRect.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
|
||||
#else
|
||||
if (screenID == QApplication::desktop()->screenNumber(this))
|
||||
{
|
||||
QRect desktopRect = QApplication::desktop()->screenGeometry(this);
|
||||
this->move(desktopRect.x(), desktopRect.y());
|
||||
this->resize(desktopRect.width(), desktopRect.height());
|
||||
this->showFullScreen();
|
||||
move(desktopRect.x(), desktopRect.y());
|
||||
resize(desktopRect.width(), desktopRect.height());
|
||||
showFullScreen();
|
||||
pictureLabel->setPixmap(QPixmap::fromImage(image.scaled(desktopRect.width(), desktopRect.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -35,6 +35,7 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
|
|||
|
||||
listUpdated = false;
|
||||
ui->setupUi(this);
|
||||
ui->cmdCancel->setDefault(true);
|
||||
ui->cmdCancel->setFocus();
|
||||
|
||||
// Set Icon for Apply Button
|
||||
|
@ -72,13 +73,35 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
|
|||
// Set Icon for Manage Buttons
|
||||
if (QIcon::hasThemeIcon("go-previous") && QIcon::hasThemeIcon("go-next") && QIcon::hasThemeIcon("list-add"))
|
||||
{
|
||||
#if QT_VERSION < 0x050600
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
if (screenRatio != 1) {
|
||||
QSize iconSize = ui->cmdMakeAv->iconSize();
|
||||
iconSize = QSize(iconSize.width() * screenRatio, iconSize.height() * screenRatio);
|
||||
ui->cmdMakeAv->setIconSize(iconSize);
|
||||
ui->cmdMakeSe->setIconSize(iconSize);
|
||||
ui->cmdMakeAd->setIconSize(iconSize);
|
||||
}
|
||||
#endif
|
||||
ui->cmdMakeAv->setIcon(QIcon::fromTheme("go-previous"));
|
||||
ui->cmdMakeSe->setIcon(QIcon::fromTheme("go-next"));
|
||||
ui->cmdMakeAd->setIcon(QIcon::fromTheme("list-add"));
|
||||
}
|
||||
else
|
||||
{
|
||||
drawSwitchButtons();
|
||||
#if QT_VERSION < 0x050600
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
if (screenRatio != 1) {
|
||||
QSize iconSize = ui->cmdMakeAv->iconSize();
|
||||
iconSize = QSize(iconSize.width() * screenRatio, iconSize.height() * screenRatio);
|
||||
ui->cmdMakeAv->setIconSize(iconSize);
|
||||
ui->cmdMakeSe->setIconSize(iconSize);
|
||||
ui->cmdMakeAd->setIconSize(iconSize);
|
||||
}
|
||||
#endif
|
||||
ui->cmdMakeAv->setIcon(QIcon(":/img/back.svgz"));
|
||||
ui->cmdMakeSe->setIcon(QIcon(":/img/next.svgz"));
|
||||
ui->cmdMakeAd->setIcon(QIcon(":/img/add.svgz"));
|
||||
}
|
||||
buildInterface();
|
||||
|
||||
|
@ -100,79 +123,6 @@ PlayerListDialog::~PlayerListDialog()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void PlayerListDialog::drawSwitchButtons()
|
||||
{
|
||||
QFont painterFont = ui->cmdApply->font();
|
||||
QPalette palette;
|
||||
|
||||
QFontMetrics fontMetrics(painterFont);
|
||||
QRect makeAvRect = fontMetrics.boundingRect(QRect(0, 0, 0, 0), Qt::AlignCenter | Qt::TextDontClip, "<");
|
||||
QRect makeSeRect = fontMetrics.boundingRect(QRect(0, 0, 0, 0), Qt::AlignCenter | Qt::TextDontClip, ">");
|
||||
QRect makeAdRect = fontMetrics.boundingRect(QRect(0, 0, 0, 0), Qt::AlignCenter | Qt::TextDontClip, "+");
|
||||
|
||||
int makeAvSize;
|
||||
if (makeAvRect.height() > makeAvRect.width())
|
||||
{
|
||||
makeAvSize = makeAvRect.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAvSize = makeAvRect.width();
|
||||
}
|
||||
int makeSeSize;
|
||||
if (makeSeRect.height() > makeSeRect.width())
|
||||
{
|
||||
makeSeSize = makeSeRect.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
makeSeSize = makeSeRect.width();
|
||||
}
|
||||
int makeAdSize;
|
||||
if (makeAdRect.height() > makeAdRect.width())
|
||||
{
|
||||
makeAdSize = makeAdRect.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAdSize = makeAdRect.width();
|
||||
}
|
||||
|
||||
QImage avImage(makeAvSize, makeAvSize, QImage::Format_ARGB32_Premultiplied);
|
||||
avImage.fill(Qt::transparent);
|
||||
QImage seImage(makeSeSize, makeSeSize, QImage::Format_ARGB32_Premultiplied);
|
||||
seImage.fill(Qt::transparent);
|
||||
QImage adImage(makeAdSize, makeAdSize, QImage::Format_ARGB32_Premultiplied);
|
||||
adImage.fill(Qt::transparent);
|
||||
|
||||
QPainter avPainter(&avImage);
|
||||
avPainter.setFont(painterFont);
|
||||
avPainter.setBrush(palette.buttonText());
|
||||
avPainter.setPen(palette.buttonText().color());
|
||||
avPainter.drawText(0, 0, makeAvSize, makeAvSize, Qt::AlignCenter | Qt::TextDontClip, "<");
|
||||
avPainter.end();
|
||||
QPainter sePainter(&seImage);
|
||||
sePainter.setFont(painterFont);
|
||||
sePainter.setBrush(palette.buttonText());
|
||||
sePainter.setPen(palette.buttonText().color());
|
||||
sePainter.drawText(0, 0, makeSeSize, makeSeSize, Qt::AlignCenter | Qt::TextDontClip, ">");
|
||||
sePainter.end();
|
||||
QPainter adPainter(&adImage);
|
||||
adPainter.setFont(painterFont);
|
||||
adPainter.setBrush(palette.buttonText());
|
||||
adPainter.setPen(palette.buttonText().color());
|
||||
adPainter.drawText(0, 0, makeAdSize, makeAdSize, Qt::AlignCenter | Qt::TextDontClip, "+");
|
||||
adPainter.end();
|
||||
|
||||
ui->cmdMakeAv->setIconSize(avImage.size());
|
||||
ui->cmdMakeSe->setIconSize(seImage.size());
|
||||
ui->cmdMakeAd->setIconSize(adImage.size());
|
||||
|
||||
ui->cmdMakeAv->setIcon(QIcon(QPixmap::fromImage(avImage)));
|
||||
ui->cmdMakeSe->setIcon(QIcon(QPixmap::fromImage(seImage)));
|
||||
ui->cmdMakeAd->setIcon(QIcon(QPixmap::fromImage(adImage)));
|
||||
}
|
||||
|
||||
void PlayerListDialog::on_cmdCancel_clicked()
|
||||
{
|
||||
close();
|
||||
|
|
|
@ -48,7 +48,6 @@ private:
|
|||
ProfileDatabase *profileDB;
|
||||
Ui::PlayerListDialog *ui;
|
||||
bool listUpdated;
|
||||
void drawSwitchButtons();
|
||||
void buildInterface();
|
||||
|
||||
signals:
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdMakeSe">
|
||||
<property name="text">
|
||||
<string/>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
|
@ -61,6 +61,9 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdMakeAv">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
@ -71,6 +74,9 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cmdMakeAd">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,7 @@
|
|||
#include "ExportThread.h"
|
||||
#include "SavegameData.h"
|
||||
#include "CrewDatabase.h"
|
||||
#include "pcg_basic.h"
|
||||
#include <QProgressDialog>
|
||||
#include <QSpacerItem>
|
||||
#include <QDateTime>
|
||||
|
@ -100,21 +101,23 @@ private:
|
|||
QMap<ProfileWidget*,QString> widgets;
|
||||
QSpacerItem *saSpacerItem;
|
||||
QStringList fixedPictures;
|
||||
QColor highlightBackColor;
|
||||
QColor highlightTextColor;
|
||||
QString enabledPicStr;
|
||||
QString profileFolder;
|
||||
QString profileName;
|
||||
QString loadingStr;
|
||||
QString language;
|
||||
pcg32_random_t rng;
|
||||
bool contextMenuOpened;
|
||||
bool isProfileLoaded;
|
||||
int selectedWidgts;
|
||||
int contentMode;
|
||||
|
||||
bool isSupportedImageFile(QString selectedFileName);
|
||||
bool importFile(QString selectedFile, QDateTime importDateTime, int *currentTime, bool notMultiple);
|
||||
void importFilesProgress(QStringList selectedFiles);
|
||||
bool importFile(QString selectedFile, QDateTime importDateTime, bool notMultiple);
|
||||
bool importUrls(const QMimeData *mimeData);
|
||||
bool importRemote(QUrl remoteUrl);
|
||||
bool importImage(QImage *snapmaticImage, QDateTime importDateTime);
|
||||
bool importFilesProgress(QStringList selectedFiles);
|
||||
bool importSnapmaticPicture(SnapmaticPicture *picture, bool warn = true);
|
||||
bool importSavegameData(SavegameData *savegame, QString sgdPath, bool warn = true);
|
||||
void pictureLoaded(SnapmaticPicture *picture, bool inserted);
|
||||
|
@ -124,6 +127,7 @@ private:
|
|||
void insertSnapmaticIPI(QWidget *widget);
|
||||
void insertSavegameIPI(QWidget *widget);
|
||||
void sortingProfileInterface();
|
||||
int getRandomUid();
|
||||
|
||||
signals:
|
||||
void profileLoaded();
|
||||
|
|
55
README.md
55
README.md
|
@ -4,38 +4,49 @@ Grand Theft Auto V Savegame and Snapmatic viewer/editor
|
|||
- View Snapmatics with the ability to disable them in-game
|
||||
- Edit Snapmatic pictures and properties in multiple ways
|
||||
- Import/Export Snapmatics, Savegames and pictures
|
||||
- Let choose between multiple Social Club accounts as GTA V profiles IDs
|
||||
- Choose between multiple Social Club accounts as GTA V profiles IDs
|
||||
|
||||
#### Screenshots
|
||||
![Snapmatic Picture Viewer](res/src/picture.png)
|
||||
![User Interface](res/src/mainui.png)
|
||||
![Snapmatic Properties](res/src/prop.png)
|
||||
|
||||
#### Build gta5view for Debian/Ubuntu
|
||||
|
||||
# Note: You can use 'sudo make install' instead of 'sudo checkinstall'
|
||||
sudo apt-get install git gcc g++ qtbase5-dev qttranslations5-l10n qt5-qmake make checkinstall
|
||||
git clone https://github.com/SyDevTeam/gta5view && cd gta5view
|
||||
mkdir -p build && cd build
|
||||
qmake -qt=5 GTA5SYNC_PREFIX=/usr ../gta5view.pro # or just qmake GTA5SYNC_PREFIX=/usr ../gta5view.pro
|
||||
make -j $(nproc --all)
|
||||
sudo checkinstall --pkgname=gta5view --pkggroup=utility --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5,qttranslations5-l10n
|
||||
|
||||
#### Build gta5view for Windows
|
||||
|
||||
# Note: Install Docker Community Edition and Git before continuing
|
||||
git clone https://github.com/SyDevTeam/gta5view && cd gta5view
|
||||
docker pull syping/qt5-static-mingw
|
||||
docker run --rm -v ${PWD}:/gta5view -it syping/qt5-static-mingw
|
||||
cd /gta5view && mkdir -p build && cd build
|
||||
qmake-static ../gta5view.pro
|
||||
make -j $(nproc --all)
|
||||
# Note: Install Docker Community Edition and Git before continuing
|
||||
git clone https://gitlab.com/Syping/gta5view && cd gta5view
|
||||
docker pull sypingauto/gta5view-build:1.8-static
|
||||
docker run --rm -v ${PWD}:/gta5view -it sypingauto/gta5view-build:1.8-static
|
||||
cd /gta5view && mkdir -p build && cd build
|
||||
mingw64-qt-cmake ../
|
||||
make -j $(nproc --all)
|
||||
|
||||
#### Build gta5view for Windows (Beginner)
|
||||
#### Build gta5view for Debian/Ubuntu
|
||||
|
||||
Download the [Qt Framework](https://www.qt.io/) and install the MinGW version.
|
||||
Download the Source Code over [GitHub](https://github.com/SyDevTeam/gta5view/archive/1.5.x.zip) or with your Git client.
|
||||
Open the gta5view.pro Project file with Qt Creator and build it over Qt Creator.
|
||||
sudo apt-get install cmake git gcc g++ libqt5svg5-dev make qtbase5-dev qttranslations5-l10n
|
||||
git clone https://gitlab.com/Syping/gta5view && cd gta5view
|
||||
mkdir -p build && cd build
|
||||
cmake ../
|
||||
make -j $(nproc --all)
|
||||
sudo make install
|
||||
|
||||
#### Build gta5view for Arch/Manjaro
|
||||
|
||||
sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations
|
||||
git clone https://gitlab.com/Syping/gta5view && cd gta5view
|
||||
mkdir -p build && cd build
|
||||
cmake ../
|
||||
make -j $(nproc --all)
|
||||
sudo make install
|
||||
|
||||
#### Build gta5view for Fedora
|
||||
|
||||
sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations
|
||||
git clone https://gitlab.com/Syping/gta5view && cd gta5view
|
||||
mkdir -p build && cd build
|
||||
cmake ../
|
||||
make -j $(nproc --all)
|
||||
sudo make install
|
||||
|
||||
#### Download Binary Releases
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "StringParser.h"
|
||||
#include "SavegameData.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QTextCodec>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include "SavegameData.h"
|
||||
#include "SavegameCopy.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
|
@ -37,6 +38,13 @@
|
|||
#include <QMenu>
|
||||
#include <QUrl>
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QDateTime>
|
||||
#endif
|
||||
|
||||
SavegameWidget::SavegameWidget(QWidget *parent) :
|
||||
ProfileWidget(parent),
|
||||
ui(new Ui::SavegameWidget)
|
||||
|
@ -50,9 +58,8 @@ SavegameWidget::SavegameWidget(QWidget *parent) :
|
|||
qreal screenRatio = AppEnv::screenRatio();
|
||||
ui->labSavegamePic->setFixedSize(48 * screenRatio, 27 * screenRatio);
|
||||
|
||||
QPixmap savegamePixmap(":/img/savegame.png");
|
||||
if (screenRatio != 1) savegamePixmap = savegamePixmap.scaledToHeight(ui->labSavegamePic->height(), Qt::SmoothTransformation);
|
||||
ui->labSavegamePic->setPixmap(savegamePixmap);
|
||||
ui->labSavegamePic->setScaledContents(true);
|
||||
ui->labSavegamePic->setPixmap(QPixmap(":/img/savegame.svgz"));
|
||||
|
||||
QString exportSavegameStr = tr("Export Savegame...");
|
||||
Q_UNUSED(exportSavegameStr)
|
||||
|
@ -134,9 +141,41 @@ void SavegameWidget::on_cmdDelete_clicked()
|
|||
if (!QFile::exists(sgdPath))
|
||||
{
|
||||
emit savegameDeleted();
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "DeleteSuccess";
|
||||
jsonObject["ExtraFlags"] = "Savegame";
|
||||
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(QFile::remove(sgdPath))
|
||||
else if (QFile::remove(sgdPath))
|
||||
{
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "DeleteSuccess";
|
||||
jsonObject["ExtraFlags"] = "Savegame";
|
||||
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
emit savegameDeleted();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "PlayerListDialog.h"
|
||||
#include "StringParser.h"
|
||||
#include "AppEnv.h"
|
||||
#include <QStringListIterator>
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
#include <QTextDocument>
|
||||
#include <QInputDialog>
|
||||
|
@ -30,6 +30,12 @@
|
|||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#endif
|
||||
|
||||
SnapmaticEditor::SnapmaticEditor(CrewDatabase *crewDB, ProfileDatabase *profileDB, QWidget *parent) :
|
||||
QDialog(parent), crewDB(crewDB), profileDB(profileDB),
|
||||
ui(new Ui::SnapmaticEditor)
|
||||
|
@ -38,6 +44,7 @@ SnapmaticEditor::SnapmaticEditor(CrewDatabase *crewDB, ProfileDatabase *profileD
|
|||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->cmdCancel->setDefault(true);
|
||||
ui->cmdCancel->setFocus();
|
||||
|
||||
// Set Icon for Apply Button
|
||||
|
@ -260,11 +267,11 @@ void SnapmaticEditor::setSnapmaticTitle(const QString &title)
|
|||
ui->labTitle->setText(titleStr);
|
||||
if (SnapmaticPicture::verifyTitle(snapmaticTitle))
|
||||
{
|
||||
ui->labAppropriate->setText(tr("Appropriate: %1").arg(QString("<span style=\"color: green\">%1</a>").arg(tr("Yes", "Yes, should work fine"))));
|
||||
ui->labAppropriate->setText(tr("Appropriate: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes", "Yes, should work fine"))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labAppropriate->setText(tr("Appropriate: %1").arg(QString("<span style=\"color: red\">%1</a>").arg(tr("No", "No, could lead to issues"))));
|
||||
ui->labAppropriate->setText(tr("Appropriate: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No", "No, could lead to issues"))));
|
||||
}
|
||||
#ifndef Q_OS_ANDROID
|
||||
ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width()));
|
||||
|
@ -329,7 +336,24 @@ void SnapmaticEditor::on_cmdApply_clicked()
|
|||
}
|
||||
else
|
||||
{
|
||||
smpic->updateStrings();
|
||||
smpic->emitUpdate();
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "PropertyEdited";
|
||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
close();
|
||||
|
@ -413,7 +437,7 @@ void SnapmaticEditor::on_labCrew_linkActivated(const QString &link)
|
|||
}
|
||||
if (crewList.contains(QString::number(crewID)))
|
||||
{
|
||||
indexNum = crewList.indexOf(QRegExp(QString::number(crewID)));
|
||||
indexNum = crewList.indexOf(QString::number(crewID));
|
||||
}
|
||||
QString newCrew = QInputDialog::getItem(this, tr("Snapmatic Crew"), tr("New Snapmatic crew:"), itemList, indexNum, true, &ok, windowFlags());
|
||||
if (ok && !newCrew.isEmpty())
|
||||
|
@ -427,6 +451,10 @@ void SnapmaticEditor::on_labCrew_linkActivated(const QString &link)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (!crewList.contains(newCrew))
|
||||
{
|
||||
crewDB->addCrew(crewID);
|
||||
}
|
||||
crewID = newCrew.toInt();
|
||||
setSnapmaticCrew(returnCrewName(crewID));
|
||||
}
|
||||
|
|
|
@ -236,6 +236,9 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Apply changes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Apply</string>
|
||||
</property>
|
||||
|
@ -249,6 +252,9 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Discard changes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Cancel</string>
|
||||
</property>
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <QJsonObject>
|
||||
#include <QStringList>
|
||||
#include <QVariantMap>
|
||||
#include <QTextCodec>
|
||||
#include <QJsonArray>
|
||||
#include <QFileInfo>
|
||||
#include <QPainter>
|
||||
|
@ -33,6 +32,10 @@
|
|||
#include <QSize>
|
||||
#include <QFile>
|
||||
|
||||
#if QT_VERSION < 0x060000
|
||||
#include <QTextCodec>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QSaveFile>
|
||||
#else
|
||||
|
@ -44,6 +47,7 @@
|
|||
#define snapmaticUsefulLength 260
|
||||
#define snapmaticFileMaxSize 528192
|
||||
#define jpegHeaderLineDifStr 2
|
||||
#define jpegHeaderLineDifLim 8
|
||||
#define jpegPreHeaderLength 14
|
||||
#define jpegPicStreamLength 524288
|
||||
#define jsonStreamLength 3076
|
||||
|
@ -57,6 +61,9 @@
|
|||
#define titlStreamEditorLength 256
|
||||
#define titlStreamCharacterMax 39
|
||||
|
||||
// LIMIT ALLOCATIONS
|
||||
#define jpegStreamLimitBegin 288
|
||||
|
||||
// IMAGES VALUES
|
||||
#define snapmaticResolutionW 960
|
||||
#define snapmaticResolutionH 536
|
||||
|
@ -91,6 +98,7 @@ void SnapmaticPicture::reset()
|
|||
|
||||
// INIT PIC BOOLS
|
||||
isCustomFormat = false;
|
||||
isModernFormat = false;
|
||||
isFormatSwitch = false;
|
||||
isLoadedInRAM = false;
|
||||
lowRamMode = false;
|
||||
|
@ -101,7 +109,7 @@ void SnapmaticPicture::reset()
|
|||
jsonStr = QString();
|
||||
|
||||
// SNAPMATIC DEFAULTS
|
||||
#ifdef GTA5SYNC_NOASSIST
|
||||
#ifdef SNAPMATIC_NODEFAULT
|
||||
careSnapDefault = false;
|
||||
#else
|
||||
careSnapDefault = true;
|
||||
|
@ -138,6 +146,7 @@ bool SnapmaticPicture::preloadFile()
|
|||
else
|
||||
{
|
||||
isCustomFormat = false;
|
||||
isModernFormat = false;
|
||||
isLoadedInRAM = true;
|
||||
}
|
||||
}
|
||||
|
@ -187,6 +196,7 @@ bool SnapmaticPicture::preloadFile()
|
|||
rawPicContent = qUncompress(g5eContent);
|
||||
|
||||
// Setting is values
|
||||
isModernFormat = false;
|
||||
isLoadedInRAM = true;
|
||||
}
|
||||
else
|
||||
|
@ -207,6 +217,29 @@ bool SnapmaticPicture::preloadFile()
|
|||
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";
|
||||
|
@ -279,6 +312,12 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo
|
|||
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())
|
||||
{
|
||||
|
@ -288,18 +327,6 @@ bool SnapmaticPicture::readingPicture(bool writeEnabled_, bool cacheEnabled_, bo
|
|||
return false;
|
||||
}
|
||||
QByteArray jpegRawContent = picStream->read(jpegPicStreamLength);
|
||||
if (jpegRawContent.contains("\xFF\xD9"))
|
||||
{
|
||||
int jpegRawContentSizeT = jpegRawContent.indexOf("\xFF\xD9") + 2;
|
||||
jpegRawContentSizeE = jpegRawContentSizeT;
|
||||
jpegRawContentSize = jpegRawContentSizeT;
|
||||
if (jpegRawContent.contains("\xFF\x45\x4F\x49"))
|
||||
{
|
||||
jpegRawContentSizeT = jpegRawContent.indexOf("\xFF\x45\x4F\x49");
|
||||
}
|
||||
jpegRawContent = jpegRawContent.left(jpegRawContentSize);
|
||||
jpegRawContentSize = jpegRawContentSizeT;
|
||||
}
|
||||
if (cacheEnabled) picOk = cachePicture.loadFromData(jpegRawContent, "JPEG");
|
||||
if (!cacheEnabled)
|
||||
{
|
||||
|
@ -409,8 +436,8 @@ QString SnapmaticPicture::getSnapmaticHeaderString(const QByteArray &snapmaticHe
|
|||
QString SnapmaticPicture::getSnapmaticJSONString(const QByteArray &jsonBytes)
|
||||
{
|
||||
QByteArray jsonUsefulBytes = jsonBytes;
|
||||
jsonUsefulBytes.replace('\x00', QString());
|
||||
jsonUsefulBytes.replace('\x0c', QString());
|
||||
jsonUsefulBytes.replace('\x00', "");
|
||||
jsonUsefulBytes.replace('\x0c', "");
|
||||
return QString::fromUtf8(jsonUsefulBytes.trimmed());
|
||||
}
|
||||
|
||||
|
@ -440,6 +467,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); }
|
||||
picExportFileName = exportStr % "_" % cmpPicTitl;
|
||||
}
|
||||
|
||||
|
@ -480,7 +508,7 @@ bool SnapmaticPicture::setImage(const QImage &picture)
|
|||
picStreamT.close();
|
||||
if (saveSuccess)
|
||||
{
|
||||
if (picByteArrayT.length() > jpegRawContentSize)
|
||||
if (picByteArrayT.length() > jpegPicStreamLength)
|
||||
{
|
||||
comLvl--;
|
||||
saveSuccess = false;
|
||||
|
@ -500,29 +528,34 @@ bool SnapmaticPicture::setPictureStream(const QByteArray &streamArray) // clean
|
|||
{
|
||||
if (writeEnabled)
|
||||
{
|
||||
bool customEOI = false;
|
||||
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;
|
||||
if (picByteArray.length() < jpegRawContentSize && jpegRawContentSize + 4 < jpegPicStreamLength)
|
||||
{
|
||||
customEOI = true;
|
||||
}
|
||||
while (picByteArray.length() != jpegPicStreamLength)
|
||||
{
|
||||
picByteArray += '\x00';
|
||||
}
|
||||
if (customEOI)
|
||||
{
|
||||
picByteArray.replace(jpegRawContentSize, 4, "\xFF\x45\x4F\x49");
|
||||
}
|
||||
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;
|
||||
|
@ -964,7 +997,11 @@ void SnapmaticPicture::parseJsonContent()
|
|||
bool timestampOk;
|
||||
QDateTime createdTimestamp;
|
||||
localProperties.createdTimestamp = jsonMap["creat"].toUInt(×tampOk);
|
||||
#if QT_VERSION >= 0x060000
|
||||
createdTimestamp.setSecsSinceEpoch(QString::number(localProperties.createdTimestamp).toLongLong());
|
||||
#else
|
||||
createdTimestamp.setTime_t(localProperties.createdTimestamp);
|
||||
#endif
|
||||
localProperties.createdDateTime = createdTimestamp;
|
||||
if (!timestampOk) { jsonError = true; }
|
||||
}
|
||||
|
@ -1004,7 +1041,7 @@ void SnapmaticPicture::parseJsonContent()
|
|||
if (jsonObject["rsedtr"].isBool()) { localProperties.isFromRSEditor = jsonObject["rsedtr"].toBool(); }
|
||||
else { jsonError = true; }
|
||||
}
|
||||
else { jsonIncomplete = true; }
|
||||
// else { jsonIncomplete = true; } // Game release Snapmatic pictures prior May 2015 left out rsedtr, so don't force exists on that one
|
||||
|
||||
if (!jsonIncomplete && !jsonError)
|
||||
{
|
||||
|
@ -1132,27 +1169,13 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, SnapmaticFormat fo
|
|||
{
|
||||
if (format == SnapmaticFormat::G5E_Format)
|
||||
{
|
||||
// Modern compressed export
|
||||
QByteArray stockFileNameUTF8 = picFileName.toUtf8();
|
||||
QByteArray numberLength = QByteArray::number(stockFileNameUTF8.length());
|
||||
if (numberLength.length() == 1)
|
||||
{
|
||||
numberLength.insert(0, '0');
|
||||
}
|
||||
else if (numberLength.length() != 2)
|
||||
{
|
||||
numberLength = "00";
|
||||
}
|
||||
// Modern compressed export (v2)
|
||||
QByteArray g5eHeader;
|
||||
g5eHeader.reserve(stockFileNameUTF8.length() + 16);
|
||||
g5eHeader.reserve(10);
|
||||
g5eHeader += '\x00'; // First Null Byte
|
||||
g5eHeader += QByteArray("G5E"); // GTA 5 Export
|
||||
g5eHeader += '\x10'; g5eHeader += '\x00'; // 2 byte GTA 5 Export Version
|
||||
g5eHeader += QByteArray("LEN"); // Before Length
|
||||
g5eHeader += QByteArray::fromHex(numberLength); // Length in HEX before Compressed
|
||||
g5eHeader += QByteArray("FIL"); // Before File Name
|
||||
g5eHeader += stockFileNameUTF8; // File Name
|
||||
g5eHeader += QByteArray("COM"); // Before Compressed
|
||||
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)
|
||||
{
|
||||
|
@ -1402,7 +1425,13 @@ bool SnapmaticPicture::verifyTitleChar(const QChar &titleChar)
|
|||
QString SnapmaticPicture::parseTitleString(const QByteArray &commitBytes, int maxLength)
|
||||
{
|
||||
Q_UNUSED(maxLength)
|
||||
#if QT_VERSION >= 0x060000
|
||||
QStringDecoder strDecoder = QStringDecoder(QStringDecoder::Utf16LE);
|
||||
QString retStr = strDecoder(commitBytes);
|
||||
retStr = retStr.trimmed();
|
||||
#else
|
||||
QString retStr = QTextCodec::codecForName("UTF-16LE")->toUnicode(commitBytes).trimmed();
|
||||
#endif
|
||||
retStr.remove(QChar('\x00'));
|
||||
return retStr;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public:
|
|||
bool setVisible() { return setPictureVisible(); } // Please use setPictureVisible instead
|
||||
|
||||
// PREDEFINED PROPERTIES
|
||||
QSize getSnapmaticResolution();
|
||||
static QSize getSnapmaticResolution();
|
||||
|
||||
// SNAPMATIC DEFAULTS
|
||||
bool isSnapmaticDefaultsEnforced();
|
||||
|
@ -160,6 +160,7 @@ private:
|
|||
bool isLoadedInRAM;
|
||||
bool isCustomFormat;
|
||||
bool isFormatSwitch;
|
||||
bool isModernFormat;
|
||||
bool careSnapDefault;
|
||||
int jpegRawContentSize;
|
||||
int jpegRawContentSizeE;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2017 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "SnapmaticWidget.h"
|
||||
#include "ui_SnapmaticWidget.h"
|
||||
#include "ImageEditorDialog.h"
|
||||
#include "MapLocationDialog.h"
|
||||
#include "JsonEditorDialog.h"
|
||||
#include "SnapmaticPicture.h"
|
||||
|
@ -27,6 +26,7 @@
|
|||
#include "PictureDialog.h"
|
||||
#include "PictureExport.h"
|
||||
#include "StringParser.h"
|
||||
#include "ImportDialog.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QStringBuilder>
|
||||
|
@ -37,6 +37,12 @@
|
|||
#include <QMenu>
|
||||
#include <QFile>
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#endif
|
||||
|
||||
SnapmaticWidget::SnapmaticWidget(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QString profileName, QWidget *parent) :
|
||||
ProfileWidget(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), profileName(profileName),
|
||||
ui(new Ui::SnapmaticWidget)
|
||||
|
@ -71,9 +77,16 @@ void SnapmaticWidget::setSnapmaticPicture(SnapmaticPicture *picture)
|
|||
QObject::connect(picture, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString)));
|
||||
|
||||
qreal screenRatio = AppEnv::screenRatio();
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
ui->labPicture->setFixedSize(48 * screenRatio, 27 * screenRatio);
|
||||
|
||||
QPixmap SnapmaticPixmap = QPixmap::fromImage(picture->getImage().scaled(ui->labPicture->width(), ui->labPicture->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::AutoColor);
|
||||
ui->labPicture->setScaledContents(true);
|
||||
|
||||
QPixmap SnapmaticPixmap = QPixmap::fromImage(picture->getImage().scaled(ui->labPicture->width() * screenRatioPR, ui->labPicture->height() * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::AutoColor);
|
||||
#if QT_VERSION >= 0x050600
|
||||
SnapmaticPixmap.setDevicePixelRatio(screenRatioPR);
|
||||
#endif
|
||||
|
||||
ui->labPicStr->setText(smpic->getPictureStr() % "\n" % smpic->getPictureTitl());
|
||||
ui->labPicture->setPixmap(SnapmaticPixmap);
|
||||
|
||||
|
@ -106,7 +119,7 @@ void SnapmaticWidget::on_cmdView_clicked()
|
|||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Interface");
|
||||
bool navigationBar = settings.value("NavigationBar", false).toBool();
|
||||
bool navigationBar = settings.value("NavigationBar", true).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
PictureDialog *picDialog = new PictureDialog(profileDB, crewDB, profileName, this);
|
||||
|
@ -128,7 +141,7 @@ void SnapmaticWidget::on_cmdView_clicked()
|
|||
picDialog->showMaximized();
|
||||
#else
|
||||
picDialog->show();
|
||||
if (navigationBar) picDialog->stylizeDialog();
|
||||
if (navigationBar) picDialog->styliseDialog();
|
||||
//picDialog->adaptNewDialogSize();
|
||||
picDialog->setMinimumSize(picDialog->size());
|
||||
picDialog->setMaximumSize(picDialog->size());
|
||||
|
@ -157,8 +170,25 @@ bool SnapmaticWidget::deletePicture()
|
|||
int uchoice = QMessageBox::question(this, tr("Delete picture"), tr("Are you sure to delete %1 from your Snapmatic pictures?").arg("\""+smpic->getPictureTitle()+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (uchoice == QMessageBox::Yes)
|
||||
{
|
||||
if (smpic->deletePicFile())
|
||||
if (smpic->deletePictureFile())
|
||||
{
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "DeleteSuccess";
|
||||
jsonObject["ExtraFlags"] = "Snapmatic";
|
||||
jsonObject["DeletedSize"] = QString::number(smpic->getContentMaxLength());
|
||||
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -320,11 +350,57 @@ void SnapmaticWidget::editSnapmaticRawJson()
|
|||
|
||||
void SnapmaticWidget::editSnapmaticImage()
|
||||
{
|
||||
ImageEditorDialog *imageEditor = new ImageEditorDialog(smpic, profileName, this);
|
||||
imageEditor->setModal(true);
|
||||
imageEditor->show();
|
||||
imageEditor->exec();
|
||||
delete imageEditor;
|
||||
QImage *currentImage = new QImage(smpic->getImage());
|
||||
ImportDialog *importDialog = new ImportDialog(profileName, this);
|
||||
importDialog->setImage(currentImage);
|
||||
importDialog->enableOverwriteMode();
|
||||
importDialog->setModal(true);
|
||||
importDialog->exec();
|
||||
if (importDialog->isImportAgreed())
|
||||
{
|
||||
const QByteArray previousPicture = smpic->getPictureStream();
|
||||
bool success = smpic->setImage(importDialog->image());
|
||||
if (success)
|
||||
{
|
||||
QString currentFilePath = smpic->getPictureFilePath();
|
||||
QString originalFilePath = smpic->getOriginalPictureFilePath();
|
||||
QString backupFileName = originalFilePath % ".bak";
|
||||
if (!QFile::exists(backupFileName))
|
||||
{
|
||||
QFile::copy(currentFilePath, backupFileName);
|
||||
}
|
||||
if (!smpic->exportPicture(currentFilePath))
|
||||
{
|
||||
smpic->setPictureStream(previousPicture);
|
||||
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of I/O Error"));
|
||||
return;
|
||||
}
|
||||
smpic->emitCustomSignal("PictureUpdated");
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "ImageEdited";
|
||||
jsonObject["ExtraFlags"] = "Interface";
|
||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
delete importDialog;
|
||||
}
|
||||
|
||||
void SnapmaticWidget::openMapViewer()
|
||||
|
@ -357,6 +433,26 @@ void SnapmaticWidget::openMapViewer()
|
|||
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error"));
|
||||
picture->setSnapmaticProperties(fallbackProperties);
|
||||
}
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
else
|
||||
{
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
|
||||
telemetrySettings.endGroup();
|
||||
if (pushUsageData && Telemetry->canPush())
|
||||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
jsonObject["Type"] = "LocationEdited";
|
||||
jsonObject["ExtraFlags"] = "Interface";
|
||||
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
|
||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
|
||||
jsonDocument.setObject(jsonObject);
|
||||
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
delete mapLocDialog;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "StringParser.h"
|
||||
#include <QTextDocument>
|
||||
#include <QLibraryInfo>
|
||||
#include <QTextCodec>
|
||||
#include <QByteArray>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
|
@ -49,12 +48,16 @@ QString StringParser::escapeString(const QString &toEscape)
|
|||
QString StringParser::convertBuildedString(const QString &buildedStr)
|
||||
{
|
||||
QString outputStr = buildedStr;
|
||||
QByteArray sharePath = GTA5SYNC_SHARE;
|
||||
outputStr.replace("APPNAME:", GTA5SYNC_APPSTR);
|
||||
outputStr.replace("SHAREDDIR:", QString::fromUtf8(sharePath));
|
||||
outputStr.replace("RUNDIR:", QFileInfo(qApp->applicationFilePath()).absoluteDir().absolutePath());
|
||||
outputStr.replace("APPNAME:", QString::fromUtf8(GTA5SYNC_APPSTR));
|
||||
outputStr.replace("SHAREDDIR:", QString::fromUtf8(GTA5SYNC_SHARE));
|
||||
outputStr.replace("RUNDIR:", QFileInfo(QApplication::applicationFilePath()).canonicalPath());
|
||||
#if QT_VERSION >= 0x060000
|
||||
outputStr.replace("QCONFLANG:", QLibraryInfo::path(QLibraryInfo::TranslationsPath));
|
||||
outputStr.replace("QCONFPLUG:", QLibraryInfo::path(QLibraryInfo::PluginsPath));
|
||||
#else
|
||||
outputStr.replace("QCONFLANG:", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
outputStr.replace("QCONFPLUG:", QLibraryInfo::location(QLibraryInfo::PluginsPath));
|
||||
#endif
|
||||
outputStr.replace("SEPARATOR:", QDir::separator());
|
||||
return outputStr;
|
||||
}
|
||||
|
|
|
@ -41,9 +41,10 @@
|
|||
#define GTA5SYNC_TELEMETRY_WEBURL ""
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#include "windows.h"
|
||||
#include "intrin.h"
|
||||
#include "d3d9.h"
|
||||
#endif
|
||||
|
||||
TelemetryClass TelemetryClass::telemetryClassInstance;
|
||||
|
@ -168,6 +169,8 @@ void TelemetryClass::push(TelemetryCategory category)
|
|||
break;
|
||||
case TelemetryCategory::UserFeedback:
|
||||
break;
|
||||
case TelemetryCategory::PersonalData:
|
||||
break;
|
||||
case TelemetryCategory::CustomEmitted:
|
||||
break;
|
||||
}
|
||||
|
@ -198,6 +201,7 @@ void TelemetryClass::push(TelemetryCategory category, QJsonDocument json)
|
|||
|
||||
QNetworkAccessManager *netManager = new QNetworkAccessManager();
|
||||
QNetworkRequest netRequest(TelemetryClassAuthenticator::getTrackingPushURL());
|
||||
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
|
||||
QNetworkReply *netReply = netManager->post(netRequest, httpMultiPart);
|
||||
httpMultiPart->setParent(netReply);
|
||||
|
||||
|
@ -209,6 +213,10 @@ QJsonDocument TelemetryClass::getOperatingSystem()
|
|||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
#if QT_VERSION >= 0x050400
|
||||
jsonObject["KernelType"] = QSysInfo::kernelType();
|
||||
jsonObject["KernelVersion"] = QSysInfo::kernelVersion();
|
||||
jsonObject["ProductType"] = QSysInfo::productType();
|
||||
jsonObject["ProductVersion"] = QSysInfo::productVersion();
|
||||
jsonObject["OSName"] = QSysInfo::prettyProductName();
|
||||
jsonObject["OSArch"] = QSysInfo::currentCpuArchitecture();
|
||||
#endif
|
||||
|
@ -220,21 +228,21 @@ QJsonDocument TelemetryClass::getSystemHardware()
|
|||
{
|
||||
QJsonDocument jsonDocument;
|
||||
QJsonObject jsonObject;
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
{
|
||||
int CPUInfo[4] = {-1};
|
||||
unsigned nExIds, i = 0;
|
||||
unsigned nExIds, ic = 0;
|
||||
char CPUBrandString[0x40];
|
||||
__cpuid(CPUInfo, 0x80000000);
|
||||
nExIds = CPUInfo[0];
|
||||
for (i = 0x80000000; i <= nExIds; ++i)
|
||||
for (ic = 0x80000000; ic <= nExIds; ic++)
|
||||
{
|
||||
__cpuid(CPUInfo, i);
|
||||
if (i == 0x80000002) { memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo)); }
|
||||
else if (i == 0x80000003) { memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo)); }
|
||||
else if (i == 0x80000004) { memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); }
|
||||
__cpuid(CPUInfo, ic);
|
||||
if (ic == 0x80000002) { memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo)); }
|
||||
else if (ic == 0x80000003) { memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo)); }
|
||||
else if (ic == 0x80000004) { memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); }
|
||||
}
|
||||
jsonObject["CPUName"] = QString(CPUBrandString).trimmed();
|
||||
jsonObject["CPUName"] = QString::fromLatin1(CPUBrandString).simplified();
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo(&sysInfo);
|
||||
jsonObject["CPUThreads"] = QString::number(sysInfo.dwNumberOfProcessors);
|
||||
|
@ -242,6 +250,21 @@ QJsonDocument TelemetryClass::getSystemHardware()
|
|||
statex.dwLength = sizeof(statex);
|
||||
GlobalMemoryStatusEx(&statex);
|
||||
jsonObject["SystemRAM"] = QString(QString::number((statex.ullTotalPhys / 1024) / 1024) % "MB");
|
||||
QStringList gpusList;
|
||||
IDirect3D9 *pD3D = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
int adapters = pD3D->GetAdapterCount();
|
||||
for (int ia = 0; ia < adapters; ia++)
|
||||
{
|
||||
D3DADAPTER_IDENTIFIER9 d3dIdent;
|
||||
HRESULT result = pD3D->GetAdapterIdentifier(ia, 0, &d3dIdent);
|
||||
if (result == D3D_OK)
|
||||
{
|
||||
QString gpuAdapter = QString::fromLatin1(d3dIdent.Description);
|
||||
if (!gpusList.contains(gpuAdapter)) { gpusList << gpuAdapter; }
|
||||
}
|
||||
}
|
||||
pD3D->Release();
|
||||
jsonObject["GPUs"] = QJsonValue::fromVariant(gpusList);
|
||||
}
|
||||
#else
|
||||
QDir procDir("/proc");
|
||||
|
@ -260,7 +283,7 @@ QJsonDocument TelemetryClass::getSystemHardware()
|
|||
QByteArray cpuData = cpuInfoBuffer.readLine();
|
||||
if (cpuData.left(toFind.length()) == toFind)
|
||||
{
|
||||
jsonObject["CPUName"] = QString::fromUtf8(cpuData).split(':').at(1).trimmed();
|
||||
jsonObject["CPUName"] = QString::fromUtf8(cpuData).split(':').at(1).simplified();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -315,6 +338,9 @@ QJsonDocument TelemetryClass::getApplicationSpec()
|
|||
jsonObject["Arch"] = QSysInfo::buildCpuArchitecture();
|
||||
#endif
|
||||
jsonObject["Name"] = GTA5SYNC_APPSTR;
|
||||
#ifdef GTA5SYNC_COMMIT
|
||||
jsonObject["Commit"] = GTA5SYNC_COMMIT;
|
||||
#endif
|
||||
jsonObject["Version"] = GTA5SYNC_APPVER;
|
||||
jsonObject["BuildDateTime"] = AppEnv::getBuildDateTime();
|
||||
jsonObject["BuildType"] = GTA5SYNC_BUILDTYPE;
|
||||
|
@ -369,6 +395,7 @@ QJsonDocument TelemetryClass::getApplicationConf()
|
|||
QJsonObject startupObject;
|
||||
startupObject["AppStyle"] = settings.value("AppStyle", "System").toString();
|
||||
startupObject["CustomStyle"] = settings.value("CustomStyle", false).toBool();
|
||||
startupObject["StartCount"] = QString::number(settings.value("StartCount", 0).toUInt());
|
||||
jsonObject["Startup"] = startupObject;
|
||||
settings.endGroup();
|
||||
|
||||
|
@ -410,11 +437,14 @@ QString TelemetryClass::categoryToString(TelemetryCategory category)
|
|||
case TelemetryCategory::ApplicationConf:
|
||||
return QString("ApplicationConf");
|
||||
break;
|
||||
case TelemetryCategory::ApplicationSpec:
|
||||
return QString("ApplicationSpec");
|
||||
break;
|
||||
case TelemetryCategory::UserFeedback:
|
||||
return QString("UserFeedback");
|
||||
break;
|
||||
case TelemetryCategory::ApplicationSpec:
|
||||
return QString("ApplicationSpec");
|
||||
case TelemetryCategory::PersonalData:
|
||||
return QString("PersonalData");
|
||||
break;
|
||||
case TelemetryCategory::CustomEmitted:
|
||||
return QString("CustomEmitted");
|
||||
|
@ -434,6 +464,7 @@ void TelemetryClass::registerClient()
|
|||
{
|
||||
QNetworkAccessManager *netManager = new QNetworkAccessManager();
|
||||
QNetworkRequest netRequest(TelemetryClassAuthenticator::getTrackingRegURL());
|
||||
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
|
||||
netManager->get(netRequest);
|
||||
|
||||
connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(registerFinished(QNetworkReply*)));
|
||||
|
@ -464,6 +495,10 @@ void TelemetryClass::work_p(bool doWork)
|
|||
{
|
||||
push(TelemetryCategory::ApplicationConf);
|
||||
}
|
||||
else
|
||||
{
|
||||
push(TelemetryCategory::ApplicationConf, QJsonDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
enum class TelemetryCategory : int { OperatingSystemSpec = 0, HardwareSpec = 1, UserLocaleData = 2, ApplicationConf = 3, UserFeedback = 4, ApplicationSpec = 5, CustomEmitted = 99};
|
||||
enum class TelemetryCategory : int { OperatingSystemSpec = 0, HardwareSpec = 1, UserLocaleData = 2, ApplicationConf = 3, UserFeedback = 4, ApplicationSpec = 5, PersonalData = 6, CustomEmitted = 99 };
|
||||
|
||||
class TelemetryClass : public QObject
|
||||
{
|
||||
|
|
|
@ -63,7 +63,11 @@ void TranslationClass::loadTranslation(QApplication *app)
|
|||
{
|
||||
app->installTranslator(&inQtTranslator);
|
||||
}
|
||||
#if QT_VERSION <= 0x060000
|
||||
QLocale::setDefault(QLocale(currentLanguage));
|
||||
#else
|
||||
QLocale::setDefault(currentLanguage);
|
||||
#endif
|
||||
isLangLoaded = true;
|
||||
return;
|
||||
}
|
||||
|
@ -147,7 +151,11 @@ void TranslationClass::loadTranslation(QApplication *app)
|
|||
{
|
||||
app->installTranslator(&inQtTranslator);
|
||||
}
|
||||
#if QT_VERSION <= 0x060000
|
||||
QLocale::setDefault(QLocale(currentLanguage));
|
||||
#else
|
||||
QLocale::setDefault(currentLanguage);
|
||||
#endif
|
||||
isLangLoaded = true;
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +184,11 @@ void TranslationClass::loadTranslation(QApplication *app)
|
|||
{
|
||||
app->installTranslator(&inQtTranslator);
|
||||
}
|
||||
#if QT_VERSION <= 0x060000
|
||||
QLocale::setDefault(QLocale(currentLanguage));
|
||||
#else
|
||||
QLocale::setDefault(currentLanguage);
|
||||
#endif
|
||||
isLangLoaded = true;
|
||||
}
|
||||
else
|
||||
|
@ -195,7 +207,11 @@ void TranslationClass::loadTranslation(QApplication *app)
|
|||
{
|
||||
app->installTranslator(&inQtTranslator);
|
||||
}
|
||||
#if QT_VERSION <= 0x060000
|
||||
QLocale::setDefault(QLocale(currentLanguage));
|
||||
#else
|
||||
QLocale::setDefault(currentLanguage);
|
||||
#endif
|
||||
isLangLoaded = true;
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +235,11 @@ void TranslationClass::loadTranslation(QApplication *app)
|
|||
{
|
||||
app->installTranslator(&inQtTranslator);
|
||||
}
|
||||
#if QT_VERSION <= 0x060000
|
||||
QLocale::setDefault(QLocale(currentLanguage));
|
||||
#else
|
||||
QLocale::setDefault(currentLanguage);
|
||||
#endif
|
||||
isLangLoaded = true;
|
||||
}
|
||||
else if (!trLoadSuccess)
|
||||
|
@ -236,7 +256,11 @@ void TranslationClass::loadTranslation(QApplication *app)
|
|||
{
|
||||
app->installTranslator(&inQtTranslator);
|
||||
}
|
||||
#if QT_VERSION <= 0x060000
|
||||
QLocale::setDefault(QLocale(currentLanguage));
|
||||
#else
|
||||
QLocale::setDefault(currentLanguage);
|
||||
#endif
|
||||
isLangLoaded = true;
|
||||
}
|
||||
}
|
||||
|
@ -517,25 +541,52 @@ QString TranslationClass::getCurrentAreaLanguage()
|
|||
const QStringList areaTranslations = listAreaTranslations();
|
||||
if (userAreaLanguage == "Auto" || userAreaLanguage.trimmed().isEmpty())
|
||||
{
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageMode";
|
||||
#endif
|
||||
QString langCode = QString(currentLanguage).replace("-", "_");
|
||||
if (areaTranslations.contains(langCode))
|
||||
GameLanguage gameLanguage = AppEnv::getGameLanguage(AppEnv::getGameVersion());
|
||||
if (gameLanguage == GameLanguage::Undefined)
|
||||
{
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageSelected" << langCode;
|
||||
qDebug() << "autoAreaLanguageModeInterface";
|
||||
#endif
|
||||
return langCode;
|
||||
QString langCode = QString(currentLanguage).replace("-", "_");
|
||||
if (areaTranslations.contains(langCode))
|
||||
{
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageSelected" << langCode;
|
||||
#endif
|
||||
return langCode;
|
||||
}
|
||||
else if (langCode.contains("_"))
|
||||
{
|
||||
langCode = langCode.split("_").at(0);
|
||||
if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageSelected" << langCode;
|
||||
#endif
|
||||
return langCode;
|
||||
}
|
||||
}
|
||||
else if (langCode.contains("_"))
|
||||
else
|
||||
{
|
||||
langCode = langCode.split("_").at(0);
|
||||
if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageSelected" << langCode;
|
||||
qDebug() << "autoAreaLanguageModeGame";
|
||||
#endif
|
||||
return langCode;
|
||||
QString langCode = AppEnv::gameLanguageToString(gameLanguage).replace("-", "_");
|
||||
if (areaTranslations.contains(langCode))
|
||||
{
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageSelected" << langCode;
|
||||
#endif
|
||||
return langCode;
|
||||
}
|
||||
else if (langCode.contains("_"))
|
||||
{
|
||||
langCode = langCode.split("_").at(0);
|
||||
if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << "autoAreaLanguageSelected" << langCode;
|
||||
#endif
|
||||
return langCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (areaTranslations.contains(userAreaLanguage))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2019 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -40,14 +40,21 @@
|
|||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QMap>
|
||||
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, MessageThread *threadMessage, QWidget *parent) :
|
||||
QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), threadMessage(threadMessage),
|
||||
ui(new Ui::UserInterface)
|
||||
#else
|
||||
UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent) :
|
||||
QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB),
|
||||
ui(new Ui::UserInterface)
|
||||
#endif
|
||||
{
|
||||
ui->setupUi(this);
|
||||
contentMode = 0;
|
||||
|
@ -61,7 +68,13 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D
|
|||
defaultWindowTitle = tr("%2 - %1").arg("%1", GTA5SYNC_APPSTR);
|
||||
|
||||
this->setWindowTitle(defaultWindowTitle.arg(tr("Select Profile")));
|
||||
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER));
|
||||
QString appVersion = GTA5SYNC_APPVER;
|
||||
#ifndef GTA5SYNC_BUILDTYPE_REL
|
||||
#ifdef GTA5SYNC_COMMIT
|
||||
if (!appVersion.contains("-")) { appVersion = appVersion % "-" % GTA5SYNC_COMMIT; }
|
||||
#endif
|
||||
#endif
|
||||
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion));
|
||||
|
||||
// Set Icon for Close Button
|
||||
if (QIcon::hasThemeIcon("dialog-close"))
|
||||
|
@ -166,7 +179,7 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D
|
|||
ui->vlUserInterface->setContentsMargins(9 * screenRatio, 9 * screenRatio, 9 * screenRatio, 9 * screenRatio);
|
||||
}
|
||||
|
||||
void UserInterface::setupDirEnv()
|
||||
void UserInterface::setupDirEnv(bool showFolderDialog)
|
||||
{
|
||||
// settings init
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
|
@ -179,20 +192,23 @@ void UserInterface::setupDirEnv()
|
|||
}
|
||||
else
|
||||
{
|
||||
GTAV_Folder = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly);
|
||||
if (QFileInfo(GTAV_Folder).exists())
|
||||
if (showFolderDialog)
|
||||
{
|
||||
folderExists = true;
|
||||
QDir::setCurrent(GTAV_Folder);
|
||||
AppEnv::setGameFolder(GTAV_Folder);
|
||||
|
||||
// First time folder selection save
|
||||
settings.beginGroup("dir");
|
||||
if (settings.value("dir", "").toString().isEmpty())
|
||||
GTAV_Folder = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly);
|
||||
if (QFileInfo(GTAV_Folder).exists())
|
||||
{
|
||||
settings.setValue("dir", GTAV_Folder);
|
||||
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();
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +338,11 @@ void UserInterface::closeProfile_p()
|
|||
void UserInterface::closeEvent(QCloseEvent *ev)
|
||||
{
|
||||
Q_UNUSED(ev)
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
threadMessage->terminateThread();
|
||||
#else
|
||||
threadDB->terminateThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
UserInterface::~UserInterface()
|
||||
|
@ -597,6 +617,119 @@ void UserInterface::settingsApplied(int _contentMode, bool languageChanged)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
void UserInterface::messagesArrived(const QJsonObject &object)
|
||||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Messages");
|
||||
QJsonObject::const_iterator it = object.constBegin();
|
||||
QJsonObject::const_iterator end = object.constEnd();
|
||||
QStringList messages;
|
||||
while (it != end) {
|
||||
const QString key = it.key();
|
||||
const QJsonValue value = it.value();
|
||||
bool uintOk;
|
||||
uint messageId = key.toUInt(&uintOk);
|
||||
if (uintOk && value.isString()) {
|
||||
const QString valueStr = value.toString();
|
||||
settings.setValue(QString::number(messageId), valueStr);
|
||||
messages << valueStr;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
settings.endGroup();
|
||||
if (!messages.isEmpty())
|
||||
showMessages(messages);
|
||||
}
|
||||
|
||||
void UserInterface::showMessages(const QStringList messages)
|
||||
{
|
||||
QDialog *messageDialog = new QDialog(this);
|
||||
messageDialog->setWindowTitle(tr("%1 - Messages").arg(GTA5SYNC_APPSTR));
|
||||
messageDialog->setWindowFlags(messageDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
|
||||
QVBoxLayout *messageLayout = new QVBoxLayout;
|
||||
messageDialog->setLayout(messageLayout);
|
||||
QStackedWidget *stackWidget = new QStackedWidget(messageDialog);
|
||||
for (const QString message : messages) {
|
||||
QLabel *messageLabel = new QLabel(messageDialog);
|
||||
messageLabel->setText(message);
|
||||
messageLabel->setWordWrap(true);
|
||||
stackWidget->addWidget(messageLabel);
|
||||
}
|
||||
messageLayout->addWidget(stackWidget);
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
QPushButton *backButton = new QPushButton(messageDialog);
|
||||
QPushButton *nextButton = new QPushButton(messageDialog);
|
||||
if (QIcon::hasThemeIcon("go-previous") && QIcon::hasThemeIcon("go-next") && QIcon::hasThemeIcon("list-add")) {
|
||||
backButton->setIcon(QIcon::fromTheme("go-previous"));
|
||||
nextButton->setIcon(QIcon::fromTheme("go-next"));
|
||||
}
|
||||
else {
|
||||
backButton->setIcon(QIcon(":/img/back.svgz"));
|
||||
nextButton->setIcon(QIcon(":/img/next.svgz"));
|
||||
}
|
||||
backButton->setEnabled(false);
|
||||
if (stackWidget->count() <= 1) {
|
||||
nextButton->setEnabled(false);
|
||||
}
|
||||
buttonLayout->addWidget(backButton);
|
||||
buttonLayout->addWidget(nextButton);
|
||||
buttonLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
QPushButton *closeButton = new QPushButton(messageDialog);
|
||||
closeButton->setText(tr("&Close"));
|
||||
if (QIcon::hasThemeIcon("dialog-close")) {
|
||||
closeButton->setIcon(QIcon::fromTheme("dialog-close"));
|
||||
}
|
||||
else if (QIcon::hasThemeIcon("gtk-close")) {
|
||||
closeButton->setIcon(QIcon::fromTheme("gtk-close"));
|
||||
}
|
||||
buttonLayout->addWidget(closeButton);
|
||||
messageLayout->addLayout(buttonLayout);
|
||||
QObject::connect(backButton, &QPushButton::clicked, [stackWidget,backButton,nextButton,closeButton]() {
|
||||
int index = stackWidget->currentIndex();
|
||||
if (index > 0) {
|
||||
index--;
|
||||
stackWidget->setCurrentIndex(index);
|
||||
nextButton->setEnabled(true);
|
||||
if (index > 0) {
|
||||
backButton->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
backButton->setEnabled(false);
|
||||
closeButton->setFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
QObject::connect(nextButton, &QPushButton::clicked, [stackWidget,backButton,nextButton,closeButton]() {
|
||||
int index = stackWidget->currentIndex();
|
||||
if (index < stackWidget->count()-1) {
|
||||
index++;
|
||||
stackWidget->setCurrentIndex(index);
|
||||
backButton->setEnabled(true);
|
||||
if (index < stackWidget->count()-1) {
|
||||
nextButton->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
nextButton->setEnabled(false);
|
||||
closeButton->setFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
QObject::connect(closeButton, &QPushButton::clicked, messageDialog, &QDialog::accept);
|
||||
QObject::connect(messageDialog, &QDialog::finished, messageDialog, &QDialog::deleteLater);
|
||||
QTimer::singleShot(0, closeButton, SLOT(setFocus()));
|
||||
messageDialog->show();
|
||||
}
|
||||
|
||||
void UserInterface::updateCacheId(uint cacheId)
|
||||
{
|
||||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Messages");
|
||||
settings.setValue("CacheId", cacheId);
|
||||
settings.endGroup();
|
||||
}
|
||||
#endif
|
||||
|
||||
void UserInterface::on_actionSelect_GTA_Folder_triggered()
|
||||
{
|
||||
QString GTAV_Folder_Temp = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly);
|
||||
|
@ -633,7 +766,13 @@ void UserInterface::retranslateUi()
|
|||
{
|
||||
ui->retranslateUi(this);
|
||||
ui->actionAbout_gta5sync->setText(tr("&About %1").arg(GTA5SYNC_APPSTR));
|
||||
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER));
|
||||
QString appVersion = GTA5SYNC_APPVER;
|
||||
#ifndef GTA5SYNC_BUILDTYPE_REL
|
||||
#ifdef GTA5SYNC_COMMIT
|
||||
if (!appVersion.contains("-")) { appVersion = appVersion % "-" % GTA5SYNC_COMMIT; }
|
||||
#endif
|
||||
#endif
|
||||
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion));
|
||||
if (profileOpen)
|
||||
{
|
||||
this->setWindowTitle(defaultWindowTitle.arg(profileName));
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
#include "MessageThread.h"
|
||||
#endif
|
||||
|
||||
namespace Ui {
|
||||
class UserInterface;
|
||||
}
|
||||
|
@ -39,8 +43,12 @@ class UserInterface : public QMainWindow
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
explicit UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, MessageThread *messageThread, QWidget *parent = 0);
|
||||
#else
|
||||
explicit UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent = 0);
|
||||
void setupDirEnv();
|
||||
#endif
|
||||
void setupDirEnv(bool showFolderDialog = true);
|
||||
~UserInterface();
|
||||
|
||||
private slots:
|
||||
|
@ -67,6 +75,11 @@ private slots:
|
|||
void on_actionSet_Crew_triggered();
|
||||
void on_actionSet_Title_triggered();
|
||||
void settingsApplied(int contentMode, bool languageChanged);
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
void messagesArrived(const QJsonObject &object);
|
||||
void showMessages(const QStringList messages);
|
||||
void updateCacheId(uint cacheId);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *ev);
|
||||
|
@ -75,6 +88,9 @@ private:
|
|||
ProfileDatabase *profileDB;
|
||||
CrewDatabase *crewDB;
|
||||
DatabaseThread *threadDB;
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
MessageThread *threadMessage;
|
||||
#endif
|
||||
Ui::UserInterface *ui;
|
||||
ProfileInterface *profileUI;
|
||||
QList<QPushButton*> profileBtns;
|
||||
|
|
|
@ -0,0 +1,537 @@
|
|||
/*****************************************************************************
|
||||
* ImageCropper Qt Widget for cropping images
|
||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
|
||||
* Copyright (C) 2020 Syping
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "imagecropper.h"
|
||||
#include "AppEnv.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
namespace {
|
||||
static const QSize WIDGET_MINIMUM_SIZE(470, 470);
|
||||
}
|
||||
|
||||
ImageCropper::ImageCropper(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
pimpl(new ImageCropperPrivate)
|
||||
{
|
||||
setMinimumSize(WIDGET_MINIMUM_SIZE);
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
ImageCropper::~ImageCropper()
|
||||
{
|
||||
delete pimpl;
|
||||
}
|
||||
|
||||
void ImageCropper::setImage(const QPixmap& _image)
|
||||
{
|
||||
pimpl->imageForCropping = _image;
|
||||
update();
|
||||
}
|
||||
|
||||
void ImageCropper::setBackgroundColor(const QColor& _backgroundColor)
|
||||
{
|
||||
pimpl->backgroundColor = _backgroundColor;
|
||||
update();
|
||||
}
|
||||
|
||||
void ImageCropper::setCroppingRectBorderColor(const QColor& _borderColor)
|
||||
{
|
||||
pimpl->croppingRectBorderColor = _borderColor;
|
||||
update();
|
||||
}
|
||||
|
||||
void ImageCropper::setProportion(const QSizeF& _proportion)
|
||||
{
|
||||
// Пропорции хранятся в коэффициентах приращения сторон
|
||||
// Таким образом, при изменении размера области выделения,
|
||||
// размеры сторон изменяются на размер зависящий от
|
||||
// коэффициентов приращения.
|
||||
|
||||
// Сохраним пропорциональную зависимость области выделения в коэффициентах приращения сторон
|
||||
if (pimpl->proportion != _proportion) {
|
||||
pimpl->proportion = _proportion;
|
||||
// ... расчитаем коэффициенты
|
||||
float heightDelta = (float)_proportion.height() / _proportion.width();
|
||||
float widthDelta = (float)_proportion.width() / _proportion.height();
|
||||
// ... сохраним коэффициенты
|
||||
pimpl->deltas.setHeight(heightDelta);
|
||||
pimpl->deltas.setWidth(widthDelta);
|
||||
}
|
||||
|
||||
// Обновим пропорции области выделения
|
||||
if ( pimpl->isProportionFixed ) {
|
||||
float croppintRectSideRelation =
|
||||
(float)pimpl->croppingRect.width() / pimpl->croppingRect.height();
|
||||
float proportionSideRelation =
|
||||
(float)pimpl->proportion.width() / pimpl->proportion.height();
|
||||
// Если область выделения не соответствует необходимым пропорциям обновим её
|
||||
if (croppintRectSideRelation != proportionSideRelation) {
|
||||
bool widthShotrerThenHeight =
|
||||
pimpl->croppingRect.width() < pimpl->croppingRect.height();
|
||||
// ... установим размер той стороны, что длиннее
|
||||
if (widthShotrerThenHeight) {
|
||||
pimpl->croppingRect.setHeight(
|
||||
pimpl->croppingRect.width() * pimpl->deltas.height());
|
||||
} else {
|
||||
pimpl->croppingRect.setWidth(
|
||||
pimpl->croppingRect.height() * pimpl->deltas.width());
|
||||
}
|
||||
// ... перерисуем виджет
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ImageCropper::setProportionFixed(const bool _isFixed)
|
||||
{
|
||||
if (pimpl->isProportionFixed != _isFixed) {
|
||||
pimpl->isProportionFixed = _isFixed;
|
||||
setProportion(pimpl->proportion);
|
||||
}
|
||||
}
|
||||
|
||||
const QPixmap ImageCropper::cropImage()
|
||||
{
|
||||
// Получим размер отображаемого изображения
|
||||
QSize scaledImageSize =
|
||||
pimpl->imageForCropping.scaled(
|
||||
size(), Qt::KeepAspectRatio, Qt::SmoothTransformation
|
||||
).size();
|
||||
// Определим расстояние от левого и верхнего краёв
|
||||
float leftDelta = 0;
|
||||
float topDelta = 0;
|
||||
const float HALF_COUNT = 2;
|
||||
if (size().height() == scaledImageSize.height()) {
|
||||
leftDelta = (width() - scaledImageSize.width()) / HALF_COUNT;
|
||||
} else {
|
||||
topDelta = (height() - scaledImageSize.height()) / HALF_COUNT;
|
||||
}
|
||||
// Определим пропорцию области обрезки по отношению к исходному изображению
|
||||
float xScale = (float)pimpl->imageForCropping.width() / scaledImageSize.width();
|
||||
float yScale = (float)pimpl->imageForCropping.height() / scaledImageSize.height();
|
||||
// Расчитаем область обрезки с учётом коррекции размеров исходного изображения
|
||||
QRectF realSizeRect(
|
||||
QPointF(pimpl->croppingRect.left() - leftDelta, pimpl->croppingRect.top() - topDelta),
|
||||
pimpl->croppingRect.size());
|
||||
// ... корректируем левый и верхний края
|
||||
realSizeRect.setLeft((pimpl->croppingRect.left() - leftDelta) * xScale);
|
||||
realSizeRect.setTop ((pimpl->croppingRect.top() - topDelta) * yScale);
|
||||
// ... корректируем размер
|
||||
realSizeRect.setWidth(pimpl->croppingRect.width() * xScale);
|
||||
realSizeRect.setHeight(pimpl->croppingRect.height() * yScale);
|
||||
// Получаем обрезанное изображение
|
||||
return pimpl->imageForCropping.copy(realSizeRect.toRect());
|
||||
}
|
||||
|
||||
// ********
|
||||
// Protected section
|
||||
|
||||
void ImageCropper::paintEvent(QPaintEvent* _event)
|
||||
{
|
||||
QWidget::paintEvent(_event);
|
||||
//
|
||||
QPainter widgetPainter(this);
|
||||
// Рисуем изображение по центру виджета
|
||||
{
|
||||
#if QT_VERSION >= 0x050600
|
||||
qreal screenRatioPR = AppEnv::screenRatioPR();
|
||||
// ... подгоним изображение для отображения по размеру виджета
|
||||
QPixmap scaledImage =
|
||||
pimpl->imageForCropping.scaled(qRound((double)width() * screenRatioPR), qRound((double)height() * screenRatioPR), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
scaledImage.setDevicePixelRatio(screenRatioPR);
|
||||
#else
|
||||
QPixmap scaledImage =
|
||||
pimpl->imageForCropping.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
#endif
|
||||
// ... заливаем фон
|
||||
widgetPainter.fillRect(rect(), pimpl->backgroundColor);
|
||||
// ... рисуем изображение по центру виджета
|
||||
#if QT_VERSION >= 0x050600
|
||||
if (qRound((double)height() * screenRatioPR) == scaledImage.height()) {
|
||||
widgetPainter.drawPixmap( ( qRound((double)width() * screenRatioPR) - scaledImage.width() ) / 2, 0, scaledImage );
|
||||
} else {
|
||||
widgetPainter.drawPixmap( 0, ( qRound((double)height() * screenRatioPR) - scaledImage.height() ) / 2, scaledImage );
|
||||
}
|
||||
#else
|
||||
if (height() == scaledImage.height()) {
|
||||
widgetPainter.drawPixmap( ( width()- scaledImage.width() ) / 2, 0, scaledImage );
|
||||
} else {
|
||||
widgetPainter.drawPixmap( 0, ( height() - scaledImage.height() ) / 2, scaledImage );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// Рисуем область обрезки
|
||||
{
|
||||
// ... если это первое отображение после инициилизации, то центруем областо обрезки
|
||||
if (pimpl->croppingRect.isNull()) {
|
||||
const int cwidth = WIDGET_MINIMUM_SIZE.width()/2;
|
||||
const int cheight = WIDGET_MINIMUM_SIZE.height()/2;
|
||||
pimpl->croppingRect.setSize(QSize(cwidth, cheight));
|
||||
float x = (width() - pimpl->croppingRect.width())/2;
|
||||
float y = (height() - pimpl->croppingRect.height())/2;
|
||||
pimpl->croppingRect.moveTo(x, y);
|
||||
}
|
||||
|
||||
// ... рисуем затемненную область
|
||||
QPainterPath p;
|
||||
p.addRect(pimpl->croppingRect);
|
||||
p.addRect(rect());
|
||||
widgetPainter.setBrush(QBrush(QColor(0,0,0,120)));
|
||||
widgetPainter.setPen(Qt::transparent);
|
||||
widgetPainter.drawPath(p);
|
||||
// Рамка и контрольные точки
|
||||
widgetPainter.setPen(pimpl->croppingRectBorderColor);
|
||||
// ... рисуем прямоугольник области обрезки
|
||||
{
|
||||
widgetPainter.setBrush(QBrush(Qt::transparent));
|
||||
widgetPainter.drawRect(pimpl->croppingRect);
|
||||
}
|
||||
// ... рисуем контрольные точки
|
||||
{
|
||||
widgetPainter.setBrush(QBrush(pimpl->croppingRectBorderColor));
|
||||
// Вспомогательные X координаты
|
||||
int leftXCoord = pimpl->croppingRect.left() - 2;
|
||||
int centerXCoord = pimpl->croppingRect.center().x() - 3;
|
||||
int rightXCoord = pimpl->croppingRect.right() - 2;
|
||||
// Вспомогательные Y координаты
|
||||
int topYCoord = pimpl->croppingRect.top() - 2;
|
||||
int middleYCoord = pimpl->croppingRect.center().y() - 3;
|
||||
int bottomYCoord = pimpl->croppingRect.bottom() - 2;
|
||||
//
|
||||
const QSize pointSize(6, 6);
|
||||
//
|
||||
QVector<QRect> points;
|
||||
points
|
||||
// левая сторона
|
||||
<< QRect( QPoint(leftXCoord, topYCoord), pointSize )
|
||||
<< QRect( QPoint(leftXCoord, middleYCoord), pointSize )
|
||||
<< QRect( QPoint(leftXCoord, bottomYCoord), pointSize )
|
||||
// центр
|
||||
<< QRect( QPoint(centerXCoord, topYCoord), pointSize )
|
||||
<< QRect( QPoint(centerXCoord, middleYCoord), pointSize )
|
||||
<< QRect( QPoint(centerXCoord, bottomYCoord), pointSize )
|
||||
// правая сторона
|
||||
<< QRect( QPoint(rightXCoord, topYCoord), pointSize )
|
||||
<< QRect( QPoint(rightXCoord, middleYCoord), pointSize )
|
||||
<< QRect( QPoint(rightXCoord, bottomYCoord), pointSize );
|
||||
//
|
||||
widgetPainter.drawRects( points );
|
||||
}
|
||||
// ... рисуем пунктирные линии
|
||||
{
|
||||
QPen dashPen(pimpl->croppingRectBorderColor);
|
||||
dashPen.setStyle(Qt::DashLine);
|
||||
widgetPainter.setPen(dashPen);
|
||||
// ... вертикальная
|
||||
widgetPainter.drawLine(
|
||||
QPoint(pimpl->croppingRect.center().x(), pimpl->croppingRect.top()),
|
||||
QPoint(pimpl->croppingRect.center().x(), pimpl->croppingRect.bottom()) );
|
||||
// ... горизонтальная
|
||||
widgetPainter.drawLine(
|
||||
QPoint(pimpl->croppingRect.left(), pimpl->croppingRect.center().y()),
|
||||
QPoint(pimpl->croppingRect.right(), pimpl->croppingRect.center().y()) );
|
||||
}
|
||||
}
|
||||
//
|
||||
widgetPainter.end();
|
||||
}
|
||||
|
||||
void ImageCropper::mousePressEvent(QMouseEvent* _event)
|
||||
{
|
||||
if (_event->button() == Qt::LeftButton) {
|
||||
pimpl->isMousePressed = true;
|
||||
pimpl->startMousePos = _event->pos();
|
||||
pimpl->lastStaticCroppingRect = pimpl->croppingRect;
|
||||
}
|
||||
//
|
||||
updateCursorIcon(_event->pos());
|
||||
}
|
||||
|
||||
void ImageCropper::mouseMoveEvent(QMouseEvent* _event)
|
||||
{
|
||||
QPointF mousePos = _event->pos(); // относительно себя (виджета)
|
||||
//
|
||||
if (!pimpl->isMousePressed) {
|
||||
// Обработка обычного состояния, т.е. не изменяется размер
|
||||
// области обрезки, и она не перемещается по виджету
|
||||
pimpl->cursorPosition = cursorPosition(pimpl->croppingRect, mousePos);
|
||||
updateCursorIcon(mousePos);
|
||||
} else if (pimpl->cursorPosition != CursorPositionUndefined) {
|
||||
// Обработка действий над областью обрезки
|
||||
// ... определим смещение курсора мышки
|
||||
QPointF mouseDelta;
|
||||
mouseDelta.setX( mousePos.x() - pimpl->startMousePos.x() );
|
||||
mouseDelta.setY( mousePos.y() - pimpl->startMousePos.y() );
|
||||
//
|
||||
if (pimpl->cursorPosition != CursorPositionMiddle) {
|
||||
// ... изменяем размер области обрезки
|
||||
QRectF newGeometry =
|
||||
calculateGeometry(
|
||||
pimpl->lastStaticCroppingRect,
|
||||
pimpl->cursorPosition,
|
||||
mouseDelta);
|
||||
// ... пользователь пытается вывернуть область обрезки наизнанку
|
||||
if (!newGeometry.isNull()) {
|
||||
pimpl->croppingRect = newGeometry;
|
||||
}
|
||||
} else {
|
||||
// ... перемещаем область обрезки
|
||||
pimpl->croppingRect.moveTo( pimpl->lastStaticCroppingRect.topLeft() + mouseDelta );
|
||||
}
|
||||
// Перерисуем виджет
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageCropper::mouseReleaseEvent(QMouseEvent* _event)
|
||||
{
|
||||
pimpl->isMousePressed = false;
|
||||
updateCursorIcon(_event->pos());
|
||||
}
|
||||
|
||||
// ********
|
||||
// Private section
|
||||
|
||||
namespace {
|
||||
// Находится ли точка рядом с координатой стороны
|
||||
static bool isPointNearSide (const int _sideCoordinate, const int _pointCoordinate)
|
||||
{
|
||||
static const int indent = 10;
|
||||
return (_sideCoordinate - indent) < _pointCoordinate && _pointCoordinate < (_sideCoordinate + indent);
|
||||
}
|
||||
}
|
||||
|
||||
CursorPosition ImageCropper::cursorPosition(const QRectF& _cropRect, const QPointF& _mousePosition)
|
||||
{
|
||||
CursorPosition cursorPosition = CursorPositionUndefined;
|
||||
//
|
||||
if ( _cropRect.contains( _mousePosition ) ) {
|
||||
// Двухстороннее направление
|
||||
if (isPointNearSide(_cropRect.top(), _mousePosition.y()) &&
|
||||
isPointNearSide(_cropRect.left(), _mousePosition.x())) {
|
||||
cursorPosition = CursorPositionTopLeft;
|
||||
} else if (isPointNearSide(_cropRect.bottom(), _mousePosition.y()) &&
|
||||
isPointNearSide(_cropRect.left(), _mousePosition.x())) {
|
||||
cursorPosition = CursorPositionBottomLeft;
|
||||
} else if (isPointNearSide(_cropRect.top(), _mousePosition.y()) &&
|
||||
isPointNearSide(_cropRect.right(), _mousePosition.x())) {
|
||||
cursorPosition = CursorPositionTopRight;
|
||||
} else if (isPointNearSide(_cropRect.bottom(), _mousePosition.y()) &&
|
||||
isPointNearSide(_cropRect.right(), _mousePosition.x())) {
|
||||
cursorPosition = CursorPositionBottomRight;
|
||||
// Одностороннее направление
|
||||
} else if (isPointNearSide(_cropRect.left(), _mousePosition.x())) {
|
||||
cursorPosition = CursorPositionLeft;
|
||||
} else if (isPointNearSide(_cropRect.right(), _mousePosition.x())) {
|
||||
cursorPosition = CursorPositionRight;
|
||||
} else if (isPointNearSide(_cropRect.top(), _mousePosition.y())) {
|
||||
cursorPosition = CursorPositionTop;
|
||||
} else if (isPointNearSide(_cropRect.bottom(), _mousePosition.y())) {
|
||||
cursorPosition = CursorPositionBottom;
|
||||
// Без направления
|
||||
} else {
|
||||
cursorPosition = CursorPositionMiddle;
|
||||
}
|
||||
}
|
||||
//
|
||||
return cursorPosition;
|
||||
}
|
||||
|
||||
void ImageCropper::updateCursorIcon(const QPointF& _mousePosition)
|
||||
{
|
||||
QCursor cursorIcon;
|
||||
//
|
||||
switch (cursorPosition(pimpl->croppingRect, _mousePosition))
|
||||
{
|
||||
case CursorPositionTopRight:
|
||||
case CursorPositionBottomLeft:
|
||||
cursorIcon = QCursor(Qt::SizeBDiagCursor);
|
||||
break;
|
||||
case CursorPositionTopLeft:
|
||||
case CursorPositionBottomRight:
|
||||
cursorIcon = QCursor(Qt::SizeFDiagCursor);
|
||||
break;
|
||||
case CursorPositionTop:
|
||||
case CursorPositionBottom:
|
||||
cursorIcon = QCursor(Qt::SizeVerCursor);
|
||||
break;
|
||||
case CursorPositionLeft:
|
||||
case CursorPositionRight:
|
||||
cursorIcon = QCursor(Qt::SizeHorCursor);
|
||||
break;
|
||||
case CursorPositionMiddle:
|
||||
cursorIcon = pimpl->isMousePressed ?
|
||||
QCursor(Qt::ClosedHandCursor) :
|
||||
QCursor(Qt::OpenHandCursor);
|
||||
break;
|
||||
case CursorPositionUndefined:
|
||||
default:
|
||||
cursorIcon = QCursor(Qt::ArrowCursor);
|
||||
break;
|
||||
}
|
||||
//
|
||||
this->setCursor(cursorIcon);
|
||||
}
|
||||
|
||||
const QRectF ImageCropper::calculateGeometry(
|
||||
const QRectF& _sourceGeometry,
|
||||
const CursorPosition _cursorPosition,
|
||||
const QPointF& _mouseDelta
|
||||
)
|
||||
{
|
||||
QRectF resultGeometry;
|
||||
//
|
||||
if ( pimpl->isProportionFixed ) {
|
||||
resultGeometry =
|
||||
calculateGeometryWithFixedProportions(
|
||||
_sourceGeometry, _cursorPosition, _mouseDelta, pimpl->deltas);
|
||||
} else {
|
||||
resultGeometry =
|
||||
calculateGeometryWithCustomProportions(
|
||||
_sourceGeometry, _cursorPosition, _mouseDelta);
|
||||
}
|
||||
// Если пользователь пытается вывернуть область обрезки наизнанку,
|
||||
// возвращаем null-прямоугольник
|
||||
if ((resultGeometry.left() >= resultGeometry.right()) ||
|
||||
(resultGeometry.top() >= resultGeometry.bottom())) {
|
||||
resultGeometry = QRect();
|
||||
}
|
||||
//
|
||||
return resultGeometry;
|
||||
}
|
||||
|
||||
const QRectF ImageCropper::calculateGeometryWithCustomProportions(
|
||||
const QRectF& _sourceGeometry,
|
||||
const CursorPosition _cursorPosition,
|
||||
const QPointF& _mouseDelta
|
||||
)
|
||||
{
|
||||
QRectF resultGeometry = _sourceGeometry;
|
||||
//
|
||||
switch ( _cursorPosition )
|
||||
{
|
||||
case CursorPositionTopLeft:
|
||||
resultGeometry.setLeft( _sourceGeometry.left() + _mouseDelta.x() );
|
||||
resultGeometry.setTop ( _sourceGeometry.top() + _mouseDelta.y() );
|
||||
break;
|
||||
case CursorPositionTopRight:
|
||||
resultGeometry.setTop ( _sourceGeometry.top() + _mouseDelta.y() );
|
||||
resultGeometry.setRight( _sourceGeometry.right() + _mouseDelta.x() );
|
||||
break;
|
||||
case CursorPositionBottomLeft:
|
||||
resultGeometry.setBottom( _sourceGeometry.bottom() + _mouseDelta.y() );
|
||||
resultGeometry.setLeft ( _sourceGeometry.left() + _mouseDelta.x() );
|
||||
break;
|
||||
case CursorPositionBottomRight:
|
||||
resultGeometry.setBottom( _sourceGeometry.bottom() + _mouseDelta.y() );
|
||||
resultGeometry.setRight ( _sourceGeometry.right() + _mouseDelta.x() );
|
||||
break;
|
||||
case CursorPositionTop:
|
||||
resultGeometry.setTop( _sourceGeometry.top() + _mouseDelta.y() );
|
||||
break;
|
||||
case CursorPositionBottom:
|
||||
resultGeometry.setBottom( _sourceGeometry.bottom() + _mouseDelta.y() );
|
||||
break;
|
||||
case CursorPositionLeft:
|
||||
resultGeometry.setLeft( _sourceGeometry.left() + _mouseDelta.x() );
|
||||
break;
|
||||
case CursorPositionRight:
|
||||
resultGeometry.setRight( _sourceGeometry.right() + _mouseDelta.x() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//
|
||||
return resultGeometry;
|
||||
}
|
||||
|
||||
const QRectF ImageCropper::calculateGeometryWithFixedProportions(
|
||||
const QRectF& _sourceGeometry,
|
||||
const CursorPosition _cursorPosition,
|
||||
const QPointF& _mouseDelta,
|
||||
const QSizeF& _deltas
|
||||
)
|
||||
{
|
||||
QRectF resultGeometry = _sourceGeometry;
|
||||
//
|
||||
switch (_cursorPosition)
|
||||
{
|
||||
case CursorPositionLeft:
|
||||
resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.x() * _deltas.height());
|
||||
resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.x());
|
||||
break;
|
||||
case CursorPositionRight:
|
||||
resultGeometry.setTop(_sourceGeometry.top() - _mouseDelta.x() * _deltas.height());
|
||||
resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.x());
|
||||
break;
|
||||
case CursorPositionTop:
|
||||
resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.y());
|
||||
resultGeometry.setRight(_sourceGeometry.right() - _mouseDelta.y() * _deltas.width());
|
||||
break;
|
||||
case CursorPositionBottom:
|
||||
resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.y());
|
||||
resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.y() * _deltas.width());
|
||||
break;
|
||||
case CursorPositionTopLeft:
|
||||
if ((_mouseDelta.x() * _deltas.height()) < (_mouseDelta.y())) {
|
||||
resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.x() * _deltas.height());
|
||||
resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.x());
|
||||
} else {
|
||||
resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.y());
|
||||
resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.y() * _deltas.width());
|
||||
}
|
||||
break;
|
||||
case CursorPositionTopRight:
|
||||
if ((_mouseDelta.x() * _deltas.height() * -1) < (_mouseDelta.y())) {
|
||||
resultGeometry.setTop(_sourceGeometry.top() - _mouseDelta.x() * _deltas.height());
|
||||
resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.x() );
|
||||
} else {
|
||||
resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.y());
|
||||
resultGeometry.setRight(_sourceGeometry.right() - _mouseDelta.y() * _deltas.width());
|
||||
}
|
||||
break;
|
||||
case CursorPositionBottomLeft:
|
||||
if ((_mouseDelta.x() * _deltas.height()) < (_mouseDelta.y() * -1)) {
|
||||
resultGeometry.setBottom(_sourceGeometry.bottom() - _mouseDelta.x() * _deltas.height());
|
||||
resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.x());
|
||||
} else {
|
||||
resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.y());
|
||||
resultGeometry.setLeft(_sourceGeometry.left() - _mouseDelta.y() * _deltas.width());
|
||||
}
|
||||
break;
|
||||
case CursorPositionBottomRight:
|
||||
if ((_mouseDelta.x() * _deltas.height()) > (_mouseDelta.y())) {
|
||||
resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.x() * _deltas.height());
|
||||
resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.x());
|
||||
} else {
|
||||
resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.y());
|
||||
resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.y() * _deltas.width());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//
|
||||
return resultGeometry;
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/*****************************************************************************
|
||||
* ImageCropper Qt Widget for cropping images
|
||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef IMAGECROPPER_H
|
||||
#define IMAGECROPPER_H
|
||||
|
||||
#include "imagecropper_p.h"
|
||||
#include "imagecropper_e.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class ImageCropper : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImageCropper(QWidget *parent = 0);
|
||||
~ImageCropper();
|
||||
|
||||
public slots:
|
||||
// Установить изображение для обрезки
|
||||
void setImage(const QPixmap& _image);
|
||||
// Установить цвет фона виджета обрезки
|
||||
void setBackgroundColor(const QColor& _backgroundColor);
|
||||
// Установить цвет рамки области обрезки
|
||||
void setCroppingRectBorderColor(const QColor& _borderColor);
|
||||
// Установить пропорции области выделения
|
||||
void setProportion(const QSizeF& _proportion);
|
||||
// Использовать фиксированные пропорции области виделения
|
||||
void setProportionFixed(const bool _isFixed);
|
||||
|
||||
public:
|
||||
// Обрезать изображение
|
||||
const QPixmap cropImage();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* _event);
|
||||
virtual void mousePressEvent(QMouseEvent* _event);
|
||||
virtual void mouseMoveEvent(QMouseEvent* _event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* _event);
|
||||
|
||||
private:
|
||||
// Определение местоположения курсора над виджетом
|
||||
CursorPosition cursorPosition(const QRectF& _cropRect, const QPointF& _mousePosition);
|
||||
// Обновить иконку курсора соответствующую местоположению мыши
|
||||
void updateCursorIcon(const QPointF& _mousePosition);
|
||||
|
||||
// Получить размер виджета после его изменения мышью
|
||||
// --------
|
||||
// Контракты:
|
||||
// 1. Метод должен вызываться, только при зажатой кнопке мыши
|
||||
// (т.е. при перемещении или изменении размера виджета)
|
||||
// --------
|
||||
// В случае неудачи возвращает null-прямоугольник
|
||||
const QRectF calculateGeometry(
|
||||
const QRectF& _sourceGeometry,
|
||||
const CursorPosition _cursorPosition,
|
||||
const QPointF& _mouseDelta
|
||||
);
|
||||
// Получить размер виджета после его изменения мышью
|
||||
// Метод изменяет виджет не сохраняя начальных пропорций сторон
|
||||
// ------
|
||||
// Контракты:
|
||||
// 1. Метод должен вызываться, только при зажатой кнопке мыши
|
||||
// (т.е. при перемещении или изменении размера виджета)
|
||||
const QRectF calculateGeometryWithCustomProportions(
|
||||
const QRectF& _sourceGeometry,
|
||||
const CursorPosition _cursorPosition,
|
||||
const QPointF& _mouseDelta
|
||||
);
|
||||
// Получить размер виджета после его изменения мышью
|
||||
// Метод изменяет виджет сохраняя начальные пропорции сторон
|
||||
// ------
|
||||
// Контракты:
|
||||
// 1. Метод должен вызываться, только при зажатой кнопке мыши
|
||||
// (т.е. при перемещении или изменении размера виджета)
|
||||
const QRectF calculateGeometryWithFixedProportions(const QRectF &_sourceGeometry,
|
||||
const CursorPosition _cursorPosition,
|
||||
const QPointF &_mouseDelta,
|
||||
const QSizeF &_deltas
|
||||
);
|
||||
|
||||
private:
|
||||
// Private data implementation
|
||||
ImageCropperPrivate* pimpl;
|
||||
};
|
||||
|
||||
#endif // IMAGECROPPER_H
|
|
@ -0,0 +1,36 @@
|
|||
/*****************************************************************************
|
||||
* ImageCropper Qt Widget for cropping images
|
||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef IMAGECROPPER_E_H
|
||||
#define IMAGECROPPER_E_H
|
||||
|
||||
enum CursorPosition
|
||||
{
|
||||
CursorPositionUndefined,
|
||||
CursorPositionMiddle,
|
||||
CursorPositionTop,
|
||||
CursorPositionBottom,
|
||||
CursorPositionLeft,
|
||||
CursorPositionRight,
|
||||
CursorPositionTopLeft,
|
||||
CursorPositionTopRight,
|
||||
CursorPositionBottomLeft,
|
||||
CursorPositionBottomRight
|
||||
};
|
||||
|
||||
#endif // IMAGECROPPER_E_H
|
|
@ -0,0 +1,76 @@
|
|||
/*****************************************************************************
|
||||
* ImageCropper Qt Widget for cropping images
|
||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef IMAGECROPPER_P_H
|
||||
#define IMAGECROPPER_P_H
|
||||
|
||||
#include "imagecropper_e.h"
|
||||
|
||||
#include <QtCore/QRect>
|
||||
#include <QtGui/QPixmap>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
namespace {
|
||||
const QRect INIT_CROPPING_RECT = QRect();
|
||||
const QSizeF INIT_PROPORTION = QSizeF(1.0, 1.0);
|
||||
}
|
||||
|
||||
class ImageCropperPrivate {
|
||||
public:
|
||||
ImageCropperPrivate() :
|
||||
imageForCropping(QPixmap()),
|
||||
croppingRect(INIT_CROPPING_RECT),
|
||||
lastStaticCroppingRect(QRect()),
|
||||
cursorPosition(CursorPositionUndefined),
|
||||
isMousePressed(false),
|
||||
isProportionFixed(false),
|
||||
startMousePos(QPoint()),
|
||||
proportion(INIT_PROPORTION),
|
||||
deltas(INIT_PROPORTION),
|
||||
backgroundColor(Qt::black),
|
||||
croppingRectBorderColor(Qt::white)
|
||||
{}
|
||||
|
||||
public:
|
||||
// Изображение для обрезки
|
||||
QPixmap imageForCropping;
|
||||
// Область обрезки
|
||||
QRectF croppingRect;
|
||||
// Последняя фиксированная область обрезки
|
||||
QRectF lastStaticCroppingRect;
|
||||
// Позиция курсора относительно области обрезки
|
||||
CursorPosition cursorPosition;
|
||||
// Зажата ли левая кнопка мыши
|
||||
bool isMousePressed;
|
||||
// Фиксировать пропорции области обрезки
|
||||
bool isProportionFixed;
|
||||
// Начальная позиция курсора при изменении размера области обрезки
|
||||
QPointF startMousePos;
|
||||
// Пропорции
|
||||
QSizeF proportion;
|
||||
// Приращения
|
||||
// width - приращение по x
|
||||
// height - приращение по y
|
||||
QSizeF deltas;
|
||||
// Цвет заливки фона под изображением
|
||||
QColor backgroundColor;
|
||||
// Цвет рамки области обрезки
|
||||
QColor croppingRectBorderColor;
|
||||
};
|
||||
|
||||
#endif // IMAGECROPPER_P_H
|
21
config.h
21
config.h
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2020 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,14 +18,17 @@
|
|||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#if __cplusplus
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_APPVENDOR
|
||||
#define GTA5SYNC_APPVENDOR "Syping"
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_APPVENDORLINK
|
||||
#define GTA5SYNC_APPVENDORLINK "https://github.com/Syping/"
|
||||
#define GTA5SYNC_APPVENDORLINK "g5e://about?U3lwaW5n:R2l0TGFiOiA8YSBocmVmPSJodHRwczovL2dpdGxhYi5jb20vU3lwaW5nIj5TeXBpbmc8L2E+PGJyLz5HaXRIdWI6IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9TeXBpbmciPlN5cGluZzwvYT48YnIvPlNvY2lhbCBDbHViOiA8YSBocmVmPSJodHRwczovL3NvY2lhbGNsdWIucm9ja3N0YXJnYW1lcy5jb20vbWVtYmVyL1N5cGluZy80NjMwMzA1NiI+U3lwaW5nPC9hPg=="
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_APPSTR
|
||||
|
@ -37,13 +40,14 @@
|
|||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_COPYRIGHT
|
||||
#define GTA5SYNC_COPYRIGHT "2016-2018"
|
||||
#define GTA5SYNC_COPYRIGHT "2016-2020"
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_APPVER
|
||||
#define GTA5SYNC_APPVER "1.5.5"
|
||||
#define GTA5SYNC_APPVER "1.8.0"
|
||||
#endif
|
||||
|
||||
#if __cplusplus
|
||||
#ifdef GTA5SYNC_BUILDTYPE_REL
|
||||
#ifndef GTA5SYNC_BUILDTYPE
|
||||
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Release")
|
||||
|
@ -103,22 +107,16 @@
|
|||
#define GTA5SYNC_INLANG ":/tr"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
#ifndef GTA5SYNC_SHARE
|
||||
#define GTA5SYNC_SHARE "RUNDIR:"
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_LANG
|
||||
#define GTA5SYNC_LANG "SHAREDDIR:SEPARATOR:lang"
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_PLUG
|
||||
#define GTA5SYNC_PLUG "RUNDIR:SEPARATOR:plugins"
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_WINRT
|
||||
#undef GTA5SYNC_WIN
|
||||
#endif
|
||||
|
||||
#ifndef GTA5SYNC_COMPILER
|
||||
|
@ -146,5 +144,6 @@
|
|||
#ifndef GTA5SYNC_BUILDSTRING
|
||||
#define GTA5SYNC_BUILDSTRING QString("%1, %2").arg(QT_VERSION_STR, GTA5SYNC_COMPILER)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_H
|
||||
|
|
102
gta5view.pro
102
gta5view.pro
|
@ -1,6 +1,6 @@
|
|||
#/*****************************************************************************
|
||||
#* gta5view Grand Theft Auto V Profile Viewer
|
||||
#* Copyright (C) 2015-2018 Syping
|
||||
#* Copyright (C) 2015-2020 Syping
|
||||
#*
|
||||
#* This program is free software: you can redistribute it and/or modify
|
||||
#* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,7 +16,7 @@
|
|||
#* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#*****************************************************************************/
|
||||
|
||||
QT += core gui network
|
||||
QT += core gui network svg
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): greaterThan(QT_MINOR_VERSION, 1): win32: QT += winextras
|
||||
|
@ -37,10 +37,10 @@ SOURCES += main.cpp \
|
|||
ExportThread.cpp \
|
||||
GlobalString.cpp \
|
||||
IconLoader.cpp \
|
||||
ImageEditorDialog.cpp \
|
||||
ImportDialog.cpp \
|
||||
JsonEditorDialog.cpp \
|
||||
MapLocationDialog.cpp \
|
||||
MessageThread.cpp \
|
||||
OptionsDialog.cpp \
|
||||
PictureDialog.cpp \
|
||||
PictureExport.cpp \
|
||||
|
@ -63,12 +63,14 @@ SOURCES += main.cpp \
|
|||
TelemetryClass.cpp \
|
||||
TranslationClass.cpp \
|
||||
UserInterface.cpp \
|
||||
anpro/JSHighlighter.cpp \
|
||||
anpro/imagecropper.cpp \
|
||||
pcg/pcg_basic.c \
|
||||
tmext/TelemetryClassAuthenticator.cpp \
|
||||
uimod/JSHighlighter.cpp \
|
||||
uimod/UiModLabel.cpp \
|
||||
uimod/UiModWidget.cpp
|
||||
|
||||
HEADERS += \
|
||||
HEADERS += \
|
||||
AboutDialog.h \
|
||||
AppEnv.h \
|
||||
CrewDatabase.h \
|
||||
|
@ -77,10 +79,10 @@ HEADERS += \
|
|||
ExportThread.h \
|
||||
GlobalString.h \
|
||||
IconLoader.h \
|
||||
ImageEditorDialog.h \
|
||||
ImportDialog.h \
|
||||
JsonEditorDialog.h \
|
||||
MapLocationDialog.h \
|
||||
MessageThread.h \
|
||||
OptionsDialog.h \
|
||||
PictureDialog.h \
|
||||
PictureExport.h \
|
||||
|
@ -103,15 +105,18 @@ HEADERS += \
|
|||
TelemetryClass.h \
|
||||
TranslationClass.h \
|
||||
UserInterface.h \
|
||||
anpro/JSHighlighter.h \
|
||||
anpro/imagecropper.h \
|
||||
anpro/imagecropper_e.h \
|
||||
anpro/imagecropper_p.h \
|
||||
pcg/pcg_basic.h \
|
||||
tmext/TelemetryClassAuthenticator.h \
|
||||
uimod/JSHighlighter.h \
|
||||
uimod/UiModLabel.h \
|
||||
uimod/UiModWidget.h
|
||||
|
||||
FORMS += \
|
||||
FORMS += \
|
||||
AboutDialog.ui \
|
||||
ExportDialog.ui \
|
||||
ImageEditorDialog.ui \
|
||||
ImportDialog.ui \
|
||||
JsonEditorDialog.ui \
|
||||
MapLocationDialog.ui \
|
||||
|
@ -126,21 +131,37 @@ FORMS += \
|
|||
UserInterface.ui
|
||||
|
||||
TRANSLATIONS += \
|
||||
res/gta5sync_en_US.ts \
|
||||
res/gta5sync.ts \
|
||||
res/gta5sync_de.ts \
|
||||
res/gta5sync_en_US.ts \
|
||||
res/gta5sync_fr.ts \
|
||||
res/gta5sync_ko.ts \
|
||||
res/gta5sync_ru.ts \
|
||||
res/gta5sync_uk.ts \
|
||||
res/gta5sync_zh_TW.ts
|
||||
|
||||
RESOURCES += \
|
||||
res/tr_g5p.qrc \
|
||||
res/app.qrc
|
||||
res/app.qrc \
|
||||
res/tr_g5p.qrc
|
||||
|
||||
DISTFILES += res/app.rc \
|
||||
res/gta5view.desktop \
|
||||
DISTFILES += \
|
||||
res/gta5view-16.png \
|
||||
res/gta5view-24.png \
|
||||
res/gta5view-32.png \
|
||||
res/gta5view-40.png \
|
||||
res/gta5view-48.png \
|
||||
res/gta5view-64.png \
|
||||
res/gta5view-96.png \
|
||||
res/gta5view-128.png \
|
||||
res/gta5view-256.png \
|
||||
res/gta5view-512.png \
|
||||
res/app.rc \
|
||||
res/de.syping.gta5view.desktop \
|
||||
res/de.syping.gta5view.png \
|
||||
res/gta5sync_de.ts \
|
||||
res/gta5sync_en_US.ts \
|
||||
res/gta5sync_fr.ts \
|
||||
res/gta5sync_ko.ts \
|
||||
res/gta5sync_ru.ts \
|
||||
res/gta5sync_uk.ts \
|
||||
res/gta5sync_zh_TW.ts \
|
||||
|
@ -148,20 +169,19 @@ DISTFILES += res/app.rc \
|
|||
res/gta5view.png \
|
||||
lang/README.txt
|
||||
|
||||
INCLUDEPATH += ./anpro ./tmext ./uimod
|
||||
INCLUDEPATH += ./anpro ./pcg ./tmext ./uimod
|
||||
|
||||
# GTA5SYNC/GTA5VIEW ONLY
|
||||
|
||||
DEFINES += GTA5SYNC_QMAKE # We using qmake do we?
|
||||
DEFINES += GTA5SYNC_PROJECT # Enable exclusive gta5sync/gta5view functions
|
||||
DEFINES += GTA5SYNC_NOASSIST # Not assisting at proper usage of SnapmaticPicture class
|
||||
DEFINES += SNAPMATIC_NODEFAULT # Not assisting at proper usage of SnapmaticPicture class
|
||||
|
||||
# WINDOWS ONLY
|
||||
|
||||
win32: DEFINES += GTA5SYNC_WIN
|
||||
win32: RC_FILE += res/app.rc
|
||||
win32: LIBS += -luser32
|
||||
win32: CONFIG -= embed_manifest_exe
|
||||
contains(DEFINES, GTA5SYNC_APV): greaterThan(QT_MAJOR_VERSION, 4): greaterThan(QT_MINOR_VERSION, 1): win32: LIBS += -ldwmapi
|
||||
contains(DEFINES, GTA5SYNC_TELEMETRY): win32: LIBS += -ld3d9 # Required for getting information about GPU
|
||||
|
||||
# MAC OS X ONLY
|
||||
macx: ICON = res/5sync.icns
|
||||
|
@ -187,39 +207,71 @@ isEqual(QT_MAJOR_VERSION, 4): SOURCES += qjson4/QJsonArray.cpp \
|
|||
qjson4/QJsonParser.cpp
|
||||
|
||||
isEqual(QT_MAJOR_VERSION, 4): RESOURCES += res/tr_qt4.qrc
|
||||
isEqual(QT_MAJOR_VERSION, 4): GTA5SYNC_RCC = $$[QT_INSTALL_BINS]/rcc
|
||||
|
||||
# QT5 ONLY STUFF
|
||||
|
||||
isEqual(QT_MAJOR_VERSION, 5): RESOURCES += res/tr_qt5.qrc
|
||||
|
||||
# QT5+ ONLY STUFF
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): GTA5SYNC_RCC = $$[QT_HOST_BINS]/rcc
|
||||
|
||||
# RESOURCE COMPILATION
|
||||
|
||||
system($$GTA5SYNC_RCC -threshold 0 -compress 9 $$PWD/res/global.qrc -o $$OUT_PWD/qrc_global.cpp) {
|
||||
SOURCES += $$OUT_PWD/qrc_global.cpp
|
||||
} else {
|
||||
message("Failed to generate qrc_global.cpp")
|
||||
}
|
||||
|
||||
# PROJECT INSTALLATION
|
||||
|
||||
isEmpty(GTA5SYNC_PREFIX): GTA5SYNC_PREFIX = /usr/local
|
||||
|
||||
appfiles.path = $$GTA5SYNC_PREFIX/share/applications
|
||||
appfiles.files = $$PWD/res/gta5view.desktop
|
||||
appfiles.files = $$PWD/res/de.syping.gta5view.desktop
|
||||
pixmaps.path = $$GTA5SYNC_PREFIX/share/pixmaps
|
||||
pixmaps.files = $$PWD/res/gta5view.png
|
||||
pixmaps.files = $$PWD/res/de.syping.gta5view.png
|
||||
target.path = $$GTA5SYNC_PREFIX/bin
|
||||
INSTALLS += target pixmaps appfiles
|
||||
|
||||
# QCONF BASED BUILD STUFF
|
||||
|
||||
contains(DEFINES, GTA5SYNC_QCONF){
|
||||
contains(DEFINES, GTA5SYNC_QCONF) {
|
||||
isEqual(QT_MAJOR_VERSION, 4): RESOURCES -= res/tr_qt4.qrc
|
||||
isEqual(QT_MAJOR_VERSION, 5): RESOURCES -= res/tr_qt5.qrc
|
||||
!contains(DEFINES, GTA5SYNC_QCONF_IN){
|
||||
!contains(DEFINES, GTA5SYNC_QCONF_IN) {
|
||||
RESOURCES -= res/tr_g5p.qrc
|
||||
langfiles.path = $$GTA5SYNC_PREFIX/share/gta5view/translations
|
||||
langfiles.files = $$PWD/res/gta5sync_en_US.qm $$PWD/res/gta5sync_de.qm $$PWD/res/gta5sync_fr.qm $$PWD/res/gta5sync_ru.qm $$PWD/res/gta5sync_uk.qm $$PWD/res/gta5sync_zh_TW.qm $$PWD/res/qtbase_en_GB.qm $$PWD/res/qtbase_zh_TW.qm
|
||||
langfiles.files = $$PWD/res/gta5sync_en_US.qm $$PWD/res/gta5sync_de.qm $$PWD/res/gta5sync_fr.qm $$PWD/res/gta5sync_ko.qm $$PWD/res/gta5sync_ru.qm $$PWD/res/gta5sync_uk.qm $$PWD/res/gta5sync_zh_TW.qm $$PWD/res/qtbase_en_GB.qm
|
||||
INSTALLS += langfiles
|
||||
}
|
||||
}
|
||||
|
||||
# TELEMETRY BASED STUFF
|
||||
|
||||
!contains(DEFINES, GTA5SYNC_TELEMETRY){
|
||||
!contains(DEFINES, GTA5SYNC_TELEMETRY) {
|
||||
SOURCES -= TelemetryClass.cpp \
|
||||
tmext/TelemetryClassAuthenticator.cpp
|
||||
HEADERS -= TelemetryClass.h \
|
||||
tmext/TelemetryClassAuthenticator.h
|
||||
}
|
||||
|
||||
!contains(DEFINES, GTA5SYNC_MOTD) {
|
||||
SOURCES -= MessageThread.cpp
|
||||
HEADERS -= MessageThread.h
|
||||
} else {
|
||||
lessThan(QT_MAJOR_VERSION, 5) {
|
||||
SOURCES -= MessageThread.cpp
|
||||
HEADERS -= MessageThread.h
|
||||
DEFINES -= GTA5SYNC_MOTD
|
||||
message("Messages require Qt5 or newer!")
|
||||
}
|
||||
}
|
||||
|
||||
# CMAKE BASED STUFF
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
message("Building gta5view with QMake is deprecated, please use CMake instead!")
|
||||
}
|
||||
|
|
124
main.cpp
124
main.cpp
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
* gta5view Grand Theft Auto V Profile Viewer
|
||||
* Copyright (C) 2016-2018 Syping
|
||||
* Copyright (C) 2016-2019 Syping
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -31,7 +31,6 @@
|
|||
#include "IconLoader.h"
|
||||
#include "AppEnv.h"
|
||||
#include "config.h"
|
||||
#include <QDesktopWidget>
|
||||
#include <QStringBuilder>
|
||||
#include <QSignalMapper>
|
||||
#include <QStyleFactory>
|
||||
|
@ -43,6 +42,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QStringList>
|
||||
#include <QTranslator>
|
||||
#include <QResource>
|
||||
#include <QCheckBox>
|
||||
#include <QFileInfo>
|
||||
#include <QSysInfo>
|
||||
|
@ -53,17 +53,31 @@
|
|||
#include <QFont>
|
||||
#include <QFile>
|
||||
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#if QT_VERSION < 0x060000
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "windows.h"
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
#include "MessageThread.h"
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
#include "TelemetryClass.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if QT_VERSION >= 0x050600
|
||||
#if QT_VERSION < 0x060000
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
#endif
|
||||
#endif
|
||||
QApplication a(argc, argv);
|
||||
a.setApplicationName(GTA5SYNC_APPSTR);
|
||||
a.setApplicationVersion(GTA5SYNC_APPVER);
|
||||
|
@ -72,6 +86,14 @@ int main(int argc, char *argv[])
|
|||
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
settings.beginGroup("Startup");
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
// Increase Start count at every startup
|
||||
uint startCount = settings.value("StartCount", 0).toUInt();
|
||||
startCount++;
|
||||
settings.setValue("StartCount", startCount);
|
||||
settings.sync();
|
||||
#endif
|
||||
|
||||
bool isFirstStart = settings.value("IsFirstStart", true).toBool();
|
||||
bool customStyle = settings.value("CustomStyle", false).toBool();
|
||||
QString appStyle = settings.value("AppStyle", "Default").toString();
|
||||
|
@ -84,25 +106,12 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef GTA5SYNC_WIN
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION >= 0x050400
|
||||
bool alwaysUseMessageFont = settings.value("AlwaysUseMessageFont", false).toBool();
|
||||
if (QSysInfo::windowsVersion() >= 0x0080 || alwaysUseMessageFont)
|
||||
{
|
||||
// Get Windows Font
|
||||
NONCLIENTMETRICS ncm;
|
||||
ncm.cbSize = sizeof(ncm);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
|
||||
LOGFONTW uiFont = ncm.lfMessageFont;
|
||||
QString uiFontStr(QString::fromStdWString(std::wstring(uiFont.lfFaceName)));
|
||||
|
||||
#ifdef GTA5SYNC_DEBUG
|
||||
qDebug() << QApplication::tr("Font") << QApplication::tr("Selected Font: %1").arg(uiFontStr);
|
||||
#endif
|
||||
|
||||
// Set Application Font
|
||||
QFont appFont(uiFontStr, 9);
|
||||
a.setFont(appFont);
|
||||
a.setFont(QApplication::font("QMenu"));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -124,7 +133,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
if (isFirstStart)
|
||||
{
|
||||
QMessageBox::StandardButton button = QMessageBox::information(a.desktop(), QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER), QApplication::tr("<h4>Welcome to %1!</h4>You want to configure %1 before you start using it?").arg(GTA5SYNC_APPSTR), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
QMessageBox::StandardButton button = QMessageBox::information(nullptr, QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER), QApplication::tr("<h4>Welcome to %1!</h4>You want to configure %1 before you start using it?").arg(GTA5SYNC_APPSTR), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (button == QMessageBox::Yes)
|
||||
{
|
||||
ProfileDatabase profileDB;
|
||||
|
@ -136,6 +145,58 @@ int main(int argc, char *argv[])
|
|||
settings.setValue("IsFirstStart", false);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GTA5SYNC_TELEMETRY
|
||||
bool telemetryWindowLaunched = settings.value("PersonalUsageDataWindowLaunched", false).toBool();
|
||||
bool pushUsageData = settings.value("PushUsageData", false).toBool();
|
||||
if (!telemetryWindowLaunched && !pushUsageData)
|
||||
{
|
||||
QDialog *telemetryDialog = new QDialog();
|
||||
telemetryDialog->setObjectName(QStringLiteral("TelemetryDialog"));
|
||||
telemetryDialog->setWindowTitle(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER));
|
||||
telemetryDialog->setWindowFlags(telemetryDialog->windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint);
|
||||
telemetryDialog->setWindowIcon(IconLoader::loadingAppIcon());
|
||||
QVBoxLayout *telemetryLayout = new QVBoxLayout(telemetryDialog);
|
||||
telemetryLayout->setObjectName(QStringLiteral("TelemetryLayout"));
|
||||
telemetryDialog->setLayout(telemetryLayout);
|
||||
UiModLabel *telemetryLabel = new UiModLabel(telemetryDialog);
|
||||
telemetryLabel->setObjectName(QStringLiteral("TelemetryLabel"));
|
||||
telemetryLabel->setText(QString("<h4>%2</h4>%1").arg(
|
||||
QApplication::translate("TelemetryDialog", "You want help %1 to improve in the future by including personal usage data in your submission?").arg(GTA5SYNC_APPSTR),
|
||||
QApplication::translate("TelemetryDialog", "%1 User Statistics").arg(GTA5SYNC_APPSTR)));
|
||||
telemetryLayout->addWidget(telemetryLabel);
|
||||
QCheckBox *telemetryCheckBox = new QCheckBox(telemetryDialog);
|
||||
telemetryCheckBox->setObjectName(QStringLiteral("TelemetryCheckBox"));
|
||||
telemetryCheckBox->setText(QApplication::translate("TelemetryDialog", "Yes, I want include personal usage data."));
|
||||
telemetryLayout->addWidget(telemetryCheckBox);
|
||||
QHBoxLayout *telemetryButtonLayout = new QHBoxLayout();
|
||||
telemetryButtonLayout->setObjectName(QStringLiteral("TelemetryButtonLayout"));
|
||||
telemetryLayout->addLayout(telemetryButtonLayout);
|
||||
QSpacerItem *telemetryButtonSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
telemetryButtonLayout->addSpacerItem(telemetryButtonSpacer);
|
||||
QPushButton *telemetryButton = new QPushButton(telemetryDialog);
|
||||
telemetryButton->setObjectName(QStringLiteral("TelemetryButton"));
|
||||
telemetryButton->setText(QApplication::translate("TelemetryDialog", "&OK"));
|
||||
telemetryButtonLayout->addWidget(telemetryButton);
|
||||
QObject::connect(telemetryButton, SIGNAL(clicked(bool)), telemetryDialog, SLOT(close()));
|
||||
telemetryDialog->setFixedSize(telemetryDialog->sizeHint());
|
||||
telemetryDialog->exec();
|
||||
QObject::disconnect(telemetryButton, SIGNAL(clicked(bool)), telemetryDialog, SLOT(close()));
|
||||
if (telemetryCheckBox->isChecked())
|
||||
{
|
||||
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
telemetrySettings.beginGroup("Telemetry");
|
||||
telemetrySettings.setValue("PushUsageData", true);
|
||||
telemetrySettings.setValue("PushAppConf", true);
|
||||
telemetrySettings.endGroup();
|
||||
telemetrySettings.sync();
|
||||
Telemetry->init();
|
||||
Telemetry->work();
|
||||
}
|
||||
settings.setValue("PersonalUsageDataWindowLaunched", true);
|
||||
delete telemetryDialog;
|
||||
}
|
||||
#endif
|
||||
settings.endGroup();
|
||||
|
||||
for (QString currentArg : applicationArgs)
|
||||
|
@ -193,9 +254,7 @@ int main(int argc, char *argv[])
|
|||
bool readOk = picture.readingPictureFromFile(arg1);
|
||||
picDialog.setWindowIcon(IconLoader::loadingAppIcon());
|
||||
picDialog.setSnapmaticPicture(&picture, readOk);
|
||||
#ifndef Q_OS_LINUX
|
||||
picDialog.setWindowFlags(picDialog.windowFlags()^Qt::Dialog^Qt::Window);
|
||||
#endif
|
||||
|
||||
int crewID = picture.getSnapmaticProperties().crewID;
|
||||
if (crewID != 0) { crewDB.addCrew(crewID); }
|
||||
|
@ -240,9 +299,32 @@ int main(int argc, char *argv[])
|
|||
QObject::connect(&threadDB, SIGNAL(finished()), &a, SLOT(quit()));
|
||||
threadDB.start();
|
||||
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
uint cacheId;
|
||||
{
|
||||
QSettings messageSettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
|
||||
messageSettings.beginGroup("Messages");
|
||||
cacheId = messageSettings.value("CacheId", 0).toUInt();
|
||||
messageSettings.endGroup();
|
||||
}
|
||||
MessageThread threadMessage(cacheId);
|
||||
QObject::connect(&threadMessage, SIGNAL(finished()), &threadDB, SLOT(terminateThread()));
|
||||
threadMessage.start();
|
||||
#endif
|
||||
|
||||
#ifdef GTA5SYNC_MOTD
|
||||
UserInterface uiWindow(&profileDB, &crewDB, &threadDB, &threadMessage);
|
||||
QObject::connect(&threadMessage, SIGNAL(messagesArrived(QJsonObject)), &uiWindow, SLOT(messagesArrived(QJsonObject)));
|
||||
QObject::connect(&threadMessage, SIGNAL(updateCacheId(uint)), &uiWindow, SLOT(updateCacheId(uint)));
|
||||
#else
|
||||
UserInterface uiWindow(&profileDB, &crewDB, &threadDB);
|
||||
#endif
|
||||
uiWindow.setWindowIcon(IconLoader::loadingAppIcon());
|
||||
#ifdef GTA5SYNC_FLATPAK
|
||||
uiWindow.setupDirEnv(false);
|
||||
#else
|
||||
uiWindow.setupDirEnv();
|
||||
#endif
|
||||
#ifdef Q_OS_ANDROID
|
||||
uiWindow.showMaximized();
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* PCG Random Number Generation for C.
|
||||
*
|
||||
* Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* For additional information about the PCG random number generation scheme,
|
||||
* including its license and other licensing options, visit
|
||||
*
|
||||
* http://www.pcg-random.org
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is derived from the full C implementation, which is in turn
|
||||
* derived from the canonical C++ PCG implementation. The C++ version
|
||||
* has many additional features and is preferable if you can use C++ in
|
||||
* your project.
|
||||
*/
|
||||
|
||||
#include "pcg_basic.h"
|
||||
|
||||
// state for global RNGs
|
||||
|
||||
static pcg32_random_t pcg32_global = PCG32_INITIALIZER;
|
||||
|
||||
// pcg32_srandom(initstate, initseq)
|
||||
// pcg32_srandom_r(rng, initstate, initseq):
|
||||
// Seed the rng. Specified in two parts, state initializer and a
|
||||
// sequence selection constant (a.k.a. stream id)
|
||||
|
||||
void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq)
|
||||
{
|
||||
rng->state = 0U;
|
||||
rng->inc = (initseq << 1u) | 1u;
|
||||
pcg32_random_r(rng);
|
||||
rng->state += initstate;
|
||||
pcg32_random_r(rng);
|
||||
}
|
||||
|
||||
void pcg32_srandom(uint64_t seed, uint64_t seq)
|
||||
{
|
||||
pcg32_srandom_r(&pcg32_global, seed, seq);
|
||||
}
|
||||
|
||||
// pcg32_random()
|
||||
// pcg32_random_r(rng)
|
||||
// Generate a uniformly distributed 32-bit random number
|
||||
|
||||
uint32_t pcg32_random_r(pcg32_random_t* rng)
|
||||
{
|
||||
uint64_t oldstate = rng->state;
|
||||
rng->state = oldstate * 6364136223846793005ULL + rng->inc;
|
||||
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
||||
uint32_t rot = oldstate >> 59u;
|
||||
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
||||
}
|
||||
|
||||
uint32_t pcg32_random()
|
||||
{
|
||||
return pcg32_random_r(&pcg32_global);
|
||||
}
|
||||
|
||||
|
||||
// pcg32_boundedrand(bound):
|
||||
// pcg32_boundedrand_r(rng, bound):
|
||||
// Generate a uniformly distributed number, r, where 0 <= r < bound
|
||||
|
||||
uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound)
|
||||
{
|
||||
// To avoid bias, we need to make the range of the RNG a multiple of
|
||||
// bound, which we do by dropping output less than a threshold.
|
||||
// A naive scheme to calculate the threshold would be to do
|
||||
//
|
||||
// uint32_t threshold = 0x100000000ull % bound;
|
||||
//
|
||||
// but 64-bit div/mod is slower than 32-bit div/mod (especially on
|
||||
// 32-bit platforms). In essence, we do
|
||||
//
|
||||
// uint32_t threshold = (0x100000000ull-bound) % bound;
|
||||
//
|
||||
// because this version will calculate the same modulus, but the LHS
|
||||
// value is less than 2^32.
|
||||
|
||||
uint32_t threshold = -bound % bound;
|
||||
|
||||
// Uniformity guarantees that this loop will terminate. In practice, it
|
||||
// should usually terminate quickly; on average (assuming all bounds are
|
||||
// equally likely), 82.25% of the time, we can expect it to require just
|
||||
// one iteration. In the worst case, someone passes a bound of 2^31 + 1
|
||||
// (i.e., 2147483649), which invalidates almost 50% of the range. In
|
||||
// practice, bounds are typically small and only a tiny amount of the range
|
||||
// is eliminated.
|
||||
for (;;) {
|
||||
uint32_t r = pcg32_random_r(rng);
|
||||
if (r >= threshold)
|
||||
return r % bound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t pcg32_boundedrand(uint32_t bound)
|
||||
{
|
||||
return pcg32_boundedrand_r(&pcg32_global, bound);
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* PCG Random Number Generation for C.
|
||||
*
|
||||
* Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* For additional information about the PCG random number generation scheme,
|
||||
* including its license and other licensing options, visit
|
||||
*
|
||||
* http://www.pcg-random.org
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is derived from the full C implementation, which is in turn
|
||||
* derived from the canonical C++ PCG implementation. The C++ version
|
||||
* has many additional features and is preferable if you can use C++ in
|
||||
* your project.
|
||||
*/
|
||||
|
||||
#ifndef PCG_BASIC_H_INCLUDED
|
||||
#define PCG_BASIC_H_INCLUDED 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct pcg_state_setseq_64 { // Internals are *Private*.
|
||||
uint64_t state; // RNG state. All values are possible.
|
||||
uint64_t inc; // Controls which RNG sequence (stream) is
|
||||
// selected. Must *always* be odd.
|
||||
};
|
||||
typedef struct pcg_state_setseq_64 pcg32_random_t;
|
||||
|
||||
// If you *must* statically initialize it, here's one.
|
||||
|
||||
#define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
|
||||
|
||||
// pcg32_srandom(initstate, initseq)
|
||||
// pcg32_srandom_r(rng, initstate, initseq):
|
||||
// Seed the rng. Specified in two parts, state initializer and a
|
||||
// sequence selection constant (a.k.a. stream id)
|
||||
|
||||
void pcg32_srandom(uint64_t initstate, uint64_t initseq);
|
||||
void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate,
|
||||
uint64_t initseq);
|
||||
|
||||
// pcg32_random()
|
||||
// pcg32_random_r(rng)
|
||||
// Generate a uniformly distributed 32-bit random number
|
||||
|
||||
uint32_t pcg32_random(void);
|
||||
uint32_t pcg32_random_r(pcg32_random_t* rng);
|
||||
|
||||
// pcg32_boundedrand(bound):
|
||||
// pcg32_boundedrand_r(rng, bound):
|
||||
// Generate a uniformly distributed number, r, where 0 <= r < bound
|
||||
|
||||
uint32_t pcg32_boundedrand(uint32_t bound);
|
||||
uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PCG_BASIC_H_INCLUDED
|
|
@ -39,45 +39,45 @@ QJsonDocument::QJsonDocument() : root_(0) {
|
|||
// Name: QJsonDocument
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument::QJsonDocument(const QJsonObject &object) : root_(0) {
|
||||
setObject(object);
|
||||
setObject(object);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: QJsonDocument
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument::QJsonDocument(const QJsonArray &array) : root_(0) {
|
||||
setArray(array);
|
||||
setArray(array);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: QJsonDocument
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument::QJsonDocument(const QJsonDocument &other) : root_(0) {
|
||||
if(other.root_) {
|
||||
root_ = other.root_->clone();
|
||||
}
|
||||
if(other.root_) {
|
||||
root_ = other.root_->clone();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: ~QJsonDocument
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument::~QJsonDocument() {
|
||||
delete root_;
|
||||
delete root_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: operator=
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument &QJsonDocument::operator=(const QJsonDocument &other) {
|
||||
QJsonDocument(other).swap(*this);
|
||||
return *this;
|
||||
QJsonDocument(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: operator!=
|
||||
//------------------------------------------------------------------------------
|
||||
bool QJsonDocument::operator!=(const QJsonDocument &other) const {
|
||||
return !(*this == other);
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -85,30 +85,30 @@ bool QJsonDocument::operator!=(const QJsonDocument &other) const {
|
|||
//------------------------------------------------------------------------------
|
||||
bool QJsonDocument::operator==(const QJsonDocument &other) const {
|
||||
|
||||
if(isArray() && other.isArray()) {
|
||||
return array() == other.array();
|
||||
}
|
||||
if(isArray() && other.isArray()) {
|
||||
return array() == other.array();
|
||||
}
|
||||
|
||||
if(isObject() && other.isObject()) {
|
||||
return object() == other.object();
|
||||
}
|
||||
if(isObject() && other.isObject()) {
|
||||
return object() == other.object();
|
||||
}
|
||||
|
||||
if(isEmpty() && other.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if(isEmpty() && other.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(isNull() && other.isNull()) {
|
||||
return true;
|
||||
}
|
||||
if(isNull() && other.isNull()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: isArray
|
||||
//------------------------------------------------------------------------------
|
||||
bool QJsonDocument::isArray() const {
|
||||
return root_ && root_->toArray();
|
||||
return root_ && root_->toArray();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -116,56 +116,56 @@ bool QJsonDocument::isArray() const {
|
|||
//------------------------------------------------------------------------------
|
||||
bool QJsonDocument::isEmpty() const {
|
||||
|
||||
// TODO(eteran): figure out the rules here that Qt5 uses
|
||||
// it *looks* like they define empty as being NULL
|
||||
// which is obviously different than this
|
||||
// TODO(eteran): figure out the rules here that Qt5 uses
|
||||
// it *looks* like they define empty as being NULL
|
||||
// which is obviously different than this
|
||||
|
||||
return !root_;
|
||||
return !root_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: isNull
|
||||
//------------------------------------------------------------------------------
|
||||
bool QJsonDocument::isNull() const {
|
||||
return !root_;
|
||||
return !root_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: isObject
|
||||
//------------------------------------------------------------------------------
|
||||
bool QJsonDocument::isObject() const {
|
||||
return root_ && root_->toObject();
|
||||
return root_ && root_->toObject();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: setArray
|
||||
//------------------------------------------------------------------------------
|
||||
void QJsonDocument::setArray(const QJsonArray &array) {
|
||||
setRoot(array);
|
||||
setRoot(array);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: setObject
|
||||
//------------------------------------------------------------------------------
|
||||
void QJsonDocument::setObject(const QJsonObject &object) {
|
||||
setRoot(object);
|
||||
setRoot(object);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: setRoot
|
||||
//------------------------------------------------------------------------------
|
||||
void QJsonDocument::setRoot(const QJsonRoot &root) {
|
||||
delete root_;
|
||||
root_ = root.clone();
|
||||
delete root_;
|
||||
root_ = root.clone();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: toBinaryData
|
||||
//------------------------------------------------------------------------------
|
||||
QByteArray QJsonDocument::toBinaryData() const {
|
||||
QByteArray r;
|
||||
// TODO(eteran): implement this
|
||||
return r;
|
||||
QByteArray r;
|
||||
// TODO(eteran): implement this
|
||||
return r;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -173,100 +173,107 @@ QByteArray QJsonDocument::toBinaryData() const {
|
|||
//------------------------------------------------------------------------------
|
||||
QString QJsonDocument::escapeString(const QString &s) const {
|
||||
|
||||
QString r;
|
||||
QString r;
|
||||
|
||||
Q_FOREACH(QChar ch, s) {
|
||||
switch(ch.toLatin1()) {
|
||||
case '\"': r.append("\\\""); break;
|
||||
case '\\': r.append("\\\\"); break;
|
||||
#if 0
|
||||
case '/': r.append("\\/"); break;
|
||||
#endif
|
||||
case '\b': r.append("\\b"); break;
|
||||
case '\f': r.append("\\f"); break;
|
||||
case '\n': r.append("\\n"); break;
|
||||
case '\r': r.append("\\r"); break;
|
||||
case '\t': r.append("\\t"); break;
|
||||
default:
|
||||
r += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Q_FOREACH(QChar ch, s) {
|
||||
switch(ch.toLatin1()) {
|
||||
case '\"': r.append("\\\""); break;
|
||||
case '\\': r.append("\\\\"); break;
|
||||
#if 0
|
||||
case '/': r.append("\\/"); break;
|
||||
#endif
|
||||
case '\b': r.append("\\b"); break;
|
||||
case '\f': r.append("\\f"); break;
|
||||
case '\n': r.append("\\n"); break;
|
||||
case '\r': r.append("\\r"); break;
|
||||
case '\t': r.append("\\t"); break;
|
||||
default:
|
||||
r += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: toJson
|
||||
//------------------------------------------------------------------------------
|
||||
QString QJsonDocument::toJson(const QJsonValue &v, JsonFormat format) const {
|
||||
QString QJsonDocument::toJson(const QJsonValue &v, JsonFormat format, int indent) const {
|
||||
|
||||
QString b;
|
||||
QTextStream ss(&b, QIODevice::WriteOnly | QIODevice::Text);
|
||||
QString b;
|
||||
QTextStream ss(&b, QIODevice::WriteOnly | QIODevice::Text);
|
||||
bool compact = (format == JsonFormat::Compact);
|
||||
|
||||
switch(v.type()) {
|
||||
case QJsonValue::Null:
|
||||
ss << "null";
|
||||
break;
|
||||
case QJsonValue::Bool:
|
||||
ss << (v.toBool() ? "true" : "false");
|
||||
break;
|
||||
case QJsonValue::Double:
|
||||
{
|
||||
double d = v.toDouble ();
|
||||
if (qIsFinite(d)) {
|
||||
// +2 to format to ensure the expected precision
|
||||
ss << QByteArray::number(d, 'g', 15 + 2); // ::digits10 is 15
|
||||
} else {
|
||||
ss << "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QJsonValue::String:
|
||||
ss << '"' << escapeString(v.toString()) << '"';
|
||||
break;
|
||||
case QJsonValue::Array:
|
||||
{
|
||||
const QJsonArray a = v.toArray();
|
||||
ss << "[";
|
||||
if(!a.empty()) {
|
||||
QJsonArray::const_iterator it = a.begin();
|
||||
QJsonArray::const_iterator e = a.end();
|
||||
switch(v.type()) {
|
||||
case QJsonValue::Null:
|
||||
ss << "null";
|
||||
break;
|
||||
case QJsonValue::Bool:
|
||||
ss << (v.toBool() ? "true" : "false");
|
||||
break;
|
||||
case QJsonValue::Double:
|
||||
{
|
||||
double d = v.toDouble ();
|
||||
if (qIsFinite(d)) {
|
||||
// +2 to format to ensure the expected precision
|
||||
ss << QByteArray::number(d, 'g', 15 + 2); // ::digits10 is 15
|
||||
} else {
|
||||
ss << "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QJsonValue::String:
|
||||
ss << '"' << escapeString(v.toString()) << '"';
|
||||
break;
|
||||
case QJsonValue::Array:
|
||||
{
|
||||
const QJsonArray a = v.toArray();
|
||||
ss << (compact ? "[" : "[\n");
|
||||
if(!a.empty()) {
|
||||
QJsonArray::const_iterator it = a.begin();
|
||||
QJsonArray::const_iterator e = a.end();
|
||||
|
||||
ss << toJson(*it++, format);
|
||||
if (!compact) ss << QByteArray(4*indent, ' ');
|
||||
ss << toJson(*it++, format, indent+1);
|
||||
|
||||
for(;it != e; ++it) {
|
||||
ss << ',';
|
||||
ss << toJson(*it, format);
|
||||
}
|
||||
}
|
||||
ss << "]";
|
||||
}
|
||||
break;
|
||||
case QJsonValue::Object:
|
||||
{
|
||||
const QJsonObject o = v.toObject();
|
||||
ss << "{";
|
||||
if(!o.empty()) {
|
||||
QJsonObject::const_iterator it = o.begin();
|
||||
QJsonObject::const_iterator e = o.end();
|
||||
for(;it != e; ++it) {
|
||||
ss << (compact ? "," : ",\n");
|
||||
if (!compact) ss << QByteArray(4*indent, ' ');
|
||||
ss << toJson(*it, format, indent+1);
|
||||
}
|
||||
}
|
||||
indent--;
|
||||
ss << (compact ? "]" : QString("\n%1]").arg(QString(4*indent, ' ')));
|
||||
}
|
||||
break;
|
||||
case QJsonValue::Object:
|
||||
{
|
||||
const QJsonObject o = v.toObject();
|
||||
ss << (compact ? "{" : "{\n");
|
||||
if(!o.empty()) {
|
||||
QJsonObject::const_iterator it = o.begin();
|
||||
QJsonObject::const_iterator e = o.end();
|
||||
|
||||
ss << '"' << escapeString(it.key()) << "\": " << toJson(it.value(), format);
|
||||
++it;
|
||||
for(;it != e; ++it) {
|
||||
ss << ',';
|
||||
ss << '"' << escapeString(it.key()) << "\": " << toJson(it.value(), format);
|
||||
}
|
||||
}
|
||||
ss << "}";
|
||||
}
|
||||
break;
|
||||
case QJsonValue::Undefined:
|
||||
Q_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
if (!compact) ss << QByteArray(4*indent, ' ');
|
||||
ss << '"' << escapeString(it.key()) << (compact ? "\":" : "\": ") << toJson(it.value(), format, indent+1);
|
||||
++it;
|
||||
for(;it != e; ++it) {
|
||||
ss << (compact ? "," : ",\n");
|
||||
if (!compact) ss << QByteArray(4*indent, ' ');
|
||||
ss << '"' << escapeString(it.key()) << (compact ? "\":" : "\": ") << toJson(it.value(), format, indent+1);
|
||||
}
|
||||
}
|
||||
indent--;
|
||||
ss << (compact ? "}" : QString("\n%1}").arg(QString(4*indent, ' ')));
|
||||
}
|
||||
break;
|
||||
case QJsonValue::Undefined:
|
||||
Q_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return b;
|
||||
return b;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -274,19 +281,19 @@ QString QJsonDocument::toJson(const QJsonValue &v, JsonFormat format) const {
|
|||
//------------------------------------------------------------------------------
|
||||
QByteArray QJsonDocument::toJson(JsonFormat format) const {
|
||||
|
||||
Q_UNUSED(format);
|
||||
Q_UNUSED(format);
|
||||
|
||||
if(isArray()) {
|
||||
QString s = toJson(array(), format);
|
||||
return s.toUtf8();
|
||||
}
|
||||
if(isArray()) {
|
||||
QString s = toJson(array(), format);
|
||||
return s.toUtf8();
|
||||
}
|
||||
|
||||
if(isObject()) {
|
||||
QString s = toJson(object(), format);
|
||||
return s.toUtf8();
|
||||
}
|
||||
if(isObject()) {
|
||||
QString s = toJson(object(), format);
|
||||
return s.toUtf8();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -294,17 +301,17 @@ QByteArray QJsonDocument::toJson(JsonFormat format) const {
|
|||
//------------------------------------------------------------------------------
|
||||
QVariant QJsonDocument::toVariant() const {
|
||||
|
||||
if(!isEmpty()) {
|
||||
if(QJsonObject *const object = root_->toObject()) {
|
||||
return object->toVariantMap();
|
||||
}
|
||||
if(!isEmpty()) {
|
||||
if(QJsonObject *const object = root_->toObject()) {
|
||||
return object->toVariantMap();
|
||||
}
|
||||
|
||||
if(QJsonArray *const array = root_->toArray()) {
|
||||
return array->toVariantList();
|
||||
}
|
||||
}
|
||||
if(QJsonArray *const array = root_->toArray()) {
|
||||
return array->toVariantList();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -312,13 +319,13 @@ QVariant QJsonDocument::toVariant() const {
|
|||
//------------------------------------------------------------------------------
|
||||
QJsonArray QJsonDocument::array() const {
|
||||
|
||||
if(!isEmpty()) {
|
||||
if(QJsonArray *const array = root_->toArray()) {
|
||||
return *array;
|
||||
}
|
||||
}
|
||||
if(!isEmpty()) {
|
||||
if(QJsonArray *const array = root_->toArray()) {
|
||||
return *array;
|
||||
}
|
||||
}
|
||||
|
||||
return QJsonArray();
|
||||
return QJsonArray();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -326,54 +333,54 @@ QJsonArray QJsonDocument::array() const {
|
|||
//------------------------------------------------------------------------------
|
||||
QJsonObject QJsonDocument::object() const {
|
||||
|
||||
if(!isEmpty()) {
|
||||
if(QJsonObject *const object = root_->toObject()) {
|
||||
return *object;
|
||||
}
|
||||
}
|
||||
if(!isEmpty()) {
|
||||
if(QJsonObject *const object = root_->toObject()) {
|
||||
return *object;
|
||||
}
|
||||
}
|
||||
|
||||
return QJsonObject();
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: rawData
|
||||
//------------------------------------------------------------------------------
|
||||
const char *QJsonDocument::rawData(int *size) const {
|
||||
Q_UNUSED(size);
|
||||
// TODO(eteran): implement this
|
||||
return 0;
|
||||
Q_UNUSED(size);
|
||||
// TODO(eteran): implement this
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: fromBinaryData
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation) {
|
||||
Q_UNUSED(data);
|
||||
Q_UNUSED(validation);
|
||||
Q_UNUSED(data);
|
||||
Q_UNUSED(validation);
|
||||
|
||||
QJsonDocument doc;
|
||||
// TODO(eteran): implement this
|
||||
return doc;
|
||||
QJsonDocument doc;
|
||||
// TODO(eteran): implement this
|
||||
return doc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: fromJson
|
||||
//------------------------------------------------------------------------------
|
||||
QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error) {
|
||||
QJsonDocument doc;
|
||||
QJsonDocument doc;
|
||||
|
||||
const char *const begin = json.constData();
|
||||
const char *const end = begin + json.size();
|
||||
const char *const begin = json.constData();
|
||||
const char *const end = begin + json.size();
|
||||
|
||||
QJsonParser parser(begin, end);
|
||||
QJsonParser parser(begin, end);
|
||||
|
||||
doc.root_ = parser.parse();
|
||||
doc.root_ = parser.parse();
|
||||
|
||||
if(error) {
|
||||
*error = parser.state();
|
||||
}
|
||||
if(error) {
|
||||
*error = parser.state();
|
||||
}
|
||||
|
||||
return doc;
|
||||
return doc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -381,10 +388,10 @@ QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *e
|
|||
//------------------------------------------------------------------------------
|
||||
QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation) {
|
||||
|
||||
// data has to be aligned to a 4 byte boundary.
|
||||
Q_ASSERT(!(reinterpret_cast<quintptr>(data) % 3));
|
||||
// data has to be aligned to a 4 byte boundary.
|
||||
Q_ASSERT(!(reinterpret_cast<quintptr>(data) % 3));
|
||||
|
||||
return fromBinaryData(QByteArray::fromRawData(data, size), validation);
|
||||
return fromBinaryData(QByteArray::fromRawData(data, size), validation);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -392,26 +399,26 @@ QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidat
|
|||
//------------------------------------------------------------------------------
|
||||
QJsonDocument QJsonDocument::fromVariant(const QVariant &variant) {
|
||||
|
||||
QJsonDocument doc;
|
||||
QJsonDocument doc;
|
||||
|
||||
if (variant.type() == QVariant::Map) {
|
||||
doc.setObject(QJsonObject::fromVariantMap(variant.toMap()));
|
||||
} else if (variant.type() == QVariant::Hash) {
|
||||
doc.setObject(QJsonObject::fromVariantHash(variant.toHash()));
|
||||
} else if (variant.type() == QVariant::List) {
|
||||
doc.setArray(QJsonArray::fromVariantList(variant.toList()));
|
||||
} else if (variant.type() == QVariant::StringList) {
|
||||
doc.setArray(QJsonArray::fromStringList(variant.toStringList()));
|
||||
}
|
||||
if (variant.type() == QVariant::Map) {
|
||||
doc.setObject(QJsonObject::fromVariantMap(variant.toMap()));
|
||||
} else if (variant.type() == QVariant::Hash) {
|
||||
doc.setObject(QJsonObject::fromVariantHash(variant.toHash()));
|
||||
} else if (variant.type() == QVariant::List) {
|
||||
doc.setArray(QJsonArray::fromVariantList(variant.toList()));
|
||||
} else if (variant.type() == QVariant::StringList) {
|
||||
doc.setArray(QJsonArray::fromStringList(variant.toStringList()));
|
||||
}
|
||||
|
||||
return doc;
|
||||
return doc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Name: swap
|
||||
//------------------------------------------------------------------------------
|
||||
void QJsonDocument::swap(QJsonDocument &other) {
|
||||
qSwap(root_, other.root_);
|
||||
qSwap(root_, other.root_);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,66 +36,66 @@ class QJsonRoot;
|
|||
|
||||
class QJsonDocument {
|
||||
public:
|
||||
enum DataValidation {
|
||||
Validate = 0,
|
||||
BypassValidation = 1
|
||||
};
|
||||
enum DataValidation {
|
||||
Validate = 0,
|
||||
BypassValidation = 1
|
||||
};
|
||||
|
||||
enum JsonFormat {
|
||||
Indented,
|
||||
Compact
|
||||
};
|
||||
enum JsonFormat {
|
||||
Indented,
|
||||
Compact
|
||||
};
|
||||
|
||||
public:
|
||||
QJsonDocument();
|
||||
QJsonDocument(const QJsonObject &object);
|
||||
QJsonDocument(const QJsonArray &array);
|
||||
QJsonDocument(const QJsonDocument &other);
|
||||
~QJsonDocument();
|
||||
QJsonDocument();
|
||||
QJsonDocument(const QJsonObject &object);
|
||||
QJsonDocument(const QJsonArray &array);
|
||||
QJsonDocument(const QJsonDocument &other);
|
||||
~QJsonDocument();
|
||||
|
||||
public:
|
||||
QJsonDocument &operator=(const QJsonDocument &other);
|
||||
QJsonDocument &operator=(const QJsonDocument &other);
|
||||
|
||||
public:
|
||||
bool operator!=(const QJsonDocument &other) const;
|
||||
bool operator==(const QJsonDocument &other) const;
|
||||
bool operator!=(const QJsonDocument &other) const;
|
||||
bool operator==(const QJsonDocument &other) const;
|
||||
|
||||
public:
|
||||
bool isArray() const;
|
||||
bool isEmpty() const;
|
||||
bool isNull() const;
|
||||
bool isObject() const;
|
||||
bool isArray() const;
|
||||
bool isEmpty() const;
|
||||
bool isNull() const;
|
||||
bool isObject() const;
|
||||
|
||||
public:
|
||||
QByteArray toBinaryData() const;
|
||||
QByteArray toJson(JsonFormat format = Indented) const;
|
||||
QVariant toVariant() const;
|
||||
QByteArray toBinaryData() const;
|
||||
QByteArray toJson(JsonFormat format = Indented) const;
|
||||
QVariant toVariant() const;
|
||||
|
||||
public:
|
||||
QJsonArray array() const;
|
||||
QJsonObject object() const;
|
||||
const char *rawData(int *size) const;
|
||||
QJsonArray array() const;
|
||||
QJsonObject object() const;
|
||||
const char *rawData(int *size) const;
|
||||
|
||||
public:
|
||||
void setArray(const QJsonArray &array);
|
||||
void setObject(const QJsonObject &object);
|
||||
void setArray(const QJsonArray &array);
|
||||
void setObject(const QJsonObject &object);
|
||||
|
||||
public:
|
||||
static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
|
||||
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = 0);
|
||||
static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate);
|
||||
static QJsonDocument fromVariant(const QVariant &variant);
|
||||
static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
|
||||
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = 0);
|
||||
static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate);
|
||||
static QJsonDocument fromVariant(const QVariant &variant);
|
||||
|
||||
private:
|
||||
void setRoot(const QJsonRoot &root);
|
||||
QString toJson(const QJsonValue &v, JsonFormat format) const;
|
||||
QString escapeString(const QString &s) const;
|
||||
void setRoot(const QJsonRoot &root);
|
||||
QString toJson(const QJsonValue &v, JsonFormat format, int indent = 1) const;
|
||||
QString escapeString(const QString &s) const;
|
||||
|
||||
private:
|
||||
void swap(QJsonDocument &other);
|
||||
void swap(QJsonDocument &other);
|
||||
|
||||
private:
|
||||
QJsonRoot *root_;
|
||||
QJsonRoot *root_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB |
BIN
res/5sync-16.png
BIN
res/5sync-16.png
Binary file not shown.
Before Width: | Height: | Size: 415 B |
BIN
res/5sync-24.png
BIN
res/5sync-24.png
Binary file not shown.
Before Width: | Height: | Size: 649 B |
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB |
BIN
res/5sync-32.png
BIN
res/5sync-32.png
Binary file not shown.
Before Width: | Height: | Size: 822 B |
BIN
res/5sync-40.png
BIN
res/5sync-40.png
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue