Compare commits

..

No commits in common. "1.10.x" and "1.8.x" have entirely different histories.

164 changed files with 24421 additions and 10915 deletions

View file

@ -24,7 +24,7 @@ BEGIN
VALUE "FileDescription", "gta5view" VALUE "FileDescription", "gta5view"
VALUE "FileVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER" VALUE "FileVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER"
VALUE "InternalName", "gta5view" VALUE "InternalName", "gta5view"
VALUE "LegalCopyright", "Copyright © 2016-2023 Syping" VALUE "LegalCopyright", "Copyright © 2016-2020 Syping"
VALUE "OriginalFilename", "gta5view.exe" VALUE "OriginalFilename", "gta5view.exe"
VALUE "ProductName", "gta5view" VALUE "ProductName", "gta5view"
VALUE "ProductVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER" VALUE "ProductVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER"

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
if [ $(git name-rev --tags --name-only $(git rev-parse HEAD)) == "undefined" ]; then 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') 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')
@ -16,7 +16,7 @@ export APPLICATION_PATCH_VERSION=$(cut -d. -f3 <<< $APPLICATION_VERSION)
if [ "${PACKAGE_BUILD}" == "" ]; then if [ "${PACKAGE_BUILD}" == "" ]; then
export PACKAGE_BUILD=1 export PACKAGE_BUILD=1
else else
export APPLICATION_BUILD_INT_VERSION=$(grep -oE '[1-9]*$' <<< $PACKAGE_BUILD) export APPLICATION_BUILD_INT_VERSION=$(grep -oE "[1-9]*$" <<< $PACKAGE_BUILD)
export APPLICATION_BUILD_STR_VERSION=-${PACKAGE_BUILD} export APPLICATION_BUILD_STR_VERSION=-${PACKAGE_BUILD}
fi fi
@ -30,41 +30,41 @@ cat ".ci/app.rc" | sed \
> "res/app.rc" > "res/app.rc"
if [ "${BUILD_TYPE}" == "ALPHA" ]; then if [ "${BUILD_TYPE}" == "ALPHA" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Alpha" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_ALPHA=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Alpha\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_ALPHA"
elif [ "${BUILD_TYPE}" == "Alpha" ]; then elif [ "${BUILD_TYPE}" == "Alpha" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Alpha" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_ALPHA=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Alpha\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_ALPHA"
elif [ "${BUILD_TYPE}" == "BETA" ]; then elif [ "${BUILD_TYPE}" == "BETA" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Beta" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_BETA=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Beta\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_BETA"
elif [ "${BUILD_TYPE}" == "Beta" ]; then elif [ "${BUILD_TYPE}" == "Beta" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Beta" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_BETA=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Beta\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_BETA"
elif [ "${BUILD_TYPE}" == "DEV" ]; then elif [ "${BUILD_TYPE}" == "DEV" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Developer" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DEV=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Developer\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DEV"
elif [ "${BUILD_TYPE}" == "Development" ]; then elif [ "${BUILD_TYPE}" == "Development" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Developer" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DEV=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Developer\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DEV"
elif [ "${BUILD_TYPE}" == "DAILY" ]; then elif [ "${BUILD_TYPE}" == "DAILY" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Daily Build" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DAILY=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Daily Build\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DAILY"
elif [ "${BUILD_TYPE}" == "Daily" ]; then elif [ "${BUILD_TYPE}" == "Daily" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Daily Build" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_DAILY=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Daily Build\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_DAILY"
elif [ "${BUILD_TYPE}" == "RC" ]; then elif [ "${BUILD_TYPE}" == "RC" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release Candidate" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_RC=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release Candidate\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_RC"
elif [ "${BUILD_TYPE}" == "Release Candidate" ]; then elif [ "${BUILD_TYPE}" == "Release Candidate" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release Candidate" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_RC=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release Candidate\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_RC"
elif [ "${BUILD_TYPE}" == "REL" ]; then elif [ "${BUILD_TYPE}" == "REL" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_REL=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_REL"
elif [ "${BUILD_TYPE}" == "Release" ]; then elif [ "${BUILD_TYPE}" == "Release" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release" export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE_REL=TRUE"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release\\\\\\\"" export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE_REL"
fi fi
export PROJECT_DIR=$(pwd) export PROJECT_DIR=$(pwd)

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Creating folders # Creating folders
cd ${PROJECT_DIR} && \ cd ${PROJECT_DIR} && \
@ -7,6 +7,10 @@ mkdir -p build && \
mkdir -p assets && \ mkdir -p assets && \
chmod -x res/gta5sync_*.qm res/*.desktop res/*gta5view*.png && \ chmod -x res/gta5sync_*.qm res/*.desktop res/*gta5view*.png && \
cd build && \ cd build && \
mkdir -p qt4 && \
cd qt4 && \
echo "Grand Theft Auto V Snapmatic and Savegame viewer/editor" > ./description-pak && \
cd .. && \
mkdir -p qt5 && \ mkdir -p qt5 && \
cd qt5 && \ cd qt5 && \
echo "Grand Theft Auto V Snapmatic and Savegame viewer/editor" > ./description-pak && \ echo "Grand Theft Auto V Snapmatic and Savegame viewer/editor" > ./description-pak && \
@ -23,16 +27,18 @@ mkdir -p /usr/share/gta5view && \
cd qt5 && \ cd qt5 && \
cmake \ cmake \
"-DCMAKE_INSTALL_PREFIX=/usr" \ "-DCMAKE_INSTALL_PREFIX=/usr" \
"${CMAKE_BUILD_TYPE}" \ ${CMAKE_BUILD_TYPE} \
"-DFORCE_QT_VERSION=5" \
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \ "-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \ "-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \ "-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
"-DWITH_DONATE=ON" \
"-DWITH_TELEMETRY=ON" \ "-DWITH_TELEMETRY=ON" \
"-DDONATE_ADDRESSES=$(cat ${PROJECT_DIR}/.ci/donate.txt)" \
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \ "-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
"-DQCONF_BUILD=ON" \ "-DQCONF_BUILD=ON" \
../../ && \ ../../ && \
make -j 4 && \ make -j 4 && \
checkinstall -D --default --nodoc --install=no --pkgname=gta5view --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5svg5,libqt5widgets5,qttranslations5-l10n --conflicts=gta5view-qt4,gta5view-qt5 --replaces=gta5view-qt4,gta5view-qt5 --pakdir=${PROJECT_DIR}/assets 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

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Install packages # Install packages
.ci/debian_install.sh && \ .ci/debian_install.sh && \

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
if [ "${DOCKER_USER}" != "" ]; then if [ "${DOCKER_USER}" != "" ]; then
DOCKER_IMAGE=${DOCKER_USER}/debian:${DEBIAN_VERSION} DOCKER_IMAGE=${DOCKER_USER}/debian:${DEBIAN_VERSION}

View file

@ -1,13 +1,5 @@
#!/usr/bin/env bash #!/bin/bash
# Source OS Release
source /etc/os-release
# When Debian add backports
if [ "${ID}" == "debian" ]; then
echo "deb http://deb.debian.org/debian ${VERSION_CODENAME}-backports main" >> /etc/apt/sources.list
fi
# Install packages # Install packages
apt-get update -qq && \ apt-get update -qq && \
apt-get install -qq ${APT_INSTALL} checkinstall cmake dpkg-dev fakeroot g++ gcc qtbase5-dev qt5-qmake qttranslations5-l10n libqt5svg5-dev apt-get install -qq ${APT_INSTALL} checkinstall cmake dpkg-dev fakeroot g++ gcc qtbase5-dev qt5-qmake qttranslations5-l10n libqt4-dev libqt5svg5-dev

View file

@ -1 +0,0 @@
btc:187NSQSPzdMpQDGhxZAuw4AhZ7LgoAPV7D,eth:0x19d71DfCa86104d37a13D3c5d419936421CDC569,ltc:LKr6yvBoMMGmcxViS8Kc1A2sDjVSWTXn4m,xmr:43TB3ZMP5nk1pu5EQXRGPzdTKvmFEBGgccX3tNhRknLLiUYQ7z7dNedVHEA6WrWdByZv1isvFmjSGhCF7ddx3eRxFdm5Fzz

View file

@ -1,12 +1,11 @@
###################################################################### ######################################################################
!define APP_NAME "gta5view" !define APP_NAME "gta5view"
!define APP_EXT ".g5e"
!define COMP_NAME "Syping" !define COMP_NAME "Syping"
!define WEB_SITE "https://gta5view.syping.de/" !define WEB_SITE "https://gta5view.syping.de/"
!define VERSION "1.10.2.0" !define VERSION "1.8.0.0"
!define COPYRIGHT "Copyright © 2016-2022 Syping" !define COPYRIGHT "Copyright © 2016-2020 Syping"
!define DESCRIPTION "Open Source Snapmatic and Savegame viewer/editor for GTA V" !define DESCRIPTION "Grand Theft Auto V Savegame and Snapmatic Viewer/Editor"
!define INSTALLER_NAME "gta5view_setup.exe" !define INSTALLER_NAME "gta5view_setup.exe"
!define MAIN_APP_EXE "gta5view.exe" !define MAIN_APP_EXE "gta5view.exe"
!define INSTALL_TYPE "SetShellVarContext all" !define INSTALL_TYPE "SetShellVarContext all"
@ -114,6 +113,7 @@ 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/Qt5Network.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Svg.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/Qt5Widgets.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5WinExtras.dll"
SetOutPath "$INSTDIR\lang" SetOutPath "$INSTDIR\lang"
File "../build/gta5sync_en_US.qm" File "../build/gta5sync_en_US.qm"
File "../build/gta5sync_de.qm" File "../build/gta5sync_de.qm"
@ -123,45 +123,12 @@ File "../build/gta5sync_ru.qm"
File "../build/gta5sync_uk.qm" File "../build/gta5sync_uk.qm"
File "../build/gta5sync_zh_TW.qm" File "../build/gta5sync_zh_TW.qm"
File "../build/qtbase_en_GB.qm" File "../build/qtbase_en_GB.qm"
File "../res/qt5/qtbase_de.qm" File "../res/qtbase_de.qm"
File "../res/qt5/qtbase_fr.qm" File "../res/qtbase_fr.qm"
File "../res/qt5/qtbase_ko.qm" File "../res/qtbase_ko.qm"
File "../res/qt5/qtbase_ru.qm" File "../res/qtbase_ru.qm"
File "../res/qt5/qtbase_uk.qm" File "../res/qtbase_uk.qm"
File "../res/qt5/qtbase_zh_TW.qm" File "../res/qtbase_zh_TW.qm"
SetOutPath "$INSTDIR\resources"
File "../res/add.svgz"
File "../res/avatararea.png"
File "../res/avatarareaimport.png"
File "../res/back.svgz"
File "../res/flag-de.png"
File "../res/flag-fr.png"
File "../res/flag-gb.png"
File "../res/flag-kr.png"
File "../res/flag-ru.png"
File "../res/flag-tw.png"
File "../res/flag-ua.png"
File "../res/flag-us.png"
File "../res/gta5view-16.png"
File "../res/gta5view-24.png"
File "../res/gta5view-32.png"
File "../res/gta5view-40.png"
File "../res/gta5view-48.png"
File "../res/gta5view-64.png"
File "../res/gta5view-96.png"
File "../res/gta5view-128.png"
File "../res/gta5view-256.png"
File "../res/mapcayoperico.jpg"
File "../res/mappreview.jpg"
File "../res/next.svgz"
File "../res/pointmaker-8.png"
File "../res/pointmaker-16.png"
File "../res/pointmaker-24.png"
File "../res/pointmaker-32.png"
File "../res/savegame.svgz"
File "../res/watermark_1b.png"
File "../res/watermark_2b.png"
File "../res/watermark_2r.png"
SetOutPath "$INSTDIR\imageformats" SetOutPath "$INSTDIR\imageformats"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qgif.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/qicns.dll"
@ -224,30 +191,6 @@ SectionEnd
###################################################################### ######################################################################
Section -ShellAssoc
WriteRegStr ${REG_ROOT} "Software\Classes\${APP_NAME}\DefaultIcon" "" "$INSTDIR\${MAIN_APP_EXE},0"
WriteRegStr ${REG_ROOT} "Software\Classes\${APP_NAME}\shell\open\command" "" '"$INSTDIR\${MAIN_APP_EXE}" "%1"'
WriteRegStr ${REG_ROOT} "Software\Classes\${APP_EXT}" "" "${APP_NAME}"
WriteRegStr ${REG_ROOT} "Software\Classes\${APP_EXT}" "Content Type" "application/x-gta5view-export"
System::Call 'SHELL32::SHChangeNotify(i0x8000000,i0,p0,p0)'
SectionEnd
######################################################################
Section -un.ShellAssoc
ClearErrors
ReadRegStr $0 ${REG_ROOT} "Software\Classes\${APP_EXT}" ""
DeleteRegKey ${REG_ROOT} "Software\Classes\${APP_NAME}"
${IfNot} ${Errors}
${AndIf} $0 == "${APP_NAME}"
DeleteRegValue ${REG_ROOT} "Software\Classes\${APP_EXT}" ""
DeleteRegKey /IfEmpty ${REG_ROOT} "Software\Classes\${APP_EXT}"
${EndIf}
System::Call 'SHELL32::SHChangeNotify(i0x8000000,i0,p0,p0)'
SectionEnd
######################################################################
Section Uninstall Section Uninstall
${INSTALL_TYPE} ${INSTALL_TYPE}
Delete "$INSTDIR\gta5view.exe" Delete "$INSTDIR\gta5view.exe"
@ -260,6 +203,7 @@ Delete "$INSTDIR\Qt5Gui.dll"
Delete "$INSTDIR\Qt5Network.dll" Delete "$INSTDIR\Qt5Network.dll"
Delete "$INSTDIR\Qt5Svg.dll" Delete "$INSTDIR\Qt5Svg.dll"
Delete "$INSTDIR\Qt5Widgets.dll" Delete "$INSTDIR\Qt5Widgets.dll"
Delete "$INSTDIR\Qt5WinExtras.dll"
Delete "$INSTDIR\lang\gta5sync_en_US.qm" Delete "$INSTDIR\lang\gta5sync_en_US.qm"
Delete "$INSTDIR\lang\gta5sync_de.qm" Delete "$INSTDIR\lang\gta5sync_de.qm"
Delete "$INSTDIR\lang\gta5sync_fr.qm" Delete "$INSTDIR\lang\gta5sync_fr.qm"
@ -274,38 +218,6 @@ Delete "$INSTDIR\lang\qtbase_ko.qm"
Delete "$INSTDIR\lang\qtbase_ru.qm" Delete "$INSTDIR\lang\qtbase_ru.qm"
Delete "$INSTDIR\lang\qtbase_uk.qm" Delete "$INSTDIR\lang\qtbase_uk.qm"
Delete "$INSTDIR\lang\qtbase_zh_TW.qm" Delete "$INSTDIR\lang\qtbase_zh_TW.qm"
Delete "$INSTDIR\resources\add.svgz"
Delete "$INSTDIR\resources\avatararea.png"
Delete "$INSTDIR\resources\avatarareaimport.png"
Delete "$INSTDIR\resources\back.svgz"
Delete "$INSTDIR\resources\flag-de.png"
Delete "$INSTDIR\resources\flag-fr.png"
Delete "$INSTDIR\resources\flag-gb.png"
Delete "$INSTDIR\resources\flag-kr.png"
Delete "$INSTDIR\resources\flag-ru.png"
Delete "$INSTDIR\resources\flag-tw.png"
Delete "$INSTDIR\resources\flag-ua.png"
Delete "$INSTDIR\resources\flag-us.png"
Delete "$INSTDIR\resources\gta5view-16.png"
Delete "$INSTDIR\resources\gta5view-24.png"
Delete "$INSTDIR\resources\gta5view-32.png"
Delete "$INSTDIR\resources\gta5view-40.png"
Delete "$INSTDIR\resources\gta5view-48.png"
Delete "$INSTDIR\resources\gta5view-64.png"
Delete "$INSTDIR\resources\gta5view-96.png"
Delete "$INSTDIR\resources\gta5view-128.png"
Delete "$INSTDIR\resources\gta5view-256.png"
Delete "$INSTDIR\resources\mapcayoperico.jpg"
Delete "$INSTDIR\resources\mappreview.jpg"
Delete "$INSTDIR\resources\next.svgz"
Delete "$INSTDIR\resources\pointmaker-8.png"
Delete "$INSTDIR\resources\pointmaker-16.png"
Delete "$INSTDIR\resources\pointmaker-24.png"
Delete "$INSTDIR\resources\pointmaker-32.png"
Delete "$INSTDIR\resources\savegame.svgz"
Delete "$INSTDIR\resources\watermark_1b.png"
Delete "$INSTDIR\resources\watermark_2b.png"
Delete "$INSTDIR\resources\watermark_2r.png"
Delete "$INSTDIR\imageformats\qgif.dll" Delete "$INSTDIR\imageformats\qgif.dll"
Delete "$INSTDIR\imageformats\qicns.dll" Delete "$INSTDIR\imageformats\qicns.dll"
Delete "$INSTDIR\imageformats\qico.dll" Delete "$INSTDIR\imageformats\qico.dll"

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Creating folders # Creating folders
cd ${PROJECT_DIR} && \ cd ${PROJECT_DIR} && \
@ -8,17 +8,7 @@ mkdir -p build && \
mkdir -p assets && \ mkdir -p assets && \
cd build && \ cd build && \
/usr/local/bin/cmake \ /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 && \
"-DCMAKE_PREFIX_PATH=/usr/local/opt/qt" \
"${CMAKE_BUILD_TYPE}" \
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
"-DWITH_DONATE=ON" \
"-DWITH_TELEMETRY=ON" \
"-DDONATE_ADDRESSES=$(cat ${PROJECT_DIR}/.ci/donate.txt)" \
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
../ && \
make -j 4 && \ make -j 4 && \
/usr/local/opt/qt/bin/macdeployqt gta5view.app -dmg && \ /usr/local/opt/qt/bin/macdeployqt gta5view.app -dmg && \
cp -Rf gta5view.dmg ../assets/gta5view-osx_${APPLICATION_VERSION}.dmg cp -Rf gta5view.dmg ../assets/gta5view-osx_${APPLICATION_VERSION}.dmg

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Install packages # Install packages
.ci/osx_install.sh && \ .ci/osx_install.sh && \

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Install packages # Install packages
brew upgrade cmake qt brew upgrade qt

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Prepare environment variable # Prepare environment variable
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \ export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
@ -13,13 +13,11 @@ mkdir -p assets && \
# Starting build # Starting build
cd build && \ cd build && \
mingw64-qt-cmake \ mingw64-qt-cmake \
"${CMAKE_BUILD_TYPE}" \ ${CMAKE_BUILD_TYPE} \
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \ "-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \ "-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \ "-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
"-DWITH_DONATE=ON" \
"-DWITH_TELEMETRY=ON" \ "-DWITH_TELEMETRY=ON" \
"-DDONATE_ADDRESSES=$(cat ${PROJECT_DIR}/.ci/donate.txt)" \
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \ "-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
.. && \ .. && \
make -j 4 && \ make -j 4 && \

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/bin/bash
DOCKER_IMAGE=sypingauto/gta5view-build:1.10-static DOCKER_IMAGE=sypingauto/gta5view-build:1.8-static
PROJECT_DIR_DOCKER=/gta5view PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \ cd ${PROJECT_DIR} && \

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/bin/bash
# Creating folders # Creating folders
cd ${PROJECT_DIR} && \ cd ${PROJECT_DIR} && \
@ -9,13 +9,11 @@ mkdir -p assets && \
# Starting build # Starting build
cd build && \ cd build && \
mingw64-qt-cmake \ mingw64-qt-cmake \
"${CMAKE_BUILD_TYPE}" \ ${CMAKE_BUILD_TYPE} \
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \ "-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \ "-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \ "-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
"-DWITH_DONATE=ON" \
"-DWITH_TELEMETRY=ON" \ "-DWITH_TELEMETRY=ON" \
"-DDONATE_ADDRESSES=$(cat ${PROJECT_DIR}/.ci/donate.txt)" \
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \ "-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
"-DQCONF_BUILD=ON" \ "-DQCONF_BUILD=ON" \
"-DGTA5VIEW_INLANG=RUNDIR:SEPARATOR:lang" \ "-DGTA5VIEW_INLANG=RUNDIR:SEPARATOR:lang" \
@ -25,5 +23,5 @@ mingw64-qt-cmake \
make -j 4 && \ make -j 4 && \
x86_64-w64-mingw32-strip -s gta5view.exe && \ x86_64-w64-mingw32-strip -s gta5view.exe && \
cd ${PROJECT_DIR}/assets && \ cd ${PROJECT_DIR}/assets && \
makensis "-XTarget amd64-unicode" -NOCD ${PROJECT_DIR}/.ci/gta5view.nsi && \ makensis -NOCD ${PROJECT_DIR}/.ci/gta5view.nsi && \
mv -f gta5view_setup.exe gta5view-${EXECUTABLE_VERSION}_setup.exe mv -f gta5view_setup.exe gta5view-${EXECUTABLE_VERSION}_setup.exe

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/bin/bash
DOCKER_IMAGE=sypingauto/gta5view-build:1.10-shared DOCKER_IMAGE=sypingauto/gta5view-build:1.8-shared
PROJECT_DIR_DOCKER=/gta5view PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \ cd ${PROJECT_DIR} && \

View file

@ -6,7 +6,7 @@ environment:
steps: steps:
- name: Windows Installer - name: Windows Installer
image: sypingauto/gta5view-build:1.10-shared image: sypingauto/gta5view-build:1.8-shared
environment: environment:
BUILD_SCRIPT: "wininstall_build.sh" BUILD_SCRIPT: "wininstall_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32" QT_SELECT: "qt5-x86_64-w64-mingw32"
@ -18,7 +18,7 @@ steps:
- name: gta5view - name: gta5view
path: /srv/gta5view path: /srv/gta5view
- name: Windows Portable - name: Windows Portable
image: sypingauto/gta5view-build:1.10-static image: sypingauto/gta5view-build:1.8-static
environment: environment:
BUILD_SCRIPT: "windows_build.sh" BUILD_SCRIPT: "windows_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32" QT_SELECT: "qt5-x86_64-w64-mingw32"

View file

@ -1,6 +1,6 @@
app-id: de.syping.gta5view app-id: de.syping.gta5view
runtime: org.kde.Platform runtime: org.kde.Platform
runtime-version: '5.15-21.08' runtime-version: '5.15'
sdk: org.kde.Sdk sdk: org.kde.Sdk
command: gta5view command: gta5view
finish-args: finish-args:
@ -15,8 +15,6 @@ modules:
config-opts: config-opts:
- -DFLATPAK_BUILD=ON - -DFLATPAK_BUILD=ON
- -DQCONF_BUILD=ON - -DQCONF_BUILD=ON
- -DGTA5VIEW_BUILDCODE=Flatpak
- -DGTA5VIEW_BUILDTYPE=Release
sources: sources:
- type: dir - type: dir
path: ../ path: ../

View file

@ -6,7 +6,7 @@ variables:
Windows Installer: Windows Installer:
stage: build stage: build
image: sypingauto/gta5view-build:1.10-shared image: sypingauto/gta5view-build:1.8-shared
variables: variables:
BUILD_SCRIPT: "wininstall_build.sh" BUILD_SCRIPT: "wininstall_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32" QT_SELECT: "qt5-x86_64-w64-mingw32"
@ -19,7 +19,7 @@ Windows Installer:
Windows Portable: Windows Portable:
stage: build stage: build
image: sypingauto/gta5view-build:1.10-static image: sypingauto/gta5view-build:1.8-static
variables: variables:
BUILD_SCRIPT: "windows_build.sh" BUILD_SCRIPT: "windows_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32" QT_SELECT: "qt5-x86_64-w64-mingw32"

View file

@ -3,7 +3,7 @@ sudo: required
language: cpp language: cpp
services: service:
- docker - docker
env: env:
@ -15,19 +15,28 @@ matrix:
- env: - env:
- BUILD_SCRIPT=debian_docker.sh - BUILD_SCRIPT=debian_docker.sh
- RELEASE_LABEL="Debian 64-Bit Package" - RELEASE_LABEL="Debian 64-Bit Package"
- DEBIAN_VERSION=buster - DEBIAN_VERSION=stretch
- DOCKER_USER=amd64 - DOCKER_USER=amd64
- APT_INSTALL=clang - APT_INSTALL=clang
- env: - env:
- BUILD_SCRIPT=windows_docker.sh - BUILD_SCRIPT=windows_docker.sh
- QT_SELECT=qt5-x86_64-w64-mingw32 - QT_SELECT=qt5-x86_64-w64-mingw32
- RELEASE_LABEL="Windows 64-Bit Portable" - RELEASE_LABEL="Windows 64-Bit Portable"
- env:
- 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=windows_docker.sh
- QT_SELECT=qt5-x86_64-w64-mingw32
- RELEASE_LABEL="Windows 64-Bit Portable for gtainside"
- PACKAGE_CODE=gtainside
- env: - env:
- BUILD_SCRIPT=wininstall_docker.sh - BUILD_SCRIPT=wininstall_docker.sh
- QT_SELECT=qt5-x86_64-w64-mingw32 - QT_SELECT=qt5-x86_64-w64-mingw32
- RELEASE_LABEL="Windows 64-Bit Installer" - RELEASE_LABEL="Windows 64-Bit Installer"
- os: osx - os: osx
osx_image: xcode14.2
env: env:
- BUILD_SCRIPT=osx_ci.sh - BUILD_SCRIPT=osx_ci.sh
- RELEASE_LABEL="Mac OS X 64-Bit Disk Image" - RELEASE_LABEL="Mac OS X 64-Bit Disk Image"

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2019 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -29,47 +29,48 @@ AboutDialog::AboutDialog(QWidget *parent) :
ui(new Ui::AboutDialog) ui(new Ui::AboutDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
// Build Strings // Build Strings
QString appVersion = QApplication::applicationVersion(); QString appVersion = qApp->applicationVersion();
const char* literalBuildType = GTA5SYNC_BUILDTYPE; QString buildType = tr(GTA5SYNC_BUILDTYPE);
const QString buildType = tr(literalBuildType); buildType.replace("_", " ");
const QString projectBuild = AppEnv::getBuildDateTime(); QString projectBuild = AppEnv::getBuildDateTime();
const QString buildStr = GTA5SYNC_BUILDSTRING; QString buildStr = GTA5SYNC_BUILDSTRING;
#ifndef GTA5SYNC_BUILDTYPE_REL
#ifdef GTA5SYNC_COMMIT #ifdef GTA5SYNC_COMMIT
if ((strcmp(literalBuildType, REL_BUILDTYPE) != 0) && !appVersion.contains("-")) if (!appVersion.contains("-")) { appVersion = appVersion % "-" % GTA5SYNC_COMMIT; }
appVersion = appVersion % "-" % GTA5SYNC_COMMIT; #endif
#endif #endif
// Translator Comments // Translator Comments
//: Translated by translator, example Translated by Syping //: Translated by translator, example Translated by Syping
const QString translatedByStr = tr("Translated by %1"); QString translatedByStr = tr("Translated by %1");
//: Insert your name here and profile here in following scheme, First Translator,First Profile\\nSecond Translator\\nThird Translator,Second Profile //: Insert your name here and profile here in following scheme, First Translator,First Profile\\nSecond Translator\\nThird Translator,Second Profile
const QString translatorVal = tr("TRANSLATOR"); QString translatorVal = tr("TRANSLATOR");
QStringList translatorContent; QStringList translatorContent;
if (translatorVal != "TRANSLATOR") { if (translatorVal != "TRANSLATOR")
{
const QStringList translatorList = translatorVal.split('\n'); const QStringList translatorList = translatorVal.split('\n');
for (const QString &translatorStr : translatorList) { for (const QString &translatorStr : translatorList)
{
QStringList translatorStrList = translatorStr.split(','); QStringList translatorStrList = translatorStr.split(',');
const QString translatorName = translatorStrList.at(0); QString translatorName = translatorStrList.at(0);
translatorStrList.removeFirst(); translatorStrList.removeFirst();
QString translatorProfile = translatorStrList.join(QString()); QString translatorProfile = translatorStrList.join(QString());
if (!translatorProfile.isEmpty()) { if (!translatorProfile.isEmpty())
{
translatorContent += QString("<a href=\"%1\">%2</a>").arg(translatorProfile, translatorName); translatorContent += QString("<a href=\"%1\">%2</a>").arg(translatorProfile, translatorName);
} }
else { else
{
translatorContent += translatorName; translatorContent += translatorName;
} }
} }
} }
// Project Description // Project Description
const QString projectDes = tr("A project for viewing Grand Theft Auto V Snapmatic<br/>\nPictures and Savegames"); QString projectDes = tr("A project for viewing Grand Theft Auto V Snapmatic<br/>\nPictures and Savegames");
// Copyright Description // Copyright Description
QString copyrightDes1 = tr("Copyright &copy; <a href=\"%1\">%2</a> %3"); QString copyrightDes1 = tr("Copyright &copy; <a href=\"%1\">%2</a> %3");
@ -77,34 +78,40 @@ AboutDialog::AboutDialog(QWidget *parent) :
QString copyrightDes2 = tr("%1 is licensed under <a href=\"https://www.gnu.org/licenses/gpl-3.0.html#content\">GNU GPLv3</a>"); QString copyrightDes2 = tr("%1 is licensed under <a href=\"https://www.gnu.org/licenses/gpl-3.0.html#content\">GNU GPLv3</a>");
copyrightDes2 = copyrightDes2.arg(GTA5SYNC_APPSTR); copyrightDes2 = copyrightDes2.arg(GTA5SYNC_APPSTR);
QString copyrightDesA; QString copyrightDesA;
if (!translatorContent.isEmpty()) { if (!translatorContent.isEmpty())
{
copyrightDesA = copyrightDes1 % "<br/>" % translatedByStr.arg(translatorContent.join(", ")) % "<br/>" % copyrightDes2; copyrightDesA = copyrightDes1 % "<br/>" % translatedByStr.arg(translatorContent.join(", ")) % "<br/>" % copyrightDes2;
} }
else { else
{
copyrightDesA = copyrightDes1 % "<br/>" % copyrightDes2; copyrightDesA = copyrightDes1 % "<br/>" % copyrightDes2;
} }
// Setup User Interface // Setup User Interface
ui->setupUi(this); ui->setupUi(this);
aboutStr = ui->labAbout->text(); aboutStr = ui->labAbout->text();
titleStr = windowTitle(); titleStr = this->windowTitle();
ui->labAbout->setText(aboutStr.arg(GTA5SYNC_APPSTR, projectDes, appVersion % " (" % buildType % ")", projectBuild, buildStr, qVersion(), copyrightDesA)); ui->labAbout->setText(aboutStr.arg(GTA5SYNC_APPSTR, projectDes, appVersion % " (" % buildType % ")", projectBuild, buildStr, qVersion(), copyrightDesA));
setWindowTitle(titleStr.arg(GTA5SYNC_APPSTR)); this->setWindowTitle(titleStr.arg(GTA5SYNC_APPSTR));
// Set Icon for Close Button // Set Icon for Close Button
if (QIcon::hasThemeIcon("dialog-close")) { if (QIcon::hasThemeIcon("dialog-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close")); ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
} }
else if (QIcon::hasThemeIcon("gtk-close")) { else if (QIcon::hasThemeIcon("gtk-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close")); ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close"));
} }
// DPI calculation // DPI calculation
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
if (!translatorContent.isEmpty()) { if (!translatorContent.isEmpty())
{
resize(375 * screenRatio, 270 * screenRatio); resize(375 * screenRatio, 270 * screenRatio);
} }
else { else
{
resize(375 * screenRatio, 260 * screenRatio); resize(375 * screenRatio, 260 * screenRatio);
} }
} }
@ -116,11 +123,13 @@ AboutDialog::~AboutDialog()
void AboutDialog::on_labAbout_linkActivated(const QString &link) void AboutDialog::on_labAbout_linkActivated(const QString &link)
{ {
if (link.left(12) == "g5e://about?") { if (link.left(12) == "g5e://about?")
{
QStringList aboutStrList = QString(link).remove(0, 12).split(":"); QStringList aboutStrList = QString(link).remove(0, 12).split(":");
QMessageBox::information(this, QString::fromUtf8(QByteArray::fromBase64(aboutStrList.at(0).toUtf8())), QString::fromUtf8(QByteArray::fromBase64(aboutStrList.at(1).toUtf8()))); QMessageBox::information(this, QString::fromUtf8(QByteArray::fromBase64(aboutStrList.at(0).toUtf8())), QString::fromUtf8(QByteArray::fromBase64(aboutStrList.at(1).toUtf8())));
} }
else { else
{
QDesktopServices::openUrl(QUrl(link)); QDesktopServices::openUrl(QUrl(link));
} }
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -28,6 +28,7 @@ class AboutDialog;
class AboutDialog : public QDialog class AboutDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AboutDialog(QWidget *parent = 0); explicit AboutDialog(QWidget *parent = 0);
~AboutDialog(); ~AboutDialog();

View file

@ -26,7 +26,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>&lt;span style=&quot;font-weight:600&quot;&gt;%1&lt;/span&gt;&lt;br/&gt; <string>&lt;span style=&quot; font-weight:600;&quot;&gt;%1&lt;/span&gt;&lt;br/&gt;
&lt;br/&gt; &lt;br/&gt;
%2&lt;br/&gt; %2&lt;br/&gt;
&lt;br/&gt; &lt;br/&gt;

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -33,8 +33,12 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#endif #endif
#include <iostream>
using namespace std;
AppEnv::AppEnv() AppEnv::AppEnv()
{ {
} }
// Build Stuff // Build Stuff
@ -55,17 +59,18 @@ QString AppEnv::getGameFolder(bool *ok)
{ {
QDir dir; QDir dir;
QString GTAV_FOLDER = QString::fromUtf8(qgetenv("GTAV_FOLDER")); QString GTAV_FOLDER = QString::fromUtf8(qgetenv("GTAV_FOLDER"));
if (GTAV_FOLDER != "") { if (GTAV_FOLDER != "")
{
dir.setPath(GTAV_FOLDER); dir.setPath(GTAV_FOLDER);
if (dir.exists()) { if (dir.exists())
if (ok != NULL) {
*ok = true; if (ok != NULL) *ok = true;
qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8()); qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8());
return dir.absolutePath(); return dir.absolutePath();
} }
} }
const QString GTAV_defaultFolder = StandardPaths::documentsLocation() % "/Rockstar Games/GTA V"; QString GTAV_defaultFolder = StandardPaths::documentsLocation() % QDir::separator() % "Rockstar Games" % QDir::separator() % "GTA V";
QString GTAV_returnFolder = GTAV_defaultFolder; QString GTAV_returnFolder = GTAV_defaultFolder;
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
@ -74,44 +79,46 @@ QString AppEnv::getGameFolder(bool *ok)
GTAV_returnFolder = settings.value("dir", GTAV_defaultFolder).toString(); GTAV_returnFolder = settings.value("dir", GTAV_defaultFolder).toString();
settings.endGroup(); settings.endGroup();
if (forceDir) { if (forceDir)
{
dir.setPath(GTAV_returnFolder); dir.setPath(GTAV_returnFolder);
if (dir.exists()) { if (dir.exists())
if (ok != 0) {
*ok = true; if (ok != 0) *ok = true;
qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8()); qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8());
return dir.absolutePath(); return dir.absolutePath();
} }
} }
dir.setPath(GTAV_defaultFolder); dir.setPath(GTAV_defaultFolder);
if (dir.exists()) { if (dir.exists())
if (ok != 0) {
*ok = true; if (ok != 0) *ok = true;
qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8()); qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8());
return dir.absolutePath(); return dir.absolutePath();
} }
if (!forceDir) { if (!forceDir)
{
dir.setPath(GTAV_returnFolder); dir.setPath(GTAV_returnFolder);
if (dir.exists()) { if (dir.exists())
if (ok != 0) {
*ok = true; if (ok != 0) *ok = true;
qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8()); qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8());
return dir.absolutePath(); return dir.absolutePath();
} }
} }
if (ok != 0) if (ok != 0) *ok = false;
*ok = false; return "";
return QString();
} }
bool AppEnv::setGameFolder(QString gameFolder) bool AppEnv::setGameFolder(QString gameFolder)
{ {
QDir dir; QDir dir;
dir.setPath(gameFolder); dir.setPath(gameFolder);
if (dir.exists()) { if (dir.exists())
{
qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8()); qputenv("GTAV_FOLDER", dir.absolutePath().toUtf8());
return true; return true;
} }
@ -129,13 +136,13 @@ QString AppEnv::getInLangFolder()
#ifdef GTA5SYNC_INLANG #ifdef GTA5SYNC_INLANG
return StringParser::convertBuildedString(GTA5SYNC_INLANG); return StringParser::convertBuildedString(GTA5SYNC_INLANG);
#else #else
return StringParser::convertBuildedString(GTA5SYNC_SHARE % QLatin1String("/APPNAME:/translations")); return StringParser::convertBuildedString(GTA5SYNC_SHARE % QLatin1String("SEPARATOR:APPNAME:SEPARATOR:translations"));
#endif #endif
#else #else
#ifdef GTA5SYNC_INLANG #ifdef GTA5SYNC_INLANG
return StringParser::convertBuildedString(GTA5SYNC_INLANG); return StringParser::convertBuildedString(GTA5SYNC_INLANG);
#else #else
return QLatin1String(":/tr"); return QString(":/tr");
#endif #endif
#endif #endif
} }
@ -145,24 +152,6 @@ QString AppEnv::getPluginsFolder()
return StringParser::convertBuildedString(GTA5SYNC_PLUG); return StringParser::convertBuildedString(GTA5SYNC_PLUG);
} }
QString AppEnv::getImagesFolder()
{
#if defined(GTA5SYNC_QCONF) && defined(GTA5SYNC_CMAKE)
#ifdef Q_OS_WIN
return StringParser::convertBuildedString(GTA5SYNC_SHARE % QLatin1String("/resources"));
#else
return StringParser::convertBuildedString(GTA5SYNC_SHARE % QLatin1String("/APPNAME:/resources"));
#endif
#else
return QLatin1String(":/img");
#endif
}
QString AppEnv::getShareFolder()
{
return StringParser::convertBuildedString(GTA5SYNC_SHARE);
}
// Web Stuff // Web Stuff
QByteArray AppEnv::getUserAgent() QByteArray AppEnv::getUserAgent()
@ -171,19 +160,24 @@ QByteArray AppEnv::getUserAgent()
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString kernelVersion = QSysInfo::kernelVersion(); QString kernelVersion = QSysInfo::kernelVersion();
const QStringList &kernelVersionList = kernelVersion.split("."); const QStringList &kernelVersionList = kernelVersion.split(".");
if (kernelVersionList.length() > 2) { if (kernelVersionList.length() > 2)
{
kernelVersion = kernelVersionList.at(0) % "." % kernelVersionList.at(1); kernelVersion = kernelVersionList.at(0) % "." % kernelVersionList.at(1);
} }
QString runArch = QSysInfo::buildCpuArchitecture(); QString runArch = QSysInfo::buildCpuArchitecture();
if (runArch == "x86_64") { if (runArch == "x86_64")
{
runArch = "Win64; x64"; runArch = "Win64; x64";
} }
else if (runArch == "i686") { else if (runArch == "i686")
{
const QString &curArch = QSysInfo::currentCpuArchitecture(); const QString &curArch = QSysInfo::currentCpuArchitecture();
if (curArch == "x86_64") { if (curArch == "x86_64")
{
runArch = "WOW64"; runArch = "WOW64";
} }
else if (curArch == "i686") { else if (curArch == "i686")
{
runArch = "Win32; x86"; runArch = "Win32; x86";
} }
} }
@ -196,6 +190,11 @@ QByteArray AppEnv::getUserAgent()
#endif #endif
} }
// QUrl AppEnv::getCrewFetchingUrl(QString crewID)
// {
// return QUrl(QString("https://socialclub.rockstargames.com/reference/crewfeed/%1").arg(crewID));
// }
QUrl AppEnv::getCrewFetchingUrl(QString crewID) QUrl AppEnv::getCrewFetchingUrl(QString crewID)
{ {
return QUrl(QString("https://socialclub.rockstargames.com/crew/%1/%1").arg(crewID)); return QUrl(QString("https://socialclub.rockstargames.com/crew/%1/%1").arg(crewID));
@ -224,7 +223,8 @@ GameVersion AppEnv::getGameVersion()
QString installFolderSc = registrySettingsSc.value("InstallFolder", "").toString(); QString installFolderSc = registrySettingsSc.value("InstallFolder", "").toString();
QDir installFolderScDir(installFolderSc); QDir installFolderScDir(installFolderSc);
bool scVersionInstalled = false; bool scVersionInstalled = false;
if (!installFolderSc.isEmpty() && installFolderScDir.exists()) { if (!installFolderSc.isEmpty() && installFolderScDir.exists())
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "gameVersionFoundSocialClubVersion"; qDebug() << "gameVersionFoundSocialClubVersion";
#endif #endif
@ -233,28 +233,34 @@ GameVersion AppEnv::getGameVersion()
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\GTAV").arg(argumentValue), QSettings::NativeFormat); QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\GTAV").arg(argumentValue), QSettings::NativeFormat);
QString installFolderSteam = registrySettingsSteam.value("installfoldersteam", "").toString(); QString installFolderSteam = registrySettingsSteam.value("installfoldersteam", "").toString();
if (installFolderSteam.right(5) == "\\GTAV") { if (installFolderSteam.right(5) == "\\GTAV")
{
installFolderSteam = installFolderSteam.remove(installFolderSteam.length() - 5, 5); installFolderSteam = installFolderSteam.remove(installFolderSteam.length() - 5, 5);
} }
QDir installFolderSteamDir(installFolderSteam); QDir installFolderSteamDir(installFolderSteam);
bool steamVersionInstalled = false; bool steamVersionInstalled = false;
if (!installFolderSteam.isEmpty() && installFolderSteamDir.exists()) { if (!installFolderSteam.isEmpty() && installFolderSteamDir.exists())
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "gameVersionFoundSteamVersion"; qDebug() << "gameVersionFoundSteamVersion";
#endif #endif
steamVersionInstalled = true; steamVersionInstalled = true;
} }
if (scVersionInstalled && steamVersionInstalled) { if (scVersionInstalled && steamVersionInstalled)
{
return GameVersion::BothVersions; return GameVersion::BothVersions;
} }
else if (scVersionInstalled) { else if (scVersionInstalled)
{
return GameVersion::SocialClubVersion; return GameVersion::SocialClubVersion;
} }
else if (steamVersionInstalled) { else if (steamVersionInstalled)
{
return GameVersion::SteamVersion; return GameVersion::SteamVersion;
} }
else { else
{
return GameVersion::NoVersion; return GameVersion::NoVersion;
} }
#else #else
@ -264,7 +270,8 @@ GameVersion AppEnv::getGameVersion()
GameLanguage AppEnv::getGameLanguage(GameVersion gameVersion) GameLanguage AppEnv::getGameLanguage(GameVersion gameVersion)
{ {
if (gameVersion == GameVersion::SocialClubVersion) { if (gameVersion == GameVersion::SocialClubVersion)
{
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString argumentValue; QString argumentValue;
#ifdef _WIN64 #ifdef _WIN64
@ -277,7 +284,8 @@ GameLanguage AppEnv::getGameLanguage(GameVersion gameVersion)
return GameLanguage::Undefined; return GameLanguage::Undefined;
#endif #endif
} }
else if (gameVersion == GameVersion::SteamVersion) { else if (gameVersion == GameVersion::SteamVersion)
{
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString argumentValue; QString argumentValue;
#ifdef _WIN64 #ifdef _WIN64
@ -290,81 +298,128 @@ GameLanguage AppEnv::getGameLanguage(GameVersion gameVersion)
return GameLanguage::Undefined; return GameLanguage::Undefined;
#endif #endif
} }
else
{
return GameLanguage::Undefined; return GameLanguage::Undefined;
} }
}
GameLanguage AppEnv::gameLanguageFromString(QString gameLanguage) GameLanguage AppEnv::gameLanguageFromString(QString gameLanguage)
{ {
if (gameLanguage == "en-US") { if (gameLanguage == "en-US")
{
return GameLanguage::English; return GameLanguage::English;
} }
else if (gameLanguage == "fr-FR") { else if (gameLanguage == "fr-FR")
{
return GameLanguage::French; return GameLanguage::French;
} }
else if (gameLanguage == "it-IT") { else if (gameLanguage == "it-IT")
{
return GameLanguage::Italian; return GameLanguage::Italian;
} }
else if (gameLanguage == "de-DE") { else if (gameLanguage == "de-DE")
{
return GameLanguage::German; return GameLanguage::German;
} }
else if (gameLanguage == "es-ES") { else if (gameLanguage == "es-ES")
{
return GameLanguage::Spanish; return GameLanguage::Spanish;
} }
else if (gameLanguage == "es-MX") { else if (gameLanguage == "es-MX")
{
return GameLanguage::Mexican; return GameLanguage::Mexican;
} }
else if (gameLanguage == "pt-BR") { else if (gameLanguage == "pt-BR")
{
return GameLanguage::Brasilian; return GameLanguage::Brasilian;
} }
else if (gameLanguage == "ru-RU") { else if (gameLanguage == "ru-RU")
{
return GameLanguage::Russian; return GameLanguage::Russian;
} }
else if (gameLanguage == "pl-PL") { else if (gameLanguage == "pl-PL")
{
return GameLanguage::Polish; return GameLanguage::Polish;
} }
else if (gameLanguage == "ja-JP") { else if (gameLanguage == "ja-JP")
{
return GameLanguage::Japanese; return GameLanguage::Japanese;
} }
else if (gameLanguage == "zh-CHS") { else if (gameLanguage == "zh-CHS")
{
return GameLanguage::SChinese; return GameLanguage::SChinese;
} }
else if (gameLanguage == "zh-CHT") { else if (gameLanguage == "zh-CHT")
{
return GameLanguage::TChinese; return GameLanguage::TChinese;
} }
else if (gameLanguage == "ko-KR") { else if (gameLanguage == "ko-KR")
return GameLanguage::Korean; {
return GameLanguage::Koreana;
} }
else
{
return GameLanguage::Undefined; return GameLanguage::Undefined;
} }
}
QString AppEnv::gameLanguageToString(GameLanguage gameLanguage) QString AppEnv::gameLanguageToString(GameLanguage gameLanguage)
{ {
switch (gameLanguage) { if (gameLanguage == GameLanguage::English)
case GameLanguage::English: {
return "en-US"; return "en-US";
case GameLanguage::French: }
else if (gameLanguage == GameLanguage::French)
{
return "fr-FR"; return "fr-FR";
case GameLanguage::Italian: }
else if (gameLanguage == GameLanguage::Italian)
{
return "it-IT"; return "it-IT";
case GameLanguage::German: }
else if (gameLanguage == GameLanguage::German)
{
return "de-DE"; return "de-DE";
case GameLanguage::Spanish: }
else if (gameLanguage == GameLanguage::Spanish)
{
return "es-ES"; return "es-ES";
case GameLanguage::Mexican: }
else if (gameLanguage == GameLanguage::Mexican)
{
return "es-MX"; return "es-MX";
case GameLanguage::Brasilian: }
else if (gameLanguage == GameLanguage::Brasilian)
{
return "pt-BR"; return "pt-BR";
case GameLanguage::Polish: }
else if (gameLanguage == GameLanguage::Russian)
{
return "ru-RU";
}
else if (gameLanguage == GameLanguage::Polish)
{
return "pl-PL"; return "pl-PL";
case GameLanguage::Japanese: }
else if (gameLanguage == GameLanguage::Japanese)
{
return "ja-JP"; return "ja-JP";
case GameLanguage::SChinese: }
else if (gameLanguage == GameLanguage::SChinese)
{
return "zh-CHS"; return "zh-CHS";
case GameLanguage::TChinese: }
else if (gameLanguage == GameLanguage::TChinese)
{
return "zh-CHT"; return "zh-CHT";
case GameLanguage::Korean: }
else if (gameLanguage == GameLanguage::Koreana)
{
return "ko-KR"; return "ko-KR";
default: }
else
{
return "Undefinied"; return "Undefinied";
} }
} }
@ -373,55 +428,67 @@ bool AppEnv::setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage)
{ {
bool socialClubVersion = false; bool socialClubVersion = false;
bool steamVersion = false; bool steamVersion = false;
if (gameVersion == GameVersion::SocialClubVersion) { if (gameVersion == GameVersion::SocialClubVersion)
{
socialClubVersion = true; socialClubVersion = true;
} }
else if (gameVersion == GameVersion::SteamVersion) { else if (gameVersion == GameVersion::SteamVersion)
{
steamVersion = true; steamVersion = true;
} }
else if (gameVersion == GameVersion::BothVersions) { else if (gameVersion == GameVersion::BothVersions)
{
socialClubVersion = true; socialClubVersion = true;
steamVersion = true; steamVersion = true;
} }
else { else
{
return false; return false;
} }
if (socialClubVersion) { if (socialClubVersion)
{
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString argumentValue; QString argumentValue;
#ifdef _WIN64 #ifdef _WIN64
argumentValue = "\\WOW6432Node"; argumentValue = "\\WOW6432Node";
#endif #endif
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat); QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
if (gameLanguage != GameLanguage::Undefined) { if (gameLanguage != GameLanguage::Undefined)
{
registrySettingsSc.setValue("Language", gameLanguageToString(gameLanguage)); registrySettingsSc.setValue("Language", gameLanguageToString(gameLanguage));
} }
else { else
{
registrySettingsSc.remove("Language"); registrySettingsSc.remove("Language");
} }
registrySettingsSc.sync(); registrySettingsSc.sync();
if (registrySettingsSc.status() != QSettings::NoError) { if (registrySettingsSc.status() != QSettings::NoError)
{
return false; return false;
} }
#else #else
Q_UNUSED(gameLanguage) Q_UNUSED(gameLanguage)
#endif #endif
} }
if (steamVersion) { if (steamVersion)
{
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString argumentValue; QString argumentValue;
#ifdef _WIN64 #ifdef _WIN64
argumentValue = "\\WOW6432Node"; argumentValue = "\\WOW6432Node";
#endif #endif
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V Steam").arg(argumentValue), QSettings::NativeFormat); QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V Steam").arg(argumentValue), QSettings::NativeFormat);
if (gameLanguage != GameLanguage::Undefined) { if (gameLanguage != GameLanguage::Undefined)
{
registrySettingsSteam.setValue("Language", gameLanguageToString(gameLanguage)); registrySettingsSteam.setValue("Language", gameLanguageToString(gameLanguage));
} }
else { else
{
registrySettingsSteam.remove("Language"); registrySettingsSteam.remove("Language");
} }
registrySettingsSteam.sync(); registrySettingsSteam.sync();
if (registrySettingsSteam.status() != QSettings::NoError) { if (registrySettingsSteam.status() != QSettings::NoError)
{
return false; return false;
} }
#else #else

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2018 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -23,7 +23,7 @@
#include <QUrl> #include <QUrl>
enum class GameVersion : int { NoVersion = 0, SocialClubVersion = 1, SteamVersion = 2, BothVersions = 3 }; 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, Korean = 13 }; 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 class AppEnv
{ {
@ -39,9 +39,7 @@ public:
static bool setGameFolder(QString gameFolder); static bool setGameFolder(QString gameFolder);
static QString getExLangFolder(); static QString getExLangFolder();
static QString getInLangFolder(); static QString getInLangFolder();
static QString getImagesFolder();
static QString getPluginsFolder(); static QString getPluginsFolder();
static QString getShareFolder();
// Web Stuff // Web Stuff
static QByteArray getUserAgent(); static QByteArray getUserAgent();

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.5)
project(gta5view LANGUAGES C CXX) project(gta5view LANGUAGES C CXX)
@ -11,18 +11,13 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(FORCE_QT_VERSION "" CACHE STRING "Force Qt Version") find_package(Qt5 COMPONENTS Network Svg Widgets REQUIRED)
if(FORCE_QT_VERSION) find_package(Qt5 COMPONENTS LinguistTools QUIET)
set(QT_VERSION_MAJOR ${FORCE_QT_VERSION})
else()
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
endif()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network Svg Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools QUIET)
if(WIN32) if(WIN32)
find_package(Qt5 COMPONENTS WinExtras REQUIRED)
list(APPEND GTA5VIEW_LIBS list(APPEND GTA5VIEW_LIBS
dwmapi Qt5::WinExtras
) )
list(APPEND GTA5VIEW_DEFINES list(APPEND GTA5VIEW_DEFINES
-DUNICODE -DUNICODE
@ -33,20 +28,11 @@ if(WIN32)
res/app.rc res/app.rc
) )
endif() endif()
if(APPLE)
list(APPEND GTA5VIEW_RESOURCES
res/gta5view.icns
)
set(MACOSX_BUNDLE_BUNDLE_NAME gta5view)
set(MACOSX_BUNDLE_BUNDLE_VERSION 1.10.2)
set(MACOSX_BUNDLE_ICON_FILE gta5view.icns)
set(MACOSX_BUNDLE_GUI_IDENTIFIER de.syping.gta5view)
set_source_files_properties(res/gta5view.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
endif()
list(APPEND GTA5VIEW_DEFINES list(APPEND GTA5VIEW_DEFINES
-DGTA5SYNC_CMAKE -DGTA5SYNC_CMAKE
-DGTA5SYNC_PROJECT -DGTA5SYNC_PROJECT
-DSNAPMATIC_NODEFAULT
) )
set(GTA5VIEW_SOURCES set(GTA5VIEW_SOURCES
@ -71,7 +57,6 @@ set(GTA5VIEW_SOURCES
ProfileInterface.cpp ProfileInterface.cpp
ProfileLoader.cpp ProfileLoader.cpp
ProfileWidget.cpp ProfileWidget.cpp
RagePhoto.cpp
SavegameCopy.cpp SavegameCopy.cpp
SavegameData.cpp SavegameData.cpp
SavegameDialog.cpp SavegameDialog.cpp
@ -93,7 +78,6 @@ set(GTA5VIEW_SOURCES
set(GTA5VIEW_HEADERS set(GTA5VIEW_HEADERS
config.h config.h
wrapper.h
AboutDialog.h AboutDialog.h
AppEnv.h AppEnv.h
CrewDatabase.h CrewDatabase.h
@ -114,7 +98,6 @@ set(GTA5VIEW_HEADERS
ProfileInterface.h ProfileInterface.h
ProfileLoader.h ProfileLoader.h
ProfileWidget.h ProfileWidget.h
RagePhoto.h
SavegameCopy.h SavegameCopy.h
SavegameData.h SavegameData.h
SavegameDialog.h SavegameDialog.h
@ -157,7 +140,14 @@ set(GTA5VIEW_FORMS
UserInterface.ui UserInterface.ui
) )
set(GTA5VIEW_TRANSLATIONS 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_de.ts
res/gta5sync_en_US.ts res/gta5sync_en_US.ts
res/gta5sync_fr.ts res/gta5sync_fr.ts
@ -165,28 +155,11 @@ set(GTA5VIEW_TRANSLATIONS
res/gta5sync_ru.ts res/gta5sync_ru.ts
res/gta5sync_uk.ts res/gta5sync_uk.ts
res/gta5sync_zh_TW.ts res/gta5sync_zh_TW.ts
res/qtbase_en_GB.ts
) )
add_custom_target(translations DEPENDS ${GTA5VIEW_TRANSLATIONS})
list(APPEND GTA5VIEW_RESOURCES
res/global.qrc
res/template.qrc
)
set_property(SOURCE res/global.qrc PROPERTY AUTORCC_OPTIONS "-threshold;0;-compress;9")
if(Qt5LinguistTools_FOUND)
qt5_add_translation(GTA5VIEW_QMFILES
${GTA5VIEW_TRANSLATIONS}
res/qt5/qtbase_en_GB.ts
)
set(LINGUIST_FOUND TRUE)
elseif(Qt6LinguistTools_FOUND)
qt6_add_translation(GTA5VIEW_QMFILES
${GTA5VIEW_TRANSLATIONS}
res/qt6/qtbase_en_GB.ts
)
set(LINGUIST_FOUND TRUE)
else() else()
set(GTA5VIEW_QMFILES set(GTA5VIEW_TRANSLATIONS
res/gta5sync_de.qm res/gta5sync_de.qm
res/gta5sync_en_US.qm res/gta5sync_en_US.qm
res/gta5sync_fr.qm res/gta5sync_fr.qm
@ -194,7 +167,7 @@ else()
res/gta5sync_ru.qm res/gta5sync_ru.qm
res/gta5sync_uk.qm res/gta5sync_uk.qm
res/gta5sync_zh_TW.qm res/gta5sync_zh_TW.qm
res/qt${QT_VERSION_MAJOR}/qtbase_en_GB.qm res/qtbase_en_GB.qm
) )
endif() endif()
@ -205,44 +178,22 @@ if(QCONF_BUILD)
) )
else() else()
list(APPEND GTA5VIEW_RESOURCES list(APPEND GTA5VIEW_RESOURCES
res/img.qrc
res/tr_g5p.qrc res/tr_g5p.qrc
res/qt${QT_VERSION_MAJOR}/tr_qt.qrc res/tr_qt5.qrc
) )
endif() endif()
option(FLATPAK_BUILD "Flatpak modifications and optimisations" OFF) option(FLATPAK_BUILD "Flatpak modifications and identifications" OFF)
if(FLATPAK_BUILD) if(FLATPAK_BUILD)
list(APPEND GTA5VIEW_DEFINES list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_BUILDCODE=\"Flatpak\""
"-DGTA5SYNC_BUILDTYPE=\"Flatpak\""
-DGTA5SYNC_FLATPAK -DGTA5SYNC_FLATPAK
) )
endif() endif()
option(WITH_DONATE "Donate menu option and donation dialog" OFF)
if(WITH_DONATE)
set(DONATE_ADDRESSES "" CACHE STRING "Donation addresses")
list(APPEND GTA5VIEW_HEADERS
anpro/QrCode.h
)
list(APPEND GTA5VIEW_SOURCES
anpro/QrCode.cpp
)
list(APPEND GTA5VIEW_DEFINES
-DGTA5SYNC_DONATE
)
list(APPEND GTA5VIEW_RESOURCES
res/donate.qrc
)
if(DONATE_ADDRESSES)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_DONATE_ADDRESSES=\"${DONATE_ADDRESSES}\""
)
endif()
endif()
option(WITH_MOTD "Developer message system directed to users" OFF) option(WITH_MOTD "Developer message system directed to users" OFF)
if(WITH_MOTD) if(WITH_MOTD)
set(MOTD_WEBURL "" CACHE STRING "Messages WebURL")
list(APPEND GTA5VIEW_HEADERS list(APPEND GTA5VIEW_HEADERS
MessageThread.h MessageThread.h
) )
@ -261,11 +212,6 @@ endif()
option(WITH_TELEMETRY "Hardware survey and basic telemetry system" OFF) option(WITH_TELEMETRY "Hardware survey and basic telemetry system" OFF)
if(WITH_TELEMETRY) if(WITH_TELEMETRY)
set(TELEMETRY_AUTHID "" CACHE STRING "Telemetry AuthID")
set(TELEMETRY_AUTHPW "" CACHE STRING "Telemetry AuthPW")
set(TELEMETRY_PUSHURL "" CACHE STRING "Telemetry PushURL")
set(TELEMETRY_REGURL "" CACHE STRING "Telemetry RegURL")
set(TELEMETRY_WEBURL "" CACHE STRING "Telemetry WebURL")
list(APPEND GTA5VIEW_HEADERS list(APPEND GTA5VIEW_HEADERS
TelemetryClass.h TelemetryClass.h
tmext/TelemetryClassAuthenticator.h tmext/TelemetryClassAuthenticator.h
@ -314,6 +260,37 @@ if(GTA5VIEW_BUILDTYPE)
list(APPEND GTA5VIEW_DEFINES list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_BUILDTYPE=\"${GTA5VIEW_BUILDTYPE}\"" "-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() endif()
if(GTA5VIEW_COMMIT) if(GTA5VIEW_COMMIT)
list(APPEND GTA5VIEW_DEFINES list(APPEND GTA5VIEW_DEFINES
@ -345,8 +322,7 @@ add_executable(gta5view
${GTA5VIEW_RESOURCES} ${GTA5VIEW_RESOURCES}
) )
if(LINGUIST_FOUND AND QCONF_BUILD) if(Qt5LinguistTools_FOUND AND QCONF_BUILD)
add_custom_target(translations DEPENDS ${GTA5VIEW_QMFILES})
add_dependencies(gta5view translations) add_dependencies(gta5view translations)
endif() endif()
@ -360,12 +336,11 @@ endif()
target_compile_definitions(gta5view PRIVATE ${GTA5VIEW_DEFINES}) target_compile_definitions(gta5view PRIVATE ${GTA5VIEW_DEFINES})
target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR}) target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR})
target_link_libraries(gta5view PRIVATE Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Widgets ${GTA5VIEW_LIBS}) target_link_libraries(gta5view PRIVATE Qt5::Network Qt5::Svg Qt5::Widgets ${GTA5VIEW_LIBS})
install(TARGETS gta5view DESTINATION bin) install(TARGETS gta5view DESTINATION bin)
install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications) install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications)
install(FILES res/de.syping.gta5view.metainfo.xml DESTINATION share/metainfo) install(FILES res/de.syping.gta5view.metainfo.xml DESTINATION share/metainfo)
install(FILES res/de.syping.gta5view.xml DESTINATION share/mime/packages)
install(FILES res/gta5view-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME de.syping.gta5view.png) 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-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-32.png DESTINATION share/icons/hicolor/32x32/apps RENAME de.syping.gta5view.png)
@ -375,8 +350,7 @@ install(FILES res/gta5view-96.png DESTINATION share/icons/hicolor/96x96/apps REN
install(FILES res/gta5view-128.png DESTINATION share/icons/hicolor/128x128/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-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/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) if(QCONF_BUILD)
include(res/img.cmake) install(FILES ${GTA5VIEW_TRANSLATIONS} DESTINATION share/gta5view/translations)
install(FILES ${GTA5VIEW_IMGFILES} DESTINATION share/gta5view/resources)
install(FILES ${GTA5VIEW_QMFILES} DESTINATION share/gta5view/translations)
endif() endif()

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -46,7 +46,8 @@ void DatabaseThread::run()
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit())); QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
while (threadRunning) { while (threadRunning)
{
QTimer::singleShot(300000, &threadLoop, SLOT(quit())); QTimer::singleShot(300000, &threadLoop, SLOT(quit()));
threadLoop.exec(); threadLoop.exec();
} }
@ -54,8 +55,10 @@ void DatabaseThread::run()
void DatabaseThread::scanCrewReference(const QStringList &crewList, const int &requestDelay) void DatabaseThread::scanCrewReference(const QStringList &crewList, const int &requestDelay)
{ {
for (const QString &crewID : crewList) { for (QString crewID : crewList)
if (threadRunning && crewID != QLatin1String("0")) { {
if (threadRunning && crewID != QLatin1String("0"))
{
QNetworkAccessManager *netManager = new QNetworkAccessManager(); QNetworkAccessManager *netManager = new QNetworkAccessManager();
QNetworkRequest netRequest(AppEnv::getCrewFetchingUrl(crewID)); QNetworkRequest netRequest(AppEnv::getCrewFetchingUrl(crewID));
#if QT_VERSION >= 0x050600 #if QT_VERSION >= 0x050600
@ -73,36 +76,40 @@ void DatabaseThread::scanCrewReference(const QStringList &crewList, const int &r
QEventLoop *downloadLoop = new QEventLoop(); QEventLoop *downloadLoop = new QEventLoop();
QObject::connect(netReply, SIGNAL(finished()), downloadLoop, SLOT(quit())); QObject::connect(netReply, SIGNAL(finished()), downloadLoop, SLOT(quit()));
if (!continueLastCrew) if (!continueLastCrew) { QObject::connect(this, SIGNAL(threadTerminated()), downloadLoop, SLOT(quit())); }
QObject::connect(this, SIGNAL(threadTerminated()), downloadLoop, SLOT(quit()));
QTimer::singleShot(30000, downloadLoop, SLOT(quit())); QTimer::singleShot(30000, downloadLoop, SLOT(quit()));
downloadLoop->exec(); downloadLoop->exec();
downloadLoop->disconnect(); downloadLoop->disconnect();
delete downloadLoop; delete downloadLoop;
if (netReply->isFinished()) { if (netReply->isFinished())
{
QString crewName; QString crewName;
QByteArray crewHtml = netReply->readAll(); QByteArray crewHtml = netReply->readAll();
QStringList crewHtmlSplit1 = QString::fromUtf8(crewHtml).split("<title>Rockstar Games Social Club - Crew : "); QStringList crewHtmlSplit1 = QString::fromUtf8(crewHtml).split("<title>Rockstar Games Social Club - Crew : ");
if (crewHtmlSplit1.length() >= 2) { if (crewHtmlSplit1.length() >= 2)
{
QStringList crewHtmlSplit2 = QString(crewHtmlSplit1.at(1)).split("</title>"); QStringList crewHtmlSplit2 = QString(crewHtmlSplit1.at(1)).split("</title>");
if (crewHtmlSplit2.length() >= 1) { if (crewHtmlSplit2.length() >= 1)
{
crewName = crewHtmlSplit2.at(0); crewName = crewHtmlSplit2.at(0);
} }
} }
if (!crewName.isEmpty()) { if (!crewName.isEmpty())
{
emit crewNameFound(crewID.toInt(), crewName); emit crewNameFound(crewID.toInt(), crewName);
} }
} }
else { else
{
netReply->abort(); netReply->abort();
} }
if (threadRunning) { if (threadRunning)
{
QEventLoop *waitingLoop = new QEventLoop(); QEventLoop *waitingLoop = new QEventLoop();
QTimer::singleShot(requestDelay, waitingLoop, SLOT(quit())); QTimer::singleShot(requestDelay, waitingLoop, SLOT(quit()));
if (!continueLastCrew) if (!continueLastCrew) { QObject::connect(this, SIGNAL(threadTerminated()), waitingLoop, SLOT(quit())); }
QObject::connect(this, SIGNAL(threadTerminated()), waitingLoop, SLOT(quit()));
waitingLoop->exec(); waitingLoop->exec();
waitingLoop->disconnect(); waitingLoop->disconnect();
delete waitingLoop; delete waitingLoop;
@ -116,14 +123,17 @@ void DatabaseThread::scanCrewReference(const QStringList &crewList, const int &r
void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int &maxPages, const int &requestDelay) void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int &maxPages, const int &requestDelay)
{ {
for (const QString &crewID : crewList) { for (QString crewID : crewList)
if (threadRunning && crewID != QLatin1String("0")) { {
if (threadRunning && crewID != QLatin1String("0"))
{
int currentFail = 0; int currentFail = 0;
int currentPage = 0; int currentPage = 0;
int foundPlayers = 0; int foundPlayers = 0;
int totalPlayers = 1000; int totalPlayers = 1000;
while(foundPlayers < totalPlayers && currentPage < maxPages && (continueLastCrew ? true : threadRunning)) { while(foundPlayers < totalPlayers && currentPage < maxPages && (continueLastCrew ? true : threadRunning))
{
QNetworkAccessManager *netManager = new QNetworkAccessManager(); QNetworkAccessManager *netManager = new QNetworkAccessManager();
QNetworkRequest netRequest(AppEnv::getPlayerFetchingUrl(crewID, currentPage)); QNetworkRequest netRequest(AppEnv::getPlayerFetchingUrl(crewID, currentPage));
#if QT_VERSION >= 0x050600 #if QT_VERSION >= 0x050600
@ -141,14 +151,14 @@ void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int
QEventLoop *downloadLoop = new QEventLoop(); QEventLoop *downloadLoop = new QEventLoop();
QObject::connect(netReply, SIGNAL(finished()), downloadLoop, SLOT(quit())); QObject::connect(netReply, SIGNAL(finished()), downloadLoop, SLOT(quit()));
if (!continueLastCrew) if (!continueLastCrew) { QObject::connect(this, SIGNAL(threadTerminated()), downloadLoop, SLOT(quit())); }
QObject::connect(this, SIGNAL(threadTerminated()), downloadLoop, SLOT(quit()));
QTimer::singleShot(30000, downloadLoop, SLOT(quit())); QTimer::singleShot(30000, downloadLoop, SLOT(quit()));
downloadLoop->exec(); downloadLoop->exec();
downloadLoop->disconnect(); downloadLoop->disconnect();
delete downloadLoop; delete downloadLoop;
if (netReply->isFinished()) { if (netReply->isFinished())
{
QByteArray crewJson = netReply->readAll(); QByteArray crewJson = netReply->readAll();
QJsonDocument crewDocument = QJsonDocument::fromJson(crewJson); QJsonDocument crewDocument = QJsonDocument::fromJson(crewJson);
QJsonObject crewObject = crewDocument.object(); QJsonObject crewObject = crewDocument.object();
@ -156,25 +166,32 @@ void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int
if (crewMap.contains("Total")) { totalPlayers = crewMap["Total"].toInt(); } if (crewMap.contains("Total")) { totalPlayers = crewMap["Total"].toInt(); }
if (crewMap.contains("Members")) { if (crewMap.contains("Members"))
{
const QList<QVariant> memberList = crewMap["Members"].toList(); const QList<QVariant> memberList = crewMap["Members"].toList();
for (const QVariant &memberVariant : memberList) { for (QVariant memberVariant : memberList)
{
QMap<QString, QVariant> memberMap = memberVariant.toMap(); QMap<QString, QVariant> memberMap = memberVariant.toMap();
if (memberMap.contains("RockstarId") && memberMap.contains("Name")) { if (memberMap.contains("RockstarId") && memberMap.contains("Name"))
{
int RockstarId = memberMap["RockstarId"].toInt(); int RockstarId = memberMap["RockstarId"].toInt();
QString memberName = memberMap["Name"].toString(); QString memberName = memberMap["Name"].toString();
if (!memberName.isEmpty() && RockstarId != 0) { if (!memberName.isEmpty() && RockstarId != 0)
{
foundPlayers++; foundPlayers++;
emit playerNameFound(RockstarId, memberName); emit playerNameFound(RockstarId, memberName);
} }
} }
} }
} }
currentPage++; currentPage++;
} }
else { else
{
currentFail++; currentFail++;
if (currentFail == maxLoadFails) { if (currentFail == maxLoadFails)
{
currentFail = 0; currentFail = 0;
currentPage++; currentPage++;
} }
@ -183,7 +200,8 @@ void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int
delete netReply; delete netReply;
delete netManager; delete netManager;
if (foundPlayers < totalPlayers && currentPage < maxPages && (continueLastCrew ? true : threadRunning)) { if (foundPlayers < totalPlayers && currentPage < maxPages && (continueLastCrew ? true : threadRunning))
{
QEventLoop *waitingLoop = new QEventLoop(); QEventLoop *waitingLoop = new QEventLoop();
QTimer::singleShot(requestDelay, waitingLoop, SLOT(quit())); QTimer::singleShot(requestDelay, waitingLoop, SLOT(quit()));
if (!continueLastCrew) { QObject::connect(this, SIGNAL(threadTerminated()), waitingLoop, SLOT(quit())); } if (!continueLastCrew) { QObject::connect(this, SIGNAL(threadTerminated()), waitingLoop, SLOT(quit())); }
@ -198,8 +216,10 @@ void DatabaseThread::scanCrewMembersList(const QStringList &crewList, const int
void DatabaseThread::deleteCompatibleCrews(QStringList *crewList) void DatabaseThread::deleteCompatibleCrews(QStringList *crewList)
{ {
for (const QString &crewNID : *crewList) { for (QString crewNID : *crewList)
if (crewDB->isCompatibleCrew(crewNID)) { {
if (crewDB->isCompatibleCrew(crewNID))
{
crewList->removeAll(crewNID); crewList->removeAll(crewNID);
} }
} }
@ -208,8 +228,10 @@ void DatabaseThread::deleteCompatibleCrews(QStringList *crewList)
QStringList DatabaseThread::deleteCompatibleCrews(const QStringList &crewList) QStringList DatabaseThread::deleteCompatibleCrews(const QStringList &crewList)
{ {
QStringList crewListR = crewList; QStringList crewListR = crewList;
for (const QString &crewNID : crewListR) { for (QString crewNID : crewListR)
if (crewDB->isCompatibleCrew(crewNID)) { {
if (crewDB->isCompatibleCrew(crewNID))
{
crewListR.removeAll(crewNID); crewListR.removeAll(crewNID);
} }
} }

View file

@ -49,7 +49,7 @@ void ExportThread::run()
// Quality Settings // Quality Settings
settings.beginGroup("Pictures"); settings.beginGroup("Pictures");
int defaultQuality = 100; int defaultQuality = 100;
QSize defExportSize = SnapmaticPicture::getSnapmaticResolution(); QSize defExportSize = QSize(960, 536);
int customQuality = settings.value("CustomQuality", defaultQuality).toInt(); int customQuality = settings.value("CustomQuality", defaultQuality).toInt();
if (customQuality < 1 || customQuality > 100) if (customQuality < 1 || customQuality > 100)
{ {

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -28,6 +28,7 @@
GlobalString::GlobalString() GlobalString::GlobalString()
{ {
} }
QMap<QString, QString> GlobalString::getGlobalMap() QMap<QString, QString> GlobalString::getGlobalMap()
@ -38,7 +39,8 @@ QMap<QString, QString> GlobalString::getGlobalMap()
globalFile.setIniCodec("UTF-8"); globalFile.setIniCodec("UTF-8");
#endif #endif
globalFile.beginGroup("Global"); globalFile.beginGroup("Global");
for (const QString &globalStr : globalFile.childKeys()) { for (const QString &globalStr : globalFile.childKeys())
{
globalMap[globalStr] = globalFile.value(globalStr, globalStr).toString(); globalMap[globalStr] = globalFile.value(globalStr, globalStr).toString();
} }
globalFile.endGroup(); globalFile.endGroup();
@ -54,9 +56,9 @@ QString GlobalString::getString(QString valueStr, bool *ok)
#endif #endif
globalFile.beginGroup("Global"); globalFile.beginGroup("Global");
QStringList globalStrList = globalFile.childKeys(); QStringList globalStrList = globalFile.childKeys();
if (globalStrList.contains(valueStr)) { if (globalStrList.contains(valueStr))
if (ok != nullptr) {
*ok = true; if (ok != nullptr) *ok = true;
globalString = globalFile.value(valueStr, valueStr).toString(); globalString = globalFile.value(valueStr, valueStr).toString();
} }
globalFile.endGroup(); globalFile.endGroup();
@ -67,14 +69,10 @@ QString GlobalString::getLanguageFile()
{ {
QString language = getLanguage(); QString language = getLanguage();
QString languageFile = ":/global/global." % language % ".ini"; QString languageFile = ":/global/global." % language % ".ini";
#if QT_VERSION >= 0x050200
if (!QFileInfo::exists(languageFile))
languageFile = ":/global/global.en.ini";
#else
if (!QFileInfo(languageFile).exists()) if (!QFileInfo(languageFile).exists())
{
languageFile = ":/global/global.en.ini"; languageFile = ":/global/global.en.ini";
#endif }
return languageFile; return languageFile;
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -17,45 +17,34 @@
*****************************************************************************/ *****************************************************************************/
#include "IconLoader.h" #include "IconLoader.h"
#include "AppEnv.h"
#include <QStringBuilder>
#include <QIcon> #include <QIcon>
IconLoader::IconLoader() IconLoader::IconLoader()
{ {
} }
QIcon IconLoader::loadingAppIcon() QIcon IconLoader::loadingAppIcon()
{ {
QIcon appIcon; QIcon appIcon;
#if defined(GTA5SYNC_QCONF) && defined(GTA5SYNC_CMAKE) appIcon.addFile(":/img/gta5view-16.png", QSize(16, 16));
#ifdef Q_OS_WIN appIcon.addFile(":/img/gta5view-24.png", QSize(24, 24));
const QString pattern = AppEnv::getImagesFolder() % QLatin1String("/gta5view-%1.png"); appIcon.addFile(":/img/gta5view-32.png", QSize(32, 32));
#else appIcon.addFile(":/img/gta5view-40.png", QSize(40, 40));
const QString pattern = AppEnv::getShareFolder() % QLatin1String("/icons/hicolor/%1x%1/apps/de.syping.gta5view.png"); appIcon.addFile(":/img/gta5view-48.png", QSize(48, 48));
#endif appIcon.addFile(":/img/gta5view-64.png", QSize(64, 64));
#else appIcon.addFile(":/img/gta5view-96.png", QSize(96, 96));
const QString pattern = AppEnv::getImagesFolder() % QLatin1String("/gta5view-%1.png"); appIcon.addFile(":/img/gta5view-128.png", QSize(128, 128));
#endif appIcon.addFile(":/img/gta5view-256.png", QSize(256, 256));
appIcon.addFile(pattern.arg("16"), QSize(16, 16));
appIcon.addFile(pattern.arg("24"), QSize(24, 24));
appIcon.addFile(pattern.arg("32"), QSize(32, 32));
appIcon.addFile(pattern.arg("40"), QSize(40, 40));
appIcon.addFile(pattern.arg("48"), QSize(48, 48));
appIcon.addFile(pattern.arg("64"), QSize(64, 64));
appIcon.addFile(pattern.arg("96"), QSize(96, 96));
appIcon.addFile(pattern.arg("128"), QSize(128, 128));
appIcon.addFile(pattern.arg("256"), QSize(256, 256));
return appIcon; return appIcon;
} }
QIcon IconLoader::loadingPointmakerIcon() QIcon IconLoader::loadingPointmakerIcon()
{ {
QIcon pointmakerIcon; QIcon pointmakerIcon;
const QString pattern = AppEnv::getImagesFolder() % QLatin1String("/pointmaker-%1.png"); pointmakerIcon.addFile(":/img/pointmaker-8.png", QSize(8, 8));
pointmakerIcon.addFile(pattern.arg("8"), QSize(8, 8)); pointmakerIcon.addFile(":/img/pointmaker-16.png", QSize(16, 16));
pointmakerIcon.addFile(pattern.arg("16"), QSize(16, 16)); pointmakerIcon.addFile(":/img/pointmaker-24.png", QSize(24, 24));
pointmakerIcon.addFile(pattern.arg("24"), QSize(24, 24)); pointmakerIcon.addFile(":/img/pointmaker-32.png", QSize(32, 32));
pointmakerIcon.addFile(pattern.arg("32"), QSize(32, 32));
return pointmakerIcon; return pointmakerIcon;
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2022 Syping * Copyright (C) 2017-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -16,11 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/ *****************************************************************************/
#include "ImportDialog.h"
#include "ui_ImportDialog.h" #include "ui_ImportDialog.h"
#include "SnapmaticPicture.h"
#include "SidebarGenerator.h" #include "SidebarGenerator.h"
#include "StandardPaths.h" #include "StandardPaths.h"
#include "ImportDialog.h"
#include "imagecropper.h" #include "imagecropper.h"
#include "AppEnv.h" #include "AppEnv.h"
#include "config.h" #include "config.h"
@ -40,6 +39,8 @@
#include <QRgb> #include <QRgb>
// IMAGES VALUES // IMAGES VALUES
#define snapmaticResolutionW 960
#define snapmaticResolutionH 536
#define snapmaticAvatarResolution 470 #define snapmaticAvatarResolution 470
#define snapmaticAvatarPlacementW 145 #define snapmaticAvatarPlacementW 145
#define snapmaticAvatarPlacementH 66 #define snapmaticAvatarPlacementH 66
@ -49,11 +50,7 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
ui(new Ui::ImportDialog) ui(new Ui::ImportDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
ui->setupUi(this); ui->setupUi(this);
ui->cmdOK->setDefault(true); ui->cmdOK->setDefault(true);
@ -63,22 +60,26 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
watermarkAvatar = true; watermarkAvatar = true;
watermarkPicture = false; watermarkPicture = false;
insideAvatarZone = false; insideAvatarZone = false;
avatarAreaImage = QImage(AppEnv::getImagesFolder() % "/avatarareaimport.png"); avatarAreaImage = QImage(":/img/avatarareaimport.png");
selectedColour = QColor::fromRgb(0, 0, 0, 255); selectedColour = QColor::fromRgb(0, 0, 0, 255);
// Set Icon for OK Button // Set Icon for OK Button
if (QIcon::hasThemeIcon("dialog-ok")) { if (QIcon::hasThemeIcon("dialog-ok"))
{
ui->cmdOK->setIcon(QIcon::fromTheme("dialog-ok")); ui->cmdOK->setIcon(QIcon::fromTheme("dialog-ok"));
} }
else if (QIcon::hasThemeIcon("gtk-ok")) { else if (QIcon::hasThemeIcon("gtk-ok"))
{
ui->cmdOK->setIcon(QIcon::fromTheme("gtk-ok")); ui->cmdOK->setIcon(QIcon::fromTheme("gtk-ok"));
} }
// Set Icon for Cancel Button // Set Icon for Cancel Button
if (QIcon::hasThemeIcon("dialog-cancel")) { if (QIcon::hasThemeIcon("dialog-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
} }
else if (QIcon::hasThemeIcon("gtk-cancel")) { else if (QIcon::hasThemeIcon("gtk-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel"));
} }
@ -87,14 +88,6 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
ui->labBackgroundImage->setText(tr("Background Image:")); ui->labBackgroundImage->setText(tr("Background Image:"));
ui->cmdBackgroundWipe->setVisible(false); ui->cmdBackgroundWipe->setVisible(false);
// Snapmatic Resolution
snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
ui->cbResolution->addItem("GTA V", snapmaticResolution);
ui->cbResolution->addItem("FiveM", QSize(1920, 1072));
ui->cbResolution->addItem("1280x720", QSize(1280, 720));
ui->cbResolution->addItem("1920x1080", QSize(1920, 1080));
ui->cbResolution->addItem("2560x1440", QSize(2560, 1440));
// Set Import Settings // Set Import Settings
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Import"); settings.beginGroup("Import");
@ -112,157 +105,123 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
ui->vlButtom->setContentsMargins(9 * screenRatio, 6 * screenRatio, 9 * screenRatio, 9 * screenRatio); ui->vlButtom->setContentsMargins(9 * screenRatio, 6 * screenRatio, 9 * screenRatio, 9 * screenRatio);
#else #else
#if QT_VERSION >= 0x060000 if (QApplication::style()->objectName() == "macintosh")
if (QApplication::style()->objectName() == "macos") { {
#else
if (QApplication::style()->objectName() == "macintosh") {
#endif
ui->vlButtom->setContentsMargins(9 * screenRatio, 9 * screenRatio, 9 * screenRatio, 9 * screenRatio); ui->vlButtom->setContentsMargins(9 * screenRatio, 9 * screenRatio, 9 * screenRatio, 9 * screenRatio);
} }
else { else
{
ui->vlButtom->setContentsMargins(9 * screenRatio, 6 * screenRatio, 9 * screenRatio, 9 * screenRatio); ui->vlButtom->setContentsMargins(9 * screenRatio, 6 * screenRatio, 9 * screenRatio, 9 * screenRatio);
} }
#endif #endif
// Options menu // Options menu
optionsMenu.addAction(tr("&Import new Picture..."), this, SLOT(importNewPicture())); optionsMenu = new QMenu(this);
optionsMenu.addAction(tr("&Crop Picture..."), this, SLOT(cropPicture())); optionsMenu->addAction(tr("&Import new Picture..."), this, SLOT(importNewPicture()));
optionsMenu.addSeparator(); optionsMenu->addAction(tr("&Crop Picture..."), this, SLOT(cropPicture()));
optionsMenu.addAction(tr("&Load Settings..."), this, SLOT(loadImportSettings())); optionsMenu->addSeparator();
optionsMenu.addAction(tr("&Save Settings..."), this, SLOT(saveImportSettings())); optionsMenu->addAction(tr("&Load Settings..."), this, SLOT(loadImportSettings()));
ui->cmdOptions->setMenu(&optionsMenu); optionsMenu->addAction(tr("&Save Settings..."), this, SLOT(saveImportSettings()));
ui->cmdOptions->setMenu(optionsMenu);
const QSize windowSize = sizeHint(); setMaximumSize(sizeHint());
setMinimumSize(windowSize); setMinimumSize(sizeHint());
setMaximumSize(windowSize); setFixedSize(sizeHint());
} }
ImportDialog::~ImportDialog() ImportDialog::~ImportDialog()
{ {
delete optionsMenu;
delete ui; delete ui;
} }
void ImportDialog::processImage() void ImportDialog::processImage()
{ {
if (workImage.isNull()) if (workImage.isNull()) return;
return;
QImage snapmaticImage = workImage; QImage snapmaticImage = workImage;
QPixmap snapmaticPixmap(snapmaticResolution); QPixmap snapmaticPixmap(snapmaticResolutionW, snapmaticResolutionH);
snapmaticPixmap.fill(selectedColour); snapmaticPixmap.fill(selectedColour);
QPainter snapmaticPainter(&snapmaticPixmap); QPainter snapmaticPainter(&snapmaticPixmap);
qreal screenRatioPR = AppEnv::screenRatioPR(); qreal screenRatioPR = AppEnv::screenRatioPR();
if (!backImage.isNull()) { if (!backImage.isNull())
if (!ui->cbStretch->isChecked()) { {
if (!ui->cbStretch->isChecked())
{
int diffWidth = 0; int diffWidth = 0;
int diffHeight = 0; int diffHeight = 0;
if (backImage.width() != snapmaticResolution.width()) { if (backImage.width() != snapmaticResolutionW)
diffWidth = snapmaticResolution.width() - backImage.width(); {
diffWidth = snapmaticResolutionW - backImage.width();
diffWidth = diffWidth / 2; diffWidth = diffWidth / 2;
} }
else if (backImage.height() != snapmaticResolution.height()) { else if (backImage.height() != snapmaticResolutionH)
diffHeight = snapmaticResolution.height() - backImage.height(); {
diffHeight = snapmaticResolutionH - backImage.height();
diffHeight = diffHeight / 2; diffHeight = diffHeight / 2;
} }
snapmaticPainter.drawImage(0 + diffWidth, 0 + diffHeight, backImage); snapmaticPainter.drawImage(0 + diffWidth, 0 + diffHeight, backImage);
} }
else { else
snapmaticPainter.drawImage(0, 0, QImage(backImage).scaled(snapmaticResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); {
snapmaticPainter.drawImage(0, 0, QImage(backImage).scaled(snapmaticResolutionW, snapmaticResolutionH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
} }
if (ui->cbAvatar->isChecked() && ui->cbForceAvatarColour->isChecked()) { if (ui->cbAvatar->isChecked() && ui->cbForceAvatarColour->isChecked())
{
snapmaticPainter.fillRect(snapmaticAvatarPlacementW, snapmaticAvatarPlacementH, snapmaticAvatarResolution, snapmaticAvatarResolution, selectedColour); snapmaticPainter.fillRect(snapmaticAvatarPlacementW, snapmaticAvatarPlacementH, snapmaticAvatarResolution, snapmaticAvatarResolution, selectedColour);
} }
} }
if (insideAvatarZone) { if (insideAvatarZone)
{
// Avatar mode // Avatar mode
int diffWidth = 0; int diffWidth = 0;
int diffHeight = 0; int diffHeight = 0;
if (ui->cbIgnore->isChecked()) { if (!ui->cbIgnore->isChecked())
snapmaticImage = snapmaticImage.scaled(snapmaticAvatarResolution, snapmaticAvatarResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); {
}
else if (ui->cbBorderless->isChecked()) {
snapmaticImage = snapmaticImage.scaled(snapmaticAvatarResolution, snapmaticAvatarResolution, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
if (snapmaticImage.width() > snapmaticAvatarResolution) {
int diffWidth = snapmaticImage.width() - snapmaticAvatarResolution;
diffWidth = diffWidth / 2;
QImage croppedImage(snapmaticAvatarResolution, snapmaticAvatarResolution, QImage::Format_ARGB32);
croppedImage.fill(Qt::transparent);
QPainter croppedPainter(&croppedImage);
croppedPainter.drawImage(0 - diffWidth, 0, snapmaticImage);
croppedPainter.end();
snapmaticImage = croppedImage;
}
else if (snapmaticImage.height() > snapmaticAvatarResolution) {
int diffHeight = snapmaticImage.height() - snapmaticAvatarResolution;
diffHeight = diffHeight / 2;
QImage croppedImage(snapmaticAvatarResolution, snapmaticAvatarResolution, QImage::Format_ARGB32);
croppedImage.fill(Qt::transparent);
QPainter croppedPainter(&croppedImage);
croppedPainter.drawImage(0, 0 - diffHeight, snapmaticImage);
croppedPainter.end();
snapmaticImage = croppedImage;
}
}
else {
snapmaticImage = snapmaticImage.scaled(snapmaticAvatarResolution, snapmaticAvatarResolution, Qt::KeepAspectRatio, Qt::SmoothTransformation); snapmaticImage = snapmaticImage.scaled(snapmaticAvatarResolution, snapmaticAvatarResolution, Qt::KeepAspectRatio, Qt::SmoothTransformation);
if (snapmaticImage.width() > snapmaticImage.height()) { if (snapmaticImage.width() > snapmaticImage.height())
{
diffHeight = snapmaticAvatarResolution - snapmaticImage.height(); diffHeight = snapmaticAvatarResolution - snapmaticImage.height();
diffHeight = diffHeight / 2; diffHeight = diffHeight / 2;
} }
else if (snapmaticImage.width() < snapmaticImage.height()) { else if (snapmaticImage.width() < snapmaticImage.height())
{
diffWidth = snapmaticAvatarResolution - snapmaticImage.width(); diffWidth = snapmaticAvatarResolution - snapmaticImage.width();
diffWidth = diffWidth / 2; diffWidth = diffWidth / 2;
} }
} }
else
{
snapmaticImage = snapmaticImage.scaled(snapmaticAvatarResolution, snapmaticAvatarResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
snapmaticPainter.drawImage(snapmaticAvatarPlacementW + diffWidth, snapmaticAvatarPlacementH + diffHeight, snapmaticImage); snapmaticPainter.drawImage(snapmaticAvatarPlacementW + diffWidth, snapmaticAvatarPlacementH + diffHeight, snapmaticImage);
if (ui->cbWatermark->isChecked()) if (ui->cbWatermark->isChecked()) { processWatermark(&snapmaticPainter); }
processWatermark(&snapmaticPainter);
imageTitle = tr("Custom Avatar", "Custom Avatar Description in SC, don't use Special Character!"); imageTitle = tr("Custom Avatar", "Custom Avatar Description in SC, don't use Special Character!");
} }
else { else
{
// Picture mode // Picture mode
int diffWidth = 0; int diffWidth = 0;
int diffHeight = 0; int diffHeight = 0;
if (ui->cbIgnore->isChecked()) { if (!ui->cbIgnore->isChecked())
snapmaticImage = snapmaticImage.scaled(snapmaticResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); {
} snapmaticImage = snapmaticImage.scaled(snapmaticResolutionW, snapmaticResolutionH, Qt::KeepAspectRatio, Qt::SmoothTransformation);
else if (ui->cbBorderless->isChecked()) { if (snapmaticImage.width() != snapmaticResolutionW)
snapmaticImage = snapmaticImage.scaled(snapmaticResolution, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); {
if (snapmaticImage.width() > snapmaticResolution.width()) { diffWidth = snapmaticResolutionW - snapmaticImage.width();
int diffWidth = snapmaticImage.width() - snapmaticResolution.width();
diffWidth = diffWidth / 2;
QImage croppedImage(snapmaticResolution, QImage::Format_ARGB32);
croppedImage.fill(Qt::transparent);
QPainter croppedPainter(&croppedImage);
croppedPainter.drawImage(0 - diffWidth, 0, snapmaticImage);
croppedPainter.end();
snapmaticImage = croppedImage;
}
else if (snapmaticImage.height() > snapmaticResolution.height()) {
int diffHeight = snapmaticImage.height() - snapmaticResolution.height();
diffHeight = diffHeight / 2;
QImage croppedImage(snapmaticResolution, QImage::Format_ARGB32);
croppedImage.fill(Qt::transparent);
QPainter croppedPainter(&croppedImage);
croppedPainter.drawImage(0, 0 - diffHeight, snapmaticImage);
croppedPainter.end();
snapmaticImage = croppedImage;
}
}
else {
snapmaticImage = snapmaticImage.scaled(snapmaticResolution, Qt::KeepAspectRatio, Qt::SmoothTransformation);
if (snapmaticImage.width() != snapmaticResolution.width()) {
diffWidth = snapmaticResolution.width() - snapmaticImage.width();
diffWidth = diffWidth / 2; diffWidth = diffWidth / 2;
} }
else if (snapmaticImage.height() != snapmaticResolution.height()) { else if (snapmaticImage.height() != snapmaticResolutionH)
diffHeight = snapmaticResolution.height() - snapmaticImage.height(); {
diffHeight = snapmaticResolutionH - snapmaticImage.height();
diffHeight = diffHeight / 2; diffHeight = diffHeight / 2;
} }
} }
else
{
snapmaticImage = snapmaticImage.scaled(snapmaticResolutionW, snapmaticResolutionH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
snapmaticPainter.drawImage(0 + diffWidth, 0 + diffHeight, snapmaticImage); snapmaticPainter.drawImage(0 + diffWidth, 0 + diffHeight, snapmaticImage);
if (ui->cbWatermark->isChecked()) if (ui->cbWatermark->isChecked()) { processWatermark(&snapmaticPainter); }
processWatermark(&snapmaticPainter);
imageTitle = tr("Custom Picture", "Custom Picture Description in SC, don't use Special Character!"); imageTitle = tr("Custom Picture", "Custom Picture Description in SC, don't use Special Character!");
} }
snapmaticPainter.end(); snapmaticPainter.end();
@ -273,136 +232,94 @@ void ImportDialog::processImage()
ui->labPicture->setPixmap(snapmaticPixmap.scaled(snapmaticResolutionLW * screenRatioPR, snapmaticResolutionLH * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); ui->labPicture->setPixmap(snapmaticPixmap.scaled(snapmaticResolutionLW * screenRatioPR, snapmaticResolutionLH * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
} }
void ImportDialog::reworkImage()
{
workImage = QImage();
if (origImage.width() == origImage.height()) {
if (ui->cbResolution->currentIndex() == 0) {
insideAvatarZone = true;
ui->cbAvatar->setChecked(true);
}
else {
insideAvatarZone = false;
ui->cbAvatar->setChecked(false);
}
if (origImage.height() > snapmaticResolution.height()) {
workImage = origImage.scaled(snapmaticResolution.height(), snapmaticResolution.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
else {
workImage = origImage;
}
}
else if (origImage.width() > snapmaticResolution.width() && origImage.width() > origImage.height()) {
insideAvatarZone = false;
ui->cbAvatar->setChecked(false);
workImage = origImage.scaledToWidth(snapmaticResolution.width(), Qt::SmoothTransformation);
}
else if (origImage.height() > snapmaticResolution.height() && origImage.height() > origImage.width()) {
insideAvatarZone = false;
ui->cbAvatar->setChecked(false);
workImage = origImage.scaledToHeight(snapmaticResolution.height(), Qt::SmoothTransformation);
}
else {
insideAvatarZone = false;
ui->cbAvatar->setChecked(false);
workImage = origImage;
}
processImage();
}
void ImportDialog::processWatermark(QPainter *snapmaticPainter) void ImportDialog::processWatermark(QPainter *snapmaticPainter)
{ {
bool blackWatermark = false; bool blackWatermark = false;
bool redWatermark = false; bool redWatermark = false;
if (selectedColour.red() > 127) { if (selectedColour.red() > 127)
if (selectedColour.green() > 127 || selectedColour.blue() > 127) { {
if (selectedColour.green() > 127 || selectedColour.blue() > 127)
{
redWatermark = true; redWatermark = true;
} }
} }
else {
redWatermark = true;
}
if (selectedColour.lightness() > 127) {
blackWatermark = true;
}
// draw watermark
if (redWatermark) {
const QImage viewWatermark = QImage(AppEnv::getImagesFolder() % "/watermark_2r.png");
snapmaticPainter->drawImage(snapmaticResolution.width() - viewWatermark.width(), 0, viewWatermark);
}
else else
{ {
QImage viewWatermark = QImage(AppEnv::getImagesFolder() % "/watermark_2b.png"); redWatermark = true;
if (!blackWatermark) { }
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); viewWatermark.invertPixels(QImage::InvertRgb);
} }
snapmaticPainter->drawImage(snapmaticResolution.width() - viewWatermark.width(), 0, viewWatermark); snapmaticPainter->drawImage(0, 0, viewWatermark);
} }
QImage textWatermark = QImage(AppEnv::getImagesFolder() % "/watermark_1b.png"); QImage textWatermark = QImage(":/img/watermark_1b.png");
if (!blackWatermark) { if (!blackWatermark)
{
textWatermark.invertPixels(QImage::InvertRgb); textWatermark.invertPixels(QImage::InvertRgb);
} }
snapmaticPainter->drawImage(snapmaticResolution.width() - textWatermark.width(), 0, textWatermark); snapmaticPainter->drawImage(0, 0, textWatermark);
} }
void ImportDialog::processSettings(QString settingsProfile, bool setDefault) void ImportDialog::processSettings(QString settingsProfile, bool setDefault)
{ {
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Import"); settings.beginGroup("Import");
if (setDefault) { if (setDefault)
{
settings.setValue("Profile", settingsProfile); settings.setValue("Profile", settingsProfile);
} }
if (settingsProfile == "Default") { if (settingsProfile == "Default")
{
watermarkAvatar = true; watermarkAvatar = true;
watermarkPicture = false; watermarkPicture = false;
selectedColour = QColor::fromRgb(0, 0, 0, 255); selectedColour = QColor::fromRgb(0, 0, 0, 255);
backImage = QImage(); backImage = QImage();
ui->cbBorderless->setChecked(false);
ui->cbStretch->setChecked(false); ui->cbStretch->setChecked(false);
ui->cbForceAvatarColour->setChecked(false); ui->cbForceAvatarColour->setChecked(false);
ui->cbUnlimited->setChecked(false);
ui->cbImportAsIs->setChecked(false);
ui->cbResolution->setCurrentIndex(0);
} }
else { else
{
settings.beginGroup(settingsProfile); settings.beginGroup(settingsProfile);
watermarkAvatar = settings.value("WatermarkAvatar", true).toBool(); watermarkAvatar = settings.value("WatermarkAvatar", true).toBool();
watermarkPicture = settings.value("WatermarkPicture", false).toBool(); watermarkPicture = settings.value("WatermarkPicture", false).toBool();
backImage = qvariant_cast<QImage>(settings.value("BackgroundImage", QImage())); backImage = qvariant_cast<QImage>(settings.value("BackgroundImage", QImage()));
selectedColour = qvariant_cast<QColor>(settings.value("SelectedColour", QColor::fromRgb(0, 0, 0, 255))); selectedColour = qvariant_cast<QColor>(settings.value("SelectedColour", QColor::fromRgb(0, 0, 0, 255)));
ui->cbBorderless->setChecked(settings.value("BorderlessImage", false).toBool());
ui->cbStretch->setChecked(settings.value("BackgroundStretch", false).toBool()); ui->cbStretch->setChecked(settings.value("BackgroundStretch", false).toBool());
ui->cbForceAvatarColour->setChecked(settings.value("ForceAvatarColour", false).toBool()); ui->cbForceAvatarColour->setChecked(settings.value("ForceAvatarColour", false).toBool());
ui->cbUnlimited->setChecked(settings.value("UnlimitedBuffer", false).toBool());
ui->cbImportAsIs->setChecked(settings.value("ImportAsIs", false).toBool());
const QVariant data = settings.value("Resolution", SnapmaticPicture::getSnapmaticResolution());
#if QT_VERSION >= 0x060000
if (data.typeId() == QMetaType::QSize)
#else
if (data.type() == QVariant::Size)
#endif
{
int index = ui->cbResolution->findData(data);
if (index != -1) {
ui->cbResolution->setCurrentIndex(index);
}
}
settings.endGroup(); settings.endGroup();
} }
if (!workImage.isNull()) { if (!workImage.isNull())
if (ui->cbAvatar->isChecked()) { {
if (ui->cbAvatar->isChecked())
{
ui->cbWatermark->setChecked(watermarkAvatar); ui->cbWatermark->setChecked(watermarkAvatar);
} }
else { else
{
ui->cbWatermark->setChecked(watermarkPicture); ui->cbWatermark->setChecked(watermarkPicture);
} }
} }
ui->labColour->setText(tr("Background Colour: <span style=\"color: %1\">%1</span>").arg(selectedColour.name())); ui->labColour->setText(tr("Background Colour: <span style=\"color: %1\">%1</span>").arg(selectedColour.name()));
if (!backImage.isNull()) { if (!backImage.isNull())
{
ui->labBackgroundImage->setText(tr("Background Image: %1").arg(tr("Storage", "Background Image: Storage"))); ui->labBackgroundImage->setText(tr("Background Image: %1").arg(tr("Storage", "Background Image: Storage")));
ui->cmdBackgroundWipe->setVisible(true); ui->cmdBackgroundWipe->setVisible(true);
} }
else { else
{
ui->labBackgroundImage->setText(tr("Background Image:")); ui->labBackgroundImage->setText(tr("Background Image:"));
ui->cmdBackgroundWipe->setVisible(false); ui->cmdBackgroundWipe->setVisible(false);
} }
@ -418,27 +335,8 @@ void ImportDialog::saveSettings(QString settingsProfile)
settings.setValue("WatermarkPicture", watermarkPicture); settings.setValue("WatermarkPicture", watermarkPicture);
settings.setValue("BackgroundImage", backImage); settings.setValue("BackgroundImage", backImage);
settings.setValue("SelectedColour", selectedColour); settings.setValue("SelectedColour", selectedColour);
settings.setValue("BorderlessImage", ui->cbBorderless->isChecked());
settings.setValue("BackgroundStretch", ui->cbStretch->isChecked()); settings.setValue("BackgroundStretch", ui->cbStretch->isChecked());
settings.setValue("ForceAvatarColour", ui->cbForceAvatarColour->isChecked()); settings.setValue("ForceAvatarColour", ui->cbForceAvatarColour->isChecked());
#if QT_VERSION >= 0x050000
const QVariant data = ui->cbResolution->currentData();
#else
const QVariant data = ui->cbResolution->itemData(ui->cbResolution->currentIndex());
#endif
#if QT_VERSION >= 0x060000
if (data.typeId() == QMetaType::QSize)
#else
if (data.type() == QVariant::Size)
#endif
{
settings.setValue("Resolution", data);
}
else {
settings.setValue("Resolution", SnapmaticPicture::getSnapmaticResolution());
}
settings.setValue("UnlimitedBuffer", ui->cbUnlimited->isChecked());
settings.setValue("ImportAsIs", ui->cbImportAsIs->isChecked());
settings.endGroup(); settings.endGroup();
settings.setValue("Profile", settingsProfile); settings.setValue("Profile", settingsProfile);
settings.endGroup(); settings.endGroup();
@ -504,7 +402,8 @@ void ImportDialog::cropPicture()
cropDialog.show(); cropDialog.show();
cropDialog.setFixedSize(cropDialog.sizeHint()); cropDialog.setFixedSize(cropDialog.sizeHint());
if (cropDialog.exec() == QDialog::Accepted) { if (cropDialog.exec() == QDialog::Accepted)
{
QImage *croppedImage = new QImage(imageCropper.cropImage().toImage()); QImage *croppedImage = new QImage(imageCropper.cropImage().toImage());
setImage(croppedImage); setImage(croppedImage);
} }
@ -529,7 +428,8 @@ fileDialogPreOpen: //Work?
// Getting readable Image formats // Getting readable Image formats
QString imageFormatsStr = " "; QString imageFormatsStr = " ";
for (const QByteArray &imageFormat : QImageReader::supportedImageFormats()) { for (QByteArray imageFormat : QImageReader::supportedImageFormats())
{
imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " "; imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
} }
@ -544,14 +444,17 @@ fileDialogPreOpen: //Work?
fileDialog.setDirectory(settings.value(profileName % "+Directory", StandardPaths::documentsLocation()).toString()); fileDialog.setDirectory(settings.value(profileName % "+Directory", StandardPaths::documentsLocation()).toString());
fileDialog.restoreGeometry(settings.value(profileName % "+Geometry", "").toByteArray()); fileDialog.restoreGeometry(settings.value(profileName % "+Geometry", "").toByteArray());
if (fileDialog.exec()) { if (fileDialog.exec())
{
QStringList selectedFiles = fileDialog.selectedFiles(); QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1) { if (selectedFiles.length() == 1)
{
QString selectedFile = selectedFiles.at(0); QString selectedFile = selectedFiles.at(0);
QString selectedFileName = QFileInfo(selectedFile).fileName(); QString selectedFileName = QFileInfo(selectedFile).fileName();
QFile snapmaticFile(selectedFile); QFile snapmaticFile(selectedFile);
if (!snapmaticFile.open(QFile::ReadOnly)) { 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+"\"")); QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be open").arg("\""+selectedFileName+"\""));
goto fileDialogPreOpen; goto fileDialogPreOpen;
} }
@ -559,7 +462,8 @@ fileDialogPreOpen: //Work?
QImageReader snapmaticImageReader; QImageReader snapmaticImageReader;
snapmaticImageReader.setDecideFormatFromContent(true); snapmaticImageReader.setDecideFormatFromContent(true);
snapmaticImageReader.setDevice(&snapmaticFile); snapmaticImageReader.setDevice(&snapmaticFile);
if (!snapmaticImageReader.read(importImage)) { 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+"\"")); 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; delete importImage;
goto fileDialogPreOpen; goto fileDialogPreOpen;
@ -576,7 +480,8 @@ fileDialogPreOpen: //Work?
void ImportDialog::loadImportSettings() void ImportDialog::loadImportSettings()
{ {
if (settingsLocked) { if (settingsLocked)
{
QMessageBox::information(this, tr("Load Settings..."), tr("Please import a new picture first")); QMessageBox::information(this, tr("Load Settings..."), tr("Please import a new picture first"));
return; return;
} }
@ -589,25 +494,31 @@ void ImportDialog::loadImportSettings()
<< tr("Profile %1", "Profile %1 as Profile 1").arg("4") << tr("Profile %1", "Profile %1 as Profile 1").arg("4")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("5"); << 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()); QString sProfile = QInputDialog::getItem(this, tr("Load Settings..."), tr("Please select your settings profile"), profileList, 0, false, &ok, windowFlags());
if (ok) { if (ok)
{
QString pProfile; QString pProfile;
if (sProfile == tr("Default", "Default as Default Profile")) { if (sProfile == tr("Default", "Default as Default Profile"))
{
pProfile = "Default"; pProfile = "Default";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1"))
{
pProfile = "Profile 1"; pProfile = "Profile 1";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2"))
{
pProfile = "Profile 2"; pProfile = "Profile 2";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3"))
{
pProfile = "Profile 3"; pProfile = "Profile 3";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4")) else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4"))
{ {
pProfile = "Profile 4"; pProfile = "Profile 4";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5"))
{
pProfile = "Profile 5"; pProfile = "Profile 5";
} }
processSettings(pProfile, true); processSettings(pProfile, true);
@ -617,7 +528,8 @@ void ImportDialog::loadImportSettings()
void ImportDialog::saveImportSettings() void ImportDialog::saveImportSettings()
{ {
if (settingsLocked) { if (settingsLocked)
{
QMessageBox::information(this, tr("Save Settings..."), tr("Please import a new picture first")); QMessageBox::information(this, tr("Save Settings..."), tr("Please import a new picture first"));
return; return;
} }
@ -629,21 +541,27 @@ void ImportDialog::saveImportSettings()
<< tr("Profile %1", "Profile %1 as Profile 1").arg("4") << tr("Profile %1", "Profile %1 as Profile 1").arg("4")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("5"); << 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()); QString sProfile = QInputDialog::getItem(this, tr("Save Settings..."), tr("Please select your settings profile"), profileList, 0, false, &ok, windowFlags());
if (ok) { if (ok)
{
QString pProfile; QString pProfile;
if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1")) { if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1"))
{
pProfile = "Profile 1"; pProfile = "Profile 1";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2"))
{
pProfile = "Profile 2"; pProfile = "Profile 2";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3"))
{
pProfile = "Profile 3"; pProfile = "Profile 3";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4"))
{
pProfile = "Profile 4"; pProfile = "Profile 4";
} }
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5")) { else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5"))
{
pProfile = "Profile 5"; pProfile = "Profile 5";
} }
saveSettings(pProfile); saveSettings(pProfile);
@ -652,49 +570,44 @@ void ImportDialog::saveImportSettings()
QImage ImportDialog::image() QImage ImportDialog::image()
{ {
if (ui->cbImportAsIs->isChecked()) {
return origImage;
}
else {
return newImage; return newImage;
} }
}
void ImportDialog::setImage(QImage *image_) void ImportDialog::setImage(QImage *image_)
{ {
origImage = *image_; origImage = *image_;
workImage = QImage(); workImage = QImage();
if (image_->width() == image_->height()) { if (image_->width() == image_->height())
if (ui->cbResolution->currentIndex() == 0) { {
insideAvatarZone = true; insideAvatarZone = true;
ui->cbAvatar->setChecked(true); ui->cbAvatar->setChecked(true);
} if (image_->height() > snapmaticResolutionH)
else { {
insideAvatarZone = false; workImage = image_->scaled(snapmaticResolutionH, snapmaticResolutionH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
ui->cbAvatar->setChecked(false);
}
if (image_->height() > snapmaticResolution.height()) {
workImage = image_->scaled(snapmaticResolution.height(), snapmaticResolution.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
delete image_; delete image_;
} }
else { else
{
workImage = *image_; workImage = *image_;
delete image_; delete image_;
} }
} }
else if (image_->width() > snapmaticResolution.width() && image_->width() > image_->height()) { else if (image_->width() > snapmaticResolutionW && image_->width() > image_->height())
{
insideAvatarZone = false; insideAvatarZone = false;
ui->cbAvatar->setChecked(false); ui->cbAvatar->setChecked(false);
workImage = image_->scaledToWidth(snapmaticResolution.width(), Qt::SmoothTransformation); workImage = image_->scaledToWidth(snapmaticResolutionW, Qt::SmoothTransformation);
delete image_; delete image_;
} }
else if (image_->height() > snapmaticResolution.height() && image_->height() > image_->width()) { else if (image_->height() > snapmaticResolutionH && image_->height() > image_->width())
{
insideAvatarZone = false; insideAvatarZone = false;
ui->cbAvatar->setChecked(false); ui->cbAvatar->setChecked(false);
workImage = image_->scaledToHeight(snapmaticResolution.height(), Qt::SmoothTransformation); workImage = image_->scaledToHeight(snapmaticResolutionH, Qt::SmoothTransformation);
delete image_; delete image_;
} }
else { else
{
insideAvatarZone = false; insideAvatarZone = false;
ui->cbAvatar->setChecked(false); ui->cbAvatar->setChecked(false);
workImage = *image_; workImage = *image_;
@ -706,15 +619,18 @@ void ImportDialog::setImage(QImage *image_)
void ImportDialog::lockSettings(bool lock) void ImportDialog::lockSettings(bool lock)
{ {
ui->gbAdvanced->setDisabled(lock); ui->cbAvatar->setDisabled(lock);
if (ui->cbImportAsIs->isChecked()) { ui->cbForceAvatarColour->setDisabled(lock);
ui->gbBackground->setDisabled(true); ui->cbIgnore->setDisabled(lock);
ui->gbSettings->setDisabled(true); ui->cbStretch->setDisabled(lock);
} ui->cbWatermark->setDisabled(lock);
else { ui->cmdBackgroundChange->setDisabled(lock);
ui->gbBackground->setDisabled(lock); ui->cmdBackgroundWipe->setDisabled(lock);
ui->cmdColourChange->setDisabled(lock);
ui->labBackgroundImage->setDisabled(lock);
ui->labColour->setDisabled(lock);
ui->gbSettings->setDisabled(lock); ui->gbSettings->setDisabled(lock);
} ui->gbBackground->setDisabled(lock);
ui->cmdOK->setDisabled(lock); ui->cmdOK->setDisabled(lock);
settingsLocked = lock; settingsLocked = lock;
} }
@ -736,11 +652,6 @@ bool ImportDialog::isImportAgreed()
return importAgreed; return importAgreed;
} }
bool ImportDialog::isUnlimitedBuffer()
{
return ui->cbUnlimited->isChecked();
}
bool ImportDialog::areSettingsLocked() bool ImportDialog::areSettingsLocked()
{ {
return settingsLocked; return settingsLocked;
@ -748,27 +659,21 @@ bool ImportDialog::areSettingsLocked()
QString ImportDialog::getImageTitle() QString ImportDialog::getImageTitle()
{ {
if (ui->cbImportAsIs->isChecked()) {
return tr("Custom Picture", "Custom Picture Description in SC, don't use Special Character!");
}
else {
return imageTitle; return imageTitle;
} }
}
void ImportDialog::on_cbIgnore_toggled(bool checked) void ImportDialog::on_cbIgnore_toggled(bool checked)
{ {
ui->cbBorderless->setDisabled(checked); Q_UNUSED(checked)
processImage(); processImage();
} }
void ImportDialog::on_cbAvatar_toggled(bool checked) void ImportDialog::on_cbAvatar_toggled(bool checked)
{ {
if (ui->cbResolution->currentIndex() != 0) if (!workImage.isNull() && workImage.width() == workImage.height() && !checked)
return; {
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))
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)) {
ui->cbAvatar->setChecked(true); ui->cbAvatar->setChecked(true);
insideAvatarZone = true; insideAvatarZone = true;
return; return;
@ -776,10 +681,12 @@ void ImportDialog::on_cbAvatar_toggled(bool checked)
} }
insideAvatarZone = ui->cbAvatar->isChecked(); insideAvatarZone = ui->cbAvatar->isChecked();
watermarkBlock = true; watermarkBlock = true;
if (insideAvatarZone) { if (insideAvatarZone)
{
ui->cbWatermark->setChecked(watermarkAvatar); ui->cbWatermark->setChecked(watermarkAvatar);
} }
else { else
{
ui->cbWatermark->setChecked(watermarkPicture); ui->cbWatermark->setChecked(watermarkPicture);
} }
watermarkBlock = false; watermarkBlock = false;
@ -799,9 +706,11 @@ void ImportDialog::on_cmdOK_clicked()
void ImportDialog::on_labPicture_labelPainted() void ImportDialog::on_labPicture_labelPainted()
{ {
if (insideAvatarZone) { if (insideAvatarZone)
{
QImage avatarAreaFinalImage(avatarAreaImage); QImage avatarAreaFinalImage(avatarAreaImage);
if (selectedColour.lightness() > 127) { if (selectedColour.lightness() > 127)
{
avatarAreaFinalImage.setColor(1, qRgb(0, 0, 0)); avatarAreaFinalImage.setColor(1, qRgb(0, 0, 0));
} }
QPainter labelPainter(ui->labPicture); QPainter labelPainter(ui->labPicture);
@ -813,7 +722,8 @@ void ImportDialog::on_labPicture_labelPainted()
void ImportDialog::on_cmdColourChange_clicked() void ImportDialog::on_cmdColourChange_clicked()
{ {
QColor newSelectedColour = QColorDialog::getColor(selectedColour, this, tr("Select Colour...")); QColor newSelectedColour = QColorDialog::getColor(selectedColour, this, tr("Select Colour..."));
if (newSelectedColour.isValid()) { if (newSelectedColour.isValid())
{
selectedColour = newSelectedColour; selectedColour = newSelectedColour;
ui->labColour->setText(tr("Background Colour: <span style=\"color: %1\">%1</span>").arg(selectedColour.name())); ui->labColour->setText(tr("Background Colour: <span style=\"color: %1\">%1</span>").arg(selectedColour.name()));
processImage(); processImage();
@ -839,7 +749,8 @@ fileDialogPreOpen:
// Getting readable Image formats // Getting readable Image formats
QString imageFormatsStr = " "; QString imageFormatsStr = " ";
for (const QByteArray &imageFormat : QImageReader::supportedImageFormats()) { for (QByteArray imageFormat : QImageReader::supportedImageFormats())
{
imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " "; imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
} }
@ -854,14 +765,17 @@ fileDialogPreOpen:
fileDialog.setDirectory(settings.value("Directory", StandardPaths::documentsLocation()).toString()); fileDialog.setDirectory(settings.value("Directory", StandardPaths::documentsLocation()).toString());
fileDialog.restoreGeometry(settings.value("Geometry", "").toByteArray()); fileDialog.restoreGeometry(settings.value("Geometry", "").toByteArray());
if (fileDialog.exec()) { if (fileDialog.exec())
{
QStringList selectedFiles = fileDialog.selectedFiles(); QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1) { if (selectedFiles.length() == 1)
{
QString selectedFile = selectedFiles.at(0); QString selectedFile = selectedFiles.at(0);
QString selectedFileName = QFileInfo(selectedFile).fileName(); QString selectedFileName = QFileInfo(selectedFile).fileName();
QFile snapmaticFile(selectedFile); QFile snapmaticFile(selectedFile);
if (!snapmaticFile.open(QFile::ReadOnly)) { 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+"\"")); QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be open").arg("\""+selectedFileName+"\""));
goto fileDialogPreOpen; goto fileDialogPreOpen;
} }
@ -869,11 +783,12 @@ fileDialogPreOpen:
QImageReader snapmaticImageReader; QImageReader snapmaticImageReader;
snapmaticImageReader.setDecideFormatFromContent(true); snapmaticImageReader.setDecideFormatFromContent(true);
snapmaticImageReader.setDevice(&snapmaticFile); snapmaticImageReader.setDevice(&snapmaticFile);
if (!snapmaticImageReader.read(&importImage)) { 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+"\"")); QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be parsed properly").arg("\""+selectedFileName+"\""));
goto fileDialogPreOpen; goto fileDialogPreOpen;
} }
backImage = importImage.scaled(snapmaticResolution, Qt::KeepAspectRatio, Qt::SmoothTransformation); backImage = importImage.scaled(snapmaticResolutionW, snapmaticResolutionH, Qt::KeepAspectRatio, Qt::SmoothTransformation);
backgroundPath = selectedFile; backgroundPath = selectedFile;
ui->labBackgroundImage->setText(tr("Background Image: %1").arg(tr("File", "Background Image: File"))); ui->labBackgroundImage->setText(tr("Background Image: %1").arg(tr("File", "Background Image: File")));
ui->cmdBackgroundWipe->setVisible(true); ui->cmdBackgroundWipe->setVisible(true);
@ -909,66 +824,16 @@ void ImportDialog::on_cbForceAvatarColour_toggled(bool checked)
void ImportDialog::on_cbWatermark_toggled(bool checked) void ImportDialog::on_cbWatermark_toggled(bool checked)
{ {
if (!watermarkBlock) { if (!watermarkBlock)
if (insideAvatarZone) { {
if (insideAvatarZone)
{
watermarkAvatar = checked; watermarkAvatar = checked;
} }
else { else
{
watermarkPicture = checked; watermarkPicture = checked;
} }
processImage(); processImage();
} }
} }
void ImportDialog::on_cbBorderless_toggled(bool checked)
{
ui->cbIgnore->setDisabled(checked);
processImage();
}
void ImportDialog::on_cbImportAsIs_toggled(bool checked)
{
ui->cbResolution->setDisabled(checked);
ui->labResolution->setDisabled(checked);
ui->gbBackground->setDisabled(checked);
ui->gbSettings->setDisabled(checked);
}
void ImportDialog::on_cbResolution_currentIndexChanged(int index)
{
Q_UNUSED(index)
#if QT_VERSION >= 0x050000
const QVariant data = ui->cbResolution->currentData();
#else
const QVariant data = ui->cbResolution->itemData(ui->cbResolution->currentIndex());
#endif
#if QT_VERSION >= 0x060000
if (data.typeId() == QMetaType::QSize)
#else
if (data.type() == QVariant::Size)
#endif
{
const QSize dataSize = data.toSize();
if (dataSize == SnapmaticPicture::getSnapmaticResolution()) {
ui->cbAvatar->setEnabled(true);
snapmaticResolution = dataSize;
reworkImage();
}
else {
if (!workImage.isNull() && workImage.width() == workImage.height() && ui->cbAvatar->isChecked()) {
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)) {
ui->cbResolution->setCurrentIndex(0);
ui->cbAvatar->setChecked(true);
insideAvatarZone = true;
return;
}
}
ui->cbAvatar->setChecked(false);
ui->cbAvatar->setDisabled(true);
insideAvatarZone = false;
ui->cbWatermark->setChecked(watermarkPicture);
snapmaticResolution = dataSize;
reworkImage();
}
}
}

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2021 Syping * Copyright (C) 2017-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -39,12 +39,10 @@ public:
void lockSettings(bool lock); void lockSettings(bool lock);
void enableOverwriteMode(); void enableOverwriteMode();
bool isImportAgreed(); bool isImportAgreed();
bool isUnlimitedBuffer();
bool areSettingsLocked(); bool areSettingsLocked();
private slots: private slots:
void processImage(); void processImage();
void reworkImage();
void cropPicture(); void cropPicture();
void importNewPicture(); void importNewPicture();
void loadImportSettings(); void loadImportSettings();
@ -60,9 +58,6 @@ private slots:
void on_cbStretch_toggled(bool checked); void on_cbStretch_toggled(bool checked);
void on_cbForceAvatarColour_toggled(bool checked); void on_cbForceAvatarColour_toggled(bool checked);
void on_cbWatermark_toggled(bool checked); void on_cbWatermark_toggled(bool checked);
void on_cbBorderless_toggled(bool checked);
void on_cbImportAsIs_toggled(bool checked);
void on_cbResolution_currentIndexChanged(int index);
private: private:
QString profileName; QString profileName;
@ -75,8 +70,7 @@ private:
QImage origImage; QImage origImage;
QImage newImage; QImage newImage;
QColor selectedColour; QColor selectedColour;
QMenu optionsMenu; QMenu *optionsMenu;
QSize snapmaticResolution;
bool insideAvatarZone; bool insideAvatarZone;
bool watermarkPicture; bool watermarkPicture;
bool watermarkAvatar; bool watermarkAvatar;

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>516</width> <width>516</width>
<height>673</height> <height>512</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
@ -85,32 +85,47 @@
</property> </property>
<layout class="QVBoxLayout" name="vlSettings"> <layout class="QVBoxLayout" name="vlSettings">
<item> <item>
<layout class="QGridLayout" name="glPicture"> <layout class="QHBoxLayout" name="hlCheckboxesTop">
<item row="0" column="1"> <item>
<widget class="QCheckBox" name="cbIgnore">
<property name="text">
<string>Ignore Aspect Ratio</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="cbAvatar"> <widget class="QCheckBox" name="cbAvatar">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Avatar</string> <string>Avatar</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item>
<widget class="QCheckBox" name="cbWatermark"> <widget class="QCheckBox" name="cbIgnore">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Watermark</string> <string>Ignore Aspect Ratio</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> </layout>
<widget class="QCheckBox" name="cbBorderless"> </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"> <property name="text">
<string>Crop to Aspect Ratio</string> <string>Watermark</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -126,8 +141,8 @@
</property> </property>
<layout class="QVBoxLayout" name="vlBackground"> <layout class="QVBoxLayout" name="vlBackground">
<item> <item>
<layout class="QGridLayout" name="glBackground"> <layout class="QHBoxLayout" name="hlColour">
<item row="0" column="0"> <item>
<layout class="QHBoxLayout" name="hlColourManage"> <layout class="QHBoxLayout" name="hlColourManage">
<item> <item>
<widget class="QLabel" name="labColour"> <widget class="QLabel" name="labColour">
@ -159,7 +174,7 @@
<string>Select background colour</string> <string>Select background colour</string>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">...</string> <string>...</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -180,24 +195,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="1"> <item>
<widget class="QCheckBox" name="cbStretch">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Ignore Aspect Ratio</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="cbForceAvatarColour">
<property name="text">
<string>Force Colour in Avatar Zone</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="hlBackgroundManage"> <layout class="QHBoxLayout" name="hlBackgroundManage">
<item> <item>
<widget class="QLabel" name="labBackgroundImage"> <widget class="QLabel" name="labBackgroundImage">
@ -229,7 +227,7 @@
<string>Select background image</string> <string>Select background image</string>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">...</string> <string>...</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -239,7 +237,7 @@
<string>Remove background image</string> <string>Remove background image</string>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">X</string> <string>X</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -262,61 +260,25 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout> <item>
<layout class="QHBoxLayout" name="hlBackground">
<item>
<widget class="QCheckBox" name="cbForceAvatarColour">
<property name="text">
<string>Force Colour in Avatar Zone</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="gbAdvanced"> <widget class="QCheckBox" name="cbStretch">
<property name="title"> <property name="enabled">
<string>Advanced</string> <bool>true</bool>
</property>
<layout class="QVBoxLayout" name="vlAdvanced">
<item>
<layout class="QGridLayout" name="glAdvanced">
<item row="1" column="0">
<widget class="QCheckBox" name="cbUnlimited">
<property name="toolTip">
<string>Avoid compression and expand buffer instead, improves picture quality, but may break Snapmatic</string>
</property> </property>
<property name="text"> <property name="text">
<string>Unlimited Buffer</string> <string>Ignore Aspect Ratio</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="cbImportAsIs">
<property name="toolTip">
<string>Import as-is, don't change the picture at all, guaranteed to break Snapmatic unless you know what you doing</string>
</property>
<property name="text">
<string>Import as-is</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="hlResolution">
<item>
<widget class="QLabel" name="labResolution">
<property name="text">
<string>Resolution:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbResolution">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Snapmatic resolution</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2021 Syping * Copyright (C) 2017-2018 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -28,6 +28,7 @@
#if QT_VERSION >= 0x050200 #if QT_VERSION >= 0x050200
#include <QFontDatabase> #include <QFontDatabase>
#include <QDebug>
#endif #endif
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
@ -39,30 +40,29 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
ui(new Ui::JsonEditorDialog) ui(new Ui::JsonEditorDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
setWindowFlag(Qt::WindowMinMaxButtonsHint, true);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowMinMaxButtonsHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowMinMaxButtonsHint);
#endif
ui->setupUi(this); ui->setupUi(this);
ui->cmdClose->setDefault(true); ui->cmdClose->setDefault(true);
ui->cmdClose->setFocus(); ui->cmdClose->setFocus();
// Set Icon for Close Button // Set Icon for Close Button
if (QIcon::hasThemeIcon("dialog-close")) { if (QIcon::hasThemeIcon("dialog-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close")); ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
} }
else if (QIcon::hasThemeIcon("gtk-close")) { else if (QIcon::hasThemeIcon("gtk-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close")); ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close"));
} }
// Set Icon for Save Button // Set Icon for Save Button
if (QIcon::hasThemeIcon("document-save")) { if (QIcon::hasThemeIcon("document-save"))
{
ui->cmdSave->setIcon(QIcon::fromTheme("document-save")); ui->cmdSave->setIcon(QIcon::fromTheme("document-save"));
} }
else if (QIcon::hasThemeIcon("gtk-save")) { else if (QIcon::hasThemeIcon("gtk-save"))
{
ui->cmdSave->setIcon(QIcon::fromTheme("gtk-save")); ui->cmdSave->setIcon(QIcon::fromTheme("gtk-save"));
} }
@ -99,7 +99,8 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
ui->hlButtons->setContentsMargins(9 * screenRatio, 0, 9 * screenRatio, 0); ui->hlButtons->setContentsMargins(9 * screenRatio, 0, 9 * screenRatio, 0);
ui->vlInterface->setContentsMargins(0, 0, 0, 9 * screenRatio); ui->vlInterface->setContentsMargins(0, 0, 0, 9 * screenRatio);
#endif #endif
if (screenRatio > 1) { if (screenRatio > 1)
{
ui->lineJSON->setMinimumHeight(qRound(1 * screenRatio)); ui->lineJSON->setMinimumHeight(qRound(1 * screenRatio));
ui->lineJSON->setMaximumHeight(qRound(1 * screenRatio)); ui->lineJSON->setMaximumHeight(qRound(1 * screenRatio));
ui->lineJSON->setLineWidth(qRound(1 * screenRatio)); ui->lineJSON->setLineWidth(qRound(1 * screenRatio));
@ -120,22 +121,28 @@ void JsonEditorDialog::closeEvent(QCloseEvent *ev)
QJsonDocument jsonOriginal = QJsonDocument::fromJson(jsonCode.toUtf8()); QJsonDocument jsonOriginal = QJsonDocument::fromJson(jsonCode.toUtf8());
QString originalCode = QString::fromUtf8(jsonOriginal.toJson(QJsonDocument::Compact)); QString originalCode = QString::fromUtf8(jsonOriginal.toJson(QJsonDocument::Compact));
QString newCode = QString::fromUtf8(jsonNew.toJson(QJsonDocument::Compact)); QString newCode = QString::fromUtf8(jsonNew.toJson(QJsonDocument::Compact));
if (newCode != originalCode) { if (newCode != originalCode)
{
QMessageBox::StandardButton button = QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("<h4>Unsaved changes detected</h4>You want to save the JSON content before you quit?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel); QMessageBox::StandardButton button = QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("<h4>Unsaved changes detected</h4>You want to save the JSON content before you quit?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel);
if (button == QMessageBox::Yes) { if (button == QMessageBox::Yes)
if (saveJsonContent()) { {
if (saveJsonContent())
{
ev->accept(); ev->accept();
} }
else { else
{
ev->ignore(); ev->ignore();
} }
return; return;
} }
else if (button == QMessageBox::No) { else if (button == QMessageBox::No)
{
ev->accept(); ev->accept();
return; return;
} }
else { else
{
ev->ignore(); ev->ignore();
return; return;
} }
@ -146,38 +153,47 @@ bool JsonEditorDialog::saveJsonContent()
{ {
QString jsonPatched = QString(ui->txtJSON->toPlainText()).replace("\t", " "); QString jsonPatched = QString(ui->txtJSON->toPlainText()).replace("\t", " ");
QJsonDocument jsonNew = QJsonDocument::fromJson(jsonPatched.toUtf8()); QJsonDocument jsonNew = QJsonDocument::fromJson(jsonPatched.toUtf8());
if (!jsonNew.isEmpty()) { if (!jsonNew.isEmpty())
{
QJsonDocument jsonOriginal = QJsonDocument::fromJson(jsonCode.toUtf8()); QJsonDocument jsonOriginal = QJsonDocument::fromJson(jsonCode.toUtf8());
QString originalCode = QString::fromUtf8(jsonOriginal.toJson(QJsonDocument::Compact)); QString originalCode = QString::fromUtf8(jsonOriginal.toJson(QJsonDocument::Compact));
QString newCode = QString::fromUtf8(jsonNew.toJson(QJsonDocument::Compact)); QString newCode = QString::fromUtf8(jsonNew.toJson(QJsonDocument::Compact));
if (newCode != originalCode) { if (newCode != originalCode)
{
QString currentFilePath = smpic->getPictureFilePath(); QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath(); QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak"; QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) { if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName); QFile::copy(currentFilePath, backupFileName);
} }
smpic->setJsonStr(newCode, true); smpic->setJsonStr(newCode, true);
if (!smpic->isJsonOk()) { if (!smpic->isJsonOk())
{
QString lastStep = smpic->getLastStep(false); QString lastStep = smpic->getLastStep(false);
QString readableError; QString readableError;
if (lastStep.contains("JSONINCOMPLETE") && lastStep.contains("JSONERROR")) { if (lastStep.contains("JSONINCOMPLETE") && lastStep.contains("JSONERROR"))
{
readableError = SnapmaticPicture::tr("JSON is incomplete and malformed"); readableError = SnapmaticPicture::tr("JSON is incomplete and malformed");
} }
else if (lastStep.contains("JSONINCOMPLETE")) { else if (lastStep.contains("JSONINCOMPLETE"))
{
readableError = SnapmaticPicture::tr("JSON is incomplete"); readableError = SnapmaticPicture::tr("JSON is incomplete");
} }
else if (lastStep.contains("JSONERROR")) { else if (lastStep.contains("JSONERROR"))
{
readableError = SnapmaticPicture::tr("JSON is malformed"); readableError = SnapmaticPicture::tr("JSON is malformed");
} }
else { else
{
readableError = tr("JSON Error"); readableError = tr("JSON Error");
} }
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of %1").arg(readableError)); QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of %1").arg(readableError));
smpic->setJsonStr(originalCode, true); smpic->setJsonStr(originalCode, true);
return false; return false;
} }
if (!smpic->exportPicture(currentFilePath)) { if (!smpic->exportPicture(currentFilePath))
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error")); QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error"));
smpic->setJsonStr(originalCode, true); smpic->setJsonStr(originalCode, true);
return false; return false;
@ -190,16 +206,13 @@ bool JsonEditorDialog::saveJsonContent()
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "JSONEdited"; jsonObject["Type"] = "JSONEdited";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
@ -208,7 +221,8 @@ bool JsonEditorDialog::saveJsonContent()
} }
return true; return true;
} }
else { else
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of JSON Error")); QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of JSON Error"));
return false; return false;
} }
@ -222,5 +236,7 @@ void JsonEditorDialog::on_cmdClose_clicked()
void JsonEditorDialog::on_cmdSave_clicked() void JsonEditorDialog::on_cmdSave_clicked()
{ {
if (saveJsonContent()) if (saveJsonContent())
{
close(); close();
} }
}

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2021 Syping * Copyright (C) 2017-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -20,8 +20,8 @@
#include "ui_MapLocationDialog.h" #include "ui_MapLocationDialog.h"
#include "IconLoader.h" #include "IconLoader.h"
#include "AppEnv.h" #include "AppEnv.h"
#include <QStringBuilder>
#include <QPainter> #include <QPainter>
#include <QDebug>
#include <QStyle> #include <QStyle>
MapLocationDialog::MapLocationDialog(double x, double y, QWidget *parent) : MapLocationDialog::MapLocationDialog(double x, double y, QWidget *parent) :
@ -29,11 +29,7 @@ MapLocationDialog::MapLocationDialog(double x, double y, QWidget *parent) :
ui(new Ui::MapLocationDialog) ui(new Ui::MapLocationDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
ui->setupUi(this); ui->setupUi(this);
ui->cmdDone->setVisible(false); ui->cmdDone->setVisible(false);
@ -49,10 +45,12 @@ MapLocationDialog::MapLocationDialog(double x, double y, QWidget *parent) :
ui->vlMapDialog->setSpacing(widgetMargin); ui->vlMapDialog->setSpacing(widgetMargin);
setMinimumSize(500 * screenRatio, 600 * screenRatio); setMinimumSize(500 * screenRatio, 600 * screenRatio);
setMaximumSize(500 * screenRatio, 600 * screenRatio); setMaximumSize(500 * screenRatio, 600 * screenRatio);
setFixedSize(500 * screenRatio, 600 * screenRatio);
setMouseTracking(true);
zoomPercent = 100;
changeMode = false; changeMode = false;
propUpdate = false; propUpdate = false;
drawPointOnMap(xpos_old, ypos_old);
} }
MapLocationDialog::~MapLocationDialog() MapLocationDialog::~MapLocationDialog()
@ -68,220 +66,6 @@ void MapLocationDialog::drawPointOnMap(double xpos_d, double ypos_d)
repaint(); repaint();
} }
void MapLocationDialog::setCayoPerico(bool isCayoPerico)
{
qreal screenRatio = AppEnv::screenRatio();
p_isCayoPerico = isCayoPerico;
if (isCayoPerico) {
setMinimumSize(500 * screenRatio, 500 * screenRatio);
setMaximumSize(500 * screenRatio, 500 * screenRatio);
ui->hlMapDialog->removeItem(ui->vlMapDialog);
ui->hlMapDialog->insertLayout(0, ui->vlMapDialog);
ui->hlMapDialog->removeItem(ui->vlPosLayout);
ui->hlMapDialog->addLayout(ui->vlPosLayout);
ui->labPos->setAlignment(Qt::AlignRight);
mapImage = QImage(AppEnv::getImagesFolder() % "/mapcayoperico.jpg");
}
else {
mapImage = QImage(AppEnv::getImagesFolder() % "/mappreview.jpg");
}
drawPointOnMap(xpos_old, ypos_old);
}
void MapLocationDialog::updatePosFromEvent(double x, double y)
{
QSize mapPixelSize = size();
double x_per = x / mapPixelSize.width(); // get X %
double y_per = y / mapPixelSize.height(); // get Y %
double x_pos, y_pos;
if (p_isCayoPerico) {
x_pos = x_per * 2340; // 2340 is 100% for X (Cayo Perico)
y_pos = y_per * -2340; // -2340 is 100% for Y (Cayo Perico)
x_pos = x_pos + 3560; // +3560 gets corrected for X (Cayo Perico)
y_pos = y_pos - 3980; // -3980 gets corrected for Y (Cayo Perico)
}
else {
x_pos = x_per * 10000; // 10000 is 100% for X (Los Santos)
y_pos = y_per * -12000; // -12000 is 100% for Y (Los Santos)
x_pos = x_pos - 4000; // -4000 gets corrected for X (Los Santos)
y_pos = y_pos + 8000; // +8000 gets corrected for Y (Los Santos)
}
drawPointOnMap(x_pos, y_pos);
}
void MapLocationDialog::paintEvent(QPaintEvent *ev)
{
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
// Screen Ratio
qreal screenRatio = AppEnv::screenRatio();
qreal screenRatioPR = AppEnv::screenRatioPR();
// Paint Map
const double zoomLevel = static_cast<double>(zoomPercent) / 100;
const QSize mapImageSize = mapImage.size();
const QPointF mapImageMid(static_cast<double>(mapImageSize.width()) / 2, static_cast<double>(mapImageSize.height()) / 2);
const QSizeF srcImageSize(static_cast<double>(mapImageSize.width()) / zoomLevel , static_cast<double>(mapImageSize.height()) / zoomLevel);
const QPointF mapImageTopLeft(mapImageMid.x() - (srcImageSize.width() / 2), mapImageMid.y() - (srcImageSize.height() / 2));
const QPointF mapImageBottomRight(mapImageMid.x() + (srcImageSize.width() / 2), mapImageMid.y() + (srcImageSize.height() / 2));
painter.drawImage(QRect(QPoint(0, 0), size()), mapImage, QRectF(mapImageTopLeft, mapImageBottomRight));
// Paint Marker
QSize mapPixelSize = size();
int pointMarkerSize = 8 * screenRatio;
int pointMarkerHalfSize = pointMarkerSize / 2;
double xpos_mp, ypos_mp;
if (p_isCayoPerico) {
double xpos_per = xpos_new - 3560; // correct X in reserve
double ypos_per = ypos_new + 3980; // correct y in reserve
xpos_per = xpos_per / 2340; // divide 100% for X
ypos_per = ypos_per / -2340; // divide 100% for Y
xpos_mp = xpos_per * mapPixelSize.width(); // locate window width pos
ypos_mp = ypos_per * mapPixelSize.height(); // locate window height pos
}
else {
double xpos_per = xpos_new + 4000; // correct X in reserve
double ypos_per = ypos_new - 8000; // correct y in reserve
xpos_per = xpos_per / 10000; // divide 100% for X
ypos_per = ypos_per / -12000; // divide 100% for Y
xpos_mp = xpos_per * mapPixelSize.width(); // locate window width pos
ypos_mp = ypos_per * mapPixelSize.height(); // locate window height pos
}
QPointF pointMarkerPos(xpos_mp, ypos_mp);
if (screenRatioPR != 1) {
pointMarkerPos.setX(pointMarkerPos.x() - pointMarkerHalfSize + screenRatioPR);
pointMarkerPos.setY(pointMarkerPos.y() - pointMarkerHalfSize + screenRatioPR);
}
else {
pointMarkerPos.setX(pointMarkerPos.x() - pointMarkerHalfSize);
pointMarkerPos.setY(pointMarkerPos.y() - pointMarkerHalfSize);
}
QPixmap mapMarkerPixmap = IconLoader::loadingPointmakerIcon().pixmap(QSize(pointMarkerSize, pointMarkerSize));
painter.drawPixmap(pointMarkerPos, mapMarkerPixmap);
QDialog::paintEvent(ev);
}
void MapLocationDialog::mouseMoveEvent(QMouseEvent *ev)
{
if (changeMode && ev->buttons() & Qt::LeftButton) {
#if QT_VERSION >= 0x060000
const QPointF localPos = ev->position();
#elif QT_VERSION >= 0x050000
const QPointF localPos = ev->localPos();
#else
const QPointF localPos = ev->posF();
#endif
#ifdef Q_OS_WIN
qreal screenRatioPR = AppEnv::screenRatioPR();
if (screenRatioPR != 1) {
updatePosFromEvent(localPos.x() - screenRatioPR, localPos.y() - screenRatioPR);
}
else {
updatePosFromEvent(localPos.x(), localPos.y());
}
#else
updatePosFromEvent(localPos.x(), localPos.y());
#endif
}
else if (dragStart && ev->buttons() & Qt::LeftButton) {
#if QT_VERSION >= 0x060000
const QPointF dragNewPosition = ev->position();
#elif QT_VERSION >= 0x050000
const QPointF dragNewPosition = ev->localPos();
#else
const QPointF dragNewPosition = ev->posF();
#endif
mapDiffPosition = dragNewPosition - dragPosition + mapDiffPosition;
dragPosition = dragNewPosition;
}
}
void MapLocationDialog::mousePressEvent(QMouseEvent *ev)
{
if (!changeMode && ev->button() == Qt::LeftButton) {
#if QT_VERSION >= 0x060000
dragPosition = ev->position();
#elif QT_VERSION >= 0x050000
dragPosition = ev->localPos();
#else
dragPosition = ev->posF();
#endif
dragStart = true;
}
}
void MapLocationDialog::mouseReleaseEvent(QMouseEvent *ev)
{
if (changeMode && ev->button() == Qt::LeftButton) {
#if QT_VERSION >= 0x060000
const QPointF localPos = ev->position();
#elif QT_VERSION >= 0x050000
const QPointF localPos = ev->localPos();
#else
const QPointF localPos = ev->posF();
#endif
#ifdef Q_OS_WIN
qreal screenRatioPR = AppEnv::screenRatioPR();
if (screenRatioPR != 1) {
updatePosFromEvent(localPos.x() - screenRatioPR, localPos.y() - screenRatioPR);
}
else {
updatePosFromEvent(localPos.x(), localPos.y());
}
#else
updatePosFromEvent(localPos.x(), localPos.y());
#endif
}
else if (dragStart && ev->button() == Qt::LeftButton) {
dragStart = false;
}
}
void MapLocationDialog::wheelEvent(QWheelEvent *ev)
{
#ifdef GTA5SYNC_EXPERIMENTAL
#if QT_VERSION >= 0x050000
const QPoint numPixels = ev->pixelDelta();
const QPoint numDegrees = ev->angleDelta();
#else
QPoint numDegrees;
if (ev->orientation() == Qt::Horizontal) {
numDegrees.setX(ev->delta());
}
else {
numDegrees.setY(ev->delta());
}
#endif
#if QT_VERSION >= 0x050000
if (!numPixels.isNull()) {
if (numPixels.y() < 0 && zoomPercent != 100) {
zoomPercent = zoomPercent - 10;
repaint();
}
else if (numPixels.y() > 0 && zoomPercent != 400) {
zoomPercent = zoomPercent + 10;
repaint();
}
return;
}
#endif
if (!numDegrees.isNull()) {
if (numDegrees.y() < 0 && zoomPercent != 100) {
zoomPercent = zoomPercent - 10;
repaint();
}
else if (numDegrees.y() > 0 && zoomPercent != 400) {
zoomPercent = zoomPercent + 10;
repaint();
}
}
#else
Q_UNUSED(ev)
#endif
}
void MapLocationDialog::on_cmdChange_clicked() void MapLocationDialog::on_cmdChange_clicked()
{ {
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
@ -301,14 +85,124 @@ void MapLocationDialog::on_cmdDone_clicked()
{ {
ui->cmdDone->setVisible(false); ui->cmdDone->setVisible(false);
ui->cmdChange->setVisible(true); ui->cmdChange->setVisible(true);
if (xpos_new != xpos_old || ypos_new != ypos_old) { if (xpos_new != xpos_old || ypos_new != ypos_old)
{
ui->cmdApply->setVisible(true); ui->cmdApply->setVisible(true);
ui->cmdRevert->setVisible(true); ui->cmdRevert->setVisible(true);
} }
setCursor(Qt::ArrowCursor); setCursor(Qt::ArrowCursor);
changeMode = false; 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();
int xpos_ad = x;
int 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);
}
#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
{
ev->ignore();
}
}
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
{
ev->ignore();
}
}
void MapLocationDialog::on_cmdApply_clicked() void MapLocationDialog::on_cmdApply_clicked()
{ {
propUpdate = true; propUpdate = true;

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2021 Syping * Copyright (C) 2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -33,7 +33,6 @@ class MapLocationDialog : public QDialog
public: public:
explicit MapLocationDialog(double x, double y, QWidget *parent = 0); explicit MapLocationDialog(double x, double y, QWidget *parent = 0);
void drawPointOnMap(double x, double y); void drawPointOnMap(double x, double y);
void setCayoPerico(bool isCayoPerico);
bool propUpdated(); bool propUpdated();
double getXpos(); double getXpos();
double getYpos(); double getYpos();
@ -42,31 +41,27 @@ public:
protected: protected:
void paintEvent(QPaintEvent *ev); void paintEvent(QPaintEvent *ev);
void mouseMoveEvent(QMouseEvent *ev); void mouseMoveEvent(QMouseEvent *ev);
void mousePressEvent(QMouseEvent *ev);
void mouseReleaseEvent(QMouseEvent *ev); void mouseReleaseEvent(QMouseEvent *ev);
void wheelEvent(QWheelEvent *ev);
private slots: private slots:
void on_cmdApply_clicked();
void on_cmdDone_clicked(); void on_cmdDone_clicked();
void on_cmdClose_clicked(); void on_cmdApply_clicked();
void on_cmdChange_clicked(); void on_cmdChange_clicked();
void on_cmdRevert_clicked(); void on_cmdRevert_clicked();
#if QT_VERSION >= 0x060000
void updatePosFromEvent(double x, double y); void updatePosFromEvent(double x, double y);
#else
void updatePosFromEvent(int x, int y);
#endif
void on_cmdClose_clicked();
private: private:
int zoomPercent;
double xpos_old; double xpos_old;
double ypos_old; double ypos_old;
double xpos_new; double xpos_new;
double ypos_new; double ypos_new;
bool dragStart;
bool propUpdate; bool propUpdate;
bool changeMode; bool changeMode;
bool p_isCayoPerico;
QImage mapImage;
QPointF dragPosition;
QPointF mapDiffPosition;
Ui::MapLocationDialog *ui; Ui::MapLocationDialog *ui;
}; };

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -21,7 +21,6 @@
#include "TranslationClass.h" #include "TranslationClass.h"
#include "StandardPaths.h" #include "StandardPaths.h"
#include "UserInterface.h" #include "UserInterface.h"
#include "wrapper.h"
#include "AppEnv.h" #include "AppEnv.h"
#include "config.h" #include "config.h"
#include <QStringBuilder> #include <QStringBuilder>
@ -30,7 +29,6 @@
#include <QApplication> #include <QApplication>
#include <QJsonObject> #include <QJsonObject>
#include <QFileDialog> #include <QFileDialog>
#include <QFontDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QStringList> #include <QStringList>
#include <QClipboard> #include <QClipboard>
@ -56,11 +54,7 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
ui(new Ui::OptionsDialog) ui(new Ui::OptionsDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
// Setup User Interface // Setup User Interface
ui->setupUi(this); ui->setupUi(this);
@ -80,7 +74,7 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
int desktopSizeHeight = desktopResolution.height(); int desktopSizeHeight = desktopResolution.height();
#endif #endif
aspectRatio = Qt::KeepAspectRatio; aspectRatio = Qt::KeepAspectRatio;
defExportSize = SnapmaticPicture::getSnapmaticResolution(); defExportSize = QSize(960, 536);
cusExportSize = defExportSize; cusExportSize = defExportSize;
defaultQuality = 100; defaultQuality = 100;
customQuality = 100; customQuality = 100;
@ -93,26 +87,25 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
ui->rbPicDefaultRes->setText(ui->rbPicDefaultRes->text().arg(QString::number(defExportSize.width()), QString::number(defExportSize.height()))); ui->rbPicDefaultRes->setText(ui->rbPicDefaultRes->text().arg(QString::number(defExportSize.width()), QString::number(defExportSize.height())));
// Set Icon for OK Button // Set Icon for OK Button
if (QIcon::hasThemeIcon("dialog-ok")) { if (QIcon::hasThemeIcon("dialog-ok"))
{
ui->cmdOK->setIcon(QIcon::fromTheme("dialog-ok")); ui->cmdOK->setIcon(QIcon::fromTheme("dialog-ok"));
} }
else if (QIcon::hasThemeIcon("gtk-ok")) { else if (QIcon::hasThemeIcon("gtk-ok"))
{
ui->cmdOK->setIcon(QIcon::fromTheme("gtk-ok")); ui->cmdOK->setIcon(QIcon::fromTheme("gtk-ok"));
} }
// Set Icon for Cancel Button // Set Icon for Cancel Button
if (QIcon::hasThemeIcon("dialog-cancel")) { if (QIcon::hasThemeIcon("dialog-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
} }
else if (QIcon::hasThemeIcon("gtk-cancel")) { else if (QIcon::hasThemeIcon("gtk-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel"));
} }
// Set Icon for Copy Button
if (QIcon::hasThemeIcon("edit-copy")) {
ui->cmdCopyStatsID->setIcon(QIcon::fromTheme("edit-copy"));
}
setupTreeWidget(); setupTreeWidget();
setupLanguageBox(); setupLanguageBox();
setupRadioButtons(); setupRadioButtons();
@ -130,8 +123,6 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
resize(435 * screenRatio, 405 * screenRatio); resize(435 * screenRatio, 405 * screenRatio);
#endif #endif
ui->rbModern->setText(ui->rbModern->text().arg(GTA5SYNC_APPSTR));
ui->rbClassic->setText(ui->rbClassic->text().arg(GTA5SYNC_APPSTR));
setWindowTitle(windowTitle().arg(GTA5SYNC_APPSTR)); setWindowTitle(windowTitle().arg(GTA5SYNC_APPSTR));
} }
@ -147,11 +138,15 @@ void OptionsDialog::setupTreeWidget()
{ {
const QStringList players = profileDB->getPlayers(); const QStringList players = profileDB->getPlayers();
if (players.length() != 0) { if (players.length() != 0) {
for (auto it = players.constBegin(); it != players.constEnd(); it++) { QStringList::const_iterator it = players.constBegin();
QStringList::const_iterator end = players.constEnd();
while (it != end)
{
bool ok; bool ok;
int playerID = it->toInt(&ok); int playerID = it->toInt(&ok);
if (ok) { if (ok)
const QString playerName = profileDB->getPlayerName(playerID); {
QString playerName = profileDB->getPlayerName(playerID);
QStringList playerTreeViewList; QStringList playerTreeViewList;
playerTreeViewList += *it; playerTreeViewList += *it;
@ -161,6 +156,7 @@ void OptionsDialog::setupTreeWidget()
ui->twPlayers->addTopLevelItem(playerItem); ui->twPlayers->addTopLevelItem(playerItem);
playerItems += playerItem; playerItems += playerItem;
} }
it++;
} }
ui->twPlayers->sortItems(1, Qt::AscendingOrder); ui->twPlayers->sortItems(1, Qt::AscendingOrder);
} }
@ -176,18 +172,20 @@ void OptionsDialog::setupLanguageBox()
currentAreaLanguage = settings->value("AreaLanguage", "Auto").toString(); currentAreaLanguage = settings->value("AreaLanguage", "Auto").toString();
settings->endGroup(); settings->endGroup();
const QString cbSysStr = tr("%1 (Language priority)", "First language a person can talk with a different person/application. \"Native\" or \"Not Native\".").arg(tr("System", 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")); "System in context of System default"));
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QString cbAutoStr; QString cbAutoStr;
if (AppEnv::getGameLanguage(AppEnv::getGameVersion()) != GameLanguage::Undefined) { 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.")); cbAutoStr = tr("%1 (Game language)", "Next closest language compared to the Game settings").arg(tr("Auto", "Automatic language choice."));
} }
else { else
{
cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice.")); cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
} }
#else #else
const QString cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice.")); QString cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
#endif #endif
ui->cbLanguage->addItem(cbSysStr, "System"); ui->cbLanguage->addItem(cbSysStr, "System");
ui->cbAreaLanguage->addItem(cbAutoStr, "Auto"); ui->cbAreaLanguage->addItem(cbAutoStr, "Auto");
@ -201,18 +199,15 @@ void OptionsDialog::setupLanguageBox()
availableLanguages.removeDuplicates(); availableLanguages.removeDuplicates();
availableLanguages.sort(); availableLanguages.sort();
for (const QString &lang : qAsConst(availableLanguages)) { for (QString lang : availableLanguages)
{
QLocale langLocale(lang); QLocale langLocale(lang);
const QString cbLangStr = langLocale.nativeLanguageName() % " (" % langLocale.nativeCountryName() % ") [" % lang % "]"; QString cbLangStr = langLocale.nativeLanguageName() % " (" % langLocale.nativeCountryName() % ") [" % lang % "]";
const QString langIconPath = AppEnv::getImagesFolder() % "/flag-" % TranslationClass::getCountryCode(langLocale) % ".png"; QString langIconStr = "flag-" % TranslationClass::getCountryCode(langLocale);
if (QFile::exists(langIconPath)) { ui->cbLanguage->addItem(QIcon::fromTheme(langIconStr), cbLangStr, lang);
ui->cbLanguage->addItem(QIcon(langIconPath), cbLangStr, lang); if (currentLanguage == lang)
} {
else {
ui->cbLanguage->addItem(cbLangStr, lang);
}
if (currentLanguage == lang) {
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
ui->cbLanguage->setCurrentText(cbLangStr); ui->cbLanguage->setCurrentText(cbLangStr);
#else #else
@ -223,8 +218,7 @@ void OptionsDialog::setupLanguageBox()
} }
QString aCurrentLanguage = QString("en_GB"); QString aCurrentLanguage = QString("en_GB");
if (Translator->isLanguageLoaded()) if (Translator->isLanguageLoaded()) { aCurrentLanguage = Translator->getCurrentLanguage(); }
aCurrentLanguage = Translator->getCurrentLanguage();
QLocale currentLocale = QLocale(aCurrentLanguage); QLocale currentLocale = QLocale(aCurrentLanguage);
ui->labCurrentLanguage->setText(tr("Current: %1").arg(currentLocale.nativeLanguageName() % " (" % currentLocale.nativeCountryName() % ") [" % aCurrentLanguage % "]")); ui->labCurrentLanguage->setText(tr("Current: %1").arg(currentLocale.nativeLanguageName() % " (" % currentLocale.nativeCountryName() % ") [" % aCurrentLanguage % "]"));
@ -233,21 +227,27 @@ void OptionsDialog::setupLanguageBox()
availableLanguages.removeDuplicates(); availableLanguages.removeDuplicates();
availableLanguages.sort(); availableLanguages.sort();
for (const QString &lang : qAsConst(availableLanguages)) { for (QString lang : availableLanguages)
{
// correcting Language Location if possible // correcting Language Location if possible
QString aLang = lang; QString aLang = lang;
if (QFile::exists(":/global/global." % lang % ".loc")) { if (QFile::exists(":/global/global." % lang % ".loc"))
{
QFile locFile(":/global/global." % lang % ".loc"); QFile locFile(":/global/global." % lang % ".loc");
if (locFile.open(QFile::ReadOnly)) { if (locFile.open(QFile::ReadOnly))
{
aLang = QString::fromUtf8(locFile.readLine()).trimmed(); aLang = QString::fromUtf8(locFile.readLine()).trimmed();
locFile.close(); locFile.close();
} }
} }
QLocale langLocale(aLang); QLocale langLocale(aLang);
const QString cbLangStr = langLocale.nativeLanguageName() % " (" % langLocale.nativeCountryName() % ") [" % aLang % "]"; QString cbLangStr = langLocale.nativeLanguageName() % " (" % langLocale.nativeCountryName() % ") [" % aLang % "]";
ui->cbAreaLanguage->addItem(cbLangStr, lang); QString langIconStr = "flag-" % TranslationClass::getCountryCode(langLocale);
if (currentAreaLanguage == lang) {
ui->cbAreaLanguage->addItem(QIcon::fromTheme(langIconStr), cbLangStr, lang);
if (currentAreaLanguage == lang)
{
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
ui->cbAreaLanguage->setCurrentText(cbLangStr); ui->cbAreaLanguage->setCurrentText(cbLangStr);
#else #else
@ -258,10 +258,12 @@ void OptionsDialog::setupLanguageBox()
} }
QString aCurrentAreaLanguage = Translator->getCurrentAreaLanguage(); QString aCurrentAreaLanguage = Translator->getCurrentAreaLanguage();
if (QFile::exists(":/global/global." % aCurrentAreaLanguage % ".loc")) { if (QFile::exists(":/global/global." % aCurrentAreaLanguage % ".loc"))
{
qDebug() << "locFile found"; qDebug() << "locFile found";
QFile locFile(":/global/global." % aCurrentAreaLanguage % ".loc"); QFile locFile(":/global/global." % aCurrentAreaLanguage % ".loc");
if (locFile.open(QFile::ReadOnly)) { if (locFile.open(QFile::ReadOnly))
{
aCurrentAreaLanguage = QString::fromUtf8(locFile.readLine()).trimmed(); aCurrentAreaLanguage = QString::fromUtf8(locFile.readLine()).trimmed();
locFile.close(); locFile.close();
} }
@ -277,26 +279,18 @@ void OptionsDialog::setupRadioButtons()
contentMode = settings->value("ContentMode", 0).toInt(&contentModeOk); contentMode = settings->value("ContentMode", 0).toInt(&contentModeOk);
settings->endGroup(); settings->endGroup();
if (contentModeOk) { if (contentModeOk)
switch (contentMode) { {
switch (contentMode)
{
case 0: case 0:
case 20: ui->rbOpenWithSC->setChecked(true);
ui->rbModern->setChecked(true);
ui->cbDoubleclick->setChecked(false);
break; break;
case 1: case 1:
ui->rbOpenWithDC->setChecked(true);
break;
case 2: case 2:
case 21: ui->rbSelectWithSC->setChecked(true);
ui->rbModern->setChecked(true);
ui->cbDoubleclick->setChecked(true);
break;
case 10:
ui->rbClassic->setChecked(true);
ui->cbDoubleclick->setChecked(false);
break;
case 11:
ui->rbClassic->setChecked(true);
ui->cbDoubleclick->setChecked(true);
break; break;
} }
} }
@ -305,40 +299,55 @@ void OptionsDialog::setupRadioButtons()
void OptionsDialog::setupInterfaceSettings() void OptionsDialog::setupInterfaceSettings()
{ {
settings->beginGroup("Startup"); settings->beginGroup("Startup");
const QString currentStyle = QApplication::style()->objectName(); bool alwaysUseMessageFont = settings->value("AlwaysUseMessageFont", false).toBool();
const QString appStyle = settings->value("AppStyle", currentStyle).toString(); ui->cbAlwaysUseMessageFont->setChecked(alwaysUseMessageFont);
#ifdef Q_OS_WIN
if (QSysInfo::windowsVersion() >= 0x0080)
{
ui->gbFont->setVisible(false);
ui->cbAlwaysUseMessageFont->setVisible(false);
}
#else
ui->gbFont->setVisible(false);
ui->cbAlwaysUseMessageFont->setVisible(false);
#endif
QString currentStyle = QApplication::style()->objectName();
QString appStyle = settings->value("AppStyle", currentStyle).toString();
bool customStyle = settings->value("CustomStyle", false).toBool(); bool customStyle = settings->value("CustomStyle", false).toBool();
const QStringList availableStyles = QStyleFactory::keys(); const QStringList availableStyles = QStyleFactory::keys();
ui->cbStyleList->addItems(availableStyles); ui->cbStyleList->addItems(availableStyles);
if (availableStyles.contains(appStyle, Qt::CaseInsensitive)) { if (availableStyles.contains(appStyle, Qt::CaseInsensitive))
{
// use 'for' for select to be sure it's case insensitive // use 'for' for select to be sure it's case insensitive
int currentIndex = 0; int currentIndex = 0;
for (const QString &currentStyleFF : availableStyles) { for (QString currentStyleFF : availableStyles)
if (currentStyleFF.toLower() == appStyle.toLower()) { {
if (currentStyleFF.toLower() == appStyle.toLower())
{
ui->cbStyleList->setCurrentIndex(currentIndex); ui->cbStyleList->setCurrentIndex(currentIndex);
} }
currentIndex++; currentIndex++;
} }
} }
else { else
if (availableStyles.contains(currentStyle, Qt::CaseInsensitive)) { {
if (availableStyles.contains(currentStyle, Qt::CaseInsensitive))
{
int currentIndex = 0; int currentIndex = 0;
for (const QString &currentStyleFF : availableStyles) { for (QString currentStyleFF : availableStyles)
if (currentStyleFF.toLower() == currentStyle.toLower()) { {
if (currentStyleFF.toLower() == currentStyle.toLower())
{
ui->cbStyleList->setCurrentIndex(currentIndex); ui->cbStyleList->setCurrentIndex(currentIndex);
} }
currentIndex++; currentIndex++;
} }
} }
} }
ui->cbDefaultStyle->setChecked(!customStyle); if (customStyle)
ui->cbStyleList->setEnabled(customStyle); {
const QFont currentFont = QApplication::font(); ui->cbDefaultStyle->setChecked(false);
const QFont appFont = qvariant_cast<QFont>(settings->value("AppFont", currentFont)); }
bool customFont = settings->value("CustomFont", false).toBool();
ui->cbDefaultFont->setChecked(!customFont);
ui->cbFont->setEnabled(customFont);
ui->cbFont->setCurrentFont(appFont);
settings->endGroup(); settings->endGroup();
} }
@ -368,15 +377,18 @@ void OptionsDialog::applySettings()
settings->endGroup(); settings->endGroup();
settings->beginGroup("Profile"); settings->beginGroup("Profile");
int newContentMode = 20; int newContentMode = 0;
if (ui->rbModern->isChecked()) { if (ui->rbOpenWithSC->isChecked())
newContentMode = 20; {
newContentMode = 0;
} }
else if (ui->rbClassic->isChecked()) { else if (ui->rbOpenWithDC->isChecked())
newContentMode = 10; {
newContentMode = 1;
} }
if (ui->cbDoubleclick->isChecked()) { else if (ui->rbSelectWithSC->isChecked())
newContentMode++; {
newContentMode = 2;
} }
settings->setValue("ContentMode", newContentMode); settings->setValue("ContentMode", newContentMode);
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
@ -387,15 +399,18 @@ void OptionsDialog::applySettings()
settings->endGroup(); settings->endGroup();
settings->beginGroup("Pictures"); settings->beginGroup("Pictures");
if (ui->cbPicCustomQuality->isChecked()) { if (ui->cbPicCustomQuality->isChecked())
{
settings->setValue("CustomQuality", ui->hsPicQuality->value()); settings->setValue("CustomQuality", ui->hsPicQuality->value());
} }
settings->setValue("CustomQualityEnabled", ui->cbPicCustomQuality->isChecked()); settings->setValue("CustomQualityEnabled", ui->cbPicCustomQuality->isChecked());
QString sizeMode = "Default"; QString sizeMode = "Default";
if (ui->rbPicDesktopRes->isChecked()) { if (ui->rbPicDesktopRes->isChecked())
{
sizeMode = "Desktop"; sizeMode = "Desktop";
} }
else if (ui->rbPicCustomRes->isChecked()) { else if (ui->rbPicCustomRes->isChecked())
{
sizeMode = "Custom"; sizeMode = "Custom";
settings->setValue("CustomSize", QSize(ui->sbPicExportWidth->value(), ui->sbPicExportHeight->value())); settings->setValue("CustomSize", QSize(ui->sbPicExportWidth->value(), ui->sbPicExportHeight->value()));
} }
@ -411,25 +426,18 @@ void OptionsDialog::applySettings()
bool defaultStyle = ui->cbDefaultStyle->isChecked(); bool defaultStyle = ui->cbDefaultStyle->isChecked();
settings->beginGroup("Startup"); settings->beginGroup("Startup");
if (!defaultStyle) { if (!defaultStyle)
{
QString newStyle = ui->cbStyleList->currentText(); QString newStyle = ui->cbStyleList->currentText();
settings->setValue("CustomStyle", true); settings->setValue("CustomStyle", true);
settings->setValue("AppStyle", newStyle); settings->setValue("AppStyle", newStyle);
QApplication::setStyle(QStyleFactory::create(newStyle)); QApplication::setStyle(QStyleFactory::create(newStyle));
} }
else { else
{
settings->setValue("CustomStyle", false); settings->setValue("CustomStyle", false);
} }
bool defaultFont = ui->cbDefaultFont->isChecked(); settings->setValue("AlwaysUseMessageFont", ui->cbAlwaysUseMessageFont->isChecked());
if (!defaultFont) {
QFont newFont = ui->cbFont->currentFont();
settings->setValue("CustomFont", true);
settings->setValue("AppFont", newFont);
QApplication::setFont(newFont);
}
else {
settings->setValue("CustomFont", false);
}
settings->endGroup(); settings->endGroup();
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
@ -440,15 +448,12 @@ void OptionsDialog::applySettings()
settings->endGroup(); settings->endGroup();
Telemetry->refresh(); Telemetry->refresh();
Telemetry->work(); Telemetry->work();
if (ui->cbUsageData->isChecked() && Telemetry->canPush()) { if (ui->cbUsageData->isChecked() && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "SettingsUpdated"; jsonObject["Type"] = "SettingsUpdated";
#if QT_VERSION >= 0x060000
jsonObject["UpdateTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["UpdateTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["UpdateTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
@ -461,19 +466,22 @@ void OptionsDialog::applySettings()
bool languageChanged = ui->cbLanguage->itemData(ui->cbLanguage->currentIndex()).toString() != currentLanguage; bool languageChanged = ui->cbLanguage->itemData(ui->cbLanguage->currentIndex()).toString() != currentLanguage;
bool languageAreaChanged = ui->cbAreaLanguage->itemData(ui->cbLanguage->currentIndex()).toString() != currentAreaLanguage; bool languageAreaChanged = ui->cbAreaLanguage->itemData(ui->cbLanguage->currentIndex()).toString() != currentAreaLanguage;
#endif #endif
if (languageChanged) { if (languageChanged)
{
Translator->unloadTranslation(qApp); Translator->unloadTranslation(qApp);
Translator->initUserLanguage(); Translator->initUserLanguage();
Translator->loadTranslation(qApp); Translator->loadTranslation(qApp);
} }
else if (languageAreaChanged) { else if (languageAreaChanged)
{
Translator->initUserLanguage(); Translator->initUserLanguage();
} }
settings->sync(); settings->sync();
emit settingsApplied(newContentMode, languageChanged); emit settingsApplied(newContentMode, languageChanged);
if ((forceCustomFolder && ui->txtFolder->text() != currentCFolder) || (forceCustomFolder != currentFFolder && forceCustomFolder)) { if ((forceCustomFolder && ui->txtFolder->text() != currentCFolder) || (forceCustomFolder != currentFFolder && forceCustomFolder))
{
QMessageBox::information(this, tr("%1", "%1").arg(GTA5SYNC_APPSTR), tr("The new Custom Folder will initialise after you restart %1.").arg(GTA5SYNC_APPSTR)); QMessageBox::information(this, tr("%1", "%1").arg(GTA5SYNC_APPSTR), tr("The new Custom Folder will initialise after you restart %1.").arg(GTA5SYNC_APPSTR));
} }
} }
@ -490,9 +498,11 @@ void OptionsDialog::setupDefaultProfile()
void OptionsDialog::commitProfiles(const QStringList &profiles) void OptionsDialog::commitProfiles(const QStringList &profiles)
{ {
for (const QString &profile : profiles) { for (QString profile : profiles)
{
ui->cbProfiles->addItem(tr("Profile: %1").arg(profile), profile); ui->cbProfiles->addItem(tr("Profile: %1").arg(profile), profile);
if (defaultProfile == profile) { if (defaultProfile == profile)
{
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
ui->cbProfiles->setCurrentText(tr("Profile: %1").arg(profile)); ui->cbProfiles->setCurrentText(tr("Profile: %1").arg(profile));
#else #else
@ -530,7 +540,8 @@ void OptionsDialog::setupPictureSettings()
// Quality Settings // Quality Settings
customQuality = settings->value("CustomQuality", defaultQuality).toInt(); customQuality = settings->value("CustomQuality", defaultQuality).toInt();
if (customQuality < 1 || customQuality > 100) { if (customQuality < 1 || customQuality > 100)
{
customQuality = 100; customQuality = 100;
} }
ui->hsPicQuality->setValue(customQuality); ui->hsPicQuality->setValue(customQuality);
@ -538,34 +549,42 @@ void OptionsDialog::setupPictureSettings()
// Size Settings // Size Settings
cusExportSize = settings->value("CustomSize", defExportSize).toSize(); cusExportSize = settings->value("CustomSize", defExportSize).toSize();
if (cusExportSize.width() > 3840) { if (cusExportSize.width() > 3840)
{
cusExportSize.setWidth(3840); cusExportSize.setWidth(3840);
} }
else if (cusExportSize.height() > 2160) { else if (cusExportSize.height() > 2160)
{
cusExportSize.setHeight(2160); cusExportSize.setHeight(2160);
} }
if (cusExportSize.width() < 1) { if (cusExportSize.width() < 1)
{
cusExportSize.setWidth(1); cusExportSize.setWidth(1);
} }
else if (cusExportSize.height() < 1) { else if (cusExportSize.height() < 1)
{
cusExportSize.setHeight(1); cusExportSize.setHeight(1);
} }
ui->sbPicExportWidth->setValue(cusExportSize.width()); ui->sbPicExportWidth->setValue(cusExportSize.width());
ui->sbPicExportHeight->setValue(cusExportSize.height()); ui->sbPicExportHeight->setValue(cusExportSize.height());
QString sizeMode = settings->value("ExportSizeMode", "Default").toString(); QString sizeMode = settings->value("ExportSizeMode", "Default").toString();
if (sizeMode == "Desktop") { if (sizeMode == "Desktop")
{
ui->rbPicDesktopRes->setChecked(true); ui->rbPicDesktopRes->setChecked(true);
} }
else if (sizeMode == "Custom") { else if (sizeMode == "Custom")
{
ui->rbPicCustomRes->setChecked(true); ui->rbPicCustomRes->setChecked(true);
} }
else { else
{
ui->rbPicDefaultRes->setChecked(true); ui->rbPicDefaultRes->setChecked(true);
} }
aspectRatio = (Qt::AspectRatioMode)settings->value("AspectRatio", Qt::KeepAspectRatio).toInt(); aspectRatio = (Qt::AspectRatioMode)settings->value("AspectRatio", Qt::KeepAspectRatio).toInt();
if (aspectRatio == Qt::IgnoreAspectRatio) { if (aspectRatio == Qt::IgnoreAspectRatio)
{
ui->cbIgnoreAspectRatio->setChecked(true); ui->cbIgnoreAspectRatio->setChecked(true);
} }
@ -584,14 +603,17 @@ void OptionsDialog::setupStatisticsSettings()
ui->cbUsageData->setChecked(settings->value("PushUsageData", false).toBool()); ui->cbUsageData->setChecked(settings->value("PushUsageData", false).toBool());
settings->endGroup(); settings->endGroup();
if (Telemetry->isStateForced()) { if (Telemetry->isStateForced())
{
ui->cbParticipateStats->setEnabled(false); ui->cbParticipateStats->setEnabled(false);
} }
if (Telemetry->isRegistered()) { if (Telemetry->isRegistered())
{
ui->labParticipationID->setText(tr("Participation ID: %1").arg(Telemetry->getRegisteredID())); ui->labParticipationID->setText(tr("Participation ID: %1").arg(Telemetry->getRegisteredID()));
} }
else { else
{
ui->labParticipationID->setText(tr("Participation ID: %1").arg(tr("Not registered"))); ui->labParticipationID->setText(tr("Participation ID: %1").arg(tr("Not registered")));
ui->cmdCopyStatsID->setVisible(false); ui->cmdCopyStatsID->setVisible(false);
} }
@ -605,49 +627,62 @@ void OptionsDialog::setupWindowsGameSettings()
#ifdef GTA5SYNC_GAME #ifdef GTA5SYNC_GAME
GameVersion gameVersion = AppEnv::getGameVersion(); GameVersion gameVersion = AppEnv::getGameVersion();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (gameVersion != GameVersion::NoVersion) { if (gameVersion != GameVersion::NoVersion)
if (gameVersion == GameVersion::SocialClubVersion) { {
if (gameVersion == GameVersion::SocialClubVersion)
{
ui->gbSteam->setDisabled(true); ui->gbSteam->setDisabled(true);
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes")))); 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")))); ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No"))));
if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined) { if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined)
{
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName())); ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName()));
} }
else { else
{
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined"))); ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined")));
} }
ui->labSteamLanguage->setVisible(false); ui->labSteamLanguage->setVisible(false);
} }
else if (gameVersion == GameVersion::SteamVersion) { else if (gameVersion == GameVersion::SteamVersion)
{
ui->gbSocialClub->setDisabled(true); ui->gbSocialClub->setDisabled(true);
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No")))); 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->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
ui->labSocialClubLanguage->setVisible(false); ui->labSocialClubLanguage->setVisible(false);
if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined) { if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined)
{
ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName())); ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName()));
} }
else { else
{
ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined"))); ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined")));
} }
} }
else { else
{
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes")))); 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")))); ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined) { if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined)
{
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName())); ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName()));
} }
else { else
{
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined"))); ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined")));
} }
if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined) { if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined)
{
ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName())); ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName()));
} }
else { else
{
ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined"))); ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined")));
} }
} }
} }
else { else
{
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame)); ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
} }
#else #else
@ -660,10 +695,12 @@ void OptionsDialog::setupWindowsGameSettings()
void OptionsDialog::on_cbIgnoreAspectRatio_toggled(bool checked) void OptionsDialog::on_cbIgnoreAspectRatio_toggled(bool checked)
{ {
if (checked) { if (checked)
{
aspectRatio = Qt::IgnoreAspectRatio; aspectRatio = Qt::IgnoreAspectRatio;
} }
else { else
{
aspectRatio = Qt::KeepAspectRatio; aspectRatio = Qt::KeepAspectRatio;
} }
} }
@ -675,7 +712,8 @@ void OptionsDialog::setupCustomGTAFolder()
settings->beginGroup("dir"); settings->beginGroup("dir");
currentCFolder = settings->value("dir", "").toString(); currentCFolder = settings->value("dir", "").toString();
currentFFolder = settings->value("force", false).toBool(); currentFFolder = settings->value("force", false).toBool();
if (currentCFolder == "" && ok) { if (currentCFolder == "" && ok)
{
currentCFolder = defaultGameFolder; currentCFolder = defaultGameFolder;
} }
ui->txtFolder->setText(currentCFolder); ui->txtFolder->setText(currentCFolder);
@ -703,8 +741,9 @@ void OptionsDialog::setupSnapmaticPictureViewer()
void OptionsDialog::on_cmdExploreFolder_clicked() void OptionsDialog::on_cmdExploreFolder_clicked()
{ {
const QString GTAV_Folder = QFileDialog::getExistingDirectory(this, UserInterface::tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly); QString GTAV_Folder = QFileDialog::getExistingDirectory(this, UserInterface::tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly);
if (QDir(GTAV_Folder).exists()) { if (QFileInfo(GTAV_Folder).exists())
{
ui->txtFolder->setText(GTAV_Folder); ui->txtFolder->setText(GTAV_Folder);
} }
} }
@ -712,14 +751,6 @@ void OptionsDialog::on_cmdExploreFolder_clicked()
void OptionsDialog::on_cbDefaultStyle_toggled(bool checked) void OptionsDialog::on_cbDefaultStyle_toggled(bool checked)
{ {
ui->cbStyleList->setDisabled(checked); ui->cbStyleList->setDisabled(checked);
ui->labStyle->setDisabled(checked);
}
void OptionsDialog::on_cbDefaultFont_toggled(bool checked)
{
ui->cbFont->setDisabled(checked);
ui->cmdFont->setDisabled(checked);
ui->labFont->setDisabled(checked);
} }
void OptionsDialog::on_cmdCopyStatsID_clicked() void OptionsDialog::on_cmdCopyStatsID_clicked()
@ -728,18 +759,3 @@ void OptionsDialog::on_cmdCopyStatsID_clicked()
QApplication::clipboard()->setText(Telemetry->getRegisteredID()); QApplication::clipboard()->setText(Telemetry->getRegisteredID());
#endif #endif
} }
void OptionsDialog::on_cbFont_currentFontChanged(const QFont &font)
{
ui->cbFont->setFont(font);
}
void OptionsDialog::on_cmdFont_clicked()
{
bool ok;
const QFont font = QFontDialog::getFont(&ok, ui->cbFont->currentFont(), this);
if (ok) {
ui->cbFont->setCurrentFont(font);
ui->cbFont->setFont(font);
}
}

View file

@ -47,10 +47,7 @@ private slots:
void on_cbIgnoreAspectRatio_toggled(bool checked); void on_cbIgnoreAspectRatio_toggled(bool checked);
void on_cmdExploreFolder_clicked(); void on_cmdExploreFolder_clicked();
void on_cbDefaultStyle_toggled(bool checked); void on_cbDefaultStyle_toggled(bool checked);
void on_cbDefaultFont_toggled(bool checked);
void on_cmdCopyStatsID_clicked(); void on_cmdCopyStatsID_clicked();
void on_cbFont_currentFontChanged(const QFont &font);
void on_cmdFont_clicked();
signals: signals:
void settingsApplied(int contentMode, bool languageChanged); void settingsApplied(int contentMode, bool languageChanged);

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>435</width> <width>435</width>
<height>524</height> <height>474</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -34,9 +34,9 @@
</property> </property>
<layout class="QVBoxLayout" name="vlProfileContentMode"> <layout class="QVBoxLayout" name="vlProfileContentMode">
<item> <item>
<widget class="QRadioButton" name="rbModern"> <widget class="QRadioButton" name="rbOpenWithSC">
<property name="text"> <property name="text">
<string notr="true">%1 1.9+</string> <string>Open with Singleclick</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>true</bool> <bool>true</bool>
@ -44,16 +44,16 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QRadioButton" name="rbClassic"> <widget class="QRadioButton" name="rbOpenWithDC">
<property name="text"> <property name="text">
<string notr="true">%1 1.0-1.8</string> <string>Open with Doubleclick</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="cbDoubleclick"> <widget class="QRadioButton" name="rbSelectWithSC">
<property name="text"> <property name="text">
<string>Open with Doubleclick</string> <string>Select with Singleclick</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -660,9 +660,6 @@
<layout class="QHBoxLayout" name="hlStyle"> <layout class="QHBoxLayout" name="hlStyle">
<item> <item>
<widget class="QLabel" name="labStyle"> <widget class="QLabel" name="labStyle">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>Style:</string> <string>Style:</string>
</property> </property>
@ -693,52 +690,12 @@
</property> </property>
<layout class="QVBoxLayout" name="vlFont"> <layout class="QVBoxLayout" name="vlFont">
<item> <item>
<widget class="QCheckBox" name="cbDefaultFont"> <widget class="QCheckBox" name="cbAlwaysUseMessageFont">
<property name="text"> <property name="text">
<string>Use Default Font (Restart)</string> <string>Always use Message Font (Windows 2003 and earlier)</string>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="hlFont">
<item>
<widget class="QLabel" name="labFont">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Font:</string>
</property>
</widget>
</item>
<item>
<widget class="QFontComboBox" name="cbFont">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="cmdFont">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true">...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -38,15 +38,12 @@
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050200
#include "dwmapi.h" #include <QtWinExtras/QtWin>
#include <QtWinExtras/QWinEvent>
#endif #endif
#endif #endif
#ifdef Q_OS_MAC
#include <QStyleFactory>
#endif
#include <QStringBuilder> #include <QStringBuilder>
#include <QJsonDocument> #include <QJsonDocument>
#include <QApplication> #include <QApplication>
@ -66,7 +63,6 @@
#include <QPicture> #include <QPicture>
#include <QBitmap> #include <QBitmap>
#include <QBuffer> #include <QBuffer>
#include <QTimer>
#include <QImage> #include <QImage>
#include <QDebug> #include <QDebug>
#include <QList> #include <QList>
@ -127,20 +123,10 @@ PictureDialog::PictureDialog(bool primaryWindow, ProfileDatabase *profileDB, Cre
void PictureDialog::setupPictureDialog() void PictureDialog::setupPictureDialog()
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
setWindowFlag(Qt::CustomizeWindowHint, true);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::CustomizeWindowHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::CustomizeWindowHint);
#endif
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
// for stupid Window Manager like GNOME // for stupid Window Manager (GNOME 3 should feel triggered)
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::Dialog, false);
setWindowFlag(Qt::Window, true);
#else
setWindowFlags(windowFlags()^Qt::Dialog^Qt::Window); setWindowFlags(windowFlags()^Qt::Dialog^Qt::Window);
#endif
#endif #endif
// Setup User Interface // Setup User Interface
@ -157,16 +143,18 @@ void PictureDialog::setupPictureDialog()
crewStr = ""; crewStr = "";
// Get Snapmatic Resolution // Get Snapmatic Resolution
const QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution(); QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
// Avatar area // Avatar area
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
qreal screenRatioPR = AppEnv::screenRatioPR(); qreal screenRatioPR = AppEnv::screenRatioPR();
if (screenRatio != 1 || screenRatioPR != 1) { if (screenRatio != 1 || screenRatioPR != 1)
avatarAreaPicture = QImage(AppEnv::getImagesFolder() % "/avatararea.png").scaledToHeight(snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::FastTransformation); {
avatarAreaPicture = QImage(":/img/avatararea.png").scaledToHeight(snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::FastTransformation);
} }
else { else
avatarAreaPicture = QImage(AppEnv::getImagesFolder() % "/avatararea.png"); {
avatarAreaPicture = QImage(":/img/avatararea.png");
} }
avatarLocX = 145; avatarLocX = 145;
avatarLocY = 66; avatarLocY = 66;
@ -197,15 +185,21 @@ void PictureDialog::setupPictureDialog()
// Global map // Global map
globalMap = GlobalString::getGlobalMap(); globalMap = GlobalString::getGlobalMap();
// Event connects
connect(ui->labJSON, SIGNAL(resized(QSize)), this, SLOT(adaptNewDialogSize(QSize)));
// Set Icon for Close Button // Set Icon for Close Button
if (QIcon::hasThemeIcon("dialog-close")) { if (QIcon::hasThemeIcon("dialog-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close")); ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
} }
else if (QIcon::hasThemeIcon("gtk-close")) { else if (QIcon::hasThemeIcon("gtk-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close")); ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close"));
} }
installEventFilter(this); installEventFilter(this);
installEventFilter(ui->labPicture);
// DPI calculation // DPI calculation
ui->hlButtons->setSpacing(6 * screenRatio); ui->hlButtons->setSpacing(6 * screenRatio);
@ -214,13 +208,38 @@ void PictureDialog::setupPictureDialog()
ui->jsonLayout->setContentsMargins(4 * screenRatio, 10 * screenRatio, 4 * screenRatio, 4 * screenRatio); ui->jsonLayout->setContentsMargins(4 * screenRatio, 10 * screenRatio, 4 * screenRatio, 4 * screenRatio);
// Pre-adapt window for DPI // Pre-adapt window for DPI
const QSize windowSize(snapmaticResolution.width() * screenRatio, snapmaticResolution.height() * screenRatio); setFixedWidth(snapmaticResolution.width() * screenRatio);
setMinimumSize(windowSize); setFixedHeight(snapmaticResolution.height() * screenRatio);
setMaximumSize(windowSize);
} }
PictureDialog::~PictureDialog() PictureDialog::~PictureDialog()
{ {
#ifdef Q_OS_WIN
#if QT_VERSION >= 0x050200
if (naviEnabled)
{
for (QObject *obj : layout()->menuBar()->children())
{
delete obj;
}
delete layout()->menuBar();
}
#endif
#else
if (naviEnabled)
{
for (QObject *obj : layout()->menuBar()->children())
{
delete obj;
}
delete layout()->menuBar();
}
#endif
for (QObject *obj : manageMenu->children())
{
delete obj;
}
delete manageMenu;
delete ui; delete ui;
} }
@ -228,11 +247,24 @@ void PictureDialog::closeEvent(QCloseEvent *ev)
{ {
Q_UNUSED(ev) Q_UNUSED(ev)
if (primaryWindow) if (primaryWindow)
{
emit endDatabaseThread(); emit endDatabaseThread();
} }
}
void PictureDialog::addPreviousNextButtons() void PictureDialog::addPreviousNextButtons()
{ {
#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.svgz"), "", this, SLOT(previousPictureRequestedSlot()));
uiToolbar->addAction(QIcon(":/img/next.svgz"), "", this, SLOT(nextPictureRequestedSlot()));
layout()->setMenuBar(uiToolbar);
naviEnabled = true;
#endif
#else
QToolBar *uiToolbar = new QToolBar("Picture Toolbar", this); QToolBar *uiToolbar = new QToolBar("Picture Toolbar", this);
#if QT_VERSION < 0x050600 #if QT_VERSION < 0x050600
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
@ -243,83 +275,68 @@ void PictureDialog::addPreviousNextButtons()
#endif #endif
uiToolbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); uiToolbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
uiToolbar->setObjectName("UiToolbar"); uiToolbar->setObjectName("UiToolbar");
uiToolbar->addAction(QIcon(AppEnv::getImagesFolder() % "/back.svgz"), "", this, SLOT(previousPictureRequestedSlot())); uiToolbar->addAction(QIcon(":/img/back.svgz"), "", this, SLOT(previousPictureRequestedSlot()));
uiToolbar->addAction(QIcon(AppEnv::getImagesFolder() % "/next.svgz"), "", this, SLOT(nextPictureRequestedSlot())); uiToolbar->addAction(QIcon(":/img/next.svgz"), "", this, SLOT(nextPictureRequestedSlot()));
#ifdef Q_OS_MAC
#if QT_VERSION >= 0x050000
uiToolbar->setStyle(QStyleFactory::create("Fusion"));
#endif
#endif
layout()->setMenuBar(uiToolbar); layout()->setMenuBar(uiToolbar);
naviEnabled = true; naviEnabled = true;
#endif
} }
void PictureDialog::adaptDialogSize() void PictureDialog::adaptNewDialogSize(QSize newLabelSize)
{ {
int newDialogHeight = (SnapmaticPicture::getSnapmaticResolution().height() * AppEnv::screenRatio()) + ui->jsonFrame->heightForWidth(width()); Q_UNUSED(newLabelSize)
if (naviEnabled) #if QT_VERSION >= 0x050F00
newDialogHeight = newDialogHeight + layout()->menuBar()->height(); int newDialogHeight = SnapmaticPicture::getSnapmaticResolution().height();
const QSize windowSize(width(), newDialogHeight); #else
setMinimumSize(windowSize); int newDialogHeight = (ui->labPicture->pixmap()->height() / AppEnv::screenRatioPR());
setMaximumSize(windowSize); #endif
newDialogHeight = newDialogHeight + ui->jsonFrame->height();
if (naviEnabled) newDialogHeight = newDialogHeight + layout()->menuBar()->height();
setMaximumSize(width(), newDialogHeight);
setMinimumSize(width(), newDialogHeight);
setFixedHeight(newDialogHeight);
ui->labPicture->updateGeometry();
ui->jsonFrame->updateGeometry();
updateGeometry();
} }
void PictureDialog::styliseDialog() void PictureDialog::styliseDialog()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
BOOL isEnabled; #if QT_VERSION >= 0x050200
DwmIsCompositionEnabled(&isEnabled); if (QtWin::isCompositionEnabled())
if (isEnabled == TRUE) { {
MARGINS margins = {0, 0, qRound(layout()->menuBar()->height() * AppEnv::screenRatioPR()), 0}; QPalette palette;
HRESULT hr = S_OK; QtWin::extendFrameIntoClientArea(this, 0, qRound(layout()->menuBar()->height() * AppEnv::screenRatioPR()), 0, 0);
hr = DwmExtendFrameIntoClientArea(reinterpret_cast<HWND>(winId()), &margins); ui->jsonFrame->setStyleSheet(QString("QFrame { background: %1; }").arg(palette.window().color().name()));
if (SUCCEEDED(hr)) { setStyleSheet("PictureDialog { background: transparent; }");
setStyleSheet("PictureDialog{background:transparent}");
} }
else
{
QPalette palette;
QtWin::resetExtendedFrame(this);
ui->jsonFrame->setStyleSheet(QString("QFrame { background: %1; }").arg(palette.window().color().name()));
setStyleSheet(QString("PictureDialog { background: %1; }").arg(QtWin::realColorizationColor().name()));
} }
else { #endif
MARGINS margins = {0, 0, 0, 0};
DwmExtendFrameIntoClientArea(reinterpret_cast<HWND>(winId()), &margins);
bool colorOk = false;
QSettings dwmRegistry("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\DWM", QSettings::NativeFormat);
QRgb color = dwmRegistry.value("ColorizationColor").toUInt(&colorOk);
if (colorOk) {
setStyleSheet(QString("PictureDialog{background:%1}").arg(QColor::fromRgba(color).name()));
}
else {
HRESULT hr = S_OK;
BOOL isOpaqueBlend;
DWORD colorization;
hr = DwmGetColorizationColor(&colorization, &isOpaqueBlend);
if (SUCCEEDED(hr) && isOpaqueBlend == FALSE) {
color = colorization;
setStyleSheet(QString("PictureDialog{background:%1}").arg(QColor::fromRgba(color).name()));
}
else {
setStyleSheet("PictureDialog{background:palette(window)}");
}
}
}
ui->jsonFrame->setStyleSheet("QFrame{background:palette(window)}");
#endif #endif
} }
#ifdef Q_OS_WIN bool PictureDialog::event(QEvent *event)
#if QT_VERSION >= 0x050000 {
#if QT_VERSION >= 0x060000 #ifdef Q_OS_WIN
bool PictureDialog::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) #if QT_VERSION >= 0x050200
#else if (naviEnabled)
bool PictureDialog::nativeEvent(const QByteArray &eventType, void *message, long *result) {
#endif if (event->type() == QWinEvent::CompositionChange || event->type() == QWinEvent::ColorizationChange)
{ {
MSG *msg = reinterpret_cast<MSG*>(message);
if (msg->message == 0x031e || msg->message == 0x0320) {
styliseDialog(); styliseDialog();
} }
return QWidget::nativeEvent(eventType, message, result);
} }
#endif #endif
#endif #endif
return QDialog::event(event);
}
void PictureDialog::nextPictureRequestedSlot() void PictureDialog::nextPictureRequestedSlot()
{ {
@ -334,8 +351,10 @@ void PictureDialog::previousPictureRequestedSlot()
bool PictureDialog::eventFilter(QObject *obj, QEvent *ev) bool PictureDialog::eventFilter(QObject *obj, QEvent *ev)
{ {
bool returnValue = false; bool returnValue = false;
if (obj == this || obj == ui->labPicture) { if (obj == this || obj == ui->labPicture)
if (ev->type() == QEvent::KeyPress) { {
if (ev->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(ev); QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(ev);
switch (keyEvent->key()){ switch (keyEvent->key()){
case Qt::Key_Left: case Qt::Key_Left:
@ -347,21 +366,25 @@ bool PictureDialog::eventFilter(QObject *obj, QEvent *ev)
returnValue = true; returnValue = true;
break; break;
case Qt::Key_1: case Qt::Key_1:
if (previewMode) { if (previewMode)
{
previewMode = false; previewMode = false;
renderPicture(); renderPicture();
} }
else { else
{
previewMode = true; previewMode = true;
renderPicture(); renderPicture();
} }
break; break;
case Qt::Key_2: case Qt::Key_2:
if (overlayEnabled) { if (overlayEnabled)
{
overlayEnabled = false; overlayEnabled = false;
if (!previewMode) renderPicture(); if (!previewMode) renderPicture();
} }
else { else
{
overlayEnabled = true; overlayEnabled = true;
if (!previewMode) renderPicture(); if (!previewMode) renderPicture();
} }
@ -387,30 +410,40 @@ bool PictureDialog::eventFilter(QObject *obj, QEvent *ev)
} }
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050200
if (obj != ui->labPicture && naviEnabled) { if (obj != ui->labPicture && naviEnabled)
if (ev->type() == QEvent::MouseButtonPress) { {
if (ev->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(ev); QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(ev);
if (mouseEvent->pos().y() <= layout()->menuBar()->height()) { if (mouseEvent->pos().y() <= layout()->menuBar()->height())
if (mouseEvent->button() == Qt::LeftButton) { {
if (mouseEvent->button() == Qt::LeftButton)
{
dragPosition = mouseEvent->pos(); dragPosition = mouseEvent->pos();
dragStart = true; dragStart = true;
} }
} }
} }
if (ev->type() == QEvent::MouseButtonRelease) { if (ev->type() == QEvent::MouseButtonRelease)
{
QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(ev); QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(ev);
if (mouseEvent->pos().y() <= layout()->menuBar()->height()) { if (mouseEvent->pos().y() <= layout()->menuBar()->height())
if (mouseEvent->button() == Qt::LeftButton) { {
if (mouseEvent->button() == Qt::LeftButton)
{
dragStart = false; dragStart = false;
} }
} }
} }
if (dragStart && ev->type() == QEvent::MouseMove) { if (ev->type() == QEvent::MouseMove && dragStart)
{
QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(ev); QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(ev);
if (mouseEvent->pos().y() <= layout()->menuBar()->height()) { if (mouseEvent->pos().y() <= layout()->menuBar()->height())
if (mouseEvent->buttons() & Qt::LeftButton) { {
const QPoint diff = mouseEvent->pos() - dragPosition; if (mouseEvent->buttons() & Qt::LeftButton)
{
QPoint diff = mouseEvent->pos() - dragPosition;
move(QPoint(pos() + diff)); move(QPoint(pos() + diff));
updateGeometry(); updateGeometry();
} }
@ -468,12 +501,14 @@ void PictureDialog::renderOverlayPicture()
QRect overlaySpace = fontMetrics.boundingRect(preferedRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip | Qt::TextWordWrap, overlayText); QRect overlaySpace = fontMetrics.boundingRect(preferedRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip | Qt::TextWordWrap, overlayText);
int hOverlay = Qt::AlignTop; int hOverlay = Qt::AlignTop;
if (overlaySpace.height() < 74 * screenRatio * screenRatioPR) { if (overlaySpace.height() < 74 * screenRatio * screenRatioPR)
{
hOverlay = Qt::AlignVCenter; hOverlay = Qt::AlignVCenter;
preferedRect.setHeight(71 * screenRatio * screenRatioPR); preferedRect.setHeight(71 * screenRatio * screenRatioPR);
overlaySpace.setHeight(80 * screenRatio * screenRatioPR); overlaySpace.setHeight(80 * screenRatio * screenRatioPR);
} }
else { else
{
overlaySpace.setHeight(overlaySpace.height() + 6 * screenRatio * screenRatioPR); overlaySpace.setHeight(overlaySpace.height() + 6 * screenRatio * screenRatioPR);
} }
@ -486,10 +521,12 @@ void PictureDialog::renderOverlayPicture()
overlayPainter.drawText(preferedRect, Qt::AlignLeft | hOverlay | Qt::TextDontClip | Qt::TextWordWrap, overlayText); overlayPainter.drawText(preferedRect, Qt::AlignLeft | hOverlay | Qt::TextDontClip | Qt::TextWordWrap, overlayText);
overlayPainter.end(); overlayPainter.end();
if (overlaySpace.width() < 194 * screenRatio * screenRatioPR) { if (overlaySpace.width() < 194 * screenRatio * screenRatioPR)
{
overlaySpace.setWidth(200 * screenRatio * screenRatioPR); overlaySpace.setWidth(200 * screenRatio * screenRatioPR);
} }
else { else
{
overlaySpace.setWidth(overlaySpace.width() + 6 * screenRatio * screenRatioPR); overlaySpace.setWidth(overlaySpace.width() + 6 * screenRatio * screenRatioPR);
} }
@ -506,7 +543,8 @@ void PictureDialog::renderOverlayPicture()
void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture, bool readOk, bool _indexed, int _index) void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture, bool readOk, bool _indexed, int _index)
{ {
if (smpic != nullptr) { if (smpic != nullptr)
{
QObject::disconnect(smpic, SIGNAL(updated()), this, SLOT(updated())); QObject::disconnect(smpic, SIGNAL(updated()), this, SLOT(updated()));
QObject::disconnect(smpic, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString))); QObject::disconnect(smpic, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString)));
} }
@ -514,30 +552,35 @@ void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture, bool readOk,
indexed = _indexed; indexed = _indexed;
index = _index; index = _index;
smpic = picture; smpic = picture;
if (!readOk) { if (!readOk)
{
QMessageBox::warning(this, tr("Snapmatic Picture Viewer"), tr("Failed at %1").arg(picture->getLastStep())); QMessageBox::warning(this, tr("Snapmatic Picture Viewer"), tr("Failed at %1").arg(picture->getLastStep()));
return; return;
} }
if (picture->isPicOk()) { if (picture->isPicOk())
{
snapmaticPicture = picture->getImage(); snapmaticPicture = picture->getImage();
renderPicture(); renderPicture();
ui->cmdManage->setEnabled(true); ui->cmdManage->setEnabled(true);
} }
if (picture->isJsonOk()) { if (picture->isJsonOk())
{
crewStr = crewDB->getCrewName(crewID); crewStr = crewDB->getCrewName(crewID);
if (globalMap.contains(picArea)) { if (globalMap.contains(picArea))
picAreaStr = globalMap.value(picArea); {
picAreaStr = globalMap[picArea];
} }
else { else
{
picAreaStr = picArea; picAreaStr = picArea;
} }
setWindowTitle(windowTitleStr.arg(picTitl)); setWindowTitle(windowTitleStr.arg(picTitl));
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created)); ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
QTimer::singleShot(0, this, SLOT(adaptDialogSize()));
} }
else { else
{
ui->labJSON->setText(jsonDrawString.arg("0", "0", "0", tr("No Players"), tr("No Crew"), tr("Unknown Location"))); ui->labJSON->setText(jsonDrawString.arg("0", "0", "0", tr("No Players"), tr("No Crew"), tr("Unknown Location")));
QTimer::singleShot(0, this, SLOT(adaptDialogSize())); QMessageBox::warning(this,tr("Snapmatic Picture Viewer"),tr("Failed at %1").arg(picture->getLastStep()));
} }
QObject::connect(smpic, SIGNAL(updated()), this, SLOT(updated())); QObject::connect(smpic, SIGNAL(updated()), this, SLOT(updated()));
QObject::connect(smpic, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString))); QObject::connect(smpic, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString)));
@ -566,58 +609,76 @@ void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture)
void PictureDialog::renderPicture() void PictureDialog::renderPicture()
{ {
const qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
const qreal screenRatioPR = AppEnv::screenRatioPR(); qreal screenRatioPR = AppEnv::screenRatioPR();
const QSize snapmaticResolution(SnapmaticPicture::getSnapmaticResolution()); if (!previewMode)
const QSize renderResolution(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR); {
QPixmap shownImagePixmap(renderResolution); if (overlayEnabled)
shownImagePixmap.fill(Qt::black); {
QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
QPixmap shownImagePixmap(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR);
shownImagePixmap.fill(Qt::transparent);
QPainter shownImagePainter(&shownImagePixmap); QPainter shownImagePainter(&shownImagePixmap);
const QImage renderImage = snapmaticPicture.scaled(renderResolution, Qt::KeepAspectRatio, Qt::SmoothTransformation); shownImagePainter.drawImage(0, 0, snapmaticPicture.scaled(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
if (renderImage.width() < renderResolution.width()) { shownImagePainter.drawImage(3 * screenRatio * screenRatioPR, 3 * screenRatio * screenRatioPR, overlayTempImage);
shownImagePainter.drawImage((renderResolution.width() - renderImage.width()) / 2, 0, renderImage, Qt::AutoColor);
}
else if (renderImage.height() < renderResolution.height()) {
shownImagePainter.drawImage(0, (renderResolution.height() - renderImage.height()) / 2, renderImage, Qt::AutoColor);
}
else {
shownImagePainter.drawImage(0, 0, renderImage, Qt::AutoColor);
}
if (previewMode) {
QFont shownImagePainterFont;
shownImagePainterFont.setPixelSize(12 * screenRatio * screenRatioPR);
shownImagePainter.drawImage(0, 0, avatarAreaPicture);
shownImagePainter.setPen(QColor::fromRgb(255, 255, 255, 255));
shownImagePainter.setFont(shownImagePainterFont);
shownImagePainter.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"));
}
else if (overlayEnabled) {
shownImagePainter.drawImage(3 * screenRatio * screenRatioPR, 3 * screenRatio * screenRatioPR, overlayTempImage, Qt::AutoColor);
}
shownImagePainter.end(); shownImagePainter.end();
#if QT_VERSION >= 0x050600 #if QT_VERSION >= 0x050600
shownImagePixmap.setDevicePixelRatio(screenRatioPR); shownImagePixmap.setDevicePixelRatio(screenRatioPR);
#endif #endif
ui->labPicture->setPixmap(shownImagePixmap); ui->labPicture->setPixmap(shownImagePixmap);
} }
else
{
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
QSize snapmaticResolution = SnapmaticPicture::getSnapmaticResolution();
QPixmap avatarPixmap(snapmaticResolution.width() * screenRatio * screenRatioPR, snapmaticResolution.height() * screenRatio * screenRatioPR);
QPainter snapPainter(&avatarPixmap);
QFont snapPainterFont;
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 * 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);
}
}
void PictureDialog::crewNameUpdated() void PictureDialog::crewNameUpdated()
{ {
SnapmaticPicture *picture = smpic; // used by macro SnapmaticPicture *picture = smpic; // used by macro
QString crewIDStr = crewID; QString crewIDStr = crewID;
if (crewIDStr == crewStr) { if (crewIDStr == crewStr)
{
crewStr = crewDB->getCrewName(crewIDStr); crewStr = crewDB->getCrewName(crewIDStr);
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created)); ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
QTimer::singleShot(0, this, SLOT(adaptDialogSize()));
} }
} }
void PictureDialog::playerNameUpdated() void PictureDialog::playerNameUpdated()
{ {
SnapmaticPicture *picture = smpic; // used by macro SnapmaticPicture *picture = smpic; // used by macro
if (plyrsList.count() >= 1) { if (plyrsList.count() >= 1)
{
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created)); ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
QTimer::singleShot(0, this, SLOT(adaptDialogSize()));
} }
} }
@ -625,7 +686,8 @@ QString PictureDialog::generateCrewString()
{ {
SnapmaticPicture *picture = smpic; // used by macro SnapmaticPicture *picture = smpic; // used by macro
const QString crewIDStr = crewID; // save operation time const QString crewIDStr = crewID; // save operation time
if (crewIDStr != "0" && !crewIDStr.isEmpty()) { if (crewIDStr != "0" && !crewIDStr.isEmpty())
{
if (crewIDStr != crewStr) { if (crewIDStr != crewStr) {
return QString("<a href=\"https://socialclub.rockstargames.com/crew/" % QString(crewStr).replace(" ", "_") % "/" % crewIDStr % "\">" % crewStr % "</a>"); return QString("<a href=\"https://socialclub.rockstargames.com/crew/" % QString(crewStr).replace(" ", "_") % "/" % crewIDStr % "\">" % crewStr % "</a>");
} }
@ -641,8 +703,10 @@ QString PictureDialog::generatePlayersString()
SnapmaticPicture *picture = smpic; // used by macro SnapmaticPicture *picture = smpic; // used by macro
const QStringList playersList = plyrsList; // save operation time const QStringList playersList = plyrsList; // save operation time
QString plyrsStr; QString plyrsStr;
if (playersList.length() >= 1) { if (playersList.length() >= 1)
for (const QString &player : playersList) { {
for (const QString &player : playersList)
{
const QString playerName = profileDB->getPlayerName(player); const QString playerName = profileDB->getPlayerName(player);
if (player != playerName) { if (player != playerName) {
plyrsStr += ", <a href=\"https://socialclub.rockstargames.com/member/" % playerName % "/" % player % "\">" % playerName % "</a>"; plyrsStr += ", <a href=\"https://socialclub.rockstargames.com/member/" % playerName % "/" % player % "\">" % playerName % "</a>";
@ -653,7 +717,8 @@ QString PictureDialog::generatePlayersString()
} }
plyrsStr.remove(0, 2); plyrsStr.remove(0, 2);
} }
else { else
{
plyrsStr = tr("No Players"); plyrsStr = tr("No Players");
} }
return plyrsStr; return plyrsStr;
@ -661,27 +726,32 @@ QString PictureDialog::generatePlayersString()
void PictureDialog::exportSnapmaticPicture() void PictureDialog::exportSnapmaticPicture()
{ {
if (rqFullscreen && fullscreenWidget != nullptr) { if (rqFullscreen && fullscreenWidget != nullptr)
{
PictureExport::exportAsPicture(fullscreenWidget, smpic); PictureExport::exportAsPicture(fullscreenWidget, smpic);
} }
else { else
{
PictureExport::exportAsPicture(this, smpic); PictureExport::exportAsPicture(this, smpic);
} }
} }
void PictureDialog::copySnapmaticPicture() void PictureDialog::copySnapmaticPicture()
{ {
if (rqFullscreen && fullscreenWidget != nullptr) { if (rqFullscreen && fullscreenWidget != nullptr)
{
PictureExport::exportAsSnapmatic(fullscreenWidget, smpic); PictureExport::exportAsSnapmatic(fullscreenWidget, smpic);
} }
else { else
{
PictureExport::exportAsSnapmatic(this, smpic); PictureExport::exportAsSnapmatic(this, smpic);
} }
} }
void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button) void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button)
{ {
if (button == Qt::LeftButton) { if (button == Qt::LeftButton)
{
#if QT_VERSION >= 0x060000 #if QT_VERSION >= 0x060000
QRect desktopRect = QApplication::screenAt(pos())->geometry(); QRect desktopRect = QApplication::screenAt(pos())->geometry();
#else #else
@ -689,17 +759,14 @@ void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button)
#endif #endif
PictureWidget *pictureWidget = new PictureWidget(this); // Work! PictureWidget *pictureWidget = new PictureWidget(this); // Work!
pictureWidget->setObjectName("PictureWidget"); pictureWidget->setObjectName("PictureWidget");
#if QT_VERSION >= 0x050900 #if QT_VERSION >= 0x050600
pictureWidget->setWindowFlag(Qt::FramelessWindowHint, true);
pictureWidget->setWindowFlag(Qt::MaximizeUsingFullscreenGeometryHint, true);
#elif QT_VERSION >= 0x050600
pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint^Qt::MaximizeUsingFullscreenGeometryHint); pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint^Qt::MaximizeUsingFullscreenGeometryHint);
#else #else
pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint); pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint);
#endif #endif
pictureWidget->setWindowTitle(windowTitle()); pictureWidget->setWindowTitle(windowTitle());
pictureWidget->setStyleSheet("QLabel#pictureLabel{background-color: black;}"); pictureWidget->setStyleSheet("QLabel#pictureLabel{background-color: black;}");
pictureWidget->setImage(smpic->getImage(), desktopRect); pictureWidget->setImage(snapmaticPicture, desktopRect);
pictureWidget->setModal(true); pictureWidget->setModal(true);
fullscreenWidget = pictureWidget; fullscreenWidget = pictureWidget;
@ -709,6 +776,11 @@ void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button)
pictureWidget->move(desktopRect.x(), desktopRect.y()); pictureWidget->move(desktopRect.x(), desktopRect.y());
pictureWidget->resize(desktopRect.width(), desktopRect.height()); pictureWidget->resize(desktopRect.width(), desktopRect.height());
#ifdef Q_OS_WIN
#if QT_VERSION >= 0x050200
QtWin::markFullscreenWindow(pictureWidget, true);
#endif
#endif
pictureWidget->showFullScreen(); pictureWidget->showFullScreen();
pictureWidget->setFocus(); pictureWidget->setFocus();
pictureWidget->raise(); pictureWidget->raise();
@ -737,15 +809,15 @@ int PictureDialog::getIndex()
void PictureDialog::openPreviewMap() void PictureDialog::openPreviewMap()
{ {
SnapmaticPicture *picture = smpic; SnapmaticPicture *picture = smpic;
SnapmaticProperties currentProperties = picture->getSnapmaticProperties();
MapLocationDialog *mapLocDialog; MapLocationDialog *mapLocDialog;
if (rqFullscreen && fullscreenWidget != nullptr) { if (rqFullscreen && fullscreenWidget != nullptr)
mapLocDialog = new MapLocationDialog(currentProperties.location.x, currentProperties.location.y, fullscreenWidget); {
mapLocDialog = new MapLocationDialog(picture->getSnapmaticProperties().location.x, picture->getSnapmaticProperties().location.y, fullscreenWidget);
} }
else { else
mapLocDialog = new MapLocationDialog(currentProperties.location.x, currentProperties.location.y, this); {
mapLocDialog = new MapLocationDialog(picture->getSnapmaticProperties().location.x, picture->getSnapmaticProperties().location.y, this);
} }
mapLocDialog->setCayoPerico(currentProperties.location.isCayoPerico);
mapLocDialog->setWindowIcon(windowIcon()); mapLocDialog->setWindowIcon(windowIcon());
mapLocDialog->setModal(true); mapLocDialog->setModal(true);
#ifndef Q_OS_ANDROID #ifndef Q_OS_ANDROID
@ -754,43 +826,45 @@ void PictureDialog::openPreviewMap()
mapLocDialog->showMaximized(); mapLocDialog->showMaximized();
#endif #endif
mapLocDialog->exec(); mapLocDialog->exec();
if (mapLocDialog->propUpdated()) { if (mapLocDialog->propUpdated())
{
// Update Snapmatic Properties // Update Snapmatic Properties
currentProperties.location.x = mapLocDialog->getXpos(); SnapmaticProperties localSpJson = picture->getSnapmaticProperties();
currentProperties.location.y = mapLocDialog->getYpos(); localSpJson.location.x = mapLocDialog->getXpos();
currentProperties.location.z = 0; localSpJson.location.y = mapLocDialog->getYpos();
localSpJson.location.z = 0;
// Update Snapmatic Picture // Update Snapmatic Picture
QString currentFilePath = picture->getPictureFilePath(); QString currentFilePath = picture->getPictureFilePath();
QString originalFilePath = picture->getOriginalPictureFilePath(); QString originalFilePath = picture->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak"; QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) { if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName); QFile::copy(currentFilePath, backupFileName);
} }
SnapmaticProperties fallbackProperties = picture->getSnapmaticProperties(); SnapmaticProperties fallbackProperties = picture->getSnapmaticProperties();
picture->setSnapmaticProperties(currentProperties); picture->setSnapmaticProperties(localSpJson);
if (!picture->exportPicture(currentFilePath)) { if (!picture->exportPicture(currentFilePath))
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error")); QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error"));
picture->setSnapmaticProperties(fallbackProperties); picture->setSnapmaticProperties(fallbackProperties);
} }
else { else
{
updated(); updated();
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "LocationEdited"; jsonObject["Type"] = "LocationEdited";
jsonObject["ExtraFlags"] = "Viewer"; jsonObject["ExtraFlags"] = "Viewer";
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength()); jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
@ -804,10 +878,12 @@ void PictureDialog::editSnapmaticProperties()
{ {
SnapmaticPicture *picture = smpic; SnapmaticPicture *picture = smpic;
SnapmaticEditor *snapmaticEditor; SnapmaticEditor *snapmaticEditor;
if (rqFullscreen && fullscreenWidget != nullptr) { if (rqFullscreen && fullscreenWidget != nullptr)
{
snapmaticEditor = new SnapmaticEditor(crewDB, profileDB, fullscreenWidget); snapmaticEditor = new SnapmaticEditor(crewDB, profileDB, fullscreenWidget);
} }
else { else
{
snapmaticEditor = new SnapmaticEditor(crewDB, profileDB, this); snapmaticEditor = new SnapmaticEditor(crewDB, profileDB, this);
} }
snapmaticEditor->setWindowIcon(windowIcon()); snapmaticEditor->setWindowIcon(windowIcon());
@ -826,10 +902,12 @@ void PictureDialog::editSnapmaticImage()
{ {
QImage *currentImage = new QImage(smpic->getImage()); QImage *currentImage = new QImage(smpic->getImage());
ImportDialog *importDialog; ImportDialog *importDialog;
if (rqFullscreen && fullscreenWidget != nullptr) { if (rqFullscreen && fullscreenWidget != nullptr)
{
importDialog = new ImportDialog(profileName, fullscreenWidget); importDialog = new ImportDialog(profileName, fullscreenWidget);
} }
else { else
{
importDialog = new ImportDialog(profileName, this); importDialog = new ImportDialog(profileName, this);
} }
importDialog->setWindowIcon(windowIcon()); importDialog->setWindowIcon(windowIcon());
@ -837,17 +915,21 @@ void PictureDialog::editSnapmaticImage()
importDialog->enableOverwriteMode(); importDialog->enableOverwriteMode();
importDialog->setModal(true); importDialog->setModal(true);
importDialog->exec(); importDialog->exec();
if (importDialog->isImportAgreed()) { if (importDialog->isImportAgreed())
{
const QByteArray previousPicture = smpic->getPictureStream(); const QByteArray previousPicture = smpic->getPictureStream();
bool success = smpic->setImage(importDialog->image(), importDialog->isUnlimitedBuffer()); bool success = smpic->setImage(importDialog->image());
if (success) { if (success)
{
QString currentFilePath = smpic->getPictureFilePath(); QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath(); QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak"; QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) { if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName); QFile::copy(currentFilePath, backupFileName);
} }
if (!smpic->exportPicture(currentFilePath)) { if (!smpic->exportPicture(currentFilePath))
{
smpic->setPictureStream(previousPicture); 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")); QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of I/O Error"));
return; return;
@ -858,23 +940,21 @@ void PictureDialog::editSnapmaticImage()
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "ImageEdited"; jsonObject["Type"] = "ImageEdited";
jsonObject["ExtraFlags"] = "Viewer"; jsonObject["ExtraFlags"] = "Viewer";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
#endif #endif
} }
else { else
{
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error")); QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error"));
return; return;
} }
@ -886,10 +966,12 @@ void PictureDialog::editSnapmaticRawJson()
{ {
SnapmaticPicture *picture = smpic; SnapmaticPicture *picture = smpic;
JsonEditorDialog *jsonEditor; JsonEditorDialog *jsonEditor;
if (rqFullscreen && fullscreenWidget != nullptr) { if (rqFullscreen && fullscreenWidget != nullptr)
{
jsonEditor = new JsonEditorDialog(picture, fullscreenWidget); jsonEditor = new JsonEditorDialog(picture, fullscreenWidget);
} }
else { else
{
jsonEditor = new JsonEditorDialog(picture, this); jsonEditor = new JsonEditorDialog(picture, this);
} }
jsonEditor->setWindowIcon(windowIcon()); jsonEditor->setWindowIcon(windowIcon());
@ -907,21 +989,23 @@ void PictureDialog::updated()
{ {
SnapmaticPicture *picture = smpic; // used by macro SnapmaticPicture *picture = smpic; // used by macro
crewStr = crewDB->getCrewName(crewID); crewStr = crewDB->getCrewName(crewID);
if (globalMap.contains(picArea)) { if (globalMap.contains(picArea))
{
picAreaStr = globalMap[picArea]; picAreaStr = globalMap[picArea];
} }
else { else
{
picAreaStr = picArea; picAreaStr = picArea;
} }
setWindowTitle(windowTitleStr.arg(picTitl)); setWindowTitle(windowTitleStr.arg(picTitl));
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created)); ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
QTimer::singleShot(0, this, SLOT(adaptDialogSize()));
} }
void PictureDialog::customSignal(QString signal) void PictureDialog::customSignal(QString signal)
{ {
SnapmaticPicture *picture = smpic; // used by macro SnapmaticPicture *picture = smpic; // used by macro
if (signal == "PictureUpdated") { if (signal == "PictureUpdated")
{
snapmaticPicture = picture->getImage(); snapmaticPicture = picture->getImage();
renderPicture(); renderPicture();
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -54,11 +54,11 @@ public:
~PictureDialog(); ~PictureDialog();
public slots: public slots:
void adaptDialogSize();
void crewNameUpdated(); void crewNameUpdated();
void playerNameUpdated(); void playerNameUpdated();
void dialogNextPictureRequested(); void dialogNextPictureRequested();
void dialogPreviousPictureRequested(); void dialogPreviousPictureRequested();
void adaptNewDialogSize(QSize newLabelSize);
void exportCustomContextMenuRequested(const QPoint &pos); void exportCustomContextMenuRequested(const QPoint &pos);
private slots: private slots:
@ -89,13 +89,7 @@ protected:
void closeEvent(QCloseEvent *ev); void closeEvent(QCloseEvent *ev);
bool eventFilter(QObject *obj, QEvent *ev); bool eventFilter(QObject *obj, QEvent *ev);
void mousePressEvent(QMouseEvent *ev); void mousePressEvent(QMouseEvent *ev);
#ifdef Q_OS_WIN bool event(QEvent *event);
#if QT_VERSION >= 0x060000
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#elif QT_VERSION >= 0x050000
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#endif
#endif
private: private:
QString generateCrewString(); QString generateCrewString();
@ -126,7 +120,7 @@ private:
int avatarSize; int avatarSize;
QMenu *manageMenu; QMenu *manageMenu;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050200
QPoint dragPosition; QPoint dragPosition;
bool dragStart; bool dragStart;
#endif #endif

View file

@ -48,6 +48,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="vsJSONUpper">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QFrame" name="jsonFrame"> <widget class="QFrame" name="jsonFrame">
<property name="frameShape"> <property name="frameShape">
@ -98,10 +111,10 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>&lt;span style=&quot;font-weight:600&quot;&gt;Title: &lt;/span&gt;%6&lt;br/&gt; <string>&lt;span style=&quot; font-weight:600;&quot;&gt;Title: &lt;/span&gt;%6&lt;br/&gt;
&lt;span style=&quot;font-weight:600&quot;&gt;Location: &lt;/span&gt;%7 (%1, %2, %3)&lt;br/&gt; &lt;span style=&quot; font-weight:600;&quot;&gt;Location: &lt;/span&gt;%7 (%1, %2, %3)&lt;br/&gt;
&lt;span style=&quot;font-weight:600&quot;&gt;Players: &lt;/span&gt;%4 (Crew %5)&lt;br/&gt; &lt;span style=&quot; font-weight:600;&quot;&gt;Players: &lt;/span&gt;%4 (Crew %5)&lt;br/&gt;
&lt;span style=&quot;font-weight:600&quot;&gt;Created: &lt;/span&gt;%8</string> &lt;span style=&quot; font-weight:600;&quot;&gt;Created: &lt;/span&gt;%8</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>

View file

@ -40,6 +40,7 @@
PictureExport::PictureExport() PictureExport::PictureExport()
{ {
} }
void PictureExport::exportAsPicture(QWidget *parent, SnapmaticPicture *picture) void PictureExport::exportAsPicture(QWidget *parent, SnapmaticPicture *picture)
@ -50,25 +51,30 @@ void PictureExport::exportAsPicture(QWidget *parent, SnapmaticPicture *picture)
// Quality Settings // Quality Settings
settings.beginGroup("Pictures"); settings.beginGroup("Pictures");
int defaultQuality = 100; int defaultQuality = 100;
QSize defExportSize = SnapmaticPicture::getSnapmaticResolution(); QSize defExportSize = QSize(960, 536);
int customQuality = settings.value("CustomQuality", defaultQuality).toInt(); int customQuality = settings.value("CustomQuality", defaultQuality).toInt();
if (customQuality < 1 || customQuality > 100) { if (customQuality < 1 || customQuality > 100)
{
customQuality = 100; customQuality = 100;
} }
bool useCustomQuality = settings.value("CustomQualityEnabled", false).toBool(); bool useCustomQuality = settings.value("CustomQualityEnabled", false).toBool();
// Size Settings // Size Settings
QSize cusExportSize = settings.value("CustomSize", defExportSize).toSize(); QSize cusExportSize = settings.value("CustomSize", defExportSize).toSize();
if (cusExportSize.width() > 3840) { if (cusExportSize.width() > 3840)
{
cusExportSize.setWidth(3840); cusExportSize.setWidth(3840);
} }
else if (cusExportSize.height() > 2160) { else if (cusExportSize.height() > 2160)
{
cusExportSize.setHeight(2160); cusExportSize.setHeight(2160);
} }
if (cusExportSize.width() < 1) { if (cusExportSize.width() < 1)
{
cusExportSize.setWidth(1); cusExportSize.setWidth(1);
} }
else if (cusExportSize.height() < 1) { else if (cusExportSize.height() < 1)
{
cusExportSize.setHeight(1); cusExportSize.setHeight(1);
} }
QString sizeMode = settings.value("ExportSizeMode", "Default").toString(); QString sizeMode = settings.value("ExportSizeMode", "Default").toString();
@ -107,42 +113,54 @@ fileDialogPreSave: //Work?
QString newPictureFileName = getPictureFileName(picture) % defaultExportFormat; QString newPictureFileName = getPictureFileName(picture) % defaultExportFormat;
fileDialog.selectFile(newPictureFileName); fileDialog.selectFile(newPictureFileName);
if (fileDialog.exec()) { if (fileDialog.exec())
{
QStringList selectedFiles = fileDialog.selectedFiles(); QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1) { if (selectedFiles.length() == 1)
{
QString saveFileFormat; QString saveFileFormat;
QString selectedFile = selectedFiles.at(0); QString selectedFile = selectedFiles.at(0);
if (selectedFile.right(4) == ".jpg") { if (selectedFile.right(4) == ".jpg")
{
saveFileFormat = "JPEG"; saveFileFormat = "JPEG";
} }
else if (selectedFile.right(4) == ".jpeg") { else if (selectedFile.right(4) == ".jpeg")
{
saveFileFormat = "JPEG"; saveFileFormat = "JPEG";
} }
else if (selectedFile.right(4) == ".png") { else if (selectedFile.right(4) == ".png")
{
saveFileFormat = "PNG"; saveFileFormat = "PNG";
} }
else if (selectedFile.right(7) == ".suffix") { else if (selectedFile.right(7) == ".suffix")
if (fileDialog.selectedNameFilter() == "JPEG picture (*.jpg)") { {
if (fileDialog.selectedNameFilter() == "JPEG picture (*.jpg)")
{
selectedFile.replace(".suffix", ".jpg"); selectedFile.replace(".suffix", ".jpg");
} }
else if (fileDialog.selectedNameFilter() == "Portable Network Graphics (*.png)") { else if (fileDialog.selectedNameFilter() == "Portable Network Graphics (*.png)")
{
selectedFile.replace(".suffix", ".png"); selectedFile.replace(".suffix", ".png");
} }
else { else
{
selectedFile.replace(".suffix", ".jpg"); selectedFile.replace(".suffix", ".jpg");
} }
} }
if (QFile::exists(selectedFile)) { if (QFile::exists(selectedFile))
if (QMessageBox::No == QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Overwrite %1 with current Snapmatic picture?").arg("\""+selectedFile+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) { {
if (QMessageBox::No == QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Overwrite %1 with current Snapmatic picture?").arg("\""+selectedFile+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
{
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }
} }
// Scale Picture // Scale Picture
QImage exportPicture = picture->getImage(); QImage exportPicture = picture->getImage();
if (sizeMode == "Desktop") { if (sizeMode == "Desktop")
{
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
qreal screenRatioPR = AppEnv::screenRatioPR(); qreal screenRatioPR = AppEnv::screenRatioPR();
QRect desktopResolution = QApplication::primaryScreen()->geometry(); QRect desktopResolution = QApplication::primaryScreen()->geometry();
@ -155,7 +173,8 @@ fileDialogPreSave: //Work?
#endif #endif
exportPicture = exportPicture.scaled(desktopSizeWidth, desktopSizeHeight, aspectRatio, Qt::SmoothTransformation); exportPicture = exportPicture.scaled(desktopSizeWidth, desktopSizeHeight, aspectRatio, Qt::SmoothTransformation);
} }
else if (sizeMode == "Custom") { else if (sizeMode == "Custom")
{
exportPicture = exportPicture.scaled(cusExportSize, aspectRatio, Qt::SmoothTransformation); exportPicture = exportPicture.scaled(cusExportSize, aspectRatio, Qt::SmoothTransformation);
} }
@ -166,26 +185,32 @@ fileDialogPreSave: //Work?
#else #else
QFile *picFile = new QFile(selectedFile); QFile *picFile = new QFile(selectedFile);
#endif #endif
if (picFile->open(QIODevice::WriteOnly)) { if (picFile->open(QIODevice::WriteOnly))
{
isSaved = exportPicture.save(picFile, saveFileFormat.toStdString().c_str(), useCustomQuality ? customQuality : defaultQuality); isSaved = exportPicture.save(picFile, saveFileFormat.toStdString().c_str(), useCustomQuality ? customQuality : defaultQuality);
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
if (isSaved) { if (isSaved)
{
isSaved = picFile->commit(); isSaved = picFile->commit();
} }
else { else
{
errorId = 1; errorId = 1;
} }
#else #else
picFile->close(); picFile->close();
#endif #endif
} }
else { else
{
errorId = 2; errorId = 2;
} }
delete picFile; delete picFile;
if (!isSaved) { if (!isSaved)
switch (errorId) { {
switch (errorId)
{
case 0: case 0:
QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Failed to export the picture because the system occurred a write failure")); QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Failed to export the picture because the system occurred a write failure"));
break; break;
@ -201,7 +226,8 @@ fileDialogPreSave: //Work?
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }
} }
else { else
{
QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("No valid file is selected")); QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("No valid file is selected"));
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }
@ -237,9 +263,7 @@ fileDialogPreSave: //Work?
QStringList filters; QStringList filters;
filters << PictureDialog::tr("GTA V Export (*.g5e)"); filters << PictureDialog::tr("GTA V Export (*.g5e)");
#ifndef GTA5SYNC_FLATPAK
filters << PictureDialog::tr("GTA V Raw Export (*.auto)"); filters << PictureDialog::tr("GTA V Raw Export (*.auto)");
#endif
filters << PictureDialog::tr("Snapmatic pictures (PGTA*)"); filters << PictureDialog::tr("Snapmatic pictures (PGTA*)");
fileDialog.setNameFilters(filters); fileDialog.setNameFilters(filters);
@ -250,48 +274,58 @@ fileDialogPreSave: //Work?
fileDialog.restoreGeometry(settings.value(parent->objectName() % "+Geometry", "").toByteArray()); fileDialog.restoreGeometry(settings.value(parent->objectName() % "+Geometry", "").toByteArray());
fileDialog.selectFile(QString(picture->getExportPictureFileName() % ".g5e")); fileDialog.selectFile(QString(picture->getExportPictureFileName() % ".g5e"));
if (fileDialog.exec()) { if (fileDialog.exec())
{
QStringList selectedFiles = fileDialog.selectedFiles(); QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1) { if (selectedFiles.length() == 1)
{
QString selectedFile = selectedFiles.at(0); QString selectedFile = selectedFiles.at(0);
bool isAutoExt = false; bool isAutoExt = false;
#ifndef GTA5SYNC_FLATPAK if (selectedFile.right(5) == ".auto")
if (selectedFile.right(5) == ".auto") { {
isAutoExt = true; isAutoExt = true;
QString dirPath = QFileInfo(selectedFile).dir().path(); QString dirPath = QFileInfo(selectedFile).dir().path();
QString stockFileName = sgdFileInfo.fileName(); QString stockFileName = sgdFileInfo.fileName();
selectedFile = dirPath % "/" % stockFileName; selectedFile = dirPath % "/" % stockFileName;
} }
#endif else if (selectedFile.right(4) == ".rem")
if (selectedFile.right(4) == ".rem") { {
selectedFile.remove(selectedFile.length() - 4, 4); selectedFile.remove(selectedFile.length() - 4, 4);
} }
if (QFile::exists(selectedFile)) { if (QFile::exists(selectedFile))
if (QMessageBox::No == QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Overwrite %1 with current Snapmatic picture?").arg("\""+selectedFile+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) { {
if (QMessageBox::No == QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Overwrite %1 with current Snapmatic picture?").arg("\""+selectedFile+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
{
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }
} }
if (selectedFile.right(4) == ".g5e") { if (selectedFile.right(4) == ".g5e")
{
bool isExported = picture->exportPicture(selectedFile, SnapmaticFormat::G5E_Format); bool isExported = picture->exportPicture(selectedFile, SnapmaticFormat::G5E_Format);
if (!isExported) { if (!isExported)
{
QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Failed to export current Snapmatic picture")); QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Failed to export current Snapmatic picture"));
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }
} }
else { else
{
bool isCopied = picture->exportPicture(selectedFile, SnapmaticFormat::PGTA_Format); bool isCopied = picture->exportPicture(selectedFile, SnapmaticFormat::PGTA_Format);
if (!isCopied) { if (!isCopied)
{
QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Failed to export current Snapmatic picture")); QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Failed to export current Snapmatic picture"));
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }
else { else
{
if (isAutoExt) QMessageBox::information(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Exported Snapmatic to \"%1\" because of using the .auto extension.").arg(selectedFile)); if (isAutoExt) QMessageBox::information(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Exported Snapmatic to \"%1\" because of using the .auto extension.").arg(selectedFile));
} }
} }
} }
else { else
{
QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("No valid file is selected")); QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("No valid file is selected"));
goto fileDialogPreSave; //Work? goto fileDialogPreSave; //Work?
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2020 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -19,12 +19,16 @@
#include "PictureDialog.h" #include "PictureDialog.h"
#include "PictureWidget.h" #include "PictureWidget.h"
#include "UiModLabel.h" #include "UiModLabel.h"
#include "AppEnv.h"
#include <QApplication> #include <QApplication>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
#include <QPixmap> #include <QPixmap>
#include <QEvent> #include <QEvent>
#include <QDebug>
#if QT_VERSION < 0x060000
#include <QDesktopWidget>
#endif
PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent) PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent)
{ {
@ -43,6 +47,9 @@ PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent)
QObject::connect(pictureLabel, SIGNAL(mouseDoubleClicked(Qt::MouseButton)), this, SLOT(pictureDoubleClicked(Qt::MouseButton))); QObject::connect(pictureLabel, SIGNAL(mouseDoubleClicked(Qt::MouseButton)), this, SLOT(pictureDoubleClicked(Qt::MouseButton)));
QObject::connect(pictureLabel, SIGNAL(customContextMenuRequested(QPoint)), parent, SLOT(exportCustomContextMenuRequested(QPoint))); 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); setLayout(widgetLayout);
} }
@ -56,8 +63,10 @@ PictureWidget::~PictureWidget()
bool PictureWidget::eventFilter(QObject *obj, QEvent *ev) bool PictureWidget::eventFilter(QObject *obj, QEvent *ev)
{ {
if (obj == this) { if (obj == this)
if (ev->type() == QEvent::KeyPress) { {
if (ev->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = (QKeyEvent*)ev; QKeyEvent *keyEvent = (QKeyEvent*)ev;
switch (keyEvent->key()){ switch (keyEvent->key()){
case Qt::Key_Left: case Qt::Key_Left:
@ -74,29 +83,41 @@ bool PictureWidget::eventFilter(QObject *obj, QEvent *ev)
void PictureWidget::pictureDoubleClicked(Qt::MouseButton button) void PictureWidget::pictureDoubleClicked(Qt::MouseButton button)
{ {
if (button == Qt::LeftButton) { if (button == Qt::LeftButton)
{
close(); close();
} }
} }
void PictureWidget::setImage(QImage image_, QRect rec) void PictureWidget::setImage(QImage image_, QRect rec)
{ {
const qreal screenRatioPR = AppEnv::screenRatioPR();
image = image_; image = image_;
QPixmap pixmap = QPixmap::fromImage(image.scaled(rec.width() * screenRatioPR, rec.height() * screenRatioPR, Qt::KeepAspectRatio, Qt::SmoothTransformation)); pictureLabel->setPixmap(QPixmap::fromImage(image.scaled(rec.width(), rec.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
#if QT_VERSION >= 0x050600
pixmap.setDevicePixelRatio(AppEnv::screenRatioPR());
#endif
pictureLabel->setPixmap(pixmap);
} }
void PictureWidget::setImage(QImage image_) void PictureWidget::setImage(QImage image_)
{ {
const qreal screenRatioPR = AppEnv::screenRatioPR();
image = image_; image = image_;
QPixmap pixmap = QPixmap::fromImage(image.scaled(geometry().width() * screenRatioPR, geometry().height() * screenRatioPR, Qt::KeepAspectRatio, Qt::SmoothTransformation)); pictureLabel->setPixmap(QPixmap::fromImage(image.scaled(geometry().width(), geometry().height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
#if QT_VERSION >= 0x050600 }
pixmap.setDevicePixelRatio(screenRatioPR);
#endif void PictureWidget::updateWindowSize(int screenID)
pictureLabel->setPixmap(pixmap); {
#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);
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
} }

View file

@ -46,6 +46,7 @@ private:
private slots: private slots:
void pictureDoubleClicked(Qt::MouseButton button); void pictureDoubleClicked(Qt::MouseButton button);
void updateWindowSize(int screenID);
signals: signals:
void nextPictureRequested(); void nextPictureRequested();

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -18,9 +18,7 @@
#include "PlayerListDialog.h" #include "PlayerListDialog.h"
#include "ui_PlayerListDialog.h" #include "ui_PlayerListDialog.h"
#include "wrapper.h"
#include "AppEnv.h" #include "AppEnv.h"
#include <QStringBuilder>
#include <QFontMetrics> #include <QFontMetrics>
#include <QInputDialog> #include <QInputDialog>
#include <QMessageBox> #include <QMessageBox>
@ -33,11 +31,7 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
ui(new Ui::PlayerListDialog) ui(new Ui::PlayerListDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
listUpdated = false; listUpdated = false;
ui->setupUi(this); ui->setupUi(this);
@ -45,32 +39,40 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
ui->cmdCancel->setFocus(); ui->cmdCancel->setFocus();
// Set Icon for Apply Button // Set Icon for Apply Button
if (QIcon::hasThemeIcon("dialog-ok-apply")) { if (QIcon::hasThemeIcon("dialog-ok-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok-apply")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok-apply"));
} }
else if (QIcon::hasThemeIcon("dialog-apply")) { else if (QIcon::hasThemeIcon("dialog-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-apply")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-apply"));
} }
else if (QIcon::hasThemeIcon("gtk-apply")) { else if (QIcon::hasThemeIcon("gtk-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("gtk-apply")); ui->cmdApply->setIcon(QIcon::fromTheme("gtk-apply"));
} }
else if (QIcon::hasThemeIcon("dialog-ok")) { else if (QIcon::hasThemeIcon("dialog-ok"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok"));
} }
else if (QIcon::hasThemeIcon("gtk-ok")) { else if (QIcon::hasThemeIcon("gtk-ok"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok"));
} }
// Set Icon for Cancel Button // Set Icon for Cancel Button
if (QIcon::hasThemeIcon("dialog-cancel")) { if (QIcon::hasThemeIcon("dialog-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
} }
else if (QIcon::hasThemeIcon("gtk-cancel")) { else if (QIcon::hasThemeIcon("gtk-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel"));
} }
// Set Icon for Manage Buttons // Set Icon for Manage Buttons
if (QIcon::hasThemeIcon("go-previous") && QIcon::hasThemeIcon("go-next") && QIcon::hasThemeIcon("list-add")) { if (QIcon::hasThemeIcon("go-previous") && QIcon::hasThemeIcon("go-next") && QIcon::hasThemeIcon("list-add"))
{
#if QT_VERSION < 0x050600 #if QT_VERSION < 0x050600
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
if (screenRatio != 1) { if (screenRatio != 1) {
@ -85,7 +87,8 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
ui->cmdMakeSe->setIcon(QIcon::fromTheme("go-next")); ui->cmdMakeSe->setIcon(QIcon::fromTheme("go-next"));
ui->cmdMakeAd->setIcon(QIcon::fromTheme("list-add")); ui->cmdMakeAd->setIcon(QIcon::fromTheme("list-add"));
} }
else { else
{
#if QT_VERSION < 0x050600 #if QT_VERSION < 0x050600
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
if (screenRatio != 1) { if (screenRatio != 1) {
@ -96,9 +99,9 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
ui->cmdMakeAd->setIconSize(iconSize); ui->cmdMakeAd->setIconSize(iconSize);
} }
#endif #endif
ui->cmdMakeAv->setIcon(QIcon(AppEnv::getImagesFolder() % "/back.svgz")); ui->cmdMakeAv->setIcon(QIcon(":/img/back.svgz"));
ui->cmdMakeSe->setIcon(QIcon(AppEnv::getImagesFolder() % "/next.svgz")); ui->cmdMakeSe->setIcon(QIcon(":/img/next.svgz"));
ui->cmdMakeAd->setIcon(QIcon(AppEnv::getImagesFolder() % "/add.svgz")); ui->cmdMakeAd->setIcon(QIcon(":/img/add.svgz"));
} }
buildInterface(); buildInterface();
@ -109,10 +112,12 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
PlayerListDialog::~PlayerListDialog() PlayerListDialog::~PlayerListDialog()
{ {
for (QObject *object : ui->listAvPlayers->children()) { for (QObject *object : ui->listAvPlayers->children())
{
delete object; delete object;
} }
for (QObject *object : ui->listSePlayers->children()) { for (QObject *object : ui->listSePlayers->children())
{
delete object; delete object;
} }
delete ui; delete ui;
@ -126,13 +131,16 @@ void PlayerListDialog::on_cmdCancel_clicked()
void PlayerListDialog::buildInterface() void PlayerListDialog::buildInterface()
{ {
const QStringList dbPlayers = profileDB->getPlayers(); const QStringList dbPlayers = profileDB->getPlayers();
for (const QString &sePlayer : qAsConst(players)) { for (QString sePlayer : players)
{
QListWidgetItem *playerItem = new QListWidgetItem(profileDB->getPlayerName(sePlayer)); QListWidgetItem *playerItem = new QListWidgetItem(profileDB->getPlayerName(sePlayer));
playerItem->setData(Qt::UserRole, sePlayer); playerItem->setData(Qt::UserRole, sePlayer);
ui->listSePlayers->addItem(playerItem); ui->listSePlayers->addItem(playerItem);
} }
for (const QString &dbPlayer : dbPlayers) { for (QString dbPlayer : dbPlayers)
if (!players.contains(dbPlayer)) { {
if (!players.contains(dbPlayer))
{
QListWidgetItem *playerItem = new QListWidgetItem(profileDB->getPlayerName(dbPlayer)); QListWidgetItem *playerItem = new QListWidgetItem(profileDB->getPlayerName(dbPlayer));
playerItem->setData(Qt::UserRole, dbPlayer); playerItem->setData(Qt::UserRole, dbPlayer);
ui->listAvPlayers->addItem(playerItem); ui->listAvPlayers->addItem(playerItem);
@ -143,7 +151,8 @@ void PlayerListDialog::buildInterface()
void PlayerListDialog::on_cmdMakeAv_clicked() void PlayerListDialog::on_cmdMakeAv_clicked()
{ {
for (QListWidgetItem *item : ui->listSePlayers->selectedItems()) { for (QListWidgetItem *item : ui->listSePlayers->selectedItems())
{
QString playerName = item->text(); QString playerName = item->text();
int playerID = item->data(Qt::UserRole).toInt(); int playerID = item->data(Qt::UserRole).toInt();
delete item; delete item;
@ -157,11 +166,13 @@ void PlayerListDialog::on_cmdMakeAv_clicked()
void PlayerListDialog::on_cmdMakeSe_clicked() void PlayerListDialog::on_cmdMakeSe_clicked()
{ {
int maxPlayers = 30; int maxPlayers = 30;
if (maxPlayers < ui->listSePlayers->count() + ui->listAvPlayers->selectedItems().count()) { if (maxPlayers < ui->listSePlayers->count() + ui->listAvPlayers->selectedItems().count())
{
QMessageBox::warning(this, tr("Add Players..."), tr("Failed to add more Players because the limit of Players are %1!").arg(QString::number(maxPlayers))); QMessageBox::warning(this, tr("Add Players..."), tr("Failed to add more Players because the limit of Players are %1!").arg(QString::number(maxPlayers)));
return; return;
} }
for (QListWidgetItem *item : ui->listAvPlayers->selectedItems()) { for (QListWidgetItem *item : ui->listAvPlayers->selectedItems())
{
QString playerName = item->text(); QString playerName = item->text();
int playerID = item->data(Qt::UserRole).toInt(); int playerID = item->data(Qt::UserRole).toInt();
delete item; delete item;
@ -175,12 +186,15 @@ void PlayerListDialog::on_cmdMakeAd_clicked()
{ {
bool playerOk; bool playerOk;
int playerID = QInputDialog::getInt(this, tr("Add Player..."), tr("Enter Social Club Player ID"), 1, 1, 214783647, 1, &playerOk, windowFlags()); int playerID = QInputDialog::getInt(this, tr("Add Player..."), tr("Enter Social Club Player ID"), 1, 1, 214783647, 1, &playerOk, windowFlags());
if (playerOk) { if (playerOk)
for (int i = 0; i < ui->listAvPlayers->count(); ++i) { {
for (int i = 0; i < ui->listAvPlayers->count(); ++i)
{
QListWidgetItem *item = ui->listAvPlayers->item(i); QListWidgetItem *item = ui->listAvPlayers->item(i);
QString itemPlayerName = item->text(); QString itemPlayerName = item->text();
int itemPlayerID = item->data(Qt::UserRole).toInt(); int itemPlayerID = item->data(Qt::UserRole).toInt();
if (itemPlayerID == playerID) { if (itemPlayerID == playerID)
{
delete item; delete item;
QListWidgetItem *playerItem = new QListWidgetItem(itemPlayerName); QListWidgetItem *playerItem = new QListWidgetItem(itemPlayerName);
playerItem->setData(Qt::UserRole, playerID); playerItem->setData(Qt::UserRole, playerID);
@ -188,7 +202,8 @@ void PlayerListDialog::on_cmdMakeAd_clicked()
return; return;
} }
} }
for (int i = 0; i < ui->listSePlayers->count(); ++i) { for (int i = 0; i < ui->listSePlayers->count(); ++i)
{
QListWidgetItem *item = ui->listSePlayers->item(i); QListWidgetItem *item = ui->listSePlayers->item(i);
int itemPlayerID = item->data(Qt::UserRole).toInt(); int itemPlayerID = item->data(Qt::UserRole).toInt();
if (itemPlayerID == playerID) if (itemPlayerID == playerID)
@ -206,7 +221,8 @@ void PlayerListDialog::on_cmdMakeAd_clicked()
void PlayerListDialog::on_cmdApply_clicked() void PlayerListDialog::on_cmdApply_clicked()
{ {
players.clear(); players.clear();
for (int i = 0; i < ui->listSePlayers->count(); ++i) { for (int i = 0; i < ui->listSePlayers->count(); ++i)
{
players += ui->listSePlayers->item(i)->data(Qt::UserRole).toString(); players += ui->listSePlayers->item(i)->data(Qt::UserRole).toString();
} }
emit playerListUpdated(players); emit playerListUpdated(players);

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -30,7 +30,6 @@
#include "SavegameData.h" #include "SavegameData.h"
#include "CrewDatabase.h" #include "CrewDatabase.h"
#include "pcg_basic.h" #include "pcg_basic.h"
#include <QFileSystemWatcher>
#include <QProgressDialog> #include <QProgressDialog>
#include <QSpacerItem> #include <QSpacerItem>
#include <QDateTime> #include <QDateTime>
@ -53,6 +52,8 @@ public:
void settingsApplied(int contentMode, bool languageChanged); void settingsApplied(int contentMode, bool languageChanged);
void setupProfileInterface(); void setupProfileInterface();
void massTool(MassTool tool); void massTool(MassTool tool);
void disableSelected();
void enableSelected();
int selectedWidgets(); int selectedWidgets();
void retranslateUi(); void retranslateUi();
~ProfileInterface(); ~ProfileInterface();
@ -63,11 +64,8 @@ public slots:
void hoverProfileWidgetCheck(); void hoverProfileWidgetCheck();
void selectAllWidgets(); void selectAllWidgets();
void deselectAllWidgets(); void deselectAllWidgets();
void disableSelected();
void enableSelected();
void exportSelected(); void exportSelected();
void deleteSelected(); void deleteSelected();
void deleteSelectedR();
void updatePalette(); void updatePalette();
void importFiles(); void importFiles();
@ -83,17 +81,9 @@ private slots:
void profileLoaded_p(); void profileLoaded_p();
void profileWidgetSelected(); void profileWidgetSelected();
void profileWidgetDeselected(); void profileWidgetDeselected();
void massToolQualify();
void massToolPlayers();
void massToolCrew();
void massToolTitle();
void dialogNextPictureRequested(QWidget *dialog); void dialogNextPictureRequested(QWidget *dialog);
void dialogPreviousPictureRequested(QWidget *dialog); void dialogPreviousPictureRequested(QWidget *dialog);
void on_saProfileContent_dropped(const QMimeData *mimeData); void on_saProfileContent_dropped(const QMimeData *mimeData);
#if QT_VERSION >= 0x050000
void directoryChanged(const QString &path);
void directoryScanned(QVector<QString> savegameFiles, QVector<QString> snapmaticPics);
#endif
protected: protected:
bool eventFilter(QObject *watched, QEvent *event); bool eventFilter(QObject *watched, QEvent *event);
@ -109,11 +99,6 @@ private:
QList<SavegameData*> savegames; QList<SavegameData*> savegames;
QList<SnapmaticPicture*> pictures; QList<SnapmaticPicture*> pictures;
QMap<ProfileWidget*,QString> widgets; QMap<ProfileWidget*,QString> widgets;
#if QT_VERSION >= 0x050000
QFileSystemWatcher fileSystemWatcher;
QVector<QString> savegameFiles;
QVector<QString> snapmaticPics;
#endif
QSpacerItem *saSpacerItem; QSpacerItem *saSpacerItem;
QStringList fixedPictures; QStringList fixedPictures;
QString enabledPicStr; QString enabledPicStr;
@ -139,7 +124,6 @@ private:
void savegameLoaded(SavegameData *savegame, QString savegamePath, bool inserted); void savegameLoaded(SavegameData *savegame, QString savegamePath, bool inserted);
void savegameDeleted(SavegameWidget *sgdWidget, bool isRemoteEmited = false); void savegameDeleted(SavegameWidget *sgdWidget, bool isRemoteEmited = false);
void pictureDeleted(SnapmaticWidget *picWidget, bool isRemoteEmited = false); void pictureDeleted(SnapmaticWidget *picWidget, bool isRemoteEmited = false);
void deleteSelectedL(bool isRemoteEmited = false);
void insertSnapmaticIPI(QWidget *widget); void insertSnapmaticIPI(QWidget *widget);
void insertSavegameIPI(QWidget *widget); void insertSavegameIPI(QWidget *widget);
void sortingProfileInterface(); void sortingProfileInterface();

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -16,99 +16,80 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/ *****************************************************************************/
#include "SnapmaticPicture.h"
#include "ProfileLoader.h" #include "ProfileLoader.h"
#include "SnapmaticPicture.h"
#include "SavegameData.h" #include "SavegameData.h"
#include "CrewDatabase.h" #include "CrewDatabase.h"
#include "wrapper.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QVector> #include <QStringList>
#include <QString> #include <QString>
#include <QFile> #include <QThread>
#ifdef Q_OS_WIN
#include <QDir>
#include <QList> #include <QList>
#else #include <QFile>
#include "sys/types.h" #include <QDir>
#include "sys/stat.h"
#include "dirent.h"
#endif
ProfileLoader::ProfileLoader(QString profileFolder, CrewDatabase *crewDB, QObject *parent) : QThread(parent), profileFolder(profileFolder), crewDB(crewDB) ProfileLoader::ProfileLoader(QString profileFolder, CrewDatabase *crewDB, QObject *parent) : QThread(parent), profileFolder(profileFolder), crewDB(crewDB)
{ {
} }
void ProfileLoader::run() void ProfileLoader::run()
{ {
int curFile = 1; int curFile = 1;
int maximumV = 0; QDir profileDir;
QVector<int> crewList; QList<int> crewList;
QVector<QString> savegameFiles; profileDir.setPath(profileFolder);
QVector<QString> snapmaticPics;
#ifdef Q_OS_WIN // Seek pictures and savegames
QDir dir(profileFolder); profileDir.setNameFilters(QStringList("SGTA*"));
const QStringList files = dir.entryList(QDir::Files); QStringList SavegameFiles = profileDir.entryList(QDir::Files | QDir::NoDot, QDir::NoSort);
for (const QString &fileName : files) { QStringList BackupFiles = SavegameFiles.filter(".bak", Qt::CaseInsensitive);
if (fileName.startsWith("SGTA5") && !fileName.endsWith(".bak")) { profileDir.setNameFilters(QStringList("PGTA*"));
savegameFiles << fileName; QStringList SnapmaticPics = profileDir.entryList(QDir::Files | QDir::NoDot, QDir::NoSort);
maximumV++; BackupFiles += SnapmaticPics.filter(".bak", Qt::CaseInsensitive);
}
if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) {
snapmaticPics << fileName;
maximumV++;
}
}
#else
DIR *dirp = opendir(profileFolder.toUtf8().constData());
struct dirent *dp;
while ((dp = readdir(dirp)) != 0) {
const QString fileName = QString::fromUtf8(dp->d_name);
const QString filePath = profileFolder % "/" % fileName;
struct stat fileStat;
stat(filePath.toUtf8().constData(), &fileStat);
if (S_ISREG(fileStat.st_mode) != 0) {
if (fileName.startsWith("SGTA5") && !fileName.endsWith(".bak")) {
savegameFiles << fileName;
maximumV++;
}
if (fileName.startsWith("PGTA5") && !fileName.endsWith(".bak")) {
snapmaticPics << fileName;
maximumV++;
}
}
}
closedir(dirp);
#endif
// Directory successfully scanned SavegameFiles.removeDuplicates();
emit directoryScanned(savegameFiles, snapmaticPics); SnapmaticPics.removeDuplicates();
for (QString BackupFile : BackupFiles)
{
SavegameFiles.removeAll(BackupFile);
SnapmaticPics.removeAll(BackupFile);
}
int maximumV = SavegameFiles.length() + SnapmaticPics.length();
// Loading pictures and savegames // Loading pictures and savegames
emit loadingProgress(curFile, maximumV); emit loadingProgress(curFile, maximumV);
for (const QString &SavegameFile : qAsConst(savegameFiles)) { for (QString SavegameFile : SavegameFiles)
{
emit loadingProgress(curFile, maximumV); emit loadingProgress(curFile, maximumV);
const QString sgdPath = profileFolder % "/" % SavegameFile; QString sgdPath = profileFolder % "/" % SavegameFile;
SavegameData *savegame = new SavegameData(sgdPath); SavegameData *savegame = new SavegameData(sgdPath);
if (savegame->readingSavegame()) { if (savegame->readingSavegame())
{
emit savegameLoaded(savegame, sgdPath); emit savegameLoaded(savegame, sgdPath);
} }
curFile++; curFile++;
} }
for (const QString &SnapmaticPic : qAsConst(snapmaticPics)) { for (QString SnapmaticPic : SnapmaticPics)
{
emit loadingProgress(curFile, maximumV); emit loadingProgress(curFile, maximumV);
const QString picturePath = profileFolder % "/" % SnapmaticPic; QString picturePath = profileFolder % "/" % SnapmaticPic;
SnapmaticPicture *picture = new SnapmaticPicture(picturePath); SnapmaticPicture *picture = new SnapmaticPicture(picturePath);
if (picture->readingPicture(true)) { if (picture->readingPicture(true, true, true))
if (picture->isFormatSwitched()) { {
if (picture->isFormatSwitched())
{
picture->setSnapmaticFormat(SnapmaticFormat::PGTA_Format); picture->setSnapmaticFormat(SnapmaticFormat::PGTA_Format);
if (picture->exportPicture(picturePath, SnapmaticFormat::PGTA_Format)) { if (picture->exportPicture(picturePath, SnapmaticFormat::PGTA_Format))
{
emit pictureFixed(picture); emit pictureFixed(picture);
} }
} }
emit pictureLoaded(picture); emit pictureLoaded(picture);
int crewNumber = picture->getSnapmaticProperties().crewID; int crewNumber = picture->getSnapmaticProperties().crewID;
if (!crewList.contains(crewNumber)) { if (!crewList.contains(crewNumber))
{
crewList += crewNumber; crewList += crewNumber;
} }
} }
@ -117,7 +98,8 @@ void ProfileLoader::run()
// adding found crews // adding found crews
crewDB->setAddingCrews(true); crewDB->setAddingCrews(true);
for (int crewID : qAsConst(crewList)) { for (int crewID : crewList)
{
crewDB->addCrew(crewID); crewDB->addCrew(crewID);
} }
crewDB->setAddingCrews(false); crewDB->setAddingCrews(false);
@ -125,9 +107,10 @@ void ProfileLoader::run()
void ProfileLoader::preloaded() void ProfileLoader::preloaded()
{ {
} }
void ProfileLoader::loaded() void ProfileLoader::loaded()
{ {
}
}

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -48,7 +48,6 @@ signals:
void pictureFixed(SnapmaticPicture *picture); void pictureFixed(SnapmaticPicture *picture);
void savegameLoaded(SavegameData *savegame, QString savegamePath); void savegameLoaded(SavegameData *savegame, QString savegamePath);
void loadingProgress(int value, int maximum); void loadingProgress(int value, int maximum);
void directoryScanned(QVector<QString> savegameFiles, QVector<QString> snapmaticPics);
}; };
#endif // PROFILELOADER_H #endif // PROFILELOADER_H

View file

@ -1,5 +1,5 @@
## gta5view ## gta5view
Open Source Snapmatic and Savegame viewer/editor for GTA V Grand Theft Auto V Savegame and Snapmatic viewer/editor
- View Snapmatics with the ability to disable them in-game - View Snapmatics with the ability to disable them in-game
- Edit Snapmatic pictures and properties in multiple ways - Edit Snapmatic pictures and properties in multiple ways
@ -14,32 +14,40 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V
#### Build gta5view for Windows #### Build gta5view for Windows
# Note: Install Docker Community Edition and Git before continuing # Note: Install Docker Community Edition and Git before continuing
docker pull sypingauto/gta5view-build:1.10-static git clone https://gitlab.com/Syping/gta5view && cd gta5view
git clone https://gitlab.com/Syping/gta5view docker pull sypingauto/gta5view-build:1.8-static
docker run --rm -v "$PWD/gta5view:/gta5view" -it sypingauto/gta5view-build:1.10-static docker run --rm -v ${PWD}:/gta5view -it sypingauto/gta5view-build:1.8-static
mingw64-qt-cmake -B /gta5view/build /gta5view cd /gta5view && mkdir -p build && cd build
cmake --build /gta5view/build mingw64-qt-cmake ../
make -j $(nproc --all)
#### Build gta5view for Debian/Ubuntu #### Build gta5view for Debian/Ubuntu
sudo apt-get install cmake git gcc g++ libqt5svg5-dev make qtbase5-dev qttranslations5-l10n sudo apt-get install cmake git gcc g++ libqt5svg5-dev make qtbase5-dev qttranslations5-l10n
git clone https://gitlab.com/Syping/gta5view git clone https://gitlab.com/Syping/gta5view && cd gta5view
cmake -B gta5view-build gta5view mkdir -p build && cd build
cmake --build gta5view-build cmake ../
sudo cmake --install gta5view-build make -j $(nproc --all)
sudo make install
#### Build gta5view for Arch/Manjaro #### Build gta5view for Arch/Manjaro
sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations
git clone https://gitlab.com/Syping/gta5view git clone https://gitlab.com/Syping/gta5view && cd gta5view
cmake -B gta5view-build gta5view mkdir -p build && cd build
cmake --build gta5view-build cmake ../
sudo cmake --install gta5view-build make -j $(nproc --all)
sudo make install
#### Build gta5view for Fedora/RHEL #### Build gta5view for Fedora
sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations
git clone https://gitlab.com/Syping/gta5view git clone https://gitlab.com/Syping/gta5view && cd gta5view
cmake -B gta5view-build gta5view mkdir -p build && cd build
cmake --build gta5view-build cmake ../
sudo cmake --install gta5view-build make -j $(nproc --all)
sudo make install
#### Download Binary Releases
Go to [gta5view release](https://github.com/SyDevTeam/gta5view/releases) and download the .exe file for Windows, .deb file for Debian/Ubuntu and .dmg file for OS X.

View file

@ -1,893 +0,0 @@
/*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2020-2022 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 "RagePhoto.h"
#include <QJsonDocument>
#include <QBuffer>
#include <QFile>
#if QT_VERSION < 0x060000
#include <QTextCodec>
#else
#include <QStringEncoder>
#include <QStringDecoder>
#endif
#ifdef RAGEPHOTO_BENCHMARK
#include <QFileInfo>
#include <chrono>
#endif
inline quint32 joaatFromSI(const char *data, size_t size)
{
quint32 val = 0xE47AB81CUL;
for (size_t i = 0; i != size; i++) {
val += data[i];
val += (val << 10);
val ^= (val >> 6);
}
val += (val << 3);
val ^= (val >> 11);
val += (val << 15);
return val;
}
RagePhoto::RagePhoto()
{
p_photoFormat = PhotoFormat::Undefined;
p_isLoaded = false;
p_inputMode = -1;
}
RagePhoto::RagePhoto(const QByteArray &data) : p_fileData(data)
{
p_photoFormat = PhotoFormat::Undefined;
p_isLoaded = false;
p_inputMode = 0;
}
RagePhoto::RagePhoto(const QString &filePath) : p_filePath(filePath)
{
p_photoFormat = PhotoFormat::Undefined;
p_isLoaded = false;
p_inputMode = 1;
}
RagePhoto::RagePhoto(QIODevice *ioDevice) : p_ioDevice(ioDevice)
{
p_photoFormat = PhotoFormat::Undefined;
p_isLoaded = false;
p_inputMode = 2;
}
bool RagePhoto::isLoaded()
{
return p_isLoaded;
}
bool RagePhoto::load()
{
if (p_inputMode == -1)
return false;
if (p_isLoaded)
clear();
if (p_inputMode == 1) {
QFile pictureFile(p_filePath);
if (pictureFile.open(QIODevice::ReadOnly)) {
p_fileData = pictureFile.readAll();
}
pictureFile.close();
}
else if (p_inputMode == 2) {
if (!p_ioDevice->isOpen()) {
if (!p_ioDevice->open(QIODevice::ReadOnly))
return false;
}
p_fileData = p_ioDevice->readAll();
}
QBuffer dataBuffer(&p_fileData);
dataBuffer.open(QIODevice::ReadOnly);
#ifdef RAGEPHOTO_BENCHMARK
auto benchmark_parse_start = std::chrono::high_resolution_clock::now();
#endif
char uInt32Buffer[4];
qint64 size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
quint32 format = charToUInt32LE(uInt32Buffer);
if (format == static_cast<quint32>(PhotoFormat::GTA5)) {
char photoHeader[256];
size = dataBuffer.read(photoHeader, 256);
if (size != 256) {
return false;
}
for (const QChar &photoChar : utf16LEToString(photoHeader, 256)) {
if (photoChar.isNull())
break;
p_photoString += photoChar;
}
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_headerSum = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_endOfFile = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_jsonOffset = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_titlOffset = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_descOffset = charToUInt32LE(uInt32Buffer);
char markerBuffer[4];
size = dataBuffer.read(markerBuffer, 4);
if (size != 4)
return false;
if (strncmp(markerBuffer, "JPEG", 4) != 0)
return false;
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_photoBuffer = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
quint32 t_photoSize = charToUInt32LE(uInt32Buffer);
char *photoData = static_cast<char*>(malloc(t_photoSize));
if (!photoData)
return false;
size = dataBuffer.read(photoData, t_photoSize);
if (size != t_photoSize) {
free(photoData);
return false;
}
p_photoData = QByteArray(photoData, t_photoSize);
free(photoData);
dataBuffer.seek(p_jsonOffset + 264);
size = dataBuffer.read(markerBuffer, 4);
if (size != 4)
return false;
if (strncmp(markerBuffer, "JSON", 4) != 0)
return false;
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_jsonBuffer = charToUInt32LE(uInt32Buffer);
char *jsonBytes = static_cast<char*>(malloc(p_jsonBuffer));
if (!jsonBytes)
return false;
size = dataBuffer.read(jsonBytes, p_jsonBuffer);
if (size != p_jsonBuffer) {
free(jsonBytes);
return false;
}
quint32 i;
for (i = 0; i != p_jsonBuffer; i++) {
if (jsonBytes[i] == '\x00')
break;
}
p_jsonData = QByteArray(jsonBytes, i);
free(jsonBytes);
QJsonDocument t_jsonDocument = QJsonDocument::fromJson(p_jsonData);
if (t_jsonDocument.isNull())
return false;
p_jsonObject = t_jsonDocument.object();
dataBuffer.seek(p_titlOffset + 264);
size = dataBuffer.read(markerBuffer, 4);
if (size != 4)
return false;
if (strncmp(markerBuffer, "TITL", 4) != 0)
return false;
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_titlBuffer = charToUInt32LE(uInt32Buffer);
char *titlBytes = static_cast<char*>(malloc(p_titlBuffer));
if (!titlBytes)
return false;
size = dataBuffer.read(titlBytes, p_titlBuffer);
if (size != p_titlBuffer){
free(titlBytes);
return false;
}
for (i = 0; i != p_titlBuffer; i++) {
if (titlBytes[i] == '\x00')
break;
}
p_titleString = QString::fromUtf8(titlBytes, i);
free(titlBytes);
dataBuffer.seek(p_descOffset + 264);
size = dataBuffer.read(markerBuffer, 4);
if (size != 4)
return false;
if (strncmp(markerBuffer, "DESC", 4) != 0)
return false;
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_descBuffer = charToUInt32LE(uInt32Buffer);
char *descBytes = static_cast<char*>(malloc(p_descBuffer));
if (!descBytes)
return false;
size = dataBuffer.read(descBytes, p_descBuffer);
if (size != p_descBuffer) {
free(descBytes);
return false;
}
for (i = 0; i != p_descBuffer; i++) {
if (descBytes[i] == '\x00')
break;
}
p_descriptionString = QString::fromUtf8(descBytes, i);
free(descBytes);
dataBuffer.seek(p_endOfFile + 260);
size = dataBuffer.read(markerBuffer, 4);
if (size != 4)
return false;
if (strncmp(markerBuffer, "JEND", 4) != 0)
return false;
#ifdef RAGEPHOTO_BENCHMARK
auto benchmark_parse_end = std::chrono::high_resolution_clock::now();
auto benchmark_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark_parse_end - benchmark_parse_start);
if (p_inputMode == 1) {
QTextStream(stdout) << QFileInfo(p_filePath).fileName() << ": " << benchmark_ns.count() << "ns" << Qt::endl;
}
else {
QTextStream(stdout) << "PGTA5" << p_jsonObject.value("uid").toInt() << ": " << benchmark_ns.count() << "ns" << Qt::endl;
}
#endif
if (p_photoFormat != PhotoFormat::G5EX)
p_photoFormat = PhotoFormat::GTA5;
p_fileData.clear();
p_isLoaded = true;
return true;
}
else if (format == static_cast<quint32>(PhotoFormat::G5EX)) {
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
format = charToUInt32LE(uInt32Buffer);
if (format == static_cast<quint32>(ExportFormat::G5E3P)) {
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
quint32 compressedSize = charToUInt32LE(uInt32Buffer);
char *compressedPhotoHeader = static_cast<char*>(malloc(compressedSize));
if (!compressedPhotoHeader)
return false;
size = dataBuffer.read(compressedPhotoHeader, compressedSize);
if (size != compressedSize) {
free(compressedPhotoHeader);
return false;
}
QByteArray t_photoHeader = QByteArray::fromRawData(compressedPhotoHeader, compressedSize);
t_photoHeader = qUncompress(t_photoHeader);
free(compressedPhotoHeader);
if (t_photoHeader.isEmpty())
return false;
p_photoString = QString::fromUtf8(t_photoHeader);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_headerSum = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_photoBuffer = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
compressedSize = charToUInt32LE(uInt32Buffer);
char *compressedPhoto = static_cast<char*>(malloc(compressedSize));
if (!compressedPhoto)
return false;
size = dataBuffer.read(compressedPhoto, compressedSize);
if (size != compressedSize) {
free(compressedPhoto);
return false;
}
QByteArray t_photoData = QByteArray::fromRawData(compressedPhoto, compressedSize);
p_photoData = qUncompress(t_photoData);
free(compressedPhoto);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_jsonOffset = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_jsonBuffer = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
compressedSize = charToUInt32LE(uInt32Buffer);
char *compressedJson = static_cast<char*>(malloc(compressedSize));
if (!compressedJson)
return false;
size = dataBuffer.read(compressedJson, compressedSize);
if (size != compressedSize) {
free(compressedJson);
return false;
}
QByteArray t_jsonBytes = QByteArray::fromRawData(compressedJson, compressedSize);
p_jsonData = qUncompress(t_jsonBytes);
free(compressedJson);
if (p_jsonData.isEmpty())
return false;
QJsonDocument t_jsonDocument = QJsonDocument::fromJson(p_jsonData);
if (t_jsonDocument.isNull())
return false;
p_jsonObject = t_jsonDocument.object();
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_titlOffset = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_titlBuffer = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
compressedSize = charToUInt32LE(uInt32Buffer);
char *compressedTitl = static_cast<char*>(malloc(compressedSize));
if (!compressedTitl)
return false;
size = dataBuffer.read(compressedTitl, compressedSize);
if (size != compressedSize) {
free(compressedTitl);
return false;
}
QByteArray t_titlBytes = QByteArray::fromRawData(compressedTitl, compressedSize);
t_titlBytes = qUncompress(t_titlBytes);
free(compressedTitl);
p_titleString = QString::fromUtf8(t_titlBytes);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_descOffset = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_descBuffer = charToUInt32LE(uInt32Buffer);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
compressedSize = charToUInt32LE(uInt32Buffer);
char *compressedDesc = static_cast<char*>(malloc(compressedSize));
if (!compressedDesc)
return false;
size = dataBuffer.read(compressedDesc, compressedSize);
if (size != compressedSize) {
free(compressedDesc);
return false;
}
QByteArray t_descBytes = QByteArray::fromRawData(compressedDesc, compressedSize);
t_descBytes = qUncompress(t_descBytes);
free(compressedDesc);
p_descriptionString = QString::fromUtf8(t_descBytes);
size = dataBuffer.read(uInt32Buffer, 4);
if (size != 4)
return false;
p_endOfFile = charToUInt32LE(uInt32Buffer);
#ifdef RAGEPHOTO_BENCHMARK
auto benchmark_parse_end = std::chrono::high_resolution_clock::now();
auto benchmark_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(benchmark_parse_end - benchmark_parse_start);
if (p_inputMode == 1) {
QTextStream(stdout) << QFileInfo(p_filePath).fileName() << ": " << benchmark_ns.count() << "ns" << Qt::endl;
}
else {
QTextStream(stdout) << "PGTA5" << p_jsonObject.value("uid").toInt() << ": " << benchmark_ns.count() << "ns" << Qt::endl;
}
#endif
p_photoFormat = PhotoFormat::G5EX;
p_fileData.clear();
p_isLoaded = true;
return true;
}
else if (format == static_cast<quint32>(ExportFormat::G5E2P)) {
p_photoFormat = PhotoFormat::G5EX;
p_fileData = qUncompress(dataBuffer.readAll());
if (p_fileData.isEmpty())
return false;
p_inputMode = 0;
return load();
}
else if (format == static_cast<quint32>(ExportFormat::G5E1P)) {
#if QT_VERSION >= 0x050A00
size = dataBuffer.skip(1);
if (size != 1)
return false;
#else
if (!dataBuffer.seek(dataBuffer.pos() + 1))
return false;
#endif
char length[1];
size = dataBuffer.read(length, 1);
if (size != 1)
return false;
int i_length = QByteArray::number(static_cast<int>(length[0]), 16).toInt() + 6;
#if QT_VERSION >= 0x050A00
size = dataBuffer.skip(i_length);
if (size != i_length)
return false;
#else
if (!dataBuffer.seek(dataBuffer.pos() + i_length))
return false;
#endif
p_photoFormat = PhotoFormat::G5EX;
p_fileData = qUncompress(dataBuffer.readAll());
if (p_fileData.isEmpty())
return false;
p_inputMode = 0;
return load();
}
else {
return false;
}
}
else {
return false;
}
}
void RagePhoto::clear()
{
p_photoFormat = PhotoFormat::Undefined;
p_jsonObject = QJsonObject();
p_descriptionString.clear();
p_jsonData.clear();
p_photoData.clear();
p_photoString.clear();
p_titleString.clear();
p_headerSum = 0;
p_isLoaded = false;
}
void RagePhoto::setDescription(const QString &description)
{
p_descriptionString = description;
}
void RagePhoto::setFileData(const QByteArray &data)
{
p_fileData = data;
p_inputMode = 0;
}
void RagePhoto::setFilePath(const QString &filePath)
{
p_filePath = filePath;
p_inputMode = 1;
}
void RagePhoto::setIODevice(QIODevice *ioDevice)
{
p_ioDevice = ioDevice;
p_inputMode = 2;
}
bool RagePhoto::setJsonData(const QByteArray &data)
{
QJsonDocument t_jsonDocument = QJsonDocument::fromJson(data);
if (t_jsonDocument.isNull())
return false;
p_jsonObject = t_jsonDocument.object();
// serializer band-aid
QJsonObject t_jsonObject = p_jsonObject;
t_jsonObject["sign"] = "__gta5view.sign";
t_jsonDocument.setObject(t_jsonObject);
p_jsonData = t_jsonDocument.toJson(QJsonDocument::Compact);
char sign_char[24];
sprintf(sign_char, "%llu", (0x100000000000000ULL | joaatFromSI(p_photoData.constData(), p_photoData.size())));
p_jsonData.replace("\"__gta5view.sign\"", sign_char);
return true;
}
bool RagePhoto::setPhotoBuffer(quint32 size, bool moveOffsets)
{
if (size < static_cast<quint32>(p_photoData.size()))
return false;
p_photoBuffer = size;
if (moveOffsets) {
p_jsonOffset = size + 28;
p_titlOffset = p_jsonOffset + p_jsonBuffer + 8;
p_descOffset = p_titlOffset + p_titlBuffer + 8;
p_endOfFile = p_descOffset + p_descBuffer + 12;
}
return true;
}
bool RagePhoto::setPhotoData(const QByteArray &data)
{
quint32 size = data.size();
if (size > p_photoBuffer)
return false;
p_photoData = data;
// serializer band-aid
setJsonData(p_jsonData);
return true;
}
bool RagePhoto::setPhotoData(const char *data, int size)
{
if (static_cast<quint32>(size) > p_photoBuffer)
return false;
p_photoData = QByteArray(data, size);
// serializer band-aid
setJsonData(p_jsonData);
return true;
}
void RagePhoto::setPhotoFormat(PhotoFormat photoFormat)
{
p_photoFormat = photoFormat;
}
void RagePhoto::setTitle(const QString &title)
{
p_titleString = title;
}
const QByteArray RagePhoto::jsonData(JsonFormat jsonFormat)
{
if (jsonFormat == JsonFormat::Compact) {
return QJsonDocument(p_jsonObject).toJson(QJsonDocument::Compact);
}
else if (jsonFormat == JsonFormat::Indented) {
return QJsonDocument(p_jsonObject).toJson(QJsonDocument::Indented);
}
else {
return p_jsonData;
}
}
const QJsonObject RagePhoto::jsonObject()
{
return p_jsonObject;
}
const QByteArray RagePhoto::photoData()
{
return p_photoData;
}
const QString RagePhoto::description()
{
return p_descriptionString;
}
const QString RagePhoto::photoString()
{
return p_photoString;
}
const QString RagePhoto::title()
{
return p_titleString;
}
quint32 RagePhoto::photoBuffer()
{
return p_photoBuffer;
}
quint32 RagePhoto::photoSize()
{
return p_photoData.size();
}
RagePhoto::PhotoFormat RagePhoto::photoFormat()
{
return p_photoFormat;
}
QByteArray RagePhoto::save(PhotoFormat photoFormat)
{
QByteArray data;
QBuffer dataBuffer(&data);
dataBuffer.open(QIODevice::WriteOnly);
save(&dataBuffer, photoFormat);
return data;
}
void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat)
{
// serializer band-aid
setJsonData(p_jsonData);
if (photoFormat == PhotoFormat::G5EX) {
char uInt32Buffer[4];
quint32 format = static_cast<quint32>(PhotoFormat::G5EX);
uInt32ToCharLE(format, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
format = static_cast<quint32>(ExportFormat::G5E3P);
uInt32ToCharLE(format, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
QByteArray compressedData = qCompress(p_photoString.toUtf8(), 9);
quint32 compressedSize = compressedData.size();
uInt32ToCharLE(compressedSize, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write(compressedData);
uInt32ToCharLE(p_headerSum, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_photoBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
compressedData = qCompress(p_photoData, 9);
compressedSize = compressedData.size();
uInt32ToCharLE(compressedSize, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write(compressedData);
uInt32ToCharLE(p_jsonOffset, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_jsonBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
compressedData = qCompress(p_jsonData, 9);
compressedSize = compressedData.size();
uInt32ToCharLE(compressedSize, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write(compressedData);
uInt32ToCharLE(p_titlOffset, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_titlBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
compressedData = qCompress(p_titleString.toUtf8(), 9);
compressedSize = compressedData.size();
uInt32ToCharLE(compressedSize, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write(compressedData);
uInt32ToCharLE(p_descOffset, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_descBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
compressedData = qCompress(p_descriptionString.toUtf8(), 9);
compressedSize = compressedData.size();
uInt32ToCharLE(compressedSize, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write(compressedData);
uInt32ToCharLE(p_endOfFile, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
}
else if (photoFormat == PhotoFormat::GTA5) {
char uInt32Buffer[4];
quint32 format = static_cast<quint32>(PhotoFormat::GTA5);
uInt32ToCharLE(format, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
QByteArray photoHeader = stringToUtf16LE(p_photoString);
if (photoHeader.startsWith("\xFF\xFE")) {
photoHeader.remove(0, 2);
}
qint64 photoHeaderSize = photoHeader.size();
if (photoHeaderSize > 256) {
photoHeader = photoHeader.left(256);
photoHeaderSize = 256;
}
ioDevice->write(photoHeader);
for (qint64 size = photoHeaderSize; size < 256; size++) {
ioDevice->write("\x00", 1);
}
uInt32ToCharLE(p_headerSum, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_endOfFile, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_jsonOffset, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_titlOffset, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
uInt32ToCharLE(p_descOffset, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write("JPEG", 4);
uInt32ToCharLE(p_photoBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
quint32 t_photoSize = p_photoData.size();
uInt32ToCharLE(t_photoSize, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
ioDevice->write(p_photoData);
for (qint64 size = t_photoSize; size < p_photoBuffer; size++) {
ioDevice->write("\x00", 1);
}
ioDevice->seek(p_jsonOffset + 264);
ioDevice->write("JSON", 4);
uInt32ToCharLE(p_jsonBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
qint64 dataSize = p_jsonData.size();
ioDevice->write(p_jsonData);
for (qint64 size = dataSize; size < p_jsonBuffer; size++) {
ioDevice->write("\x00", 1);
}
ioDevice->seek(p_titlOffset + 264);
ioDevice->write("TITL", 4);
uInt32ToCharLE(p_titlBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
QByteArray data = p_titleString.toUtf8();
dataSize = data.size();
ioDevice->write(data);
for (qint64 size = dataSize; size < p_titlBuffer; size++) {
ioDevice->write("\x00", 1);
}
ioDevice->seek(p_descOffset + 264);
ioDevice->write("DESC", 4);
uInt32ToCharLE(p_descBuffer, uInt32Buffer);
ioDevice->write(uInt32Buffer, 4);
data = p_descriptionString.toUtf8();
dataSize = data.size();
ioDevice->write(data);
for (qint64 size = dataSize; size < p_descBuffer; size++) {
ioDevice->write("\x00", 1);
}
ioDevice->seek(p_endOfFile + 260);
ioDevice->write("JEND", 4);
}
}
RagePhoto* RagePhoto::loadFile(const QString &filePath)
{
RagePhoto *ragePhoto = new RagePhoto(filePath);
ragePhoto->load();
return ragePhoto;
}
quint32 RagePhoto::charToUInt32BE(char *x)
{
return (static_cast<unsigned char>(x[0]) << 24 |
static_cast<unsigned char>(x[1]) << 16 |
static_cast<unsigned char>(x[2]) << 8 |
static_cast<unsigned char>(x[3]));
}
quint32 RagePhoto::charToUInt32LE(char *x)
{
return (static_cast<unsigned char>(x[3]) << 24 |
static_cast<unsigned char>(x[2]) << 16 |
static_cast<unsigned char>(x[1]) << 8 |
static_cast<unsigned char>(x[0]));
}
void RagePhoto::uInt32ToCharBE(quint32 x, char *y)
{
y[0] = x >> 24;
y[1] = x >> 16;
y[2] = x >> 8;
y[3] = x;
}
void RagePhoto::uInt32ToCharLE(quint32 x, char *y)
{
y[0] = x;
y[1] = x >> 8;
y[2] = x >> 16;
y[3] = x >> 24;
}
const QByteArray RagePhoto::stringToUtf16LE(const QString &string)
{
#if QT_VERSION >= 0x060000
return QStringEncoder(QStringEncoder::Utf16LE)(string);
#else
return QTextCodec::codecForName("UTF-16LE")->fromUnicode(string);
#endif
}
const QString RagePhoto::utf16LEToString(const QByteArray &data)
{
#if QT_VERSION >= 0x060000
return QStringDecoder(QStringDecoder::Utf16LE)(data);
#else
return QTextCodec::codecForName("UTF-16LE")->toUnicode(data);
#endif
}
const QString RagePhoto::utf16LEToString(const char *data, int size)
{
#if QT_VERSION >= 0x060000
return QStringDecoder(QStringDecoder::Utf16LE)(QByteArray::fromRawData(data, size));
#else
return QTextCodec::codecForName("UTF-16LE")->toUnicode(data, size);
#endif
}

View file

@ -1,110 +0,0 @@
/*****************************************************************************
* 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/>.
*****************************************************************************/
#ifndef RAGEPHOTO_H
#define RAGEPHOTO_H
#include <QJsonObject>
#include <QIODevice>
#include <QObject>
class RagePhoto : public QObject
{
Q_OBJECT
public:
enum class JsonFormat : quint8 {
Original = 0,
Compact = 1,
Indented = 2,
};
enum class ExportFormat : quint32 {
G5E1P = 0x454C0010U,
G5E2P = 0x01000032U,
G5E2S = 0x02000032U,
G5E3P = 0x01000033U,
G5E3S = 0x02000033U,
Undefined = 0,
};
enum class PhotoFormat : quint32 {
G5EX = 0x45354700U,
GTA5 = 0x01000000U,
RDR2 = 0x04000000U,
Undefined = 0,
};
explicit RagePhoto();
explicit RagePhoto(const QByteArray &data);
explicit RagePhoto(const QString &filePath);
explicit RagePhoto(QIODevice *ioDevice);
bool isLoaded();
bool load();
void clear();
void setDescription(const QString &description);
void setFileData(const QByteArray &data);
void setFilePath(const QString &filePath);
void setIODevice(QIODevice *ioDevice);
bool setJsonData(const QByteArray &data);
bool setPhotoBuffer(quint32 size, bool moveOffsets = true);
bool setPhotoData(const QByteArray &data);
bool setPhotoData(const char *data, int size);
void setPhotoFormat(PhotoFormat photoFormat);
void setTitle(const QString &title);
const QJsonObject jsonObject();
const QByteArray jsonData(JsonFormat jsonFormat = JsonFormat::Original);
const QByteArray photoData();
const QString description();
const QString photoString();
const QString title();
quint32 photoBuffer();
quint32 photoSize();
PhotoFormat photoFormat();
QByteArray save(PhotoFormat photoFormat);
void save(QIODevice *ioDevice, PhotoFormat photoFormat);
static RagePhoto* loadFile(const QString &filePath);
private:
inline quint32 charToUInt32BE(char *x);
inline quint32 charToUInt32LE(char *x);
inline void uInt32ToCharBE(quint32 x, char *y);
inline void uInt32ToCharLE(quint32 x, char *y);
inline const QByteArray stringToUtf16LE(const QString &string);
inline const QString utf16LEToString(const QByteArray &data);
inline const QString utf16LEToString(const char *data, int size);
PhotoFormat p_photoFormat;
QJsonObject p_jsonObject;
QByteArray p_fileData;
QByteArray p_jsonData;
QByteArray p_photoData;
QIODevice *p_ioDevice;
QString p_descriptionString;
QString p_filePath;
QString p_photoString;
QString p_titleString;
quint32 p_descBuffer;
quint32 p_descOffset;
quint32 p_endOfFile;
quint32 p_headerSum;
quint32 p_jsonBuffer;
quint32 p_jsonOffset;
quint32 p_photoBuffer;
quint32 p_titlBuffer;
quint32 p_titlOffset;
bool p_isLoaded;
int p_inputMode;
};
#endif // RAGEPHOTO_H

View file

@ -28,11 +28,7 @@ SavegameDialog::SavegameDialog(QWidget *parent) :
ui(new Ui::SavegameDialog) ui(new Ui::SavegameDialog)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
// Setup User Interface // Setup User Interface
ui->setupUi(this); ui->setupUi(this);

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>112</height> <height>105</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -20,7 +20,7 @@
<item> <item>
<widget class="QLabel" name="labSavegameText"> <widget class="QLabel" name="labSavegameText">
<property name="text"> <property name="text">
<string>&lt;span style=&quot;font-weight:600&quot;&gt;Savegame&lt;/span&gt;&lt;br&gt;&lt;br&gt;%1</string> <string>&lt;span style=&quot; font-weight:600;&quot;&gt;Savegame&lt;/span&gt;&lt;br&gt;&lt;br&gt;%1</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2018 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -25,7 +25,6 @@
#include "SavegameCopy.h" #include "SavegameCopy.h"
#include "AppEnv.h" #include "AppEnv.h"
#include "config.h" #include "config.h"
#include <QStringBuilder>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
@ -60,7 +59,7 @@ SavegameWidget::SavegameWidget(QWidget *parent) :
ui->labSavegamePic->setFixedSize(48 * screenRatio, 27 * screenRatio); ui->labSavegamePic->setFixedSize(48 * screenRatio, 27 * screenRatio);
ui->labSavegamePic->setScaledContents(true); ui->labSavegamePic->setScaledContents(true);
ui->labSavegamePic->setPixmap(QPixmap(AppEnv::getImagesFolder() % "/savegame.svgz")); ui->labSavegamePic->setPixmap(QPixmap(":/img/savegame.svgz"));
QString exportSavegameStr = tr("Export Savegame..."); QString exportSavegameStr = tr("Export Savegame...");
Q_UNUSED(exportSavegameStr) Q_UNUSED(exportSavegameStr)
@ -153,11 +152,7 @@ void SavegameWidget::on_cmdDelete_clicked()
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "DeleteSuccess"; jsonObject["Type"] = "DeleteSuccess";
jsonObject["ExtraFlags"] = "Savegame"; jsonObject["ExtraFlags"] = "Savegame";
#if QT_VERSION >= 0x060000
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
@ -176,11 +171,7 @@ void SavegameWidget::on_cmdDelete_clicked()
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "DeleteSuccess"; jsonObject["Type"] = "DeleteSuccess";
jsonObject["ExtraFlags"] = "Savegame"; jsonObject["ExtraFlags"] = "Savegame";
#if QT_VERSION >= 0x060000
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
@ -226,8 +217,7 @@ void SavegameWidget::mouseReleaseEvent(QMouseEvent *ev)
} }
else else
{ {
const int contentMode = getContentMode(); if (getContentMode() == 0 && rect().contains(ev->pos()) && ev->button() == Qt::LeftButton)
if ((contentMode == 0 || contentMode == 10 || contentMode == 20) && rect().contains(ev->pos()) && ev->button() == Qt::LeftButton)
{ {
if (ev->modifiers().testFlag(Qt::ShiftModifier)) if (ev->modifiers().testFlag(Qt::ShiftModifier))
{ {
@ -238,7 +228,7 @@ void SavegameWidget::mouseReleaseEvent(QMouseEvent *ev)
on_cmdView_clicked(); on_cmdView_clicked();
} }
} }
else if (!ui->cbSelected->isVisible() && (contentMode == 1 || contentMode == 11 || contentMode == 21) && ev->button() == Qt::LeftButton && ev->modifiers().testFlag(Qt::ShiftModifier)) else if (!ui->cbSelected->isVisible() && getContentMode() == 1 && ev->button() == Qt::LeftButton && ev->modifiers().testFlag(Qt::ShiftModifier))
{ {
ui->cbSelected->setChecked(!ui->cbSelected->isChecked()); ui->cbSelected->setChecked(!ui->cbSelected->isChecked());
} }
@ -249,8 +239,7 @@ void SavegameWidget::mouseDoubleClickEvent(QMouseEvent *ev)
{ {
ProfileWidget::mouseDoubleClickEvent(ev); ProfileWidget::mouseDoubleClickEvent(ev);
const int contentMode = getContentMode(); if (!ui->cbSelected->isVisible() && getContentMode() == 1 && ev->button() == Qt::LeftButton)
if (!ui->cbSelected->isVisible() && (contentMode == 1 || contentMode == 11 || contentMode == 21) && ev->button() == Qt::LeftButton)
{ {
on_cmdView_clicked(); on_cmdView_clicked();
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2018 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -21,7 +21,6 @@
#include "SnapmaticPicture.h" #include "SnapmaticPicture.h"
#include "PlayerListDialog.h" #include "PlayerListDialog.h"
#include "StringParser.h" #include "StringParser.h"
#include "wrapper.h"
#include "AppEnv.h" #include "AppEnv.h"
#include "config.h" #include "config.h"
#include <QStringBuilder> #include <QStringBuilder>
@ -42,38 +41,41 @@ SnapmaticEditor::SnapmaticEditor(CrewDatabase *crewDB, ProfileDatabase *profileD
ui(new Ui::SnapmaticEditor) ui(new Ui::SnapmaticEditor)
{ {
// Set Window Flags // Set Window Flags
#if QT_VERSION >= 0x050900
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
ui->setupUi(this); ui->setupUi(this);
ui->cmdCancel->setDefault(true); ui->cmdCancel->setDefault(true);
ui->cmdCancel->setFocus(); ui->cmdCancel->setFocus();
// Set Icon for Apply Button // Set Icon for Apply Button
if (QIcon::hasThemeIcon("dialog-ok-apply")) { if (QIcon::hasThemeIcon("dialog-ok-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok-apply")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok-apply"));
} }
else if (QIcon::hasThemeIcon("dialog-apply")) { else if (QIcon::hasThemeIcon("dialog-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-apply")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-apply"));
} }
else if (QIcon::hasThemeIcon("gtk-apply")) { else if (QIcon::hasThemeIcon("gtk-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("gtk-apply")); ui->cmdApply->setIcon(QIcon::fromTheme("gtk-apply"));
} }
else if (QIcon::hasThemeIcon("dialog-ok")) { else if (QIcon::hasThemeIcon("dialog-ok"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok"));
} }
else if (QIcon::hasThemeIcon("gtk-ok")) { else if (QIcon::hasThemeIcon("gtk-ok"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok")); ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok"));
} }
// Set Icon for Cancel Button // Set Icon for Cancel Button
if (QIcon::hasThemeIcon("dialog-cancel")) { if (QIcon::hasThemeIcon("dialog-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
} }
else if (QIcon::hasThemeIcon("gtk-cancel")) { else if (QIcon::hasThemeIcon("gtk-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel")); ui->cmdCancel->setIcon(QIcon::fromTheme("gtk-cancel"));
} }
@ -94,18 +96,27 @@ SnapmaticEditor::~SnapmaticEditor()
void SnapmaticEditor::selfie_toggled(bool checked) void SnapmaticEditor::selfie_toggled(bool checked)
{ {
isSelfie = checked; if (checked)
{
isSelfie = true;
}
else
{
isSelfie = false;
}
} }
void SnapmaticEditor::mugshot_toggled(bool checked) void SnapmaticEditor::mugshot_toggled(bool checked)
{ {
if (checked) { if (checked)
{
isMugshot = true; isMugshot = true;
ui->cbDirector->setEnabled(false); ui->cbDirector->setEnabled(false);
ui->cbDirector->setChecked(false); ui->cbDirector->setChecked(false);
} }
else { else
{
isMugshot = false; isMugshot = false;
ui->cbDirector->setEnabled(true); ui->cbDirector->setEnabled(true);
} }
@ -113,12 +124,14 @@ void SnapmaticEditor::mugshot_toggled(bool checked)
void SnapmaticEditor::editor_toggled(bool checked) void SnapmaticEditor::editor_toggled(bool checked)
{ {
if (checked) { if (checked)
{
isEditor = true; isEditor = true;
ui->cbDirector->setEnabled(false); ui->cbDirector->setEnabled(false);
ui->cbDirector->setChecked(false); ui->cbDirector->setChecked(false);
} }
else { else
{
isEditor = false; isEditor = false;
ui->cbDirector->setEnabled(true); ui->cbDirector->setEnabled(true);
} }
@ -126,7 +139,8 @@ void SnapmaticEditor::editor_toggled(bool checked)
void SnapmaticEditor::on_rbSelfie_toggled(bool checked) void SnapmaticEditor::on_rbSelfie_toggled(bool checked)
{ {
if (checked) { if (checked)
{
mugshot_toggled(false); mugshot_toggled(false);
editor_toggled(false); editor_toggled(false);
selfie_toggled(true); selfie_toggled(true);
@ -135,7 +149,8 @@ void SnapmaticEditor::on_rbSelfie_toggled(bool checked)
void SnapmaticEditor::on_rbMugshot_toggled(bool checked) void SnapmaticEditor::on_rbMugshot_toggled(bool checked)
{ {
if (checked) { if (checked)
{
selfie_toggled(false); selfie_toggled(false);
editor_toggled(false); editor_toggled(false);
mugshot_toggled(true); mugshot_toggled(true);
@ -144,7 +159,8 @@ void SnapmaticEditor::on_rbMugshot_toggled(bool checked)
void SnapmaticEditor::on_rbEditor_toggled(bool checked) void SnapmaticEditor::on_rbEditor_toggled(bool checked)
{ {
if (checked) { if (checked)
{
selfie_toggled(false); selfie_toggled(false);
mugshot_toggled(false); mugshot_toggled(false);
editor_toggled(true); editor_toggled(true);
@ -153,7 +169,8 @@ void SnapmaticEditor::on_rbEditor_toggled(bool checked)
void SnapmaticEditor::on_rbCustom_toggled(bool checked) void SnapmaticEditor::on_rbCustom_toggled(bool checked)
{ {
if (checked) { if (checked)
{
selfie_toggled(false); selfie_toggled(false);
mugshot_toggled(false); mugshot_toggled(false);
editor_toggled(false); editor_toggled(false);
@ -172,16 +189,20 @@ void SnapmaticEditor::setSnapmaticPicture(SnapmaticPicture *picture)
playersList = snapmaticProperties.playersList; playersList = snapmaticProperties.playersList;
ui->cbDirector->setChecked(snapmaticProperties.isFromDirector); ui->cbDirector->setChecked(snapmaticProperties.isFromDirector);
ui->cbMeme->setChecked(snapmaticProperties.isMeme); ui->cbMeme->setChecked(snapmaticProperties.isMeme);
if (isSelfie) { if (isSelfie)
{
ui->rbSelfie->setChecked(true); ui->rbSelfie->setChecked(true);
} }
else if (isMugshot) { else if (isMugshot)
{
ui->rbMugshot->setChecked(true); ui->rbMugshot->setChecked(true);
} }
else if (isEditor) { else if (isEditor)
{
ui->rbEditor->setChecked(true); ui->rbEditor->setChecked(true);
} }
else { else
{
ui->rbCustom->setChecked(true); ui->rbCustom->setChecked(true);
} }
setSnapmaticCrew(returnCrewName(crewID)); setSnapmaticCrew(returnCrewName(crewID));
@ -191,7 +212,8 @@ void SnapmaticEditor::setSnapmaticPicture(SnapmaticPicture *picture)
void SnapmaticEditor::insertPlayerNames(QStringList *players) void SnapmaticEditor::insertPlayerNames(QStringList *players)
{ {
for (int i = 0; i < players->size(); ++i) { for (int i = 0; i < players->size(); ++i)
{
players->replace(i, profileDB->getPlayerName(players->at(i))); players->replace(i, profileDB->getPlayerName(players->at(i)));
} }
} }
@ -207,48 +229,54 @@ void SnapmaticEditor::setSnapmaticPlayers(const QStringList &players)
{ {
QString editStr = QString("<a href=\"g5e://editplayers\" style=\"text-decoration: none;\">%1</a>").arg(tr("Edit")); QString editStr = QString("<a href=\"g5e://editplayers\" style=\"text-decoration: none;\">%1</a>").arg(tr("Edit"));
QString playersStr; QString playersStr;
if (players.length() != 1) { if (players.length() != 1)
{
playersStr = tr("Players: %1 (%2)", "Multiple Player are inserted here"); playersStr = tr("Players: %1 (%2)", "Multiple Player are inserted here");
} }
else { else
{
playersStr = tr("Player: %1 (%2)", "One Player is inserted here"); playersStr = tr("Player: %1 (%2)", "One Player is inserted here");
} }
if (players.length() != 0) { if (players.length() != 0)
{
ui->labPlayers->setText(playersStr.arg(players.join(", "), editStr)); ui->labPlayers->setText(playersStr.arg(players.join(", "), editStr));
} }
else { else
{
ui->labPlayers->setText(playersStr.arg(QApplication::translate("PictureDialog", "No Players"), editStr)); ui->labPlayers->setText(playersStr.arg(QApplication::translate("PictureDialog", "No Players"), editStr));
} }
#ifndef Q_OS_ANDROID #ifndef Q_OS_ANDROID
ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width())); ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width()));
ui->frameWidget->resize(ui->gbValues->width(), ui->frameWidget->heightForWidth(ui->frameWidget->width())); ui->frameWidget->resize(ui->gbValues->width(), ui->frameWidget->heightForWidth(ui->frameWidget->width()));
if (heightForWidth(width()) > height()) if (heightForWidth(width()) > height()) { resize(width(), heightForWidth(width())); }
resize(width(), heightForWidth(width()));
#endif #endif
} }
void SnapmaticEditor::setSnapmaticTitle(const QString &title) void SnapmaticEditor::setSnapmaticTitle(const QString &title)
{ {
if (title.length() > 39) { if (title.length() > 39)
{
snapmaticTitle = title.left(39); snapmaticTitle = title.left(39);
} }
else { else
{
snapmaticTitle = title; snapmaticTitle = title;
} }
QString editStr = QString("<a href=\"g5e://edittitle\" style=\"text-decoration: none;\">%1</a>").arg(tr("Edit")); QString editStr = QString("<a href=\"g5e://edittitle\" style=\"text-decoration: none;\">%1</a>").arg(tr("Edit"));
QString titleStr = tr("Title: %1 (%2)").arg(StringParser::escapeString(snapmaticTitle), editStr); QString titleStr = tr("Title: %1 (%2)").arg(StringParser::escapeString(snapmaticTitle), editStr);
ui->labTitle->setText(titleStr); ui->labTitle->setText(titleStr);
if (SnapmaticPicture::verifyTitle(snapmaticTitle)) { if (SnapmaticPicture::verifyTitle(snapmaticTitle))
{
ui->labAppropriate->setText(tr("Appropriate: %1").arg(QString("<span style=\"color: green\">%1</span>").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 { else
{
ui->labAppropriate->setText(tr("Appropriate: %1").arg(QString("<span style=\"color: red\">%1</span>").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 #ifndef Q_OS_ANDROID
ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width())); ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width()));
ui->frameWidget->resize(ui->gbValues->width(), ui->frameWidget->heightForWidth(ui->frameWidget->width())); ui->frameWidget->resize(ui->gbValues->width(), ui->frameWidget->heightForWidth(ui->frameWidget->width()));
if (heightForWidth(width()) > height()) if (heightForWidth(width()) > height()) { resize(width(), heightForWidth(width())); }
resize(width(), heightForWidth(width()));
#endif #endif
} }
@ -260,8 +288,7 @@ void SnapmaticEditor::setSnapmaticCrew(const QString &crew)
#ifndef Q_OS_ANDROID #ifndef Q_OS_ANDROID
ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width())); ui->gbValues->resize(ui->gbValues->width(), ui->gbValues->heightForWidth(ui->gbValues->width()));
ui->frameWidget->resize(ui->gbValues->width(), ui->frameWidget->heightForWidth(ui->frameWidget->width())); ui->frameWidget->resize(ui->gbValues->width(), ui->frameWidget->heightForWidth(ui->frameWidget->width()));
if (heightForWidth(width()) > height()) if (heightForWidth(width()) > height()) { resize(width(), heightForWidth(width())); }
resize(width(), heightForWidth(width()));
#endif #endif
} }
@ -277,7 +304,8 @@ void SnapmaticEditor::on_cmdCancel_clicked()
void SnapmaticEditor::on_cmdApply_clicked() void SnapmaticEditor::on_cmdApply_clicked()
{ {
if (ui->cbQualify->isChecked()) { if (ui->cbQualify->isChecked())
{
qualifyAvatar(); qualifyAvatar();
} }
snapmaticProperties.crewID = crewID; snapmaticProperties.crewID = crewID;
@ -287,23 +315,27 @@ void SnapmaticEditor::on_cmdApply_clicked()
snapmaticProperties.isFromDirector = ui->cbDirector->isChecked(); snapmaticProperties.isFromDirector = ui->cbDirector->isChecked();
snapmaticProperties.isMeme = ui->cbMeme->isChecked(); snapmaticProperties.isMeme = ui->cbMeme->isChecked();
snapmaticProperties.playersList = playersList; snapmaticProperties.playersList = playersList;
if (smpic) { if (smpic)
{
QString currentFilePath = smpic->getPictureFilePath(); QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath(); QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak"; QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) { if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName); QFile::copy(currentFilePath, backupFileName);
} }
SnapmaticProperties fallbackProperties = smpic->getSnapmaticProperties(); SnapmaticProperties fallbackProperties = smpic->getSnapmaticProperties();
QString fallbackTitle = smpic->getPictureTitle(); QString fallbackTitle = smpic->getPictureTitle();
smpic->setSnapmaticProperties(snapmaticProperties); smpic->setSnapmaticProperties(snapmaticProperties);
smpic->setPictureTitle(snapmaticTitle); smpic->setPictureTitle(snapmaticTitle);
if (!smpic->exportPicture(currentFilePath)) { if (!smpic->exportPicture(currentFilePath))
{
QMessageBox::warning(this, tr("Snapmatic Properties"), tr("Patching of Snapmatic Properties failed because of I/O Error")); QMessageBox::warning(this, tr("Snapmatic Properties"), tr("Patching of Snapmatic Properties failed because of I/O Error"));
smpic->setSnapmaticProperties(fallbackProperties); smpic->setSnapmaticProperties(fallbackProperties);
smpic->setPictureTitle(fallbackTitle); smpic->setPictureTitle(fallbackTitle);
} }
else { else
{
smpic->updateStrings(); smpic->updateStrings();
smpic->emitUpdate(); smpic->emitUpdate();
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
@ -311,16 +343,13 @@ void SnapmaticEditor::on_cmdApply_clicked()
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "PropertyEdited"; jsonObject["Type"] = "PropertyEdited";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
@ -340,7 +369,8 @@ void SnapmaticEditor::qualifyAvatar()
void SnapmaticEditor::on_cbQualify_toggled(bool checked) void SnapmaticEditor::on_cbQualify_toggled(bool checked)
{ {
if (checked) { if (checked)
{
ui->cbMeme->setEnabled(false); ui->cbMeme->setEnabled(false);
ui->cbDirector->setEnabled(false); ui->cbDirector->setEnabled(false);
ui->rbCustom->setEnabled(false); ui->rbCustom->setEnabled(false);
@ -348,13 +378,15 @@ void SnapmaticEditor::on_cbQualify_toggled(bool checked)
ui->rbEditor->setEnabled(false); ui->rbEditor->setEnabled(false);
ui->rbMugshot->setEnabled(false); ui->rbMugshot->setEnabled(false);
} }
else { else
{
ui->cbMeme->setEnabled(true); ui->cbMeme->setEnabled(true);
ui->rbCustom->setEnabled(true); ui->rbCustom->setEnabled(true);
ui->rbSelfie->setEnabled(true); ui->rbSelfie->setEnabled(true);
ui->rbEditor->setEnabled(true); ui->rbEditor->setEnabled(true);
ui->rbMugshot->setEnabled(true); ui->rbMugshot->setEnabled(true);
if (ui->rbSelfie->isChecked() || ui->rbCustom->isChecked()) { if (ui->rbSelfie->isChecked() || ui->rbCustom->isChecked())
{
ui->cbDirector->setEnabled(true); ui->cbDirector->setEnabled(true);
} }
} }
@ -362,7 +394,8 @@ void SnapmaticEditor::on_cbQualify_toggled(bool checked)
void SnapmaticEditor::on_labPlayers_linkActivated(const QString &link) void SnapmaticEditor::on_labPlayers_linkActivated(const QString &link)
{ {
if (link == "g5e://editplayers") { if (link == "g5e://editplayers")
{
PlayerListDialog *playerListDialog = new PlayerListDialog(playersList, profileDB, this); PlayerListDialog *playerListDialog = new PlayerListDialog(playersList, profileDB, this);
connect(playerListDialog, SIGNAL(playerListUpdated(QStringList)), this, SLOT(playerListUpdated(QStringList))); connect(playerListDialog, SIGNAL(playerListUpdated(QStringList)), this, SLOT(playerListUpdated(QStringList)));
playerListDialog->setModal(true); playerListDialog->setModal(true);
@ -374,10 +407,12 @@ void SnapmaticEditor::on_labPlayers_linkActivated(const QString &link)
void SnapmaticEditor::on_labTitle_linkActivated(const QString &link) void SnapmaticEditor::on_labTitle_linkActivated(const QString &link)
{ {
if (link == "g5e://edittitle") { if (link == "g5e://edittitle")
{
bool ok; bool ok;
QString newTitle = QInputDialog::getText(this, tr("Snapmatic Title"), tr("New Snapmatic title:"), QLineEdit::Normal, snapmaticTitle, &ok, windowFlags()); QString newTitle = QInputDialog::getText(this, tr("Snapmatic Title"), tr("New Snapmatic title:"), QLineEdit::Normal, snapmaticTitle, &ok, windowFlags());
if (ok && !newTitle.isEmpty()) { if (ok && !newTitle.isEmpty())
{
setSnapmaticTitle(newTitle); setSnapmaticTitle(newTitle);
} }
} }
@ -385,33 +420,39 @@ void SnapmaticEditor::on_labTitle_linkActivated(const QString &link)
void SnapmaticEditor::on_labCrew_linkActivated(const QString &link) void SnapmaticEditor::on_labCrew_linkActivated(const QString &link)
{ {
if (link == "g5e://editcrew") { if (link == "g5e://editcrew")
{
bool ok; bool ok;
int indexNum = 0; int indexNum = 0;
QStringList itemList; QStringList itemList;
QStringList crewList = crewDB->getCrews(); QStringList crewList = crewDB->getCrews();
if (!crewList.contains(QLatin1String("0"))) { if (!crewList.contains(QLatin1String("0")))
{
crewList += QLatin1String("0"); crewList += QLatin1String("0");
} }
crewList.sort(); crewList.sort();
for (const QString &crew : crewList) { for (QString crew : crewList)
{
itemList += QString("%1 (%2)").arg(crew, returnCrewName(crew.toInt())); itemList += QString("%1 (%2)").arg(crew, returnCrewName(crew.toInt()));
} }
if (crewList.contains(QString::number(crewID))) { if (crewList.contains(QString::number(crewID)))
{
indexNum = crewList.indexOf(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()); QString newCrew = QInputDialog::getItem(this, tr("Snapmatic Crew"), tr("New Snapmatic crew:"), itemList, indexNum, true, &ok, windowFlags());
if (ok && !newCrew.isEmpty()) { if (ok && !newCrew.isEmpty())
if (newCrew.contains(" ")) {
newCrew = newCrew.split(" ").at(0); if (newCrew.contains(" ")) newCrew = newCrew.split(" ").at(0);
if (newCrew.length() > 10) if (newCrew.length() > 10) return;
return; for (QChar crewChar : newCrew)
for (const QChar &crewChar : qAsConst(newCrew)) { {
if (!crewChar.isNumber()) { if (!crewChar.isNumber())
{
return; return;
} }
} }
if (!crewList.contains(newCrew)) { if (!crewList.contains(newCrew))
{
crewDB->addCrew(crewID); crewDB->addCrew(crewID);
} }
crewID = newCrew.toInt(); crewID = newCrew.toInt();

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5spv Grand Theft Auto Snapmatic Picture Viewer * gta5spv Grand Theft Auto Snapmatic Picture Viewer
* Copyright (C) 2016-2020 Syping * Copyright (C) 2016-2018 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -19,7 +19,6 @@
#ifndef SNAPMATICPICTURE_H #ifndef SNAPMATICPICTURE_H
#define SNAPMATICPICTURE_H #define SNAPMATICPICTURE_H
#include "RagePhoto.h"
#include <QStringList> #include <QStringList>
#include <QDateTime> #include <QDateTime>
#include <QObject> #include <QObject>
@ -35,7 +34,6 @@ struct SnapmaticProperties {
double x; double x;
double y; double y;
double z; double z;
bool isCayoPerico;
}; };
int uid; int uid;
int crewID; int crewID;
@ -59,15 +57,17 @@ public:
~SnapmaticPicture(); ~SnapmaticPicture();
void reset(); void reset();
bool preloadFile(); bool preloadFile();
bool readingPictureFromFile(const QString &fileName, bool cacheEnabled = false); bool readingPictureFromFile(const QString &fileName, bool writeEnabled = true, bool cacheEnabled = false, bool fastLoad = true, bool lowRamMode = false);
bool readingPicture(bool cacheEnabled = false); bool readingPicture(bool writeEnabled = true, bool cacheEnabled = false, bool fastLoad = true, bool lowRamMode = false);
bool isPicOk(); // Please use isPictureOk instead bool isPicOk(); // Please use isPictureOk instead
void clearCache(); void clearCache();
QImage getImage(); QImage getImage(bool fastLoad = false);
QByteArray getPictureStream(); QByteArray getPictureStream();
QString getLastStep(bool readable = true); QString getLastStep(bool readable = true);
QString getPictureStr(); QString getPictureStr();
QString getPictureHead();
QString getPictureTitl(); QString getPictureTitl();
QString getPictureDesc();
QString getPictureSortStr(); QString getPictureSortStr();
QString getPictureFileName(); QString getPictureFileName();
QString getPictureFilePath(); QString getPictureFilePath();
@ -75,7 +75,7 @@ public:
QString getOriginalPictureFileName(); QString getOriginalPictureFileName();
QString getOriginalPictureFilePath(); QString getOriginalPictureFilePath();
int getContentMaxLength(); int getContentMaxLength();
bool setImage(const QImage &picture, bool eXtendMode = false); bool setImage(const QImage &picture);
bool setPictureTitl(const QString &newTitle); // Please use setPictureTitle instead bool setPictureTitl(const QString &newTitle); // Please use setPictureTitle instead
bool setPictureStream(const QByteArray &streamArray); bool setPictureStream(const QByteArray &streamArray);
void updateStrings(); void updateStrings();
@ -106,6 +106,7 @@ public:
QString getPictureJson() { return getJsonStr(); } QString getPictureJson() { return getJsonStr(); }
QString getPictureTitle() { return getPictureTitl(); } QString getPictureTitle() { return getPictureTitl(); }
QString getPictureString() { return getPictureStr(); } QString getPictureString() { return getPictureStr(); }
QString getPictureDescription() { return getPictureDesc(); }
bool setJsonString(const QString &jsonString, bool updateProperties = false) { return setJsonStr(jsonString, updateProperties); } // Please use setPictureJson instead bool setJsonString(const QString &jsonString, bool updateProperties = false) { return setJsonStr(jsonString, updateProperties); } // Please use setPictureJson instead
bool setPictureJson(const QString &json, bool updateProperties = false) { return setJsonStr(json, updateProperties); } bool setPictureJson(const QString &json, bool updateProperties = false) { return setJsonStr(json, updateProperties); }
bool setPictureTitle(const QString &title) { return setPictureTitl(title); } bool setPictureTitle(const QString &title) { return setPictureTitl(title); }
@ -121,6 +122,10 @@ public:
// PREDEFINED PROPERTIES // PREDEFINED PROPERTIES
static QSize getSnapmaticResolution(); static QSize getSnapmaticResolution();
// SNAPMATIC DEFAULTS
bool isSnapmaticDefaultsEnforced();
void setSnapmaticDefaultsEnforced(bool enforced);
// SNAPMATIC FORMAT // SNAPMATIC FORMAT
SnapmaticFormat getSnapmaticFormat(); SnapmaticFormat getSnapmaticFormat();
void setSnapmaticFormat(SnapmaticFormat format); void setSnapmaticFormat(SnapmaticFormat format);
@ -134,32 +139,44 @@ public:
static QString convertDrawStringForLog(const QString &inputStr); static QString convertDrawStringForLog(const QString &inputStr);
static QString convertLogStringForDraw(const QString &inputStr); static QString convertLogStringForDraw(const QString &inputStr);
// RAGEPHOTO
RagePhoto* ragePhoto();
private: private:
QString getSnapmaticHeaderString(const QByteArray &snapmaticHeader);
QString getSnapmaticJSONString(const QByteArray &jsonBytes);
QString getSnapmaticTIDEString(const QByteArray &tideBytes);
QImage cachePicture; QImage cachePicture;
QString picExportFileName; QString picExportFileName;
QString picFileName; QString picFileName;
QString picFilePath; QString picFilePath;
QString pictureHead;
QString pictureStr; QString pictureStr;
QString lastStep; QString lastStep;
QString sortStr; QString sortStr;
QString titlStr;
QString descStr;
bool picOk; bool picOk;
bool lowRamMode;
bool writeEnabled;
bool cacheEnabled; bool cacheEnabled;
bool isLoadedInRAM;
bool isCustomFormat;
bool isFormatSwitch; bool isFormatSwitch;
bool isModernFormat;
bool careSnapDefault;
int jpegRawContentSize;
int jpegRawContentSizeE;
// PICTURE STREAM
QByteArray rawPicContent;
// JSON // JSON
void parseJsonContent(); void parseJsonContent();
bool jsonOk; bool jsonOk;
QString jsonStr;
SnapmaticProperties localProperties; SnapmaticProperties localProperties;
// VERIFY CONTENT // VERIFY CONTENT
static bool verifyTitleChar(const QChar &titleChar); static bool verifyTitleChar(const QChar &titleChar);
// RAGEPHOTO
RagePhoto p_ragePhoto;
signals: signals:
void customSignal(QString signal); void customSignal(QString signal);
void preloaded(); void preloaded();

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -31,9 +31,9 @@
#include "config.h" #include "config.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QMessageBox> #include <QMessageBox>
#include <QPainter>
#include <QPixmap> #include <QPixmap>
#include <QTimer> #include <QTimer>
#include <QDebug>
#include <QMenu> #include <QMenu>
#include <QFile> #include <QFile>
@ -76,33 +76,19 @@ void SnapmaticWidget::setSnapmaticPicture(SnapmaticPicture *picture)
QObject::connect(picture, SIGNAL(updated()), this, SLOT(snapmaticUpdated())); QObject::connect(picture, SIGNAL(updated()), this, SLOT(snapmaticUpdated()));
QObject::connect(picture, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString))); QObject::connect(picture, SIGNAL(customSignal(QString)), this, SLOT(customSignal(QString)));
const qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
const qreal screenRatioPR = AppEnv::screenRatioPR(); qreal screenRatioPR = AppEnv::screenRatioPR();
const QSize renderResolution(48 * screenRatio * screenRatioPR, 27 * screenRatio * screenRatioPR);
ui->labPicture->setFixedSize(48 * screenRatio, 27 * screenRatio); ui->labPicture->setFixedSize(48 * screenRatio, 27 * screenRatio);
ui->labPicture->setScaledContents(true); ui->labPicture->setScaledContents(true);
QPixmap renderPixmap(renderResolution); QPixmap SnapmaticPixmap = QPixmap::fromImage(picture->getImage().scaled(ui->labPicture->width() * screenRatioPR, ui->labPicture->height() * screenRatioPR, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::AutoColor);
renderPixmap.fill(Qt::transparent);
QPainter renderPainter(&renderPixmap);
const QImage originalImage = picture->getImage();
const QImage renderImage = originalImage.scaled(renderResolution, Qt::KeepAspectRatio, Qt::SmoothTransformation); // Stack smash
if (renderImage.width() < renderResolution.width()) {
renderPainter.drawImage((renderResolution.width() - renderImage.width()) / 2, 0, renderImage, Qt::AutoColor);
}
else if (renderImage.height() < renderResolution.height()) {
renderPainter.drawImage(0, (renderResolution.height() - renderImage.height()) / 2, renderImage, Qt::AutoColor);
}
else {
renderPainter.drawImage(0, 0, renderImage, Qt::AutoColor);
}
renderPainter.end();
#if QT_VERSION >= 0x050600 #if QT_VERSION >= 0x050600
renderPixmap.setDevicePixelRatio(screenRatioPR); SnapmaticPixmap.setDevicePixelRatio(screenRatioPR);
#endif #endif
ui->labPicStr->setText(smpic->getPictureStr() % "\n" % smpic->getPictureTitl()); ui->labPicStr->setText(smpic->getPictureStr() % "\n" % smpic->getPictureTitl());
ui->labPicture->setPixmap(renderPixmap); ui->labPicture->setPixmap(SnapmaticPixmap);
picture->clearCache(); picture->clearCache();
@ -116,7 +102,8 @@ void SnapmaticWidget::snapmaticUpdated()
void SnapmaticWidget::customSignal(QString signal) void SnapmaticWidget::customSignal(QString signal)
{ {
if (signal == "PictureUpdated") { if (signal == "PictureUpdated")
{
QPixmap SnapmaticPixmap = QPixmap::fromImage(smpic->getImage().scaled(ui->labPicture->width(), ui->labPicture->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::AutoColor); QPixmap SnapmaticPixmap = QPixmap::fromImage(smpic->getImage().scaled(ui->labPicture->width(), ui->labPicture->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::AutoColor);
ui->labPicture->setPixmap(SnapmaticPixmap); ui->labPicture->setPixmap(SnapmaticPixmap);
} }
@ -146,8 +133,7 @@ void SnapmaticWidget::on_cmdView_clicked()
QObject::connect(picDialog, SIGNAL(previousPictureRequested()), this, SLOT(dialogPreviousPictureRequested())); QObject::connect(picDialog, SIGNAL(previousPictureRequested()), this, SLOT(dialogPreviousPictureRequested()));
// add previous next buttons // add previous next buttons
if (navigationBar) if (navigationBar) picDialog->addPreviousNextButtons();
picDialog->addPreviousNextButtons();
// show picture dialog // show picture dialog
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
@ -176,38 +162,37 @@ void SnapmaticWidget::on_cmdExport_clicked()
void SnapmaticWidget::on_cmdDelete_clicked() void SnapmaticWidget::on_cmdDelete_clicked()
{ {
if (deletePicture()) if (deletePicture()) emit pictureDeleted();
emit pictureDeleted();
} }
bool SnapmaticWidget::deletePicture() 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); 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 (uchoice == QMessageBox::Yes)
if (smpic->deletePictureFile()) { {
if (smpic->deletePictureFile())
{
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "DeleteSuccess"; jsonObject["Type"] = "DeleteSuccess";
jsonObject["ExtraFlags"] = "Snapmatic"; jsonObject["ExtraFlags"] = "Snapmatic";
jsonObject["DeletedSize"] = QString::number(smpic->getContentMaxLength()); jsonObject["DeletedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
#endif #endif
return true; return true;
} }
else { else
{
QMessageBox::warning(this, tr("Delete picture"), tr("Failed at deleting %1 from your Snapmatic pictures").arg("\""+smpic->getPictureTitle()+"\"")); QMessageBox::warning(this, tr("Delete picture"), tr("Failed at deleting %1 from your Snapmatic pictures").arg("\""+smpic->getPictureTitle()+"\""));
} }
} }
@ -222,22 +207,28 @@ void SnapmaticWidget::mousePressEvent(QMouseEvent *ev)
void SnapmaticWidget::mouseReleaseEvent(QMouseEvent *ev) void SnapmaticWidget::mouseReleaseEvent(QMouseEvent *ev)
{ {
ProfileWidget::mouseReleaseEvent(ev); ProfileWidget::mouseReleaseEvent(ev);
if (ui->cbSelected->isVisible()) { if (ui->cbSelected->isVisible())
if (rect().contains(ev->pos()) && ev->button() == Qt::LeftButton) { {
if (rect().contains(ev->pos()) && ev->button() == Qt::LeftButton)
{
ui->cbSelected->setChecked(!ui->cbSelected->isChecked()); ui->cbSelected->setChecked(!ui->cbSelected->isChecked());
} }
} }
else { else
const int contentMode = getContentMode(); {
if ((contentMode == 0 || contentMode == 10 || contentMode == 20) && rect().contains(ev->pos()) && ev->button() == Qt::LeftButton) { if (getContentMode() == 0 && rect().contains(ev->pos()) && ev->button() == Qt::LeftButton)
if (ev->modifiers().testFlag(Qt::ShiftModifier)) { {
if (ev->modifiers().testFlag(Qt::ShiftModifier))
{
ui->cbSelected->setChecked(!ui->cbSelected->isChecked()); ui->cbSelected->setChecked(!ui->cbSelected->isChecked());
} }
else { else
{
on_cmdView_clicked(); on_cmdView_clicked();
} }
} }
else if (!ui->cbSelected->isVisible() && (contentMode == 1 || contentMode == 11 || contentMode == 21) && ev->button() == Qt::LeftButton && ev->modifiers().testFlag(Qt::ShiftModifier)) { else if (!ui->cbSelected->isVisible() && getContentMode() == 1 && ev->button() == Qt::LeftButton && ev->modifiers().testFlag(Qt::ShiftModifier))
{
ui->cbSelected->setChecked(!ui->cbSelected->isChecked()); ui->cbSelected->setChecked(!ui->cbSelected->isChecked());
} }
} }
@ -247,8 +238,8 @@ void SnapmaticWidget::mouseDoubleClickEvent(QMouseEvent *ev)
{ {
ProfileWidget::mouseDoubleClickEvent(ev); ProfileWidget::mouseDoubleClickEvent(ev);
const int contentMode = getContentMode(); if (!ui->cbSelected->isVisible() && getContentMode() == 1 && ev->button() == Qt::LeftButton)
if (!ui->cbSelected->isVisible() && (contentMode == 1 || contentMode == 11 || contentMode == 21) && ev->button() == Qt::LeftButton) { {
on_cmdView_clicked(); on_cmdView_clicked();
} }
} }
@ -280,27 +271,32 @@ void SnapmaticWidget::dialogPreviousPictureRequested()
void SnapmaticWidget::on_cbSelected_stateChanged(int arg1) void SnapmaticWidget::on_cbSelected_stateChanged(int arg1)
{ {
if (arg1 == Qt::Checked) { if (arg1 == Qt::Checked)
{
emit widgetSelected(); emit widgetSelected();
} }
else if (arg1 == Qt::Unchecked) { else if (arg1 == Qt::Unchecked)
{
emit widgetDeselected(); emit widgetDeselected();
} }
} }
void SnapmaticWidget::adjustTextColor() void SnapmaticWidget::adjustTextColor()
{ {
if (isHidden()) { if (isHidden())
{
ui->labPicStr->setStyleSheet(QString("QLabel{color: rgb(%1, %2, %3);}").arg(QString::number(highlightHiddenColor.red()), QString::number(highlightHiddenColor.green()), QString::number(highlightHiddenColor.blue()))); ui->labPicStr->setStyleSheet(QString("QLabel{color: rgb(%1, %2, %3);}").arg(QString::number(highlightHiddenColor.red()), QString::number(highlightHiddenColor.green()), QString::number(highlightHiddenColor.blue())));
} }
else { else
{
ui->labPicStr->setStyleSheet(""); ui->labPicStr->setStyleSheet("");
} }
} }
bool SnapmaticWidget::makePictureHidden() bool SnapmaticWidget::makePictureHidden()
{ {
if (smpic->setPictureHidden()) { if (smpic->setPictureHidden())
{
adjustTextColor(); adjustTextColor();
return true; return true;
} }
@ -309,7 +305,8 @@ bool SnapmaticWidget::makePictureHidden()
bool SnapmaticWidget::makePictureVisible() bool SnapmaticWidget::makePictureVisible()
{ {
if (smpic->setPictureVisible()) { if (smpic->setPictureVisible())
{
adjustTextColor(); adjustTextColor();
return true; return true;
} }
@ -319,14 +316,18 @@ bool SnapmaticWidget::makePictureVisible()
void SnapmaticWidget::makePictureHiddenSlot() void SnapmaticWidget::makePictureHiddenSlot()
{ {
if (!makePictureHidden()) if (!makePictureHidden())
{
QMessageBox::warning(this, QApplication::translate("UserInterface", "Hide In-game"), QApplication::translate("SnapmaticWidget", "Failed to hide %1 In-game from your Snapmatic pictures").arg("\""+smpic->getPictureTitle()+"\"")); QMessageBox::warning(this, QApplication::translate("UserInterface", "Hide In-game"), QApplication::translate("SnapmaticWidget", "Failed to hide %1 In-game from your Snapmatic pictures").arg("\""+smpic->getPictureTitle()+"\""));
} }
}
void SnapmaticWidget::makePictureVisibleSlot() void SnapmaticWidget::makePictureVisibleSlot()
{ {
if (!makePictureVisible()) if (!makePictureVisible())
{
QMessageBox::warning(this, QApplication::translate("UserInterface", "Show In-game"), QApplication::translate("SnapmaticWidget", "Failed to show %1 In-game from your Snapmatic pictures").arg("\""+smpic->getPictureTitle()+"\"")); QMessageBox::warning(this, QApplication::translate("UserInterface", "Show In-game"), QApplication::translate("SnapmaticWidget", "Failed to show %1 In-game from your Snapmatic pictures").arg("\""+smpic->getPictureTitle()+"\""));
} }
}
void SnapmaticWidget::editSnapmaticProperties() void SnapmaticWidget::editSnapmaticProperties()
{ {
@ -355,17 +356,21 @@ void SnapmaticWidget::editSnapmaticImage()
importDialog->enableOverwriteMode(); importDialog->enableOverwriteMode();
importDialog->setModal(true); importDialog->setModal(true);
importDialog->exec(); importDialog->exec();
if (importDialog->isImportAgreed()) { if (importDialog->isImportAgreed())
{
const QByteArray previousPicture = smpic->getPictureStream(); const QByteArray previousPicture = smpic->getPictureStream();
bool success = smpic->setImage(importDialog->image(), importDialog->isUnlimitedBuffer()); bool success = smpic->setImage(importDialog->image());
if (success) { if (success)
{
QString currentFilePath = smpic->getPictureFilePath(); QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath(); QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak"; QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) { if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName); QFile::copy(currentFilePath, backupFileName);
} }
if (!smpic->exportPicture(currentFilePath)) { if (!smpic->exportPicture(currentFilePath))
{
smpic->setPictureStream(previousPicture); 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")); QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of I/O Error"));
return; return;
@ -376,23 +381,21 @@ void SnapmaticWidget::editSnapmaticImage()
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "ImageEdited"; jsonObject["Type"] = "ImageEdited";
jsonObject["ExtraFlags"] = "Interface"; jsonObject["ExtraFlags"] = "Interface";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }
#endif #endif
} }
else { else
{
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error")); QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error"));
return; return;
} }
@ -403,48 +406,48 @@ void SnapmaticWidget::editSnapmaticImage()
void SnapmaticWidget::openMapViewer() void SnapmaticWidget::openMapViewer()
{ {
SnapmaticPicture *picture = smpic; SnapmaticPicture *picture = smpic;
SnapmaticProperties currentProperties = picture->getSnapmaticProperties(); MapLocationDialog *mapLocDialog = new MapLocationDialog(picture->getSnapmaticProperties().location.x, picture->getSnapmaticProperties().location.y, this);
MapLocationDialog *mapLocDialog = new MapLocationDialog(currentProperties.location.x, currentProperties.location.y, this);
mapLocDialog->setCayoPerico(currentProperties.location.isCayoPerico);
mapLocDialog->setModal(true); mapLocDialog->setModal(true);
mapLocDialog->show(); mapLocDialog->show();
mapLocDialog->exec(); mapLocDialog->exec();
if (mapLocDialog->propUpdated()) { if (mapLocDialog->propUpdated())
{
// Update Snapmatic Properties // Update Snapmatic Properties
currentProperties.location.x = mapLocDialog->getXpos(); SnapmaticProperties localSpJson = picture->getSnapmaticProperties();
currentProperties.location.y = mapLocDialog->getYpos(); localSpJson.location.x = mapLocDialog->getXpos();
currentProperties.location.z = 0; localSpJson.location.y = mapLocDialog->getYpos();
localSpJson.location.z = 0;
// Update Snapmatic Picture // Update Snapmatic Picture
QString currentFilePath = picture->getPictureFilePath(); QString currentFilePath = picture->getPictureFilePath();
QString originalFilePath = picture->getOriginalPictureFilePath(); QString originalFilePath = picture->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak"; QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) { if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName); QFile::copy(currentFilePath, backupFileName);
} }
SnapmaticProperties fallbackProperties = picture->getSnapmaticProperties(); SnapmaticProperties fallbackProperties = picture->getSnapmaticProperties();
picture->setSnapmaticProperties(currentProperties); picture->setSnapmaticProperties(localSpJson);
if (!picture->exportPicture(currentFilePath)) { if (!picture->exportPicture(currentFilePath))
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error")); QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error"));
picture->setSnapmaticProperties(fallbackProperties); picture->setSnapmaticProperties(fallbackProperties);
} }
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
else { else
{
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool(); bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup(); telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) { if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
jsonObject["Type"] = "LocationEdited"; jsonObject["Type"] = "LocationEdited";
jsonObject["ExtraFlags"] = "Interface"; jsonObject["ExtraFlags"] = "Interface";
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength()); jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject); jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument); Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -23,6 +23,11 @@
#include <QDesktopServices> #include <QDesktopServices>
#endif #endif
StandardPaths::StandardPaths()
{
}
QString StandardPaths::applicationsLocation() QString StandardPaths::applicationsLocation()
{ {
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
@ -43,9 +48,7 @@ QString StandardPaths::cacheLocation()
QString StandardPaths::dataLocation() QString StandardPaths::dataLocation()
{ {
#if QT_VERSION >= 0x060000 #if QT_VERSION >= 0x050000
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
#elif QT_VERSION >= 0x050000
return QStandardPaths::writableLocation(QStandardPaths::DataLocation); return QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#else #else
return QDesktopServices::storageLocation(QDesktopServices::DataLocation); return QDesktopServices::storageLocation(QDesktopServices::DataLocation);

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -24,6 +24,7 @@
class StandardPaths class StandardPaths
{ {
public: public:
StandardPaths();
static QString applicationsLocation(); static QString applicationsLocation();
static QString cacheLocation(); static QString cacheLocation();
static QString dataLocation(); static QString dataLocation();

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -17,9 +17,7 @@
*****************************************************************************/ *****************************************************************************/
#include "StringParser.h" #include "StringParser.h"
#include "config.h"
#include <QTextDocument> #include <QTextDocument>
#include <QApplication>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QByteArray> #include <QByteArray>
#include <QFileInfo> #include <QFileInfo>
@ -27,6 +25,16 @@
#include <QList> #include <QList>
#include <QDir> #include <QDir>
#ifdef GTA5SYNC_PROJECT
#include <QApplication>
#include "config.h"
#endif
StringParser::StringParser()
{
}
QString StringParser::escapeString(const QString &toEscape) QString StringParser::escapeString(const QString &toEscape)
{ {
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
@ -36,6 +44,7 @@ QString StringParser::escapeString(const QString &toEscape)
#endif #endif
} }
#ifdef GTA5SYNC_PROJECT
QString StringParser::convertBuildedString(const QString &buildedStr) QString StringParser::convertBuildedString(const QString &buildedStr)
{ {
QString outputStr = buildedStr; QString outputStr = buildedStr;
@ -52,3 +61,4 @@ QString StringParser::convertBuildedString(const QString &buildedStr)
outputStr.replace("SEPARATOR:", QDir::separator()); outputStr.replace("SEPARATOR:", QDir::separator());
return outputStr; return outputStr;
} }
#endif

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -25,8 +25,11 @@
class StringParser class StringParser
{ {
public: public:
StringParser();
static QString escapeString(const QString &toEscape); static QString escapeString(const QString &toEscape);
#ifdef GTA5SYNC_PROJECT
static QString convertBuildedString(const QString &buildedStr); static QString convertBuildedString(const QString &buildedStr);
#endif
}; };
#endif // STRINGPARSER_H #endif // STRINGPARSER_H

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2021 Syping * Copyright (C) 2017 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -48,23 +48,22 @@ void TranslationClass::initUserLanguage()
void TranslationClass::loadTranslation(QApplication *app) void TranslationClass::loadTranslation(QApplication *app)
{ {
if (isLangLoaded) { if (isLangLoaded) { unloadTranslation(app); }
unloadTranslation(app); else { currentLangIndex = 0; }
} QString exLangPath = AppEnv::getExLangFolder();
else { QString inLangPath = AppEnv::getInLangFolder();
currentLangIndex = 0; if (userLanguage == "en" || userLanguage == "en_GB")
} {
const QString exLangPath = AppEnv::getExLangFolder();
const QString inLangPath = AppEnv::getInLangFolder();
if (userLanguage == "en" || userLanguage == "en_GB") {
currentLanguage = "en_GB"; currentLanguage = "en_GB";
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000 #if QT_VERSION <= 0x060000
QLocale::setDefault(QLocale(currentLanguage)); QLocale::setDefault(QLocale(currentLanguage));
#else #else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
@ -78,28 +77,33 @@ void TranslationClass::loadTranslation(QApplication *app)
bool externalEnglishMode = false; bool externalEnglishMode = false;
bool loadInternalLang = false; bool loadInternalLang = false;
bool trLoadSuccess = false; bool trLoadSuccess = false;
if (isUserLanguageSystem_p()) { if (isUserLanguageSystem_p())
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadExSystemLanguage"; qDebug() << "loadExSystemLanguage";
#endif #endif
trLoadSuccess = loadSystemTranslation_p(exLangPath, &exAppTranslator); trLoadSuccess = loadSystemTranslation_p(exLangPath, &exAppTranslator);
} }
else { else
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadExUserLanguage"; qDebug() << "loadExUserLanguage";
#endif #endif
trLoadSuccess = loadUserTranslation_p(exLangPath, &exAppTranslator); trLoadSuccess = loadUserTranslation_p(exLangPath, &exAppTranslator);
if (!trLoadSuccess) { if (!trLoadSuccess)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadInUserLanguage"; qDebug() << "loadInUserLanguage";
#endif #endif
trLoadSuccess = loadUserTranslation_p(inLangPath, &inAppTranslator); trLoadSuccess = loadUserTranslation_p(inLangPath, &inAppTranslator);
if (!trLoadSuccess) { if (!trLoadSuccess)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadUserLanguageFailed"; qDebug() << "loadUserLanguageFailed";
#endif #endif
} }
else { else
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadUserLanguageSuccess"; qDebug() << "loadUserLanguageSuccess";
#endif #endif
@ -107,16 +111,18 @@ void TranslationClass::loadTranslation(QApplication *app)
isLangLoaded = true; isLangLoaded = true;
} }
} }
else { else
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadUserLanguageSuccess"; qDebug() << "loadUserLanguageSuccess";
#endif #endif
isLangLoaded = true; isLangLoaded = true;
} }
} }
if (trLoadSuccess) { if (trLoadSuccess)
// Don't install the language until we know we not have a better language for the user {
if (currentLangIndex != 0 || isEnglishMode) { if (currentLangIndex != 0 || isEnglishMode) // Don't install the language until we know we not have a better language for the user
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "externalLanguageReady" << currentLanguage; qDebug() << "externalLanguageReady" << currentLanguage;
#endif #endif
@ -124,23 +130,28 @@ void TranslationClass::loadTranslation(QApplication *app)
externalLanguageStr = currentLanguage; externalLanguageStr = currentLanguage;
externalLanguageReady = true; externalLanguageReady = true;
} }
else { else
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "installTranslation"; qDebug() << "installTranslation";
#endif #endif
if (loadInternalLang) { if (loadInternalLang)
{
app->installTranslator(&inAppTranslator); app->installTranslator(&inAppTranslator);
} }
else { else
{
app->installTranslator(&exAppTranslator); app->installTranslator(&exAppTranslator);
} }
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000 #if QT_VERSION <= 0x060000
QLocale::setDefault(QLocale(currentLanguage)); QLocale::setDefault(QLocale(currentLanguage));
#else #else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
@ -148,7 +159,8 @@ void TranslationClass::loadTranslation(QApplication *app)
isLangLoaded = true; isLangLoaded = true;
} }
} }
if (externalLanguageReady) { if (externalLanguageReady)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadInSystemLanguage"; qDebug() << "loadInSystemLanguage";
#endif #endif
@ -158,38 +170,44 @@ void TranslationClass::loadTranslation(QApplication *app)
qDebug() << "externalLangIndex" << externalLangIndex << "internalLangIndex" << currentLangIndex; qDebug() << "externalLangIndex" << externalLangIndex << "internalLangIndex" << currentLangIndex;
qDebug() << "externalEnglishMode" << externalEnglishMode << "internalEnglishMode" << isEnglishMode; qDebug() << "externalEnglishMode" << externalEnglishMode << "internalEnglishMode" << isEnglishMode;
#endif #endif
if ((trLoadSuccess && externalLangIndex > currentLangIndex) || (trLoadSuccess && externalEnglishMode && !isEnglishMode)) { if ((trLoadSuccess && externalLangIndex > currentLangIndex) || (trLoadSuccess && externalEnglishMode && !isEnglishMode))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "installInternalTranslation"; qDebug() << "installInternalTranslation";
#endif #endif
app->installTranslator(&inAppTranslator); app->installTranslator(&inAppTranslator);
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000 #if QT_VERSION <= 0x060000
QLocale::setDefault(QLocale(currentLanguage)); QLocale::setDefault(QLocale(currentLanguage));
#else #else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif #endif
isLangLoaded = true; isLangLoaded = true;
} }
else { else
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "installExternalTranslation"; qDebug() << "installExternalTranslation";
#endif #endif
isEnglishMode = externalEnglishMode; isEnglishMode = externalEnglishMode;
currentLanguage = externalLanguageStr; currentLanguage = externalLanguageStr;
app->installTranslator(&exAppTranslator); app->installTranslator(&exAppTranslator);
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000 #if QT_VERSION <= 0x060000
QLocale::setDefault(QLocale(currentLanguage)); QLocale::setDefault(QLocale(currentLanguage));
#else #else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
@ -197,41 +215,48 @@ void TranslationClass::loadTranslation(QApplication *app)
isLangLoaded = true; isLangLoaded = true;
} }
} }
else if (!isLangLoaded) { else if (!isLangLoaded)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadInSystemLanguage"; qDebug() << "loadInSystemLanguage";
#endif #endif
trLoadSuccess = loadSystemTranslation_p(inLangPath, &inAppTranslator); trLoadSuccess = loadSystemTranslation_p(inLangPath, &inAppTranslator);
if (trLoadSuccess) { if (trLoadSuccess)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "installInternalTranslation"; qDebug() << "installInternalTranslation";
#endif #endif
app->installTranslator(&inAppTranslator); app->installTranslator(&inAppTranslator);
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000 #if QT_VERSION <= 0x060000
QLocale::setDefault(QLocale(currentLanguage)); QLocale::setDefault(QLocale(currentLanguage));
#else #else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif #endif
isLangLoaded = true; isLangLoaded = true;
} }
else if (!trLoadSuccess) { else if (!trLoadSuccess)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "fallbackToDefaultApplicationLanguage"; qDebug() << "fallbackToDefaultApplicationLanguage";
#endif #endif
currentLanguage = "en_GB"; currentLanguage = "en_GB";
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000 #if QT_VERSION <= 0x060000
QLocale::setDefault(QLocale(currentLanguage)); QLocale::setDefault(QLocale(currentLanguage));
#else #else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
@ -241,31 +266,33 @@ void TranslationClass::loadTranslation(QApplication *app)
} }
#else // New qconf loading method #else // New qconf loading method
bool trLoadSuccess; bool trLoadSuccess;
if (isUserLanguageSystem_p()) { if (isUserLanguageSystem_p())
{
trLoadSuccess = loadSystemTranslation_p(inLangPath, &inAppTranslator); trLoadSuccess = loadSystemTranslation_p(inLangPath, &inAppTranslator);
} }
else { else
{
trLoadSuccess = loadUserTranslation_p(inLangPath, &inAppTranslator); trLoadSuccess = loadUserTranslation_p(inLangPath, &inAppTranslator);
} }
if (!trLoadSuccess && !isUserLanguageSystem_p()) { if (!trLoadSuccess && !isUserLanguageSystem_p())
{
trLoadSuccess = loadSystemTranslation_p(inLangPath, &inAppTranslator); trLoadSuccess = loadSystemTranslation_p(inLangPath, &inAppTranslator);
} }
if (trLoadSuccess) { if (trLoadSuccess)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "installTranslation" << currentLanguage; qDebug() << "installTranslation" << currentLanguage;
#endif #endif
app->installTranslator(&inAppTranslator); app->installTranslator(&inAppTranslator);
if (loadQtTranslation_p(exLangPath, &exQtTranslator)) { if (loadQtTranslation_p(exLangPath, &exQtTranslator))
{
app->installTranslator(&exQtTranslator); app->installTranslator(&exQtTranslator);
} }
else if (loadQtTranslation_p(inLangPath, &inQtTranslator)) { else if (loadQtTranslation_p(inLangPath, &inQtTranslator))
{
app->installTranslator(&inQtTranslator); app->installTranslator(&inQtTranslator);
} }
#if QT_VERSION >= 0x060000
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif
isLangLoaded = true; isLangLoaded = true;
} }
#endif #endif
@ -277,7 +304,8 @@ QStringList TranslationClass::listTranslations(const QString &langPath)
langDir.setNameFilters(QStringList("gta5sync_*.qm")); langDir.setNameFilters(QStringList("gta5sync_*.qm"));
langDir.setPath(langPath); langDir.setPath(langPath);
QStringList availableLanguages; QStringList availableLanguages;
for (const QString &lang : langDir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort)) { for (QString lang : langDir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort))
{
availableLanguages << QString(lang).remove("gta5sync_").remove(".qm"); availableLanguages << QString(lang).remove("gta5sync_").remove(".qm");
} }
return availableLanguages; return availableLanguages;
@ -289,7 +317,8 @@ QStringList TranslationClass::listAreaTranslations()
langDir.setNameFilters(QStringList("global.*.ini")); langDir.setNameFilters(QStringList("global.*.ini"));
langDir.setPath(":/global"); langDir.setPath(":/global");
QStringList availableLanguages; QStringList availableLanguages;
for (const QString &lang : langDir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort)) { for (QString lang : langDir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort))
{
availableLanguages << QString(lang).remove("global.").remove(".ini"); availableLanguages << QString(lang).remove("global.").remove(".ini");
} }
return availableLanguages; return availableLanguages;
@ -301,17 +330,21 @@ bool TranslationClass::loadSystemTranslation_p(const QString &langPath, QTransla
qDebug() << "loadSystemTranslation_p"; qDebug() << "loadSystemTranslation_p";
#endif #endif
int currentLangCounter = 0; int currentLangCounter = 0;
for (const QString &languageName : QLocale::system().uiLanguages()) { for (QString languageName : QLocale::system().uiLanguages())
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguage" << languageName; qDebug() << "loadLanguage" << languageName;
#endif #endif
const QStringList langList = QString(languageName).replace("-","_").split("_"); QStringList langList = QString(languageName).replace("-","_").split("_");
if (langList.length() == 2) { if (langList.length() == 2)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm");
#endif #endif
if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm")) { if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"))
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm")) { {
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm");
#endif #endif
@ -324,8 +357,10 @@ bool TranslationClass::loadSystemTranslation_p(const QString &langPath, QTransla
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { {
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
@ -334,7 +369,8 @@ bool TranslationClass::loadSystemTranslation_p(const QString &langPath, QTransla
currentLangIndex = currentLangCounter; currentLangIndex = currentLangCounter;
return true; return true;
} }
else if (langList.at(0) == "en") { else if (langList.at(0) == "en")
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "languageEnglishMode index" << currentLangCounter; qDebug() << "languageEnglishMode index" << currentLangCounter;
#endif #endif
@ -344,7 +380,8 @@ bool TranslationClass::loadSystemTranslation_p(const QString &langPath, QTransla
return true; return true;
} }
} }
else if (langList.at(0) == "en") { else if (langList.at(0) == "en")
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "languageEnglishMode index" << currentLangCounter; qDebug() << "languageEnglishMode index" << currentLangCounter;
#endif #endif
@ -354,12 +391,15 @@ bool TranslationClass::loadSystemTranslation_p(const QString &langPath, QTransla
return true; return true;
} }
} }
else if (langList.length() == 1) { else if (langList.length() == 1)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { {
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
@ -383,14 +423,17 @@ bool TranslationClass::loadUserTranslation_p(const QString &langPath, QTranslato
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadUserTranslation_p"; qDebug() << "loadUserTranslation_p";
#endif #endif
const QString languageName = userLanguage; QString languageName = userLanguage;
const QStringList langList = QString(languageName).replace("-","_").split("_"); QStringList langList = QString(languageName).replace("-","_").split("_");
if (langList.length() == 2) { if (langList.length() == 2)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm");
#endif #endif
if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm")) { if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"))
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm")) { {
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % "_" % langList.at(1) % ".qm");
#endif #endif
@ -401,8 +444,10 @@ bool TranslationClass::loadUserTranslation_p(const QString &langPath, QTranslato
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { {
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
@ -411,12 +456,15 @@ bool TranslationClass::loadUserTranslation_p(const QString &langPath, QTranslato
} }
} }
} }
else if (langList.length() == 1) { else if (langList.length() == 1)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { if (QFile::exists(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm")) { {
if (appTranslator->load(langPath % "/gta5sync_" % langList.at(0) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % "/gta5sync_" % langList.at(0) % ".qm");
#endif #endif
@ -433,14 +481,17 @@ bool TranslationClass::loadQtTranslation_p(const QString &langPath, QTranslator
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadQtTranslation_p" << currentLanguage; qDebug() << "loadQtTranslation_p" << currentLanguage;
#endif #endif
const QString languageName = currentLanguage; QString languageName = currentLanguage;
const QStringList langList = QString(languageName).replace("-","_").split("_"); QStringList langList = QString(languageName).replace("-","_").split("_");
if (langList.length() == 2) { if (langList.length() == 2)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm");
#endif #endif
if (QFile::exists(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm")) { if (QFile::exists(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm"))
if (qtTranslator->load(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm")) { {
if (qtTranslator->load(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % "_" % langList.at(1) % ".qm");
#endif #endif
@ -450,8 +501,10 @@ bool TranslationClass::loadQtTranslation_p(const QString &langPath, QTranslator
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm");
#endif #endif
if (QFile::exists(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm")) { if (QFile::exists(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"))
if (qtTranslator->load(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm")) { {
if (qtTranslator->load(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm");
#endif #endif
@ -459,12 +512,15 @@ bool TranslationClass::loadQtTranslation_p(const QString &langPath, QTranslator
} }
} }
} }
else if (langList.length() == 1) { else if (langList.length() == 1)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFile" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"); qDebug() << "loadLanguageFile" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm");
#endif #endif
if (QFile::exists(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm")) { if (QFile::exists(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"))
if (qtTranslator->load(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm")) { {
if (qtTranslator->load(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadLanguageFileSuccess" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm"); qDebug() << "loadLanguageFileSuccess" << QString(langPath % QDir::separator() % QtBaseTranslationFormat % langList.at(0) % ".qm");
#endif #endif
@ -483,44 +539,49 @@ bool TranslationClass::isUserLanguageSystem_p()
QString TranslationClass::getCurrentAreaLanguage() QString TranslationClass::getCurrentAreaLanguage()
{ {
const QStringList areaTranslations = listAreaTranslations(); const QStringList areaTranslations = listAreaTranslations();
if (userAreaLanguage == "Auto" || userAreaLanguage.trimmed().isEmpty()) { if (userAreaLanguage == "Auto" || userAreaLanguage.trimmed().isEmpty())
const GameLanguage gameLanguage = AppEnv::getGameLanguage(AppEnv::getGameVersion()); {
if (gameLanguage == GameLanguage::Undefined) { GameLanguage gameLanguage = AppEnv::getGameLanguage(AppEnv::getGameVersion());
if (gameLanguage == GameLanguage::Undefined)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageModeInterface"; qDebug() << "autoAreaLanguageModeInterface";
#endif #endif
QString langCode = QString(currentLanguage).replace("-", "_"); QString langCode = QString(currentLanguage).replace("-", "_");
if (areaTranslations.contains(langCode)) { if (areaTranslations.contains(langCode))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode; qDebug() << "autoAreaLanguageSelected" << langCode;
#endif #endif
return langCode; return langCode;
} }
else if (langCode.contains("_")) { else if (langCode.contains("_"))
{
langCode = langCode.split("_").at(0); langCode = langCode.split("_").at(0);
if (!areaTranslations.contains(langCode)) if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
goto outputDefaultLanguage;
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode; qDebug() << "autoAreaLanguageSelected" << langCode;
#endif #endif
return langCode; return langCode;
} }
} }
else { else
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageModeGame"; qDebug() << "autoAreaLanguageModeGame";
#endif #endif
QString langCode = AppEnv::gameLanguageToString(gameLanguage).replace("-", "_"); QString langCode = AppEnv::gameLanguageToString(gameLanguage).replace("-", "_");
if (areaTranslations.contains(langCode)) { if (areaTranslations.contains(langCode))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode; qDebug() << "autoAreaLanguageSelected" << langCode;
#endif #endif
return langCode; return langCode;
} }
else if (langCode.contains("_")) { else if (langCode.contains("_"))
{
langCode = langCode.split("_").at(0); langCode = langCode.split("_").at(0);
if (!areaTranslations.contains(langCode)) if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
goto outputDefaultLanguage;
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode; qDebug() << "autoAreaLanguageSelected" << langCode;
#endif #endif
@ -528,16 +589,17 @@ QString TranslationClass::getCurrentAreaLanguage()
} }
} }
} }
else if (areaTranslations.contains(userAreaLanguage)) { else if (areaTranslations.contains(userAreaLanguage))
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "userAreaLanguageSelected" << userAreaLanguage; qDebug() << "userAreaLanguageSelected" << userAreaLanguage;
#endif #endif
return userAreaLanguage; return userAreaLanguage;
} }
else if (userAreaLanguage.contains("_")) { else if (userAreaLanguage.contains("_"))
const QString langCode = QString(userAreaLanguage).replace("-", "_").split("_").at(0); {
if (!areaTranslations.contains(langCode)) QString langCode = QString(userAreaLanguage).replace("-", "_").split("_").at(0);
goto outputDefaultLanguage; if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "userAreaLanguageSelected" << langCode; qDebug() << "userAreaLanguageSelected" << langCode;
#endif #endif
@ -562,7 +624,8 @@ bool TranslationClass::isLanguageLoaded()
void TranslationClass::unloadTranslation(QApplication *app) void TranslationClass::unloadTranslation(QApplication *app)
{ {
if (isLangLoaded) { if (isLangLoaded)
{
#ifndef GTA5SYNC_QCONF #ifndef GTA5SYNC_QCONF
app->removeTranslator(&exAppTranslator); app->removeTranslator(&exAppTranslator);
app->removeTranslator(&exQtTranslator); app->removeTranslator(&exQtTranslator);
@ -585,21 +648,30 @@ void TranslationClass::unloadTranslation(QApplication *app)
QString TranslationClass::getCountryCode(QLocale::Country country) QString TranslationClass::getCountryCode(QLocale::Country country)
{ {
const QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, country); QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage,
if (!locales.isEmpty()) { QLocale::AnyScript,
const QStringList localeStrList = locales.at(0).name().split("_"); country);
if (localeStrList.length() >= 2) { if (locales.isEmpty()) return QString();
QStringList localeStrList = locales.at(0).name().split("_");
if (localeStrList.length() >= 2)
{
return localeStrList.at(1).toLower(); return localeStrList.at(1).toLower();
} }
} else
{
return QString(); return QString();
} }
}
QString TranslationClass::getCountryCode(QLocale locale) QString TranslationClass::getCountryCode(QLocale locale)
{ {
QStringList localeStrList = locale.name().split("_"); QStringList localeStrList = locale.name().split("_");
if (localeStrList.length() >= 2) { if (localeStrList.length() >= 2)
{
return localeStrList.at(1).toLower(); return localeStrList.at(1).toLower();
} }
else
{
return QString(); return QString();
} }
}

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2019 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -46,16 +46,6 @@
#include <QDir> #include <QDir>
#include <QMap> #include <QMap>
#ifdef GTA5SYNC_DONATE
#ifdef GTA5SYNC_DONATE_ADDRESSES
#include <QSvgRenderer>
#include <QClipboard>
#include <QPainter>
#include "QrCode.h"
using namespace qrcodegen;
#endif
#endif
#ifdef GTA5SYNC_MOTD #ifdef GTA5SYNC_MOTD
UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, MessageThread *threadMessage, QWidget *parent) : UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, MessageThread *threadMessage, QWidget *parent) :
QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), threadMessage(threadMessage), QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), threadMessage(threadMessage),
@ -73,244 +63,113 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D
ui->menuProfile->setEnabled(false); ui->menuProfile->setEnabled(false);
ui->actionSelect_profile->setEnabled(false); ui->actionSelect_profile->setEnabled(false);
ui->actionAbout_gta5sync->setIcon(IconLoader::loadingAppIcon()); ui->actionAbout_gta5sync->setIcon(IconLoader::loadingAppIcon());
#ifdef Q_OS_MAC
ui->actionAbout_gta5sync->setText(QApplication::translate("MAC_APPLICATION_MENU", "About %1").arg(GTA5SYNC_APPSTR));
ui->actionOptions->setText(QApplication::translate("MAC_APPLICATION_MENU", "Preferences..."));
#else
ui->actionAbout_gta5sync->setText(tr("&About %1").arg(GTA5SYNC_APPSTR)); ui->actionAbout_gta5sync->setText(tr("&About %1").arg(GTA5SYNC_APPSTR));
#endif
ui->cmdClose->setToolTip(ui->cmdClose->toolTip().arg(GTA5SYNC_APPSTR)); ui->cmdClose->setToolTip(ui->cmdClose->toolTip().arg(GTA5SYNC_APPSTR));
defaultWindowTitle = tr("%2 - %1").arg("%1", GTA5SYNC_APPSTR); defaultWindowTitle = tr("%2 - %1").arg("%1", GTA5SYNC_APPSTR);
setWindowTitle(defaultWindowTitle.arg(tr("Select Profile"))); this->setWindowTitle(defaultWindowTitle.arg(tr("Select Profile")));
QString appVersion = QApplication::applicationVersion(); QString appVersion = GTA5SYNC_APPVER;
const char* literalBuildType = GTA5SYNC_BUILDTYPE; #ifndef GTA5SYNC_BUILDTYPE_REL
#ifdef GTA5SYNC_COMMIT #ifdef GTA5SYNC_COMMIT
if ((strcmp(literalBuildType, REL_BUILDTYPE) != 0) && !appVersion.contains("-")) if (!appVersion.contains("-")) { appVersion = appVersion % "-" % GTA5SYNC_COMMIT; }
appVersion = appVersion % "-" % GTA5SYNC_COMMIT; #endif
#endif #endif
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion)); ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion));
// Set Icon for Close Button // Set Icon for Close Button
if (QIcon::hasThemeIcon("dialog-close")) { if (QIcon::hasThemeIcon("dialog-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close")); ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
} }
else if (QIcon::hasThemeIcon("gtk-close")) { else if (QIcon::hasThemeIcon("gtk-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close")); ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close"));
} }
// Set Icon for Reload Button // Set Icon for Reload Button
if (QIcon::hasThemeIcon("view-refresh")) { if (QIcon::hasThemeIcon("view-refresh"))
{
ui->cmdReload->setIcon(QIcon::fromTheme("view-refresh")); ui->cmdReload->setIcon(QIcon::fromTheme("view-refresh"));
} }
else if (QIcon::hasThemeIcon("reload")) { else if (QIcon::hasThemeIcon("reload"))
{
ui->cmdReload->setIcon(QIcon::fromTheme("reload")); ui->cmdReload->setIcon(QIcon::fromTheme("reload"));
} }
// Set Icon for Choose GTA V Folder Menu Item // Set Icon for Choose GTA V Folder Menu Item
if (QIcon::hasThemeIcon("document-open-folder")) { if (QIcon::hasThemeIcon("document-open-folder"))
{
ui->actionSelect_GTA_Folder->setIcon(QIcon::fromTheme("document-open-folder")); ui->actionSelect_GTA_Folder->setIcon(QIcon::fromTheme("document-open-folder"));
} }
else if (QIcon::hasThemeIcon("gtk-directory")) { else if (QIcon::hasThemeIcon("gtk-directory"))
{
ui->actionSelect_GTA_Folder->setIcon(QIcon::fromTheme("gtk-directory")); ui->actionSelect_GTA_Folder->setIcon(QIcon::fromTheme("gtk-directory"));
} }
// Set Icon for Open File Menu Item // Set Icon for Open File Menu Item
if (QIcon::hasThemeIcon("document-open")) { if (QIcon::hasThemeIcon("document-open"))
{
ui->actionOpen_File->setIcon(QIcon::fromTheme("document-open")); ui->actionOpen_File->setIcon(QIcon::fromTheme("document-open"));
} }
// Set Icon for Close Profile Menu Item // Set Icon for Close Profile Menu Item
if (QIcon::hasThemeIcon("dialog-close")) { if (QIcon::hasThemeIcon("dialog-close"))
{
ui->actionSelect_profile->setIcon(QIcon::fromTheme("dialog-close")); ui->actionSelect_profile->setIcon(QIcon::fromTheme("dialog-close"));
} }
else if (QIcon::hasThemeIcon("gtk-close")) { else if (QIcon::hasThemeIcon("gtk-close"))
{
ui->actionSelect_profile->setIcon(QIcon::fromTheme("gtk-close")); ui->actionSelect_profile->setIcon(QIcon::fromTheme("gtk-close"));
} }
// Set Icon for Exit Menu Item // Set Icon for Exit Menu Item
if (QIcon::hasThemeIcon("application-exit")) { if (QIcon::hasThemeIcon("application-exit"))
{
#ifndef Q_OS_MACOS // Setting icon for exit/quit lead to a crash in Mac OS X #ifndef Q_OS_MACOS // Setting icon for exit/quit lead to a crash in Mac OS X
ui->actionExit->setIcon(QIcon::fromTheme("application-exit")); ui->actionExit->setIcon(QIcon::fromTheme("application-exit"));
#endif #endif
} }
// Set Icon for Preferences Menu Item // Set Icon for Preferences Menu Item
if (QIcon::hasThemeIcon("preferences-system")) { if (QIcon::hasThemeIcon("preferences-system"))
{
#ifndef Q_OS_MACOS // Setting icon for preferences/settings/options lead to a crash in Mac OS X #ifndef Q_OS_MACOS // Setting icon for preferences/settings/options lead to a crash in Mac OS X
ui->actionOptions->setIcon(QIcon::fromTheme("preferences-system")); ui->actionOptions->setIcon(QIcon::fromTheme("preferences-system"));
#endif #endif
} }
else if (QIcon::hasThemeIcon("configure")) { else if (QIcon::hasThemeIcon("configure"))
{
#ifndef Q_OS_MACOS // Setting icon for preferences/settings/options lead to a crash in Mac OS X #ifndef Q_OS_MACOS // Setting icon for preferences/settings/options lead to a crash in Mac OS X
ui->actionOptions->setIcon(QIcon::fromTheme("configure")); ui->actionOptions->setIcon(QIcon::fromTheme("configure"));
#endif #endif
} }
// Set Icon for Profile Import Menu Item // Set Icon for Profile Import Menu Item
if (QIcon::hasThemeIcon("document-import")) { if (QIcon::hasThemeIcon("document-import"))
{
ui->action_Import->setIcon(QIcon::fromTheme("document-import")); ui->action_Import->setIcon(QIcon::fromTheme("document-import"));
} }
else if (QIcon::hasThemeIcon("document-open")) { else if (QIcon::hasThemeIcon("document-open"))
{
ui->action_Import->setIcon(QIcon::fromTheme("document-open")); ui->action_Import->setIcon(QIcon::fromTheme("document-open"));
} }
// Set Icon for Profile Export Menu Item // Set Icon for Profile Export Menu Item
if (QIcon::hasThemeIcon("document-export")) { if (QIcon::hasThemeIcon("document-export"))
{
ui->actionExport_selected->setIcon(QIcon::fromTheme("document-export")); ui->actionExport_selected->setIcon(QIcon::fromTheme("document-export"));
} }
else if (QIcon::hasThemeIcon("document-save")) { else if (QIcon::hasThemeIcon("document-save"))
{
ui->actionExport_selected->setIcon(QIcon::fromTheme("document-save")); ui->actionExport_selected->setIcon(QIcon::fromTheme("document-save"));
} }
// Set Icon for Profile Remove Menu Item // Set Icon for Profile Remove Menu Item
if (QIcon::hasThemeIcon("remove")) { if (QIcon::hasThemeIcon("remove"))
{
ui->actionDelete_selected->setIcon(QIcon::fromTheme("remove")); ui->actionDelete_selected->setIcon(QIcon::fromTheme("remove"));
} }
#ifdef GTA5SYNC_DONATE
#ifdef GTA5SYNC_DONATE_ADDRESSES
donateAction = new QAction(tr("&Donate"), this);
if (QIcon::hasThemeIcon("help-donate")) {
donateAction->setIcon(QIcon::fromTheme("help-donate"));
}
else if (QIcon::hasThemeIcon("taxes-finances")) {
donateAction->setIcon(QIcon::fromTheme("taxes-finances"));
}
else {
donateAction->setIcon(QIcon(":/img/donate.svgz"));
}
ui->menuHelp->insertAction(ui->actionAbout_gta5sync, donateAction);
QObject::connect(donateAction, &QAction::triggered, this, [=](){
QDialog *donateDialog = new QDialog(this);
donateDialog->setWindowTitle(QString("%1 - %2").arg(GTA5SYNC_APPSTR, tr("Donate")));
#if QT_VERSION >= 0x050900
donateDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
donateDialog->setWindowFlags(donateDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
QVBoxLayout *donateLayout = new QVBoxLayout;
donateDialog->setLayout(donateLayout);
QLabel *methodsLabel = new QLabel(QString("<b>%1</b>").arg(tr("Donation methods").toHtmlEscaped()), donateDialog);
methodsLabel->setWordWrap(true);
donateLayout->addWidget(methodsLabel);
QHBoxLayout *currencyLayout = new QHBoxLayout;
donateLayout->addLayout(currencyLayout);
const QStringList addressList = QString::fromUtf8(GTA5SYNC_DONATE_ADDRESSES).split(',');
for (const QString &address : addressList) {
const QStringList addressList = address.split(':');
if (addressList.length() == 2) {
const QString currency = addressList.at(0);
const QString address = addressList.at(1);
QString currencyStr = currency;
const QString strPath = QString(":/donate/%1.str").arg(currency);
if (QFile::exists(strPath)) {
QFile strFile(strPath);
if (strFile.open(QIODevice::ReadOnly)) {
currencyStr = QString::fromUtf8(strFile.readAll());
strFile.close();
}
}
const QString iconPath = QString(":/donate/%1.svgz").arg(currency);
QPushButton *currencyButton = new QPushButton(currencyStr, donateDialog);
currencyButton->setToolTip(currencyStr);
if (QFile::exists(iconPath)) {
currencyButton->setIconSize(QSize(32, 32));
currencyButton->setIcon(QIcon(iconPath));
}
currencyLayout->addWidget(currencyButton);
QObject::connect(currencyButton, &QPushButton::pressed, donateDialog, [=](){
QDialog *addressDialog = new QDialog(donateDialog);
addressDialog->setWindowTitle(currencyStr);
#if QT_VERSION >= 0x050900
addressDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
addressDialog->setWindowFlags(donateDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
QVBoxLayout *addressLayout = new QVBoxLayout;
addressDialog->setLayout(addressLayout);
QLabel *addressLabel = new QLabel(address, addressDialog);
addressLabel->setAlignment(Qt::AlignCenter);
addressLabel->setTextFormat(Qt::PlainText);
addressLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
addressLayout->addWidget(addressLabel);
QHBoxLayout *qrLayout = new QHBoxLayout;
qrLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
QrCode qr = QrCode::encodeText(address.toUtf8().constData(), QrCode::Ecc::MEDIUM);
const std::string svgString = qr.toSvgString(0);
QSvgRenderer svgRenderer(QByteArray::fromRawData(svgString.c_str(), svgString.size()));
qreal screenRatioPR = AppEnv::screenRatioPR();
const QSize widgetSize = QSize(200, 200);
const QSize pixmapSize = widgetSize * screenRatioPR;
QPixmap qrPixmap(pixmapSize);
qrPixmap.fill(Qt::white);
QPainter qrPainter(&qrPixmap);
svgRenderer.render(&qrPainter, QRectF(QPointF(0, 0), pixmapSize));
qrPainter.end();
#if QT_VERSION >= 0x050600
qrPixmap.setDevicePixelRatio(screenRatioPR);
#endif
QLabel *qrLabel = new QLabel(addressDialog);
qrLabel->setFixedSize(widgetSize);
qrLabel->setPixmap(qrPixmap);
qrLayout->addWidget(qrLabel);
qrLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
addressLayout->addLayout(qrLayout);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
QPushButton *copyAddressButton = new QPushButton(tr("&Copy"), addressDialog);
if (QIcon::hasThemeIcon("edit-copy")) {
copyAddressButton->setIcon(QIcon::fromTheme("edit-copy"));
}
QObject::connect(copyAddressButton, &QPushButton::pressed, addressDialog, [=](){
QApplication::clipboard()->setText(address);
});
buttonLayout->addWidget(copyAddressButton);
QPushButton *closeButton = new QPushButton(tr("&Close"), addressDialog);
if (QIcon::hasThemeIcon("dialog-close")) {
closeButton->setIcon(QIcon::fromTheme("dialog-close"));
}
else if (QIcon::hasThemeIcon("gtk-close")) {
closeButton->setIcon(QIcon::fromTheme("gtk-close"));
}
closeButton->setDefault(true);
buttonLayout->addWidget(closeButton);
buttonLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
addressLayout->addLayout(buttonLayout);
QObject::connect(closeButton, &QPushButton::clicked, addressDialog, &QDialog::accept);
QObject::connect(addressDialog, &QDialog::finished, addressDialog, &QDialog::deleteLater);
QTimer::singleShot(0, addressDialog, [=](){
addressDialog->setFocus();
});
addressDialog->open();
addressDialog->setFixedSize(addressDialog->size());
});
}
}
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
QPushButton *closeButton = new QPushButton(donateDialog);
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"));
}
closeButton->setDefault(true);
buttonLayout->addWidget(closeButton);
donateLayout->addLayout(buttonLayout);
QObject::connect(closeButton, &QPushButton::clicked, donateDialog, &QDialog::accept);
QObject::connect(donateDialog, &QDialog::finished, donateDialog, &QDialog::deleteLater);
QTimer::singleShot(0, donateDialog, [=](){
donateDialog->setFocus();
});
donateDialog->open();
donateDialog->setFixedSize(donateDialog->size());
});
#endif
#endif
// DPI calculation // DPI calculation
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
#ifndef Q_QS_ANDROID #ifndef Q_QS_ANDROID
@ -327,38 +186,45 @@ void UserInterface::setupDirEnv(bool showFolderDialog)
bool folderExists; bool folderExists;
GTAV_Folder = AppEnv::getGameFolder(&folderExists); GTAV_Folder = AppEnv::getGameFolder(&folderExists);
if (folderExists) { if (folderExists)
{
QDir::setCurrent(GTAV_Folder); QDir::setCurrent(GTAV_Folder);
} }
else if (showFolderDialog) { else
{
if (showFolderDialog)
{
GTAV_Folder = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly); GTAV_Folder = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly);
if (QDir(GTAV_Folder).exists()) { if (QFileInfo(GTAV_Folder).exists())
{
folderExists = true; folderExists = true;
QDir::setCurrent(GTAV_Folder); QDir::setCurrent(GTAV_Folder);
AppEnv::setGameFolder(GTAV_Folder); AppEnv::setGameFolder(GTAV_Folder);
// First time folder selection save // First time folder selection save
settings.beginGroup("dir"); settings.beginGroup("dir");
if (settings.value("dir", "").toString().isEmpty()) { if (settings.value("dir", "").toString().isEmpty())
{
settings.setValue("dir", GTAV_Folder); settings.setValue("dir", GTAV_Folder);
} }
settings.endGroup(); settings.endGroup();
} }
} }
}
// profiles init // profiles init
settings.beginGroup("Profile"); settings.beginGroup("Profile");
QString defaultProfile = settings.value("Default", "").toString(); QString defaultProfile = settings.value("Default", "").toString();
contentMode = settings.value("ContentMode", 0).toInt(); bool contentModeOk;
if (contentMode == 1) { contentMode = settings.value("ContentMode", 0).toInt(&contentModeOk);
contentMode = 21; if (contentMode != 0 && contentMode != 1 && contentMode != 2)
} {
else if (contentMode != 10 && contentMode != 11 && contentMode != 20 && contentMode != 21) { contentMode = 0;
contentMode = 20;
} }
if (folderExists) { if (folderExists)
{
QDir GTAV_ProfilesDir; QDir GTAV_ProfilesDir;
GTAV_ProfilesFolder = GTAV_Folder % "/Profiles"; GTAV_ProfilesFolder = GTAV_Folder % "/Profiles";
GTAV_ProfilesDir.setPath(GTAV_ProfilesFolder); GTAV_ProfilesDir.setPath(GTAV_ProfilesFolder);
@ -366,14 +232,17 @@ void UserInterface::setupDirEnv(bool showFolderDialog)
GTAV_Profiles = GTAV_ProfilesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::NoSort); GTAV_Profiles = GTAV_ProfilesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::NoSort);
setupProfileUi(); setupProfileUi();
if (GTAV_Profiles.length() == 1) { if (GTAV_Profiles.length() == 1)
{
openProfile(GTAV_Profiles.at(0)); openProfile(GTAV_Profiles.at(0));
} }
else if(GTAV_Profiles.contains(defaultProfile)) { else if(GTAV_Profiles.contains(defaultProfile))
{
openProfile(defaultProfile); openProfile(defaultProfile);
} }
} }
else { else
{
GTAV_Profiles = QStringList(); GTAV_Profiles = QStringList();
setupProfileUi(); setupProfileUi();
} }
@ -383,7 +252,8 @@ void UserInterface::setupDirEnv(bool showFolderDialog)
void UserInterface::setupProfileUi() void UserInterface::setupProfileUi()
{ {
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
if (GTAV_Profiles.isEmpty()) { if (GTAV_Profiles.isEmpty())
{
QPushButton *changeDirBtn = new QPushButton(tr("Select &GTA V Folder..."), ui->swSelection); QPushButton *changeDirBtn = new QPushButton(tr("Select &GTA V Folder..."), ui->swSelection);
changeDirBtn->setObjectName("cmdChangeDir"); changeDirBtn->setObjectName("cmdChangeDir");
changeDirBtn->setMinimumSize(0, 40 * screenRatio); changeDirBtn->setMinimumSize(0, 40 * screenRatio);
@ -393,7 +263,8 @@ void UserInterface::setupProfileUi()
QObject::connect(changeDirBtn, SIGNAL(clicked(bool)), this, SLOT(changeFolder_clicked())); QObject::connect(changeDirBtn, SIGNAL(clicked(bool)), this, SLOT(changeFolder_clicked()));
} }
else for (const QString &GTAV_Profile : GTAV_Profiles) { else for (QString GTAV_Profile : GTAV_Profiles)
{
QPushButton *profileBtn = new QPushButton(GTAV_Profile, ui->swSelection); QPushButton *profileBtn = new QPushButton(GTAV_Profile, ui->swSelection);
profileBtn->setObjectName(GTAV_Profile); profileBtn->setObjectName(GTAV_Profile);
profileBtn->setMinimumSize(0, 40 * screenRatio); profileBtn->setMinimumSize(0, 40 * screenRatio);
@ -413,7 +284,8 @@ void UserInterface::changeFolder_clicked()
void UserInterface::on_cmdReload_clicked() void UserInterface::on_cmdReload_clicked()
{ {
for (QPushButton *profileBtn : profileBtns) { for (QPushButton *profileBtn : profileBtns)
{
ui->vlButtons->removeWidget(profileBtn); ui->vlButtons->removeWidget(profileBtn);
delete profileBtn; delete profileBtn;
} }
@ -439,15 +311,16 @@ void UserInterface::openProfile(const QString &profileName_)
profileUI->setupProfileInterface(); profileUI->setupProfileInterface();
QObject::connect(profileUI, SIGNAL(profileClosed()), this, SLOT(closeProfile())); QObject::connect(profileUI, SIGNAL(profileClosed()), this, SLOT(closeProfile()));
QObject::connect(profileUI, SIGNAL(profileLoaded()), this, SLOT(profileLoaded())); QObject::connect(profileUI, SIGNAL(profileLoaded()), this, SLOT(profileLoaded()));
setWindowTitle(defaultWindowTitle.arg(profileName)); this->setWindowTitle(defaultWindowTitle.arg(profileName));
} }
void UserInterface::closeProfile() void UserInterface::closeProfile()
{ {
if (profileOpen) { if (profileOpen)
{
closeProfile_p(); closeProfile_p();
} }
setWindowTitle(defaultWindowTitle.arg(tr("Select Profile"))); this->setWindowTitle(defaultWindowTitle.arg(tr("Select Profile")));
} }
void UserInterface::closeProfile_p() void UserInterface::closeProfile_p()
@ -475,8 +348,11 @@ void UserInterface::closeEvent(QCloseEvent *ev)
UserInterface::~UserInterface() UserInterface::~UserInterface()
{ {
if (profileOpen) if (profileOpen)
{
closeProfile_p(); closeProfile_p();
for (QPushButton *profileBtn : profileBtns) { }
for (QPushButton *profileBtn : profileBtns)
{
delete profileBtn; delete profileBtn;
} }
profileBtns.clear(); profileBtns.clear();
@ -485,7 +361,7 @@ UserInterface::~UserInterface()
void UserInterface::on_actionExit_triggered() void UserInterface::on_actionExit_triggered()
{ {
close(); this->close();
} }
void UserInterface::on_actionSelect_profile_triggered() void UserInterface::on_actionSelect_profile_triggered()
@ -523,26 +399,34 @@ void UserInterface::profileLoaded()
void UserInterface::on_actionSelect_all_triggered() void UserInterface::on_actionSelect_all_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->selectAllWidgets(); profileUI->selectAllWidgets();
} }
}
void UserInterface::on_actionDeselect_all_triggered() void UserInterface::on_actionDeselect_all_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->deselectAllWidgets(); profileUI->deselectAllWidgets();
} }
}
void UserInterface::on_actionExport_selected_triggered() void UserInterface::on_actionExport_selected_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->exportSelected(); profileUI->exportSelected();
} }
}
void UserInterface::on_actionDelete_selected_triggered() void UserInterface::on_actionDelete_selected_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->deleteSelected(); profileUI->deleteSelected();
} }
}
void UserInterface::on_actionOptions_triggered() void UserInterface::on_actionOptions_triggered()
{ {
@ -566,8 +450,10 @@ void UserInterface::on_actionOptions_triggered()
void UserInterface::on_action_Import_triggered() void UserInterface::on_action_Import_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->importFiles(); profileUI->importFiles();
} }
}
void UserInterface::on_actionOpen_File_triggered() void UserInterface::on_actionOpen_File_triggered()
{ {
@ -580,11 +466,7 @@ fileDialogPreOpen:
fileDialog.setViewMode(QFileDialog::Detail); fileDialog.setViewMode(QFileDialog::Detail);
fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setOption(QFileDialog::DontUseNativeDialog, false); fileDialog.setOption(QFileDialog::DontUseNativeDialog, false);
#if QT_VERSION >= 0x050900
fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint); fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
fileDialog.setWindowTitle(tr("Open File...")); fileDialog.setWindowTitle(tr("Open File..."));
QStringList filters; QStringList filters;
@ -601,9 +483,11 @@ fileDialogPreOpen:
fileDialog.setDirectory(settings.value("OpenDialogDirectory", StandardPaths::documentsLocation()).toString()); fileDialog.setDirectory(settings.value("OpenDialogDirectory", StandardPaths::documentsLocation()).toString());
fileDialog.restoreGeometry(settings.value("OpenDialogGeometry","").toByteArray()); fileDialog.restoreGeometry(settings.value("OpenDialogGeometry","").toByteArray());
if (fileDialog.exec()) { if (fileDialog.exec())
{
QStringList selectedFiles = fileDialog.selectedFiles(); QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1) { if (selectedFiles.length() == 1)
{
QString selectedFile = selectedFiles.at(0); QString selectedFile = selectedFiles.at(0);
if (!openFile(selectedFile, true)) goto fileDialogPreOpen; if (!openFile(selectedFile, true)) goto fileDialogPreOpen;
} }
@ -617,61 +501,68 @@ fileDialogPreOpen:
bool UserInterface::openFile(QString selectedFile, bool warn) bool UserInterface::openFile(QString selectedFile, bool warn)
{ {
QString selectedFileName = QFileInfo(selectedFile).fileName(); QString selectedFileName = QFileInfo(selectedFile).fileName();
if (QFile::exists(selectedFile)) { if (QFile::exists(selectedFile))
if (selectedFileName.left(4) == "PGTA" || selectedFileName.right(4) == ".g5e") { {
if (selectedFileName.left(4) == "PGTA" || selectedFileName.right(4) == ".g5e")
{
SnapmaticPicture *picture = new SnapmaticPicture(selectedFile); SnapmaticPicture *picture = new SnapmaticPicture(selectedFile);
if (picture->readingPicture()) { if (picture->readingPicture())
{
openSnapmaticFile(picture); openSnapmaticFile(picture);
delete picture; delete picture;
return true; return true;
} }
else { else
if (warn) {
QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("Failed to read Snapmatic picture")); if (warn) QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("Failed to read Snapmatic picture"));
delete picture; delete picture;
return false; return false;
} }
} }
else if (selectedFileName.left(4) == "SGTA") { else if (selectedFileName.left(4) == "SGTA")
{
SavegameData *savegame = new SavegameData(selectedFile); SavegameData *savegame = new SavegameData(selectedFile);
if (savegame->readingSavegame()) { if (savegame->readingSavegame())
{
openSavegameFile(savegame); openSavegameFile(savegame);
delete savegame; delete savegame;
return true; return true;
} }
else { else
if (warn) {
QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("Failed to read Savegame file")); if (warn) QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("Failed to read Savegame file"));
delete savegame; delete savegame;
return false; return false;
} }
} }
else { else
{
SnapmaticPicture *picture = new SnapmaticPicture(selectedFile); SnapmaticPicture *picture = new SnapmaticPicture(selectedFile);
SavegameData *savegame = new SavegameData(selectedFile); SavegameData *savegame = new SavegameData(selectedFile);
if (picture->readingPicture()) { if (picture->readingPicture())
{
delete savegame; delete savegame;
openSnapmaticFile(picture); openSnapmaticFile(picture);
delete picture; delete picture;
return true; return true;
} }
else if (savegame->readingSavegame()) { else if (savegame->readingSavegame())
{
delete picture; delete picture;
openSavegameFile(savegame); openSavegameFile(savegame);
delete savegame; delete savegame;
return true; return true;
} }
else { else
{
delete savegame; delete savegame;
delete picture; delete picture;
if (warn) if (warn) QMessageBox::warning(this, tr("Open File"), tr("Can't open %1 because of not valid file format").arg("\""+selectedFileName+"\""));
QMessageBox::warning(this, tr("Open File"), tr("Can't open %1 because of not valid file format").arg("\""+selectedFileName+"\""));
return false; return false;
} }
} }
} }
if (warn) if (warn) QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("No valid file is selected"));
QMessageBox::warning(this, tr("Open File"), ProfileInterface::tr("No valid file is selected"));
return false; return false;
} }
@ -682,8 +573,7 @@ void UserInterface::openSnapmaticFile(SnapmaticPicture *picture)
picDialog.setModal(true); picDialog.setModal(true);
int crewID = picture->getSnapmaticProperties().crewID; int crewID = picture->getSnapmaticProperties().crewID;
if (crewID != 0) if (crewID != 0) { crewDB->addCrew(crewID); }
crewDB->addCrew(crewID);
QObject::connect(threadDB, SIGNAL(crewNameUpdated()), &picDialog, SLOT(crewNameUpdated())); QObject::connect(threadDB, SIGNAL(crewNameUpdated()), &picDialog, SLOT(crewNameUpdated()));
QObject::connect(threadDB, SIGNAL(playerNameUpdated()), &picDialog, SLOT(playerNameUpdated())); QObject::connect(threadDB, SIGNAL(playerNameUpdated()), &picDialog, SLOT(playerNameUpdated()));
@ -716,11 +606,13 @@ void UserInterface::openSavegameFile(SavegameData *savegame)
void UserInterface::settingsApplied(int _contentMode, bool languageChanged) void UserInterface::settingsApplied(int _contentMode, bool languageChanged)
{ {
if (languageChanged) { if (languageChanged)
{
retranslateUi(); retranslateUi();
} }
contentMode = _contentMode; contentMode = _contentMode;
if (profileOpen) { if (profileOpen)
{
profileUI->settingsApplied(contentMode, languageChanged); profileUI->settingsApplied(contentMode, languageChanged);
} }
} }
@ -754,11 +646,7 @@ void UserInterface::showMessages(const QStringList messages)
{ {
QDialog *messageDialog = new QDialog(this); QDialog *messageDialog = new QDialog(this);
messageDialog->setWindowTitle(tr("%1 - Messages").arg(GTA5SYNC_APPSTR)); messageDialog->setWindowTitle(tr("%1 - Messages").arg(GTA5SYNC_APPSTR));
#if QT_VERSION >= 0x050900
messageDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
messageDialog->setWindowFlags(messageDialog->windowFlags()^Qt::WindowContextHelpButtonHint); messageDialog->setWindowFlags(messageDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
QVBoxLayout *messageLayout = new QVBoxLayout; QVBoxLayout *messageLayout = new QVBoxLayout;
messageDialog->setLayout(messageLayout); messageDialog->setLayout(messageLayout);
QStackedWidget *stackWidget = new QStackedWidget(messageDialog); QStackedWidget *stackWidget = new QStackedWidget(messageDialog);
@ -777,8 +665,8 @@ void UserInterface::showMessages(const QStringList messages)
nextButton->setIcon(QIcon::fromTheme("go-next")); nextButton->setIcon(QIcon::fromTheme("go-next"));
} }
else { else {
backButton->setIcon(QIcon(AppEnv::getImagesFolder() % "/back.svgz")); backButton->setIcon(QIcon(":/img/back.svgz"));
nextButton->setIcon(QIcon(AppEnv::getImagesFolder() % "/next.svgz")); nextButton->setIcon(QIcon(":/img/next.svgz"));
} }
backButton->setEnabled(false); backButton->setEnabled(false);
if (stackWidget->count() <= 1) { if (stackWidget->count() <= 1) {
@ -829,9 +717,7 @@ void UserInterface::showMessages(const QStringList messages)
}); });
QObject::connect(closeButton, &QPushButton::clicked, messageDialog, &QDialog::accept); QObject::connect(closeButton, &QPushButton::clicked, messageDialog, &QDialog::accept);
QObject::connect(messageDialog, &QDialog::finished, messageDialog, &QDialog::deleteLater); QObject::connect(messageDialog, &QDialog::finished, messageDialog, &QDialog::deleteLater);
QTimer::singleShot(0, closeButton, [=](){ QTimer::singleShot(0, closeButton, SLOT(setFocus()));
closeButton->setFocus();
});
messageDialog->show(); messageDialog->show();
} }
@ -847,8 +733,10 @@ void UserInterface::updateCacheId(uint cacheId)
void UserInterface::on_actionSelect_GTA_Folder_triggered() void UserInterface::on_actionSelect_GTA_Folder_triggered()
{ {
QString GTAV_Folder_Temp = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly); QString GTAV_Folder_Temp = QFileDialog::getExistingDirectory(this, tr("Select GTA V Folder..."), StandardPaths::documentsLocation(), QFileDialog::ShowDirsOnly);
if (QDir(GTAV_Folder_Temp).exists()) { if (QFileInfo(GTAV_Folder_Temp).exists())
if (profileOpen) { {
if (profileOpen)
{
closeProfile_p(); closeProfile_p();
} }
GTAV_Folder = GTAV_Folder_Temp; GTAV_Folder = GTAV_Folder_Temp;
@ -861,41 +749,37 @@ void UserInterface::on_actionSelect_GTA_Folder_triggered()
void UserInterface::on_action_Enable_In_game_triggered() void UserInterface::on_action_Enable_In_game_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->enableSelected(); profileUI->enableSelected();
} }
}
void UserInterface::on_action_Disable_In_game_triggered() void UserInterface::on_action_Disable_In_game_triggered()
{ {
if (profileOpen) if (profileOpen)
{
profileUI->disableSelected(); profileUI->disableSelected();
} }
}
void UserInterface::retranslateUi() void UserInterface::retranslateUi()
{ {
ui->retranslateUi(this); ui->retranslateUi(this);
#ifdef GTA5SYNC_DONATE
#ifdef GTA5SYNC_DONATE_ADDRESSES
donateAction->setText(tr("&Donate"));
#endif
#endif
#ifdef Q_OS_MAC
ui->actionAbout_gta5sync->setText(QApplication::translate("MAC_APPLICATION_MENU", "About %1").arg(GTA5SYNC_APPSTR));
ui->actionOptions->setText(QApplication::translate("MAC_APPLICATION_MENU", "Preferences..."));
#else
ui->actionAbout_gta5sync->setText(tr("&About %1").arg(GTA5SYNC_APPSTR)); ui->actionAbout_gta5sync->setText(tr("&About %1").arg(GTA5SYNC_APPSTR));
#endif QString appVersion = GTA5SYNC_APPVER;
QString appVersion = QApplication::applicationVersion(); #ifndef GTA5SYNC_BUILDTYPE_REL
const char* literalBuildType = GTA5SYNC_BUILDTYPE;
#ifdef GTA5SYNC_COMMIT #ifdef GTA5SYNC_COMMIT
if ((strcmp(literalBuildType, REL_BUILDTYPE) != 0) && !appVersion.contains("-")) if (!appVersion.contains("-")) { appVersion = appVersion % "-" % GTA5SYNC_COMMIT; }
appVersion = appVersion % "-" % GTA5SYNC_COMMIT; #endif
#endif #endif
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion)); ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion));
if (profileOpen) { if (profileOpen)
setWindowTitle(defaultWindowTitle.arg(profileName)); {
this->setWindowTitle(defaultWindowTitle.arg(profileName));
} }
else { else
setWindowTitle(defaultWindowTitle.arg(tr("Select Profile"))); {
this->setWindowTitle(defaultWindowTitle.arg(tr("Select Profile")));
} }
} }

View file

@ -90,11 +90,6 @@ private:
DatabaseThread *threadDB; DatabaseThread *threadDB;
#ifdef GTA5SYNC_MOTD #ifdef GTA5SYNC_MOTD
MessageThread *threadMessage; MessageThread *threadMessage;
#endif
#ifdef GTA5SYNC_DONATE
#ifdef GTA5SYNC_DONATE_ADDRESSES
QAction *donateAction;
#endif
#endif #endif
Ui::UserInterface *ui; Ui::UserInterface *ui;
ProfileInterface *profileUI; ProfileInterface *profileUI;

View file

@ -1,862 +0,0 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#include <algorithm>
#include <climits>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stdexcept>
#include <utility>
#include "QrCode.h"
using std::int8_t;
using std::uint8_t;
using std::size_t;
using std::vector;
namespace qrcodegen {
QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) :
modeBits(mode) {
numBitsCharCount[0] = cc0;
numBitsCharCount[1] = cc1;
numBitsCharCount[2] = cc2;
}
int QrSegment::Mode::getModeBits() const {
return modeBits;
}
int QrSegment::Mode::numCharCountBits(int ver) const {
return numBitsCharCount[(ver + 7) / 17];
}
const QrSegment::Mode QrSegment::Mode::NUMERIC (0x1, 10, 12, 14);
const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13);
const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16);
const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12);
const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0);
QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) {
if (data.size() > static_cast<unsigned int>(INT_MAX))
throw std::length_error("Data too long");
BitBuffer bb;
for (uint8_t b : data)
bb.appendBits(b, 8);
return QrSegment(Mode::BYTE, static_cast<int>(data.size()), std::move(bb));
}
QrSegment QrSegment::makeNumeric(const char *digits) {
BitBuffer bb;
int accumData = 0;
int accumCount = 0;
int charCount = 0;
for (; *digits != '\0'; digits++, charCount++) {
char c = *digits;
if (c < '0' || c > '9')
throw std::domain_error("String contains non-numeric characters");
accumData = accumData * 10 + (c - '0');
accumCount++;
if (accumCount == 3) {
bb.appendBits(static_cast<uint32_t>(accumData), 10);
accumData = 0;
accumCount = 0;
}
}
if (accumCount > 0) // 1 or 2 digits remaining
bb.appendBits(static_cast<uint32_t>(accumData), accumCount * 3 + 1);
return QrSegment(Mode::NUMERIC, charCount, std::move(bb));
}
QrSegment QrSegment::makeAlphanumeric(const char *text) {
BitBuffer bb;
int accumData = 0;
int accumCount = 0;
int charCount = 0;
for (; *text != '\0'; text++, charCount++) {
const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text);
if (temp == nullptr)
throw std::domain_error("String contains unencodable characters in alphanumeric mode");
accumData = accumData * 45 + static_cast<int>(temp - ALPHANUMERIC_CHARSET);
accumCount++;
if (accumCount == 2) {
bb.appendBits(static_cast<uint32_t>(accumData), 11);
accumData = 0;
accumCount = 0;
}
}
if (accumCount > 0) // 1 character remaining
bb.appendBits(static_cast<uint32_t>(accumData), 6);
return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb));
}
vector<QrSegment> QrSegment::makeSegments(const char *text) {
// Select the most efficient segment encoding automatically
vector<QrSegment> result;
if (*text == '\0'); // Leave result empty
else if (isNumeric(text))
result.push_back(makeNumeric(text));
else if (isAlphanumeric(text))
result.push_back(makeAlphanumeric(text));
else {
vector<uint8_t> bytes;
for (; *text != '\0'; text++)
bytes.push_back(static_cast<uint8_t>(*text));
result.push_back(makeBytes(bytes));
}
return result;
}
QrSegment QrSegment::makeEci(long assignVal) {
BitBuffer bb;
if (assignVal < 0)
throw std::domain_error("ECI assignment value out of range");
else if (assignVal < (1 << 7))
bb.appendBits(static_cast<uint32_t>(assignVal), 8);
else if (assignVal < (1 << 14)) {
bb.appendBits(2, 2);
bb.appendBits(static_cast<uint32_t>(assignVal), 14);
} else if (assignVal < 1000000L) {
bb.appendBits(6, 3);
bb.appendBits(static_cast<uint32_t>(assignVal), 21);
} else
throw std::domain_error("ECI assignment value out of range");
return QrSegment(Mode::ECI, 0, std::move(bb));
}
QrSegment::QrSegment(Mode md, int numCh, const std::vector<bool> &dt) :
mode(md),
numChars(numCh),
data(dt) {
if (numCh < 0)
throw std::domain_error("Invalid value");
}
QrSegment::QrSegment(Mode md, int numCh, std::vector<bool> &&dt) :
mode(md),
numChars(numCh),
data(std::move(dt)) {
if (numCh < 0)
throw std::domain_error("Invalid value");
}
int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
int result = 0;
for (const QrSegment &seg : segs) {
int ccbits = seg.mode.numCharCountBits(version);
if (seg.numChars >= (1L << ccbits))
return -1; // The segment's length doesn't fit the field's bit width
if (4 + ccbits > INT_MAX - result)
return -1; // The sum will overflow an int type
result += 4 + ccbits;
if (seg.data.size() > static_cast<unsigned int>(INT_MAX - result))
return -1; // The sum will overflow an int type
result += static_cast<int>(seg.data.size());
}
return result;
}
bool QrSegment::isAlphanumeric(const char *text) {
for (; *text != '\0'; text++) {
if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr)
return false;
}
return true;
}
bool QrSegment::isNumeric(const char *text) {
for (; *text != '\0'; text++) {
char c = *text;
if (c < '0' || c > '9')
return false;
}
return true;
}
QrSegment::Mode QrSegment::getMode() const {
return mode;
}
int QrSegment::getNumChars() const {
return numChars;
}
const std::vector<bool> &QrSegment::getData() const {
return data;
}
const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
int QrCode::getFormatBits(Ecc ecl) {
switch (ecl) {
case Ecc::LOW : return 1;
case Ecc::MEDIUM : return 0;
case Ecc::QUARTILE: return 3;
case Ecc::HIGH : return 2;
default: throw std::logic_error("Assertion error");
}
}
QrCode QrCode::encodeText(const char *text, Ecc ecl) {
vector<QrSegment> segs = QrSegment::makeSegments(text);
return encodeSegments(segs, ecl);
}
QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
vector<QrSegment> segs{QrSegment::makeBytes(data)};
return encodeSegments(segs, ecl);
}
QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
int minVersion, int maxVersion, int mask, bool boostEcl) {
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
throw std::invalid_argument("Invalid value");
// Find the minimal version number to use
int version, dataUsedBits;
for (version = minVersion; ; version++) {
int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available
dataUsedBits = QrSegment::getTotalBits(segs, version);
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable
if (version >= maxVersion) { // All versions in the range could not fit the given data
std::ostringstream sb;
if (dataUsedBits == -1)
sb << "Segment too long";
else {
sb << "Data length = " << dataUsedBits << " bits, ";
sb << "Max capacity = " << dataCapacityBits << " bits";
}
throw data_too_long(sb.str());
}
}
if (dataUsedBits == -1)
throw std::logic_error("Assertion error");
// Increase the error correction level while the data still fits in the current version number
for (Ecc newEcl : vector<Ecc>{Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { // From low to high
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
// Concatenate all segments to create the data bit string
BitBuffer bb;
for (const QrSegment &seg : segs) {
bb.appendBits(static_cast<uint32_t>(seg.getMode().getModeBits()), 4);
bb.appendBits(static_cast<uint32_t>(seg.getNumChars()), seg.getMode().numCharCountBits(version));
bb.insert(bb.end(), seg.getData().begin(), seg.getData().end());
}
if (bb.size() != static_cast<unsigned int>(dataUsedBits))
throw std::logic_error("Assertion error");
// Add terminator and pad up to a byte if applicable
size_t dataCapacityBits = static_cast<size_t>(getNumDataCodewords(version, ecl)) * 8;
if (bb.size() > dataCapacityBits)
throw std::logic_error("Assertion error");
bb.appendBits(0, std::min(4, static_cast<int>(dataCapacityBits - bb.size())));
bb.appendBits(0, (8 - static_cast<int>(bb.size() % 8)) % 8);
if (bb.size() % 8 != 0)
throw std::logic_error("Assertion error");
// Pad with alternating bytes until data capacity is reached
for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
// Pack bits into bytes in big endian
vector<uint8_t> dataCodewords(bb.size() / 8);
for (size_t i = 0; i < bb.size(); i++)
dataCodewords[i >> 3] |= (bb.at(i) ? 1 : 0) << (7 - (i & 7));
// Create the QR Code object
return QrCode(version, ecl, dataCodewords, mask);
}
QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int msk) :
// Initialize fields and check arguments
version(ver),
errorCorrectionLevel(ecl) {
if (ver < MIN_VERSION || ver > MAX_VERSION)
throw std::domain_error("Version value out of range");
if (msk < -1 || msk > 7)
throw std::domain_error("Mask value out of range");
size = ver * 4 + 17;
size_t sz = static_cast<size_t>(size);
modules = vector<vector<bool> >(sz, vector<bool>(sz)); // Initially all white
isFunction = vector<vector<bool> >(sz, vector<bool>(sz));
// Compute ECC, draw modules
drawFunctionPatterns();
const vector<uint8_t> allCodewords = addEccAndInterleave(dataCodewords);
drawCodewords(allCodewords);
// Do masking
if (msk == -1) { // Automatically choose best mask
long minPenalty = LONG_MAX;
for (int i = 0; i < 8; i++) {
applyMask(i);
drawFormatBits(i);
long penalty = getPenaltyScore();
if (penalty < minPenalty) {
msk = i;
minPenalty = penalty;
}
applyMask(i); // Undoes the mask due to XOR
}
}
if (msk < 0 || msk > 7)
throw std::logic_error("Assertion error");
this->mask = msk;
applyMask(msk); // Apply the final choice of mask
drawFormatBits(msk); // Overwrite old format bits
isFunction.clear();
isFunction.shrink_to_fit();
}
int QrCode::getVersion() const {
return version;
}
int QrCode::getSize() const {
return size;
}
QrCode::Ecc QrCode::getErrorCorrectionLevel() const {
return errorCorrectionLevel;
}
int QrCode::getMask() const {
return mask;
}
bool QrCode::getModule(int x, int y) const {
return 0 <= x && x < size && 0 <= y && y < size && module(x, y);
}
std::string QrCode::toSvgString(int border) const {
if (border < 0)
throw std::domain_error("Border must be non-negative");
if (border > INT_MAX / 2 || border * 2 > INT_MAX - size)
throw std::overflow_error("Border too large");
std::ostringstream sb;
sb << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
sb << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
sb << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ";
sb << (size + border * 2) << " " << (size + border * 2) << "\" stroke=\"none\">\n";
sb << "\t<rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\"/>\n";
sb << "\t<path d=\"";
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (getModule(x, y)) {
if (x != 0 || y != 0)
sb << " ";
sb << "M" << (x + border) << "," << (y + border) << "h1v1h-1z";
}
}
}
sb << "\" fill=\"#000000\"/>\n";
sb << "</svg>\n";
return sb.str();
}
void QrCode::drawFunctionPatterns() {
// Draw horizontal and vertical timing patterns
for (int i = 0; i < size; i++) {
setFunctionModule(6, i, i % 2 == 0);
setFunctionModule(i, 6, i % 2 == 0);
}
// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
drawFinderPattern(3, 3);
drawFinderPattern(size - 4, 3);
drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns
const vector<int> alignPatPos = getAlignmentPatternPositions();
size_t numAlign = alignPatPos.size();
for (size_t i = 0; i < numAlign; i++) {
for (size_t j = 0; j < numAlign; j++) {
// Don't draw on the three finder corners
if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)))
drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j));
}
}
// Draw configuration data
drawFormatBits(0); // Dummy mask value; overwritten later in the constructor
drawVersion();
}
void QrCode::drawFormatBits(int msk) {
// Calculate error correction code and pack bits
int data = getFormatBits(errorCorrectionLevel) << 3 | msk; // errCorrLvl is uint2, msk is uint3
int rem = data;
for (int i = 0; i < 10; i++)
rem = (rem << 1) ^ ((rem >> 9) * 0x537);
int bits = (data << 10 | rem) ^ 0x5412; // uint15
if (bits >> 15 != 0)
throw std::logic_error("Assertion error");
// Draw first copy
for (int i = 0; i <= 5; i++)
setFunctionModule(8, i, getBit(bits, i));
setFunctionModule(8, 7, getBit(bits, 6));
setFunctionModule(8, 8, getBit(bits, 7));
setFunctionModule(7, 8, getBit(bits, 8));
for (int i = 9; i < 15; i++)
setFunctionModule(14 - i, 8, getBit(bits, i));
// Draw second copy
for (int i = 0; i < 8; i++)
setFunctionModule(size - 1 - i, 8, getBit(bits, i));
for (int i = 8; i < 15; i++)
setFunctionModule(8, size - 15 + i, getBit(bits, i));
setFunctionModule(8, size - 8, true); // Always black
}
void QrCode::drawVersion() {
if (version < 7)
return;
// Calculate error correction code and pack bits
int rem = version; // version is uint6, in the range [7, 40]
for (int i = 0; i < 12; i++)
rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
long bits = static_cast<long>(version) << 12 | rem; // uint18
if (bits >> 18 != 0)
throw std::logic_error("Assertion error");
// Draw two copies
for (int i = 0; i < 18; i++) {
bool bit = getBit(bits, i);
int a = size - 11 + i % 3;
int b = i / 3;
setFunctionModule(a, b, bit);
setFunctionModule(b, a, bit);
}
}
void QrCode::drawFinderPattern(int x, int y) {
for (int dy = -4; dy <= 4; dy++) {
for (int dx = -4; dx <= 4; dx++) {
int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm
int xx = x + dx, yy = y + dy;
if (0 <= xx && xx < size && 0 <= yy && yy < size)
setFunctionModule(xx, yy, dist != 2 && dist != 4);
}
}
}
void QrCode::drawAlignmentPattern(int x, int y) {
for (int dy = -2; dy <= 2; dy++) {
for (int dx = -2; dx <= 2; dx++)
setFunctionModule(x + dx, y + dy, std::max(std::abs(dx), std::abs(dy)) != 1);
}
}
void QrCode::setFunctionModule(int x, int y, bool isBlack) {
size_t ux = static_cast<size_t>(x);
size_t uy = static_cast<size_t>(y);
modules .at(uy).at(ux) = isBlack;
isFunction.at(uy).at(ux) = true;
}
bool QrCode::module(int x, int y) const {
return modules.at(static_cast<size_t>(y)).at(static_cast<size_t>(x));
}
vector<uint8_t> QrCode::addEccAndInterleave(const vector<uint8_t> &data) const {
if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel)))
throw std::invalid_argument("Invalid argument");
// Calculate parameter numbers
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version];
int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast<int>(errorCorrectionLevel)][version];
int rawCodewords = getNumRawDataModules(version) / 8;
int numShortBlocks = numBlocks - rawCodewords % numBlocks;
int shortBlockLen = rawCodewords / numBlocks;
// Split data into blocks and append ECC to each block
vector<vector<uint8_t> > blocks;
const vector<uint8_t> rsDiv = reedSolomonComputeDivisor(blockEccLen);
for (int i = 0, k = 0; i < numBlocks; i++) {
vector<uint8_t> dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)));
k += static_cast<int>(dat.size());
const vector<uint8_t> ecc = reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks)
dat.push_back(0);
dat.insert(dat.end(), ecc.cbegin(), ecc.cend());
blocks.push_back(std::move(dat));
}
// Interleave (not concatenate) the bytes from every block into a single sequence
vector<uint8_t> result;
for (size_t i = 0; i < blocks.at(0).size(); i++) {
for (size_t j = 0; j < blocks.size(); j++) {
// Skip the padding byte in short blocks
if (i != static_cast<unsigned int>(shortBlockLen - blockEccLen) || j >= static_cast<unsigned int>(numShortBlocks))
result.push_back(blocks.at(j).at(i));
}
}
if (result.size() != static_cast<unsigned int>(rawCodewords))
throw std::logic_error("Assertion error");
return result;
}
void QrCode::drawCodewords(const vector<uint8_t> &data) {
if (data.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8))
throw std::invalid_argument("Invalid argument");
size_t i = 0; // Bit index into the data
// Do the funny zigzag scan
for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
if (right == 6)
right = 5;
for (int vert = 0; vert < size; vert++) { // Vertical counter
for (int j = 0; j < 2; j++) {
size_t x = static_cast<size_t>(right - j); // Actual x coordinate
bool upward = ((right + 1) & 2) == 0;
size_t y = static_cast<size_t>(upward ? size - 1 - vert : vert); // Actual y coordinate
if (!isFunction.at(y).at(x) && i < data.size() * 8) {
modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7));
i++;
}
// If this QR Code has any remainder bits (0 to 7), they were assigned as
// 0/false/white by the constructor and are left unchanged by this method
}
}
}
if (i != data.size() * 8)
throw std::logic_error("Assertion error");
}
void QrCode::applyMask(int msk) {
if (msk < 0 || msk > 7)
throw std::domain_error("Mask value out of range");
size_t sz = static_cast<size_t>(size);
for (size_t y = 0; y < sz; y++) {
for (size_t x = 0; x < sz; x++) {
bool invert;
switch (msk) {
case 0: invert = (x + y) % 2 == 0; break;
case 1: invert = y % 2 == 0; break;
case 2: invert = x % 3 == 0; break;
case 3: invert = (x + y) % 3 == 0; break;
case 4: invert = (x / 3 + y / 2) % 2 == 0; break;
case 5: invert = x * y % 2 + x * y % 3 == 0; break;
case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break;
case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break;
default: throw std::logic_error("Assertion error");
}
modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x));
}
}
}
long QrCode::getPenaltyScore() const {
long result = 0;
// Adjacent modules in row having same color, and finder-like patterns
for (int y = 0; y < size; y++) {
bool runColor = false;
int runX = 0;
std::array<int,7> runHistory = {};
for (int x = 0; x < size; x++) {
if (module(x, y) == runColor) {
runX++;
if (runX == 5)
result += PENALTY_N1;
else if (runX > 5)
result++;
} else {
finderPenaltyAddHistory(runX, runHistory);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = module(x, y);
runX = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
}
// Adjacent modules in column having same color, and finder-like patterns
for (int x = 0; x < size; x++) {
bool runColor = false;
int runY = 0;
std::array<int,7> runHistory = {};
for (int y = 0; y < size; y++) {
if (module(x, y) == runColor) {
runY++;
if (runY == 5)
result += PENALTY_N1;
else if (runY > 5)
result++;
} else {
finderPenaltyAddHistory(runY, runHistory);
if (!runColor)
result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
runColor = module(x, y);
runY = 1;
}
}
result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;
}
// 2*2 blocks of modules having same color
for (int y = 0; y < size - 1; y++) {
for (int x = 0; x < size - 1; x++) {
bool color = module(x, y);
if ( color == module(x + 1, y) &&
color == module(x, y + 1) &&
color == module(x + 1, y + 1))
result += PENALTY_N2;
}
}
// Balance of black and white modules
int black = 0;
for (const vector<bool> &row : modules) {
for (bool color : row) {
if (color)
black++;
}
}
int total = size * size; // Note that size is odd, so black/total != 1/2
// Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
int k = static_cast<int>((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1;
result += k * PENALTY_N4;
return result;
}
vector<int> QrCode::getAlignmentPatternPositions() const {
if (version == 1)
return vector<int>();
else {
int numAlign = version / 7 + 2;
int step = (version == 32) ? 26 :
(version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
vector<int> result;
for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step)
result.insert(result.begin(), pos);
result.insert(result.begin(), 6);
return result;
}
}
int QrCode::getNumRawDataModules(int ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION)
throw std::domain_error("Version number out of range");
int result = (16 * ver + 128) * ver + 64;
if (ver >= 2) {
int numAlign = ver / 7 + 2;
result -= (25 * numAlign - 10) * numAlign - 55;
if (ver >= 7)
result -= 36;
}
if (!(208 <= result && result <= 29648))
throw std::logic_error("Assertion error");
return result;
}
int QrCode::getNumDataCodewords(int ver, Ecc ecl) {
return getNumRawDataModules(ver) / 8
- ECC_CODEWORDS_PER_BLOCK [static_cast<int>(ecl)][ver]
* NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(ecl)][ver];
}
vector<uint8_t> QrCode::reedSolomonComputeDivisor(int degree) {
if (degree < 1 || degree > 255)
throw std::domain_error("Degree out of range");
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
vector<uint8_t> result(static_cast<size_t>(degree));
result.at(result.size() - 1) = 1; // Start off with the monomial x^0
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
// and drop the highest monomial term which is always 1x^degree.
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
uint8_t root = 1;
for (int i = 0; i < degree; i++) {
// Multiply the current product by (x - r^i)
for (size_t j = 0; j < result.size(); j++) {
result.at(j) = reedSolomonMultiply(result.at(j), root);
if (j + 1 < result.size())
result.at(j) ^= result.at(j + 1);
}
root = reedSolomonMultiply(root, 0x02);
}
return result;
}
vector<uint8_t> QrCode::reedSolomonComputeRemainder(const vector<uint8_t> &data, const vector<uint8_t> &divisor) {
vector<uint8_t> result(divisor.size());
for (uint8_t b : data) { // Polynomial division
uint8_t factor = b ^ result.at(0);
result.erase(result.begin());
result.push_back(0);
for (size_t i = 0; i < result.size(); i++)
result.at(i) ^= reedSolomonMultiply(divisor.at(i), factor);
}
return result;
}
uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) {
// Russian peasant multiplication
int z = 0;
for (int i = 7; i >= 0; i--) {
z = (z << 1) ^ ((z >> 7) * 0x11D);
z ^= ((y >> i) & 1) * x;
}
if (z >> 8 != 0)
throw std::logic_error("Assertion error");
return static_cast<uint8_t>(z);
}
int QrCode::finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const {
int n = runHistory.at(1);
if (n > size * 3)
throw std::logic_error("Assertion error");
bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n;
return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0)
+ (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0);
}
int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array<int,7> &runHistory) const {
if (currentRunColor) { // Terminate black run
finderPenaltyAddHistory(currentRunLength, runHistory);
currentRunLength = 0;
}
currentRunLength += size; // Add white border to final run
finderPenaltyAddHistory(currentRunLength, runHistory);
return finderPenaltyCountPatterns(runHistory);
}
void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const {
if (runHistory.at(0) == 0)
currentRunLength += size; // Add white border to initial run
std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end());
runHistory.at(0) = currentRunLength;
}
bool QrCode::getBit(long x, int i) {
return ((x >> i) & 1) != 0;
}
/*---- Tables of constants ----*/
const int QrCode::PENALTY_N1 = 3;
const int QrCode::PENALTY_N2 = 3;
const int QrCode::PENALTY_N3 = 40;
const int QrCode::PENALTY_N4 = 10;
const int8_t QrCode::ECC_CODEWORDS_PER_BLOCK[4][41] = {
// Version: (note that index 0 is for padding, and is set to an illegal value)
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
{-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low
{-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium
{-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile
{-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High
};
const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
// Version: (note that index 0 is for padding, and is set to an illegal value)
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
{-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low
{-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium
{-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile
{-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High
};
data_too_long::data_too_long(const std::string &msg) :
std::length_error(msg) {}
BitBuffer::BitBuffer()
: std::vector<bool>() {}
void BitBuffer::appendBits(std::uint32_t val, int len) {
if (len < 0 || len > 31 || val >> len != 0)
throw std::domain_error("Value out of range");
for (int i = len - 1; i >= 0; i--) // Append bit by bit
this->push_back(((val >> i) & 1) != 0);
}
}

View file

@ -1,556 +0,0 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#pragma once
#include <array>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <vector>
namespace qrcodegen {
/*
* A segment of character/binary/control data in a QR Code symbol.
* Instances of this class are immutable.
* The mid-level way to create a segment is to take the payload data
* and call a static factory function such as QrSegment::makeNumeric().
* The low-level way to create a segment is to custom-make the bit buffer
* and call the QrSegment() constructor with appropriate values.
* This segment class imposes no length restrictions, but QR Codes have restrictions.
* Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
* Any segment longer than this is meaningless for the purpose of generating QR Codes.
*/
class QrSegment final {
/*---- Public helper enumeration ----*/
/*
* Describes how a segment's data bits are interpreted. Immutable.
*/
public: class Mode final {
/*-- Constants --*/
public: static const Mode NUMERIC;
public: static const Mode ALPHANUMERIC;
public: static const Mode BYTE;
public: static const Mode KANJI;
public: static const Mode ECI;
/*-- Fields --*/
// The mode indicator bits, which is a uint4 value (range 0 to 15).
private: int modeBits;
// Number of character count bits for three different version ranges.
private: int numBitsCharCount[3];
/*-- Constructor --*/
private: Mode(int mode, int cc0, int cc1, int cc2);
/*-- Methods --*/
/*
* (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15).
*/
public: int getModeBits() const;
/*
* (Package-private) Returns the bit width of the character count field for a segment in
* this mode in a QR Code at the given version number. The result is in the range [0, 16].
*/
public: int numCharCountBits(int ver) const;
};
/*---- Static factory functions (mid level) ----*/
/*
* Returns a segment representing the given binary data encoded in
* byte mode. All input byte vectors are acceptable. Any text string
* can be converted to UTF-8 bytes and encoded as a byte mode segment.
*/
public: static QrSegment makeBytes(const std::vector<std::uint8_t> &data);
/*
* Returns a segment representing the given string of decimal digits encoded in numeric mode.
*/
public: static QrSegment makeNumeric(const char *digits);
/*
* Returns a segment representing the given text string encoded in alphanumeric mode.
* The characters allowed are: 0 to 9, A to Z (uppercase only), space,
* dollar, percent, asterisk, plus, hyphen, period, slash, colon.
*/
public: static QrSegment makeAlphanumeric(const char *text);
/*
* Returns a list of zero or more segments to represent the given text string. The result
* may use various segment modes and switch modes to optimize the length of the bit stream.
*/
public: static std::vector<QrSegment> makeSegments(const char *text);
/*
* Returns a segment representing an Extended Channel Interpretation
* (ECI) designator with the given assignment value.
*/
public: static QrSegment makeEci(long assignVal);
/*---- Public static helper functions ----*/
/*
* Tests whether the given string can be encoded as a segment in alphanumeric mode.
* A string is encodable iff each character is in the following set: 0 to 9, A to Z
* (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
*/
public: static bool isAlphanumeric(const char *text);
/*
* Tests whether the given string can be encoded as a segment in numeric mode.
* A string is encodable iff each character is in the range 0 to 9.
*/
public: static bool isNumeric(const char *text);
/*---- Instance fields ----*/
/* The mode indicator of this segment. Accessed through getMode(). */
private: Mode mode;
/* The length of this segment's unencoded data. Measured in characters for
* numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
* Always zero or positive. Not the same as the data's bit length.
* Accessed through getNumChars(). */
private: int numChars;
/* The data bits of this segment. Accessed through getData(). */
private: std::vector<bool> data;
/*---- Constructors (low level) ----*/
/*
* Creates a new QR Code segment with the given attributes and data.
* The character count (numCh) must agree with the mode and the bit buffer length,
* but the constraint isn't checked. The given bit buffer is copied and stored.
*/
public: QrSegment(Mode md, int numCh, const std::vector<bool> &dt);
/*
* Creates a new QR Code segment with the given parameters and data.
* The character count (numCh) must agree with the mode and the bit buffer length,
* but the constraint isn't checked. The given bit buffer is moved and stored.
*/
public: QrSegment(Mode md, int numCh, std::vector<bool> &&dt);
/*---- Methods ----*/
/*
* Returns the mode field of this segment.
*/
public: Mode getMode() const;
/*
* Returns the character count field of this segment.
*/
public: int getNumChars() const;
/*
* Returns the data bits of this segment.
*/
public: const std::vector<bool> &getData() const;
// (Package-private) Calculates the number of bits needed to encode the given segments at
// the given version. Returns a non-negative number if successful. Otherwise returns -1 if a
// segment has too many characters to fit its length field, or the total bits exceeds INT_MAX.
public: static int getTotalBits(const std::vector<QrSegment> &segs, int version);
/*---- Private constant ----*/
/* The set of all legal characters in alphanumeric mode, where
* each character value maps to the index in the string. */
private: static const char *ALPHANUMERIC_CHARSET;
};
/*
* A QR Code symbol, which is a type of two-dimension barcode.
* Invented by Denso Wave and described in the ISO/IEC 18004 standard.
* Instances of this class represent an immutable square grid of black and white cells.
* The class provides static factory functions to create a QR Code from text or binary data.
* The class covers the QR Code Model 2 specification, supporting all versions (sizes)
* from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
*
* Ways to create a QR Code object:
* - High level: Take the payload data and call QrCode::encodeText() or QrCode::encodeBinary().
* - Mid level: Custom-make the list of segments and call QrCode::encodeSegments().
* - Low level: Custom-make the array of data codeword bytes (including
* segment headers and final padding, excluding error correction codewords),
* supply the appropriate version number, and call the QrCode() constructor.
* (Note that all ways require supplying the desired error correction level.)
*/
class QrCode final {
/*---- Public helper enumeration ----*/
/*
* The error correction level in a QR Code symbol.
*/
public: enum class Ecc {
LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords
MEDIUM , // The QR Code can tolerate about 15% erroneous codewords
QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
HIGH , // The QR Code can tolerate about 30% erroneous codewords
};
// Returns a value in the range 0 to 3 (unsigned 2-bit integer).
private: static int getFormatBits(Ecc ecl);
/*---- Static factory functions (high level) ----*/
/*
* Returns a QR Code representing the given Unicode text string at the given error correction level.
* As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer
* UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible
* QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
* the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeText(const char *text, Ecc ecl);
/*
* Returns a QR Code representing the given binary data at the given error correction level.
* This function always encodes using the binary segment mode, not any text mode. The maximum number of
* bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
* The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeBinary(const std::vector<std::uint8_t> &data, Ecc ecl);
/*---- Static factory functions (mid level) ----*/
/*
* Returns a QR Code representing the given segments with the given encoding parameters.
* The smallest possible QR Code version within the given range is automatically
* chosen for the output. Iff boostEcl is true, then the ECC level of the result
* may be higher than the ecl argument if it can be done without increasing the
* version. The mask number is either between 0 to 7 (inclusive) to force that
* mask, or -1 to automatically choose an appropriate mask (which may be slow).
* This function allows the user to create a custom sequence of segments that switches
* between modes (such as alphanumeric and byte) to encode text in less space.
* This is a mid-level API; the high-level API is encodeText() and encodeBinary().
*/
public: static QrCode encodeSegments(const std::vector<QrSegment> &segs, Ecc ecl,
int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters
/*---- Instance fields ----*/
// Immutable scalar parameters:
/* The version number of this QR Code, which is between 1 and 40 (inclusive).
* This determines the size of this barcode. */
private: int version;
/* The width and height of this QR Code, measured in modules, between
* 21 and 177 (inclusive). This is equal to version * 4 + 17. */
private: int size;
/* The error correction level used in this QR Code. */
private: Ecc errorCorrectionLevel;
/* The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
* Even if a QR Code is created with automatic masking requested (mask = -1),
* the resulting object still has a mask value between 0 and 7. */
private: int mask;
// Private grids of modules/pixels, with dimensions of size*size:
// The modules of this QR Code (false = white, true = black).
// Immutable after constructor finishes. Accessed through getModule().
private: std::vector<std::vector<bool> > modules;
// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
private: std::vector<std::vector<bool> > isFunction;
/*---- Constructor (low level) ----*/
/*
* Creates a new QR Code with the given version number,
* error correction level, data codeword bytes, and mask number.
* This is a low-level API that most users should not use directly.
* A mid-level API is the encodeSegments() function.
*/
public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int msk);
/*---- Public instance methods ----*/
/*
* Returns this QR Code's version, in the range [1, 40].
*/
public: int getVersion() const;
/*
* Returns this QR Code's size, in the range [21, 177].
*/
public: int getSize() const;
/*
* Returns this QR Code's error correction level.
*/
public: Ecc getErrorCorrectionLevel() const;
/*
* Returns this QR Code's mask, in the range [0, 7].
*/
public: int getMask() const;
/*
* Returns the color of the module (pixel) at the given coordinates, which is false
* for white or true for black. The top left corner has the coordinates (x=0, y=0).
* If the given coordinates are out of bounds, then false (white) is returned.
*/
public: bool getModule(int x, int y) const;
/*
* Returns a string of SVG code for an image depicting this QR Code, with the given number
* of border modules. The string always uses Unix newlines (\n), regardless of the platform.
*/
public: std::string toSvgString(int border) const;
/*---- Private helper methods for constructor: Drawing function modules ----*/
// Reads this object's version field, and draws and marks all function modules.
private: void drawFunctionPatterns();
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
private: void drawFormatBits(int msk);
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field, iff 7 <= version <= 40.
private: void drawVersion();
// Draws a 9*9 finder pattern including the border separator,
// with the center module at (x, y). Modules can be out of bounds.
private: void drawFinderPattern(int x, int y);
// Draws a 5*5 alignment pattern, with the center module
// at (x, y). All modules must be in bounds.
private: void drawAlignmentPattern(int x, int y);
// Sets the color of a module and marks it as a function module.
// Only used by the constructor. Coordinates must be in bounds.
private: void setFunctionModule(int x, int y, bool isBlack);
// Returns the color of the module at the given coordinates, which must be in range.
private: bool module(int x, int y) const;
/*---- Private helper methods for constructor: Codewords and masking ----*/
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
private: std::vector<std::uint8_t> addEccAndInterleave(const std::vector<std::uint8_t> &data) const;
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code. Function modules need to be marked off before this is called.
private: void drawCodewords(const std::vector<std::uint8_t> &data);
// XORs the codeword modules in this QR Code with the given mask pattern.
// The function modules must be marked and the codeword bits must be drawn
// before masking. Due to the arithmetic of XOR, calling applyMask() with
// the same mask value a second time will undo the mask. A final well-formed
// QR Code needs exactly one (not zero, two, etc.) mask applied.
private: void applyMask(int msk);
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
private: long getPenaltyScore() const;
/*---- Private helper functions ----*/
// Returns an ascending list of positions of alignment patterns for this version number.
// Each position is in the range [0,177), and are used on both the x and y axes.
// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
private: std::vector<int> getAlignmentPatternPositions() const;
// Returns the number of data bits that can be stored in a QR Code of the given version number, after
// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
private: static int getNumRawDataModules(int ver);
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
// QR Code of the given version number and error correction level, with remainder bits discarded.
// This stateless pure function could be implemented as a (40*4)-cell lookup table.
private: static int getNumDataCodewords(int ver, Ecc ecl);
// Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
// implemented as a lookup table over all possible parameter values, instead of as an algorithm.
private: static std::vector<std::uint8_t> reedSolomonComputeDivisor(int degree);
// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
private: static std::vector<std::uint8_t> reedSolomonComputeRemainder(const std::vector<std::uint8_t> &data, const std::vector<std::uint8_t> &divisor);
// Returns the product of the two given field elements modulo GF(2^8/0x11D).
// All inputs are valid. This could be implemented as a 256*256 lookup table.
private: static std::uint8_t reedSolomonMultiply(std::uint8_t x, std::uint8_t y);
// Can only be called immediately after a white run is added, and
// returns either 0, 1, or 2. A helper function for getPenaltyScore().
private: int finderPenaltyCountPatterns(const std::array<int,7> &runHistory) const;
// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array<int,7> &runHistory) const;
// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
private: void finderPenaltyAddHistory(int currentRunLength, std::array<int,7> &runHistory) const;
// Returns true iff the i'th bit of x is set to 1.
private: static bool getBit(long x, int i);
/*---- Constants and tables ----*/
// The minimum version number supported in the QR Code Model 2 standard.
public: static constexpr int MIN_VERSION = 1;
// The maximum version number supported in the QR Code Model 2 standard.
public: static constexpr int MAX_VERSION = 40;
// For use in getPenaltyScore(), when evaluating which mask is best.
private: static const int PENALTY_N1;
private: static const int PENALTY_N2;
private: static const int PENALTY_N3;
private: static const int PENALTY_N4;
private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
};
/*---- Public exception class ----*/
/*
* Thrown when the supplied data does not fit any QR Code version. Ways to handle this exception include:
* - Decrease the error correction level if it was greater than Ecc::LOW.
* - If the encodeSegments() function was called with a maxVersion argument, then increase
* it if it was less than QrCode::MAX_VERSION. (This advice does not apply to the other
* factory functions because they search all versions up to QrCode::MAX_VERSION.)
* - Split the text data into better or optimal segments in order to reduce the number of bits required.
* - Change the text or binary data to be shorter.
* - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric).
* - Propagate the error upward to the caller/user.
*/
class data_too_long : public std::length_error {
public: explicit data_too_long(const std::string &msg);
};
/*
* An appendable sequence of bits (0s and 1s). Mainly used by QrSegment.
*/
class BitBuffer final : public std::vector<bool> {
/*---- Constructor ----*/
// Creates an empty bit buffer (length 0).
public: BitBuffer();
/*---- Method ----*/
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and val < 2^len.
public: void appendBits(std::uint32_t val, int len);
};
}

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2020 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -21,13 +21,6 @@
#if __cplusplus #if __cplusplus
#include <QString> #include <QString>
#define REL_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Release")
#define RC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Release Candidate")
#define BETA_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Beta")
#define ALPHA_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Alpha")
#define DEV_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Developer")
#define DAILY_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Daily Build")
#define CUSTOM_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Custom")
#endif #endif
#ifndef GTA5SYNC_APPVENDOR #ifndef GTA5SYNC_APPVENDOR
@ -35,7 +28,7 @@
#endif #endif
#ifndef GTA5SYNC_APPVENDORLINK #ifndef GTA5SYNC_APPVENDORLINK
#define GTA5SYNC_APPVENDORLINK "g5e://about?U3lwaW5n:R2l0TGFiOiA8YSBocmVmPSJodHRwczovL2dpdGxhYi5jb20vU3lwaW5nIj5TeXBpbmc8L2E+PGJyLz5HaXRIdWI6IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9TeXBpbmciPlN5cGluZzwvYT48YnIvPlNvY2lhbCBDbHViOiA8YSBocmVmPSJodHRwczovL3NvY2lhbGNsdWIucm9ja3N0YXJnYW1lcy5jb20vbWVtYmVyL1N5cGluZy80NjMwMzA1NiI+U3lwaW5nPC9hPg" #define GTA5SYNC_APPVENDORLINK "g5e://about?U3lwaW5n:R2l0TGFiOiA8YSBocmVmPSJodHRwczovL2dpdGxhYi5jb20vU3lwaW5nIj5TeXBpbmc8L2E+PGJyLz5HaXRIdWI6IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9TeXBpbmciPlN5cGluZzwvYT48YnIvPlNvY2lhbCBDbHViOiA8YSBocmVmPSJodHRwczovL3NvY2lhbGNsdWIucm9ja3N0YXJnYW1lcy5jb20vbWVtYmVyL1N5cGluZy80NjMwMzA1NiI+U3lwaW5nPC9hPg=="
#endif #endif
#ifndef GTA5SYNC_APPSTR #ifndef GTA5SYNC_APPSTR
@ -47,14 +40,50 @@
#endif #endif
#ifndef GTA5SYNC_COPYRIGHT #ifndef GTA5SYNC_COPYRIGHT
#define GTA5SYNC_COPYRIGHT "2016-2023" #define GTA5SYNC_COPYRIGHT "2016-2020"
#endif #endif
#ifndef GTA5SYNC_APPVER #ifndef GTA5SYNC_APPVER
#define GTA5SYNC_APPVER "1.10.2" #define GTA5SYNC_APPVER "1.8.0"
#endif #endif
#if __cplusplus #if __cplusplus
#ifdef GTA5SYNC_BUILDTYPE_REL
#ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Release")
#endif
#endif
#ifdef GTA5SYNC_BUILDTYPE_RC
#ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Release Candidate")
#endif
#endif
#ifdef GTA5SYNC_BUILDTYPE_DAILY
#ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Daily Build")
#endif
#endif
#ifdef GTA5SYNC_BUILDTYPE_DEV
#ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Developer")
#endif
#endif
#ifdef GTA5SYNC_BUILDTYPE_BETA
#ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Beta")
#endif
#endif
#ifdef GTA5SYNC_BUILDTYPE_ALPHA
#ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Alpha")
#endif
#endif
#ifndef GTA5SYNC_BUILDTYPE #ifndef GTA5SYNC_BUILDTYPE
#define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Custom") #define GTA5SYNC_BUILDTYPE QT_TRANSLATE_NOOP("AboutDialog", "Custom")
#endif #endif
@ -65,11 +94,7 @@
#ifdef GTA5SYNC_QCONF #ifdef GTA5SYNC_QCONF
#ifndef GTA5SYNC_SHARE #ifndef GTA5SYNC_SHARE
#ifdef Q_OS_WIN #define GTA5SYNC_SHARE "RUNDIR:SEPARATOR:..SEPARATOR:share"
#define GTA5SYNC_SHARE "RUNDIR:"
#else
#define GTA5SYNC_SHARE "RUNDIR:/../share"
#endif
#endif #endif
#ifndef GTA5SYNC_LANG #ifndef GTA5SYNC_LANG
#define GTA5SYNC_LANG "QCONFLANG:" #define GTA5SYNC_LANG "QCONFLANG:"
@ -87,10 +112,10 @@
#define GTA5SYNC_SHARE "RUNDIR:" #define GTA5SYNC_SHARE "RUNDIR:"
#endif #endif
#ifndef GTA5SYNC_LANG #ifndef GTA5SYNC_LANG
#define GTA5SYNC_LANG "SHAREDDIR:/lang" #define GTA5SYNC_LANG "SHAREDDIR:SEPARATOR:lang"
#endif #endif
#ifndef GTA5SYNC_PLUG #ifndef GTA5SYNC_PLUG
#define GTA5SYNC_PLUG "RUNDIR:/plugins" #define GTA5SYNC_PLUG "RUNDIR:SEPARATOR:plugins"
#endif #endif
#endif #endif

View file

@ -1,6 +1,6 @@
#/***************************************************************************** #/*****************************************************************************
#* gta5view Grand Theft Auto V Profile Viewer #* gta5view Grand Theft Auto V Profile Viewer
#* Copyright (C) 2015-2021 Syping #* Copyright (C) 2015-2020 Syping
#* #*
#* This program is free software: you can redistribute it and/or modify #* 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 #* it under the terms of the GNU General Public License as published by
@ -19,14 +19,13 @@
QT += core gui network svg QT += core gui network svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 4): win32: LIBS += -ldwmapi greaterThan(QT_MAJOR_VERSION, 4): greaterThan(QT_MINOR_VERSION, 1): win32: QT += winextras
DEPLOYMENT.display_name = gta5view DEPLOYMENT.display_name = gta5view
TARGET = gta5view TARGET = gta5view
TEMPLATE = app TEMPLATE = app
HEADERS += config.h \ HEADERS += config.h
wrapper.h
PRECOMPILED_HEADER += config.h PRECOMPILED_HEADER += config.h
SOURCES += main.cpp \ SOURCES += main.cpp \
@ -51,7 +50,6 @@ SOURCES += main.cpp \
ProfileInterface.cpp \ ProfileInterface.cpp \
ProfileLoader.cpp \ ProfileLoader.cpp \
ProfileWidget.cpp \ ProfileWidget.cpp \
RagePhoto.cpp \
SavegameCopy.cpp \ SavegameCopy.cpp \
SavegameData.cpp \ SavegameData.cpp \
SavegameDialog.cpp \ SavegameDialog.cpp \
@ -94,7 +92,6 @@ HEADERS += \
ProfileInterface.h \ ProfileInterface.h \
ProfileLoader.h \ ProfileLoader.h \
ProfileWidget.h \ ProfileWidget.h \
RagePhoto.h \
SavegameCopy.h \ SavegameCopy.h \
SavegameData.h \ SavegameData.h \
SavegameDialog.h \ SavegameDialog.h \
@ -144,8 +141,7 @@ TRANSLATIONS += \
res/gta5sync_zh_TW.ts res/gta5sync_zh_TW.ts
RESOURCES += \ RESOURCES += \
res/img.qrc \ res/app.qrc \
res/template.qrc \
res/tr_g5p.qrc res/tr_g5p.qrc
DISTFILES += \ DISTFILES += \
@ -179,6 +175,7 @@ INCLUDEPATH += ./anpro ./pcg ./tmext ./uimod
DEFINES += GTA5SYNC_QMAKE # We using qmake do we? DEFINES += GTA5SYNC_QMAKE # We using qmake do we?
DEFINES += GTA5SYNC_PROJECT # Enable exclusive gta5sync/gta5view functions DEFINES += GTA5SYNC_PROJECT # Enable exclusive gta5sync/gta5view functions
DEFINES += SNAPMATIC_NODEFAULT # Not assisting at proper usage of SnapmaticPicture class
# WINDOWS ONLY # WINDOWS ONLY
@ -187,7 +184,7 @@ win32: CONFIG -= embed_manifest_exe
contains(DEFINES, GTA5SYNC_TELEMETRY): win32: LIBS += -ld3d9 # Required for getting information about GPU contains(DEFINES, GTA5SYNC_TELEMETRY): win32: LIBS += -ld3d9 # Required for getting information about GPU
# MAC OS X ONLY # MAC OS X ONLY
macx: ICON = res/gta5view.icns macx: ICON = res/5sync.icns
# QT4 ONLY STUFF # QT4 ONLY STUFF
@ -209,21 +206,17 @@ isEqual(QT_MAJOR_VERSION, 4): SOURCES += qjson4/QJsonArray.cpp \
qjson4/QJsonValueRef.cpp \ qjson4/QJsonValueRef.cpp \
qjson4/QJsonParser.cpp qjson4/QJsonParser.cpp
isEqual(QT_MAJOR_VERSION, 4): RESOURCES += res/qt4/tr_qt.qrc isEqual(QT_MAJOR_VERSION, 4): RESOURCES += res/tr_qt4.qrc
isEqual(QT_MAJOR_VERSION, 4): GTA5SYNC_RCC = $$[QT_INSTALL_BINS]/rcc isEqual(QT_MAJOR_VERSION, 4): GTA5SYNC_RCC = $$[QT_INSTALL_BINS]/rcc
# QT5 ONLY STUFF # QT5 ONLY STUFF
isEqual(QT_MAJOR_VERSION, 5): RESOURCES += res/qt5/tr_qt.qrc isEqual(QT_MAJOR_VERSION, 5): RESOURCES += res/tr_qt5.qrc
# QT5+ ONLY STUFF # QT5+ ONLY STUFF
greaterThan(QT_MAJOR_VERSION, 4): GTA5SYNC_RCC = $$[QT_HOST_BINS]/rcc greaterThan(QT_MAJOR_VERSION, 4): GTA5SYNC_RCC = $$[QT_HOST_BINS]/rcc
# QT6 ONLY STUFF
isEqual(QT_MAJOR_VERSION, 6): RESOURCES += res/qt6/tr_qt.qrc
# RESOURCE COMPILATION # RESOURCE COMPILATION
system($$GTA5SYNC_RCC -threshold 0 -compress 9 $$PWD/res/global.qrc -o $$OUT_PWD/qrc_global.cpp) { system($$GTA5SYNC_RCC -threshold 0 -compress 9 $$PWD/res/global.qrc -o $$OUT_PWD/qrc_global.cpp) {
@ -246,9 +239,8 @@ INSTALLS += target pixmaps appfiles
# QCONF BASED BUILD STUFF # QCONF BASED BUILD STUFF
contains(DEFINES, GTA5SYNC_QCONF) { contains(DEFINES, GTA5SYNC_QCONF) {
isEqual(QT_MAJOR_VERSION, 4): RESOURCES -= res/qt4/tr_qt.qrc isEqual(QT_MAJOR_VERSION, 4): RESOURCES -= res/tr_qt4.qrc
isEqual(QT_MAJOR_VERSION, 5): RESOURCES -= res/qt5/tr_qt.qrc isEqual(QT_MAJOR_VERSION, 5): RESOURCES -= res/tr_qt5.qrc
isEqual(QT_MAJOR_VERSION, 6): RESOURCES -= res/qt6/tr_qt.qrc
!contains(DEFINES, GTA5SYNC_QCONF_IN) { !contains(DEFINES, GTA5SYNC_QCONF_IN) {
RESOURCES -= res/tr_g5p.qrc RESOURCES -= res/tr_g5p.qrc
langfiles.path = $$GTA5SYNC_PREFIX/share/gta5view/translations langfiles.path = $$GTA5SYNC_PREFIX/share/gta5view/translations

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2016-2021 Syping * Copyright (C) 2016-2019 Syping
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -49,6 +49,7 @@
#include <QLayout> #include <QLayout>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QDebug>
#include <QFont> #include <QFont>
#include <QFile> #include <QFile>
@ -93,30 +94,28 @@ int main(int argc, char *argv[])
settings.sync(); settings.sync();
#endif #endif
bool isFirstStart = settings.value("IsFirstStart", true).toBool();
bool customStyle = settings.value("CustomStyle", false).toBool(); bool customStyle = settings.value("CustomStyle", false).toBool();
if (customStyle) { QString appStyle = settings.value("AppStyle", "Default").toString();
const QString appStyle = settings.value("AppStyle", "Default").toString();
if (QStyleFactory::keys().contains(appStyle, Qt::CaseInsensitive)) { if (customStyle)
{
if (QStyleFactory::keys().contains(appStyle, Qt::CaseInsensitive))
{
a.setStyle(QStyleFactory::create(appStyle)); a.setStyle(QStyleFactory::create(appStyle));
} }
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#if QT_VERSION >= 0x060000 #if QT_VERSION >= 0x050400
a.setFont(QApplication::font("QMenu")); bool alwaysUseMessageFont = settings.value("AlwaysUseMessageFont", false).toBool();
#elif QT_VERSION >= 0x050400 if (QSysInfo::windowsVersion() >= 0x0080 || alwaysUseMessageFont)
if (QSysInfo::windowsVersion() >= 0x0080) { {
a.setFont(QApplication::font("QMenu")); a.setFont(QApplication::font("QMenu"));
} }
#endif #endif
#endif #endif
bool customFont = settings.value("CustomFont", false).toBool();
if (customFont) {
const QFont appFont = qvariant_cast<QFont>(settings.value("AppFont", a.font()));
a.setFont(appFont);
}
QStringList applicationArgs = a.arguments(); QStringList applicationArgs = a.arguments();
QString selectedAction; QString selectedAction;
QString arg1; QString arg1;
@ -130,10 +129,28 @@ int main(int argc, char *argv[])
Telemetry->work(); Telemetry->work();
#endif #endif
if (!applicationArgs.contains("--skip-firststart"))
{
if (isFirstStart)
{
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;
OptionsDialog optionsDialog(&profileDB);
optionsDialog.setWindowIcon(IconLoader::loadingAppIcon());
optionsDialog.show();
optionsDialog.exec();
}
settings.setValue("IsFirstStart", false);
}
}
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
bool telemetryWindowLaunched = settings.value("PersonalUsageDataWindowLaunched", false).toBool(); bool telemetryWindowLaunched = settings.value("PersonalUsageDataWindowLaunched", false).toBool();
bool pushUsageData = settings.value("PushUsageData", false).toBool(); bool pushUsageData = settings.value("PushUsageData", false).toBool();
if (!telemetryWindowLaunched && !pushUsageData) { if (!telemetryWindowLaunched && !pushUsageData)
{
QDialog *telemetryDialog = new QDialog(); QDialog *telemetryDialog = new QDialog();
telemetryDialog->setObjectName(QStringLiteral("TelemetryDialog")); telemetryDialog->setObjectName(QStringLiteral("TelemetryDialog"));
telemetryDialog->setWindowTitle(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER)); telemetryDialog->setWindowTitle(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER));
@ -165,7 +182,8 @@ int main(int argc, char *argv[])
telemetryDialog->setFixedSize(telemetryDialog->sizeHint()); telemetryDialog->setFixedSize(telemetryDialog->sizeHint());
telemetryDialog->exec(); telemetryDialog->exec();
QObject::disconnect(telemetryButton, SIGNAL(clicked(bool)), telemetryDialog, SLOT(close())); QObject::disconnect(telemetryButton, SIGNAL(clicked(bool)), telemetryDialog, SLOT(close()));
if (telemetryCheckBox->isChecked()) { if (telemetryCheckBox->isChecked())
{
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry"); telemetrySettings.beginGroup("Telemetry");
telemetrySettings.setValue("PushUsageData", true); telemetrySettings.setValue("PushUsageData", true);
@ -181,35 +199,43 @@ int main(int argc, char *argv[])
#endif #endif
settings.endGroup(); settings.endGroup();
for (const QString &currentArg : applicationArgs) { for (QString currentArg : applicationArgs)
{
QString reworkedArg; QString reworkedArg;
if (currentArg.left(9) == "-showpic=" && selectedAction == "") { if (currentArg.left(9) == "-showpic=" && selectedAction == "")
reworkedArg = QString(currentArg).remove(0,9); {
reworkedArg = currentArg.remove(0,9);
arg1 = reworkedArg; arg1 = reworkedArg;
selectedAction = "showpic"; selectedAction = "showpic";
} }
else if (currentArg.left(9) == "-showsgd=" && selectedAction == "") { else if (currentArg.left(9) == "-showsgd=" && selectedAction == "")
reworkedArg = QString(currentArg).remove(0,9); {
reworkedArg = currentArg.remove(0,9);
arg1 = reworkedArg; arg1 = reworkedArg;
selectedAction = "showsgd"; selectedAction = "showsgd";
} }
else if (selectedAction == "") { else if (selectedAction == "")
{
QFile argumentFile(currentArg); QFile argumentFile(currentArg);
QFileInfo argumentFileInfo(argumentFile); QFileInfo argumentFileInfo(argumentFile);
if (argumentFile.exists()) { if (argumentFile.exists())
{
QString argumentFileName = argumentFileInfo.fileName(); QString argumentFileName = argumentFileInfo.fileName();
QString argumentFileType = argumentFileName.left(4); QString argumentFileType = argumentFileName.left(4);
QString argumentFileExt = argumentFileName.right(4); QString argumentFileExt = argumentFileName.right(4);
if (argumentFileType == "PGTA" || argumentFileExt == ".g5e") { if (argumentFileType == "PGTA" || argumentFileExt == ".g5e")
{
arg1 = currentArg; arg1 = currentArg;
selectedAction = "showpic"; selectedAction = "showpic";
} }
else if (argumentFileType == "SGTA") { else if (argumentFileType == "SGTA")
{
arg1 = currentArg; arg1 = currentArg;
selectedAction = "showsgd"; selectedAction = "showsgd";
} }
else if (argumentFileType == "MISR") { else if (argumentFileType == "MISR")
{
arg1 = currentArg; arg1 = currentArg;
selectedAction = "showsgd"; selectedAction = "showsgd";
} }
@ -217,7 +243,8 @@ int main(int argc, char *argv[])
} }
} }
if (selectedAction == "showpic") { if (selectedAction == "showpic")
{
CrewDatabase crewDB; CrewDatabase crewDB;
ProfileDatabase profileDB; ProfileDatabase profileDB;
DatabaseThread threadDB(&crewDB); DatabaseThread threadDB(&crewDB);
@ -230,10 +257,8 @@ int main(int argc, char *argv[])
picDialog.setWindowFlags(picDialog.windowFlags()^Qt::Dialog^Qt::Window); picDialog.setWindowFlags(picDialog.windowFlags()^Qt::Dialog^Qt::Window);
int crewID = picture.getSnapmaticProperties().crewID; int crewID = picture.getSnapmaticProperties().crewID;
if (crewID != 0) if (crewID != 0) { crewDB.addCrew(crewID); }
crewDB.addCrew(crewID); if (!readOk) { return 1; }
if (!readOk)
return 1;
QObject::connect(&threadDB, SIGNAL(crewNameFound(int, QString)), &crewDB, SLOT(setCrewName(int, QString))); QObject::connect(&threadDB, SIGNAL(crewNameFound(int, QString)), &crewDB, SLOT(setCrewName(int, QString)));
QObject::connect(&threadDB, SIGNAL(crewNameUpdated()), &picDialog, SLOT(crewNameUpdated())); QObject::connect(&threadDB, SIGNAL(crewNameUpdated()), &picDialog, SLOT(crewNameUpdated()));
@ -247,7 +272,8 @@ int main(int argc, char *argv[])
return a.exec(); return a.exec();
} }
else if (selectedAction == "showsgd") { else if (selectedAction == "showsgd")
{
SavegameDialog savegameDialog; SavegameDialog savegameDialog;
SavegameData savegame; SavegameData savegame;
@ -256,8 +282,7 @@ int main(int argc, char *argv[])
savegameDialog.setSavegameData(&savegame, arg1, readOk); savegameDialog.setSavegameData(&savegame, arg1, readOk);
savegameDialog.setWindowFlags(savegameDialog.windowFlags()^Qt::Dialog^Qt::Window); savegameDialog.setWindowFlags(savegameDialog.windowFlags()^Qt::Dialog^Qt::Window);
if (!readOk) if (!readOk) { return 1; }
return 1;
a.setQuitOnLastWindowClosed(true); a.setQuitOnLastWindowClosed(true);
savegameDialog.show(); savegameDialog.show();

Binary file not shown.

View file

@ -4,14 +4,7 @@
<file>avatararea.png</file> <file>avatararea.png</file>
<file>avatarareaimport.png</file> <file>avatarareaimport.png</file>
<file>back.svgz</file> <file>back.svgz</file>
<file>flag-de.png</file> <file>empty1x16.png</file>
<file>flag-fr.png</file>
<file>flag-gb.png</file>
<file>flag-kr.png</file>
<file>flag-ru.png</file>
<file>flag-tw.png</file>
<file>flag-ua.png</file>
<file>flag-us.png</file>
<file>gta5view-16.png</file> <file>gta5view-16.png</file>
<file>gta5view-24.png</file> <file>gta5view-24.png</file>
<file>gta5view-32.png</file> <file>gta5view-32.png</file>
@ -21,7 +14,6 @@
<file>gta5view-96.png</file> <file>gta5view-96.png</file>
<file>gta5view-128.png</file> <file>gta5view-128.png</file>
<file>gta5view-256.png</file> <file>gta5view-256.png</file>
<file>mapcayoperico.jpg</file>
<file>mappreview.jpg</file> <file>mappreview.jpg</file>
<file>next.svgz</file> <file>next.svgz</file>
<file>pointmaker-8.png</file> <file>pointmaker-8.png</file>
@ -33,4 +25,7 @@
<file>watermark_2b.png</file> <file>watermark_2b.png</file>
<file>watermark_2r.png</file> <file>watermark_2r.png</file>
</qresource> </qresource>
<qresource prefix="/template">
<file>template.g5e</file>
</qresource>
</RCC> </RCC>

View file

@ -4,8 +4,8 @@ IDI_ICON1 ICON DISCARDABLE "5sync.ico"
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gta5view.exe.manifest" CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gta5view.exe.manifest"
#include <windows.h> #include <windows.h>
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1, 10, 2, 0 FILEVERSION 1, 8, 0, 0
PRODUCTVERSION 1, 10, 2, 0 PRODUCTVERSION 1, 8, 0, 0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
FILEFLAGS 0 FILEFLAGS 0
FILEOS VOS_NT_WINDOWS32 FILEOS VOS_NT_WINDOWS32
@ -22,12 +22,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Syping" VALUE "CompanyName", "Syping"
VALUE "FileDescription", "gta5view" VALUE "FileDescription", "gta5view"
VALUE "FileVersion", "1.10.2" VALUE "FileVersion", "1.8.0"
VALUE "InternalName", "gta5view" VALUE "InternalName", "gta5view"
VALUE "LegalCopyright", "Copyright © 2016-2023 Syping" VALUE "LegalCopyright", "Copyright © 2016-2020 Syping"
VALUE "OriginalFilename", "gta5view.exe" VALUE "OriginalFilename", "gta5view.exe"
VALUE "ProductName", "gta5view" VALUE "ProductName", "gta5view"
VALUE "ProductVersion", "1.10.2" VALUE "ProductVersion", "1.8.0"
END END
END END
END END

Binary file not shown.

View file

@ -1 +0,0 @@
Bitcoin

Binary file not shown.

View file

@ -3,11 +3,8 @@ Type=Application
Name=gta5view Name=gta5view
Comment=Open and edit GTA V profiles Comment=Open and edit GTA V profiles
Comment[de]=GTA V Profile öffnen und bearbeiten Comment[de]=GTA V Profile öffnen und bearbeiten
Comment[ko]=GTA V Categories=Qt;Utility;
Comment[ru]=Просмотрщик и редактор профилей GTA V Exec=gta5view
Comment[zh_TW]= GTA V
Categories=Qt;Utility;FileTools;
TryExec=gta5view
Exec=gta5view %f
Icon=de.syping.gta5view Icon=de.syping.gta5view
MimeType=application/x-gta5view-export; Terminal=false
StartupNotify=false

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2021 Syping --> <!-- Copyright 2020 Syping -->
<component type="desktop-application"> <component type="desktop-application">
<id>de.syping.gta5view</id> <id>de.syping.gta5view</id>
<launchable type="desktop-id">de.syping.gta5view.desktop</launchable> <launchable type="desktop-id">de.syping.gta5view.desktop</launchable>
@ -10,14 +10,11 @@
<summary>Open and edit GTA V profiles</summary> <summary>Open and edit GTA V profiles</summary>
<summary xml:lang="de">GTA V Profile öffnen und bearbeiten</summary> <summary xml:lang="de">GTA V Profile öffnen und bearbeiten</summary>
<summary xml:lang="ko">GTA V 프로필을 열고 편집</summary>
<summary xml:lang="ru">Просмотрщик и редактор профилей GTA V</summary>
<summary xml:lang="zh-TW">打開與編輯 GTA V 個人檔案</summary>
<icon type="remote">https://img.syping.de/gta5view/gta5view.png</icon> <icon type="remote">https://img.syping.de/gta5view/gta5view.png</icon>
<description> <description>
<p>Open Source Snapmatic and Savegame viewer/editor for GTA V</p> <p>Open Source Snapmatic picture and Savegame viewer/editor for GTA V</p>
<p>Features</p> <p>Features</p>
<ul> <ul>
<li>View Snapmatics with the ability to disable them in-game</li> <li>View Snapmatics with the ability to disable them in-game</li>
@ -34,12 +31,6 @@
<developer_name>Syping</developer_name> <developer_name>Syping</developer_name>
<releases> <releases>
<release date="2023-03-15" version="1.10.2"/>
<release date="2021-06-17" version="1.10.1"/>
<release date="2021-05-27" version="1.10.0"/>
<release date="2021-03-22" version="1.9.2"/>
<release date="2020-12-16" version="1.9.1"/>
<release date="2020-11-30" version="1.9.0"/>
<release date="2020-10-11" version="1.8.0" /> <release date="2020-10-11" version="1.8.0" />
</releases> </releases>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-gta5view-export">
<comment>gta5view Export</comment>
<glob pattern="*.g5e"/>
<generic-icon name="de.syping.gta5view"/>
</mime-type>
</mime-info>

View file

@ -1,15 +0,0 @@
<RCC>
<qresource prefix="/donate">
<file>btc.str</file>
<file>btc.svgz</file>
<file>eth.str</file>
<file>eth.svgz</file>
<file>ltc.str</file>
<file>ltc.svgz</file>
<file>xmr.str</file>
<file>xmr.svgz</file>
</qresource>
<qresource prefix="/img">
<file>donate.svgz</file>
</qresource>
</RCC>

Binary file not shown.

BIN
res/empty1x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

View file

@ -1 +0,0 @@
Ethereum

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -42,7 +42,6 @@ HAWICK="Hawick"
HEART="Heart Attacks Beach" HEART="Heart Attacks Beach"
HORS="Vinewood-Rennbahn" HORS="Vinewood-Rennbahn"
HUMLAB="Humane Labs and Research" HUMLAB="Humane Labs and Research"
ISHEIST="Cayo Perico"
JAIL="Bolingbroke-Strafanstalt" JAIL="Bolingbroke-Strafanstalt"
KOREAT="Little Seoul" KOREAT="Little Seoul"
LACT="Land-Act-Stausee" LACT="Land-Act-Stausee"

View file

@ -42,7 +42,6 @@ HAWICK="Hawick"
HEART="Heart Attacks Beach" HEART="Heart Attacks Beach"
HORS="Vinewood Racetrack" HORS="Vinewood Racetrack"
HUMLAB="Humane Labs and Research" HUMLAB="Humane Labs and Research"
ISHEIST="Cayo Perico"
JAIL="Bolingbroke Penitentiary" JAIL="Bolingbroke Penitentiary"
KOREAT="Little Seoul" KOREAT="Little Seoul"
LACT="Land Act Reservoir" LACT="Land Act Reservoir"

View file

@ -42,7 +42,6 @@ HAWICK="Hawick"
HEART="Heart Attacks Beach" HEART="Heart Attacks Beach"
HORS="Circuito de Vinewood" HORS="Circuito de Vinewood"
HUMLAB="Laboratorios Humane" HUMLAB="Laboratorios Humane"
ISHEIST="Cayo Perico"
JAIL="Penitenciaría de Bolingbroke" JAIL="Penitenciaría de Bolingbroke"
KOREAT="Little Seoul" KOREAT="Little Seoul"
LACT="Embalse de Land Act" LACT="Embalse de Land Act"

View file

@ -42,7 +42,6 @@ HAWICK="Hawick"
HEART="Heart Attacks Beach" HEART="Heart Attacks Beach"
HORS="Circuito de Vinewood" HORS="Circuito de Vinewood"
HUMLAB="Humane Labs and Research" HUMLAB="Humane Labs and Research"
ISHEIST="Cayo Perico"
JAIL="Penitenciaría de Bolingbroke" JAIL="Penitenciaría de Bolingbroke"
KOREAT="Little Seoul" KOREAT="Little Seoul"
LACT="Presa de Land Act" LACT="Presa de Land Act"

View file

@ -41,7 +41,6 @@ HAWICK="Hawick"
HEART="Heart Attacks Beach" HEART="Heart Attacks Beach"
HORS="Hippodrome de Vinewood" HORS="Hippodrome de Vinewood"
HUMLAB="Laboratoires Humane" HUMLAB="Laboratoires Humane"
ISHEIST="Cayo Perico"
JAIL="Pénitencier de Bolingbroke" JAIL="Pénitencier de Bolingbroke"
KOREAT="Little Seoul" KOREAT="Little Seoul"
LACT="Land Act Reservoir" LACT="Land Act Reservoir"

View file

@ -42,7 +42,6 @@ HAWICK="Hawick"
HEART="Heart Attacks Beach" HEART="Heart Attacks Beach"
HORS="Vinewood Racetrack" HORS="Vinewood Racetrack"
HUMLAB="Laboratori di ricerca Humane" HUMLAB="Laboratori di ricerca Humane"
ISHEIST="Cayo Perico"
JAIL="Bolingbroke Penitentiary" JAIL="Bolingbroke Penitentiary"
KOREAT="Little Seoul" KOREAT="Little Seoul"
LACT="Land Act Reservoir" LACT="Land Act Reservoir"

Some files were not shown because too many files have changed in this diff Show more