Compare commits

..

2 Commits

Author SHA1 Message Date
Syping 141be3e237 1.5.5 release 2018-06-02 08:00:57 +02:00
Syping 5dae0a9628 1.6.0 backport for 1.5.5 2018-06-02 07:26:56 +02:00
249 changed files with 24441 additions and 21169 deletions

View File

@ -1,33 +0,0 @@
IDI_ICON1 ICON DISCARDABLE "5sync.ico"
#define RT_MANIFEST 24
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gta5view.exe.manifest"
#include <windows.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION MAJOR_VER, MINOR_VER, PATCH_VER, INT_BUILD_VER
PRODUCTVERSION MAJOR_VER, MINOR_VER, PATCH_VER, INT_BUILD_VER
FILEFLAGSMASK 0x3fL
FILEFLAGS 0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0809, 1200
END
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Syping"
VALUE "FileDescription", "gta5view"
VALUE "FileVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER"
VALUE "InternalName", "gta5view"
VALUE "LegalCopyright", "Copyright © 2016-2023 Syping"
VALUE "OriginalFilename", "gta5view.exe"
VALUE "ProductName", "gta5view"
VALUE "ProductVersion", "MAJOR_VER.MINOR_VER.PATCH_VERSTR_BUILD_VER"
END
END
END

View File

@ -1,72 +0,0 @@
#!/usr/bin/env bash
if [ $(git name-rev --tags --name-only $(git rev-parse HEAD)) == "undefined" ]; then
export APPLICATION_VERSION=$(lua -e 'for line in io.lines("config.h") do local m = string.match(line, "#define GTA5SYNC_APPVER \"(.+)\"$"); if m then print(m); os.exit(0) end end')
else
export APPLICATION_VERSION=$(git name-rev --tags --name-only $(git rev-parse HEAD))
fi
export PACKAGE_VERSION=$(grep -oE '^[^\-]*' <<< $APPLICATION_VERSION)
export PACKAGE_BUILD=$(grep -oP '\-\K.+' <<< $APPLICATION_VERSION)
export EXECUTABLE_VERSION=${PACKAGE_VERSION}${PACKAGE_BUILD}${EXECUTABLE_TAG}
export APPLICATION_MAJOR_VERSION=$(cut -d. -f1 <<< $APPLICATION_VERSION)
export APPLICATION_MINOR_VERSION=$(cut -d. -f2 <<< $APPLICATION_VERSION)
export APPLICATION_PATCH_VERSION=$(cut -d. -f3 <<< $APPLICATION_VERSION)
if [ "${PACKAGE_BUILD}" == "" ]; then
export PACKAGE_BUILD=1
else
export APPLICATION_BUILD_INT_VERSION=$(grep -oE '[1-9]*$' <<< $PACKAGE_BUILD)
export APPLICATION_BUILD_STR_VERSION=-${PACKAGE_BUILD}
fi
cat ".ci/app.rc" | sed \
-e "s/MAJOR_VER/$APPLICATION_MAJOR_VERSION/g" \
-e "s/MINOR_VER/$APPLICATION_MINOR_VERSION/g" \
-e "s/PATCH_VER/$APPLICATION_PATCH_VERSION/g" \
-e "s/INT_BUILD_VER/0/g" \
-e "s/STR_BUILD_VER/$APPLICATION_BUILD_STR_VERSION/g" \
-e "s/STR_BUILD_VER/$APPLICATION_BUILD_STR_VERSION/g" \
> "res/app.rc"
if [ "${BUILD_TYPE}" == "ALPHA" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Alpha"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Alpha\\\\\\\""
elif [ "${BUILD_TYPE}" == "Alpha" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Alpha"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Alpha\\\\\\\""
elif [ "${BUILD_TYPE}" == "BETA" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Beta"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Beta\\\\\\\""
elif [ "${BUILD_TYPE}" == "Beta" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Beta"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Beta\\\\\\\""
elif [ "${BUILD_TYPE}" == "DEV" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Developer"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Developer\\\\\\\""
elif [ "${BUILD_TYPE}" == "Development" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Developer"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Developer\\\\\\\""
elif [ "${BUILD_TYPE}" == "DAILY" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Daily Build"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Daily Build\\\\\\\""
elif [ "${BUILD_TYPE}" == "Daily" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Daily Build"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Daily Build\\\\\\\""
elif [ "${BUILD_TYPE}" == "RC" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release Candidate"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release Candidate\\\\\\\""
elif [ "${BUILD_TYPE}" == "Release Candidate" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release Candidate"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release Candidate\\\\\\\""
elif [ "${BUILD_TYPE}" == "REL" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release\\\\\\\""
elif [ "${BUILD_TYPE}" == "Release" ]; then
export CMAKE_BUILD_TYPE="-DGTA5VIEW_BUILDTYPE=Release"
export QMAKE_BUILD_TYPE="DEFINES+=GTA5SYNC_BUILDTYPE=\\\\\\\"Release\\\\\\\""
fi
export PROJECT_DIR=$(pwd)
.ci/${BUILD_SCRIPT}

View File

@ -1,38 +0,0 @@
#!/usr/bin/env bash
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
mkdir -p build && \
mkdir -p assets && \
chmod -x res/gta5sync_*.qm res/*.desktop res/*gta5view*.png && \
cd build && \
mkdir -p qt5 && \
cd qt5 && \
echo "Grand Theft Auto V Snapmatic and Savegame viewer/editor" > ./description-pak && \
cd .. && \
# Set compiler
export CC=clang && \
export CXX=clang++ && \
# Prepare checkinstall step
mkdir -p /usr/share/gta5view && \
# Starting build
cd qt5 && \
cmake \
"-DCMAKE_INSTALL_PREFIX=/usr" \
"${CMAKE_BUILD_TYPE}" \
"-DFORCE_QT_VERSION=5" \
"-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/" \
"-DQCONF_BUILD=ON" \
../../ && \
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

View File

@ -1,8 +0,0 @@
#!/usr/bin/env bash
# Install packages
.ci/debian_install.sh && \
# Build gta5view
.ci/debian_build.sh && \
cd ${PROJECT_DIR}

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
if [ "${DOCKER_USER}" != "" ]; then
DOCKER_IMAGE=${DOCKER_USER}/debian:${DEBIAN_VERSION}
else
DOCKER_IMAGE=debian:${DEBIAN_VERSION}
fi
PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \
docker pull ${DOCKER_IMAGE} && \
docker run --rm \
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
${DOCKER_IMAGE} \
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APPLICATION_COMMIT=${APPLICATION_COMMIT} && export BUILD_TYPE=${BUILD_TYPE} && export APT_INSTALL=${APT_INSTALL} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && export QMAKE_BUILD_TYPE=${QMAKE_BUILD_TYPE} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .ci/debian_install.sh && .ci/debian_build.sh"

View File

@ -1,13 +0,0 @@
#!/usr/bin/env 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
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

View File

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

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
echo "gta5view image name is gta5view-osx_${APPLICATION_VERSION}.dmg" && \
mkdir -p build && \
mkdir -p assets && \
cd build && \
/usr/local/bin/cmake \
"-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 && \
/usr/local/opt/qt/bin/macdeployqt gta5view.app -dmg && \
cp -Rf gta5view.dmg ../assets/gta5view-osx_${APPLICATION_VERSION}.dmg

View File

@ -1,8 +0,0 @@
#!/usr/bin/env bash
# Install packages
.ci/osx_install.sh && \
# Build gta5view
.ci/osx_build.sh && \
cd ${PROJECT_DIR}

View File

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

View File

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Prepare environment variable
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
echo "gta5view executable is ${GTA5VIEW_EXECUTABLE}" && \
mkdir -p build && \
mkdir -p assets && \
# Starting build
cd build && \
mingw64-qt-cmake \
"${CMAKE_BUILD_TYPE}" \
"-DGTA5VIEW_BUILDCODE=${PACKAGE_CODE}" \
"-DGTA5VIEW_APPVER=${APPLICATION_VERSION}" \
"-DGTA5VIEW_COMMIT=${APPLICATION_COMMIT}" \
"-DWITH_DONATE=ON" \
"-DWITH_TELEMETRY=ON" \
"-DDONATE_ADDRESSES=$(cat ${PROJECT_DIR}/.ci/donate.txt)" \
"-DTELEMETRY_WEBURL=https://dev.syping.de/gta5view-userstats/" \
.. && \
make -j 4 && \
x86_64-w64-mingw32-strip -s gta5view.exe && \
cp -Rf *.exe ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} && \
cd ${PROJECT_DIR}/assets

View File

@ -1,25 +0,0 @@
#!/usr/bin/env bash
DOCKER_IMAGE=sypingauto/gta5view-build:1.10-static
PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \
docker pull ${DOCKER_IMAGE} && \
docker run --rm \
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
${DOCKER_IMAGE} \
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APPLICATION_COMMIT=${APPLICATION_COMMIT} && export BUILD_TYPE=${BUILD_TYPE} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && export QMAKE_BUILD_TYPE=${QMAKE_BUILD_TYPE} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .ci/windows_build.sh" && \
# Prepare environment variable
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
# Upload Assets to Dropbox
if [ "${PACKAGE_CODE}" == "gta5-mods" ]; then
${PROJECT_DIR}/.ci/dropbox_uploader.sh mkdir gta5-mods/${PACKAGE_VERSION}
${PROJECT_DIR}/.ci/dropbox_uploader.sh upload ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} gta5-mods/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
rm -rf ${GTA5VIEW_EXECUTABLE}
elif [ "${PACKAGE_CODE}" == "gtainside" ]; then
${PROJECT_DIR}/.ci/dropbox_uploader.sh mkdir gtainside/${PACKAGE_VERSION}
${PROJECT_DIR}/.ci/dropbox_uploader.sh upload ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} gtainside/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
rm -rf ${GTA5VIEW_EXECUTABLE}
fi

View File

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

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
DOCKER_IMAGE=sypingauto/gta5view-build:1.10-shared
PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \
docker pull ${DOCKER_IMAGE} && \
docker run --rm \
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
${DOCKER_IMAGE} \
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APPLICATION_COMMIT=${APPLICATION_COMMIT} && export BUILD_TYPE=${BUILD_TYPE} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} && export QMAKE_BUILD_TYPE=${QMAKE_BUILD_TYPE} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .ci/wininstall_build.sh"

View File

@ -1,36 +0,0 @@
kind: pipeline
type: docker
environment:
BUILD_TYPE: "REL"
steps:
- name: Windows Installer
image: sypingauto/gta5view-build:1.10-shared
environment:
BUILD_SCRIPT: "wininstall_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32"
TCA_PASS:
from_secret: tca_pass
commands:
- .drone/drone.sh
volumes:
- name: gta5view
path: /srv/gta5view
- name: Windows Portable
image: sypingauto/gta5view-build:1.10-static
environment:
BUILD_SCRIPT: "windows_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32"
TCA_PASS:
from_secret: tca_pass
commands:
- .drone/drone.sh
volumes:
- name: gta5view
path: /srv/gta5view
volumes:
- name: gta5view
host:
path: /srv/gta5view

View File

@ -1,33 +0,0 @@
#!/bin/bash
# Cleanup previous Drone build
if [ -d "assets" ]; then
rm -rf assets
fi
if [ -d "build" ]; then
rm -rf build
fi
# Decrypt Telemetry Authenticator
rm -rf tmext/TelemetryClassAuthenticator.cpp && \
openssl aes-256-cbc -k ${TCA_PASS} -in .drone/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d -pbkdf2
# Check if build is not tagged
if [ "${DRONE_TAG}" == "" ]; then
export EXECUTABLE_TAG=-$(git rev-parse --short HEAD)
else
export EXECUTABLE_TAG=
fi
# Check if package code is not set
if [ "${PACKAGE_CODE}" == "" ]; then
export PACKAGE_CODE=Drone
fi
# Init Application Commit Hash
export APPLICATION_COMMIT=$(git rev-parse --short HEAD)
# Start CI script and copying assets into gta5view directory
.ci/ci.sh && \
mkdir -p /srv/gta5view/${APPLICATION_COMMIT} && \
cp -Rf assets/* /srv/gta5view/${APPLICATION_COMMIT}/

View File

@ -1,22 +0,0 @@
app-id: de.syping.gta5view
runtime: org.kde.Platform
runtime-version: '5.15-21.08'
sdk: org.kde.Sdk
command: gta5view
finish-args:
- --share=network
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
- --device=dri
modules:
- name: gta5view
buildsystem: cmake-ninja
config-opts:
- -DFLATPAK_BUILD=ON
- -DQCONF_BUILD=ON
- -DGTA5VIEW_BUILDCODE=Flatpak
- -DGTA5VIEW_BUILDTYPE=Release
sources:
- type: dir
path: ../

4
.gitignore vendored
View File

@ -29,7 +29,3 @@
# Qt project user file # Qt project user file
*.pro.user *.pro.user
# Gettext translation files
*.po
*.pot

View File

@ -1,31 +0,0 @@
stages:
- build
variables:
BUILD_TYPE: "REL"
Windows Installer:
stage: build
image: sypingauto/gta5view-build:1.10-shared
variables:
BUILD_SCRIPT: "wininstall_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32"
script:
- .gitlab/gitlab.sh
artifacts:
name: "gta5view-$CI_COMMIT_REF_NAME-${CI_COMMIT_SHA:0:8}_setup"
paths:
- "gta5view-*.exe"
Windows Portable:
stage: build
image: sypingauto/gta5view-build:1.10-static
variables:
BUILD_SCRIPT: "windows_build.sh"
QT_SELECT: "qt5-x86_64-w64-mingw32"
script:
- .gitlab/gitlab.sh
artifacts:
name: "gta5view-$CI_COMMIT_REF_NAME-${CI_COMMIT_SHA:0:8}_portable"
paths:
- "gta5view-*.exe"

View File

@ -1,24 +0,0 @@
#!/bin/bash
# Decrypt Telemetry Authenticator
rm -rf tmext/TelemetryClassAuthenticator.cpp && \
openssl aes-256-cbc -k ${tca_pass} -in .gitlab/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d
# Check if build is not tagged
if [ "${CI_COMMIT_TAG}" == "" ]; then
export EXECUTABLE_TAG=-$(git rev-parse --short HEAD)
else
export EXECUTABLE_TAG=
fi
# Check if package code is not set
if [ "${PACKAGE_CODE}" == "" ]; then
export PACKAGE_CODE=GitLab
fi
# Init Application Commit Hash
export APPLICATION_COMMIT=$(git rev-parse --short HEAD)
# Start CI script and copying assets into base directory
.ci/ci.sh && \
cp -Rf assets/* ./

View File

@ -1,36 +1,45 @@
dist: bionic dist: trusty
sudo: required sudo: required
language: cpp language: cpp
services: service:
- docker - docker
env:
global:
- BUILD_TYPE=REL
matrix: matrix:
include: include:
- env: - env:
- BUILD_SCRIPT=debian_docker.sh - BUILD_SCRIPT=debian_travis.sh
- RELEASE_LABEL="Debian 64-Bit Package" - QMAKE_FLAGS_QT4=QMAKE_CXXFLAGS+=-Wno-missing-field-initializers
- DEBIAN_VERSION=buster - DEBIAN_VERSION=jessie
- DOCKER_USER=i386
- APT_INSTALL=clang
- env:
- BUILD_SCRIPT=debian_travis.sh
- QMAKE_FLAGS_QT4=QMAKE_CXXFLAGS+=-Wno-missing-field-initializers
- DEBIAN_VERSION=jessie
- DOCKER_USER=amd64 - DOCKER_USER=amd64
- APT_INSTALL=clang - APT_INSTALL=clang
- env: - env:
- BUILD_SCRIPT=windows_docker.sh - BUILD_SCRIPT=windows_travis.sh
- QT_SELECT=qt5-x86_64-w64-mingw32 - QT_SELECT=qt5-i686-w64-mingw32
- RELEASE_LABEL="Windows 64-Bit Portable"
- env: - env:
- BUILD_SCRIPT=wininstall_docker.sh - BUILD_SCRIPT=windows_travis.sh
- QT_SELECT=qt5-x86_64-w64-mingw32
- EXECUTABLE_ARCH=_x64
- env:
- BUILD_SCRIPT=windows_travis.sh
- QT_SELECT=qt5-x86_64-w64-mingw32
- PACKAGE_CODE=Dropbox
- env:
- BUILD_SCRIPT=windows_travis.sh
- QT_SELECT=qt5-x86_64-w64-mingw32
- PACKAGE_CODE=gta5-mods
- env:
- BUILD_SCRIPT=wininstall_travis.sh
- QT_SELECT=qt5-x86_64-w64-mingw32 - QT_SELECT=qt5-x86_64-w64-mingw32
- RELEASE_LABEL="Windows 64-Bit Installer"
- os: osx - os: osx
osx_image: xcode14.2 env: BUILD_SCRIPT=osx_travis.sh
env:
- BUILD_SCRIPT=osx_ci.sh
- RELEASE_LABEL="Mac OS X 64-Bit Disk Image"
before_install: before_install:
- ".travis/source.sh" - ".travis/source.sh"
@ -42,7 +51,6 @@ deploy:
provider: releases provider: releases
api_key: api_key:
secure: o7VneEz1aHfdVwZvOZLfopf6uJWNrFsZaBvunTmXFzpmNFhlNS1qwqgMUkIA2yBRbZ3wIzVs4vfwIHv7W9yE/PqK+AYL+R8+AwKGrwlgT4HqJNuk6VM/LNJ6GwT/qkQuaoOVw29bUjmzzgIRdHmw53SlJv6Hh1VE8HphlTT//aex6nCfcFhUZ0BETdZDWz5FSHwL3NalUoqfKfQrJeky5RXzCyCANQC2tKt0bV46GaWIgWrDo2KCTNqPtRWWf5GDmnkXE5IYRMQ3mXvO9iYh0v5Y2jo4PiXGUiFUU6Z3aAWFAiPdGclrBO697cf3lCTzDMhuCETR153qFYsLShUlFf61ITAmCeHAWETjZDri0lmPONo3GoNB6alGfYEA51qw14kXakrTpICtTJj7gw/gtUYOabW6hrzmieNzMBIy62RikDPjyakFnuwW2qNHRlD65e0jYv+6nCpb6E+OV16Ysh1zhV2vTfpfzVmSuyu2J+ELqXD3OZCXRSPpDIih9UQ8335p8FBji6jHORcgym/TRgdgRmENibh8tLzWp+UjpWHuWfcpvZgOskjfwU0iDMCayMJ7tDpOhXHcAhDRnd6XRIiOJ5YZCzflj2nEwmt3YUd7DwXS/AU+WHOmcNQBjXBxF/FJa35XXcy3HKJM5TTKqtph3medo30us5yXHeG6NNg= secure: o7VneEz1aHfdVwZvOZLfopf6uJWNrFsZaBvunTmXFzpmNFhlNS1qwqgMUkIA2yBRbZ3wIzVs4vfwIHv7W9yE/PqK+AYL+R8+AwKGrwlgT4HqJNuk6VM/LNJ6GwT/qkQuaoOVw29bUjmzzgIRdHmw53SlJv6Hh1VE8HphlTT//aex6nCfcFhUZ0BETdZDWz5FSHwL3NalUoqfKfQrJeky5RXzCyCANQC2tKt0bV46GaWIgWrDo2KCTNqPtRWWf5GDmnkXE5IYRMQ3mXvO9iYh0v5Y2jo4PiXGUiFUU6Z3aAWFAiPdGclrBO697cf3lCTzDMhuCETR153qFYsLShUlFf61ITAmCeHAWETjZDri0lmPONo3GoNB6alGfYEA51qw14kXakrTpICtTJj7gw/gtUYOabW6hrzmieNzMBIy62RikDPjyakFnuwW2qNHRlD65e0jYv+6nCpb6E+OV16Ysh1zhV2vTfpfzVmSuyu2J+ELqXD3OZCXRSPpDIih9UQ8335p8FBji6jHORcgym/TRgdgRmENibh8tLzWp+UjpWHuWfcpvZgOskjfwU0iDMCayMJ7tDpOhXHcAhDRnd6XRIiOJ5YZCzflj2nEwmt3YUd7DwXS/AU+WHOmcNQBjXBxF/FJa35XXcy3HKJM5TTKqtph3medo30us5yXHeG6NNg=
label: ${RELEASE_LABEL}
file_glob: true file_glob: true
file: assets/* file: assets/*
skip_cleanup: true skip_cleanup: true

31
.travis/debian_build.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
mkdir -p build && \
mkdir -p assets && \
chmod -x res/gta5sync_*.qm res/gta5view.desktop res/gta5view.png && \
cd build && \
mkdir -p qt4 && \
cd qt4 && \
echo "Grand Theft Auto V Snapmatic and Savegame viewer/manager" > ./description-pak && \
cd .. && \
mkdir -p qt5 && \
cd qt5 && \
echo "Grand Theft Auto V Snapmatic and Savegame viewer/manager" > ./description-pak && \
cd .. && \
# Prepare checkinstall step
mkdir -p /usr/share/gta5view && \
# Starting build
cd qt5 && \
qmake -qt=5 -spec linux-clang GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=gnu++11 ${QMAKE_FLAGS_QT5} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_QCONF DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../../gta5view.pro && \
make -j 4 && \
checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt5 --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5,qttranslations5-l10n --conflicts=gta5view,gta5view-qt4 --replaces=gta5view,gta5view-qt4 --pakdir=${PROJECT_DIR}/assets && \
cd .. && \
cd qt4 && \
qmake -qt=4 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=gnu++11 ${QMAKE_FLAGS_QT4} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro && \
make -j 4 && \
checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt4 --pkgversion=${PACKAGE_VERSION} --pkgrelease=${PACKAGE_BUILD} --pkggroup=utility --maintainer="Syping \<dpkg@syping.de\>" --requires=libqtcore4,libqtgui4,libqt4-network,qtcore4-l10n --conflicts=gta5view,gta5view-qt5 --replaces=gta5view,gta5view-qt5 --pakdir=${PROJECT_DIR}/assets

5
.travis/debian_install.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
# Install packages
apt-get update -qq && \
apt-get install -qq ${APT_INSTALL} checkinstall dpkg-dev fakeroot g++ gcc qtbase5-dev qt5-qmake qttranslations5-l10n libqt4-dev

15
.travis/debian_travis.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
if [[ ${DOCKER_USER} ]]; then
DOCKER_IMAGE=${DOCKER_USER}/debian:${DEBIAN_VERSION}
else
DOCKER_IMAGE=debian:${DEBIAN_VERSION}
fi
PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \
docker pull ${DOCKER_IMAGE} && \
docker run --rm \
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
${DOCKER_IMAGE} \
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export APT_INSTALL=${APT_INSTALL} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .travis/debian_install.sh && .travis/debian_build.sh"

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.5.5.0"
!define COPYRIGHT "Copyright © 2016-2022 Syping" !define COPYRIGHT "Copyright © 2016-2018 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"
@ -34,7 +33,6 @@ Caption "${APP_NAME}"
OutFile "${INSTALLER_NAME}" OutFile "${INSTALLER_NAME}"
#BrandingText "${APP_NAME}" #BrandingText "${APP_NAME}"
XPStyle on XPStyle on
Unicode true
InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" "" InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" ""
InstallDir "$PROGRAMFILES64\Syping\gta5view" InstallDir "$PROGRAMFILES64\Syping\gta5view"
@ -80,7 +78,6 @@ InstallDir "$PROGRAMFILES64\Syping\gta5view"
!insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "French" !insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "German" !insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Korean"
!insertmacro MUI_LANGUAGE "Russian" !insertmacro MUI_LANGUAGE "Russian"
!insertmacro MUI_LANGUAGE "Ukrainian" !insertmacro MUI_LANGUAGE "Ukrainian"
!insertmacro MUI_LANGUAGE "TradChinese" !insertmacro MUI_LANGUAGE "TradChinese"
@ -92,7 +89,7 @@ InstallDir "$PROGRAMFILES64\Syping\gta5view"
Function .onInit Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY !insertmacro MUI_LANGDLL_DISPLAY
!ifdef WIN32 !ifdef WIN32
MessageBox MB_OK|MB_ICONSTOP "Windows 32-Bit is not supported anymore!" MessageBox MB_OK|MB_ICONSTOP "Can't install the 64bit version on a 32bit system, please download the 32bit version!"
Quit Quit
!endif !endif
SetRegView 64 SetRegView 64
@ -104,80 +101,45 @@ Section -MainProgram
${INSTALL_TYPE} ${INSTALL_TYPE}
SetOverwrite ifnewer SetOverwrite ifnewer
SetOutPath "$INSTDIR" SetOutPath "$INSTDIR"
File "../build/gta5view.exe" File "../build/release/gta5view.exe"
File "/opt/llvm-mingw/x86_64-w64-mingw32/bin/libc++.dll" File "/usr/lib/gcc/x86_64-w64-mingw32/6.3-win32/libgcc_s_seh-1.dll"
File "/opt/llvm-mingw/x86_64-w64-mingw32/bin/libunwind.dll" File "/usr/lib/gcc/x86_64-w64-mingw32/6.3-win32/libstdc++-6.dll"
File "/usr/local/lib/x86_64-w64-mingw32/openssl/bin/libcrypto-1_1-x64.dll" File "/opt/windev/libressl-latest_qt64d/bin/libcrypto-43.dll"
File "/usr/local/lib/x86_64-w64-mingw32/openssl/bin/libssl-1_1-x64.dll" File "/opt/windev/libressl-latest_qt64d/bin/libssl-45.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Core.dll" File "/opt/windev/libjpeg-turbo-latest_qt64d/bin/libjpeg-62.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Gui.dll" File "/opt/windev/qt64d-latest/bin/Qt5Core.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Network.dll" File "/opt/windev/qt64d-latest/bin/Qt5Gui.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Svg.dll" File "/opt/windev/qt64d-latest/bin/Qt5Network.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/bin/Qt5Widgets.dll" File "/opt/windev/qt64d-latest/bin/Qt5Svg.dll"
File "/opt/windev/qt64d-latest/bin/Qt5Widgets.dll"
File "/opt/windev/qt64d-latest/bin/Qt5WinExtras.dll"
SetOutPath "$INSTDIR\lang" SetOutPath "$INSTDIR\lang"
File "../build/gta5sync_en_US.qm" File "../res/gta5sync_en_US.qm"
File "../build/gta5sync_de.qm" File "../res/gta5sync_de.qm"
File "../build/gta5sync_fr.qm" File "../res/gta5sync_fr.qm"
File "../build/gta5sync_ko.qm" File "../res/gta5sync_ru.qm"
File "../build/gta5sync_ru.qm" File "../res/gta5sync_uk.qm"
File "../build/gta5sync_uk.qm" File "../res/gta5sync_zh_TW.qm"
File "../build/gta5sync_zh_TW.qm" File "../res/qtbase_en_GB.qm"
File "../build/qtbase_en_GB.qm" File "../res/qtbase_de.qm"
File "../res/qt5/qtbase_de.qm" File "../res/qtbase_fr.qm"
File "../res/qt5/qtbase_fr.qm" File "../res/qtbase_ru.qm"
File "../res/qt5/qtbase_ko.qm" File "../res/qtbase_uk.qm"
File "../res/qt5/qtbase_ru.qm" File "../res/qtbase_zh_TW.qm"
File "../res/qt5/qtbase_uk.qm" SetOutPath "$INSTDIR\audio"
File "../res/qt5/qtbase_zh_TW.qm" File "/opt/windev/qt64d-latest/plugins/audio/qtaudio_windows.dll"
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 "/opt/windev/qt64d-latest/plugins/imageformats/qgif.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qicns.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qicns.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qico.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qico.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qjpeg.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qjpeg.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qsvg.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qsvg.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qtga.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qtga.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qtiff.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qtiff.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qwbmp.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qwbmp.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/imageformats/qwebp.dll" File "/opt/windev/qt64d-latest/plugins/imageformats/qwebp.dll"
SetOutPath "$INSTDIR\platforms" SetOutPath "$INSTDIR\platforms"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/platforms/qwindows.dll" File "/opt/windev/qt64d-latest/plugins/platforms/qwindows.dll"
SetOutPath "$INSTDIR\styles"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/styles/qcleanlooksstyle.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/styles/qplastiquestyle.dll"
File "/usr/local/lib/x86_64-w64-mingw32/qt5/plugins/styles/qwindowsvistastyle.dll"
SectionEnd SectionEnd
###################################################################### ######################################################################
@ -224,88 +186,33 @@ 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"
Delete "$INSTDIR\libc++.dll" Delete "$INSTDIR\libgcc_s_seh-1.dll"
Delete "$INSTDIR\libunwind.dll" Delete "$INSTDIR\libstdc++-6.dll"
Delete "$INSTDIR\libcrypto-1_1-x64.dll" Delete "$INSTDIR\libcrypto-43.dll"
Delete "$INSTDIR\libssl-1_1-x64.dll" Delete "$INSTDIR\libssl-45.dll"
Delete "$INSTDIR\libjpeg-62.dll"
Delete "$INSTDIR\Qt5Core.dll" Delete "$INSTDIR\Qt5Core.dll"
Delete "$INSTDIR\Qt5Gui.dll" 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"
Delete "$INSTDIR\lang\gta5sync_ko.qm"
Delete "$INSTDIR\lang\gta5sync_ru.qm" Delete "$INSTDIR\lang\gta5sync_ru.qm"
Delete "$INSTDIR\lang\gta5sync_uk.qm" Delete "$INSTDIR\lang\gta5sync_uk.qm"
Delete "$INSTDIR\lang\gta5sync_zh_TW.qm" Delete "$INSTDIR\lang\gta5sync_zh_TW.qm"
Delete "$INSTDIR\lang\qtbase_en_GB.qm" Delete "$INSTDIR\lang\qtbase_en_GB.qm"
Delete "$INSTDIR\lang\qtbase_de.qm" Delete "$INSTDIR\lang\qtbase_de.qm"
Delete "$INSTDIR\lang\qtbase_fr.qm" Delete "$INSTDIR\lang\qtbase_fr.qm"
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\audio\qtaudio_windows.dll"
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"
@ -316,13 +223,10 @@ Delete "$INSTDIR\imageformats\qtiff.dll"
Delete "$INSTDIR\imageformats\qwbmp.dll" Delete "$INSTDIR\imageformats\qwbmp.dll"
Delete "$INSTDIR\imageformats\qwebp.dll" Delete "$INSTDIR\imageformats\qwebp.dll"
Delete "$INSTDIR\platforms\qwindows.dll" Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\styles\qcleanlooksstyle.dll"
Delete "$INSTDIR\styles\qplastiquestyle.dll"
Delete "$INSTDIR\styles\qwindowsvistastyle.dll"
RmDir "$INSTDIR\lang" RmDir "$INSTDIR\lang"
RmDir "$INSTDIR\imageformats"
RmDir "$INSTDIR\platforms" RmDir "$INSTDIR\platforms"
RmDir "$INSTDIR\styles" RmDir "$INSTDIR\imageformats"
Delete "$INSTDIR\uninstall.exe" Delete "$INSTDIR\uninstall.exe"
!ifdef WEB_SITE !ifdef WEB_SITE

14
.travis/osx_build.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
echo "gta5view image name is gta5view-osx_${APPLICATION_VERSION}.dmg" && \
mkdir -p build && \
mkdir -p assets && \
cd build && \
/usr/local/opt/qt/bin/qmake ${QMAKE_FLAGS_QT5} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../gta5view.pro && \
make -j 4 && \
/usr/local/opt/qt/bin/macdeployqt gta5view.app -dmg && \
cp -Rf gta5view.dmg ../assets/gta5view-osx_${APPLICATION_VERSION}.dmg

4
.travis/osx_install.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
# Install packages
brew install qt

8
.travis/osx_travis.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
# Install packages
.travis/osx_install.sh && \
# Build gta5view
.travis/osx_build.sh && \
cd ${PROJECT_DIR}

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
rm -rf tmext/TelemetryClassAuthenticator.cpp && \ rm -rf tmext/TelemetryClassAuthenticator.cpp && \
openssl aes-256-cbc -K $encrypted_db000a5d87d6_key -iv $encrypted_db000a5d87d6_iv -in .travis/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d && \ openssl aes-256-cbc -K $encrypted_55502862a724_key -iv $encrypted_55502862a724_iv -in tmext/TelemetryClassAuthenticator.cpp.enc -out tmext/TelemetryClassAuthenticator.cpp -d && \
openssl aes-256-cbc -K $encrypted_d57e7d2f8877_key -iv $encrypted_d57e7d2f8877_iv -in .travis/dropbox_uploader.enc -out ~/.dropbox_uploader -d openssl aes-256-cbc -K $encrypted_d57e7d2f8877_key -iv $encrypted_d57e7d2f8877_iv -in .travis/dropbox_uploader.enc -out ~/.dropbox_uploader -d

View File

@ -1,11 +1,11 @@
#!/bin/bash #!/bin/bash
# Install lua # Install lua
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
brew install lua
else
sudo apt-get update -qq && \ sudo apt-get update -qq && \
sudo apt-get install -qq lua5.2 sudo apt-get install -qq lua5.2
elif [ "${TRAVIS_OS_NAME}" == "osx" ]; then
brew install lua
fi fi
# Check if build is not tagged # Check if build is not tagged
@ -20,8 +20,11 @@ if [ "${PACKAGE_CODE}" == "" ]; then
export PACKAGE_CODE=GitHub export PACKAGE_CODE=GitHub
fi fi
# Init Application Commit Hash if [ `git name-rev --tags --name-only $(git rev-parse HEAD)` == "undefined" ]; then export APPLICATION_VERSION=`lua -e 'for line in io.lines("config.h") do local m = string.match(line, "#define GTA5SYNC_APPVER \"(.+)\"$"); if m then print(m); os.exit(0) end end'`; else export APPLICATION_VERSION=`git name-rev --tags --name-only $(git rev-parse HEAD)`; fi
export APPLICATION_COMMIT=$(git rev-parse --short HEAD) export PACKAGE_VERSION=$(grep -oE '^[^\-]*' <<< $APPLICATION_VERSION)
export PACKAGE_BUILD=$(grep -oP '\-\K.+' <<< $APPLICATION_VERSION)
export EXECUTABLE_VERSION=${PACKAGE_VERSION}${PACKAGE_BUILD}${EXECUTABLE_TAG}
if [[ ! ${PACKAGE_BUILD} ]]; then export PACKAGE_BUILD=1; fi
export PROJECT_DIR=$(pwd)
# Start CI script .travis/${BUILD_SCRIPT}
.ci/ci.sh

View File

@ -1,8 +1,8 @@
#!/bin/bash #!/bin/bash
# Install packages # Install packages
sudo .ci/debian_install.sh && \ sudo .travis/debian_install.sh && \
# Build gta5view # Build gta5view
sudo .ci/debian_build.sh && \ sudo .travis/debian_build.sh && \
cd ${PROJECT_DIR} cd ${PROJECT_DIR}

31
.travis/windows_build.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
apt-get update -qq && \
apt-get install -qq curl && \
export GTA5VIEW_EXECUTABLE=gta5view-${EXECUTABLE_VERSION}${EXECUTABLE_ARCH}.exe && \
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
echo "gta5view executable is ${GTA5VIEW_EXECUTABLE}" && \
mkdir -p build && \
mkdir -p assets && \
# Starting build
cd build && \
qmake-static ${QMAKE_FLAGS} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" ../gta5view.pro && \
make -j 4 && \
cp -Rf release/*.exe ${PROJECT_DIR}/assets/${GTA5VIEW_EXECUTABLE} && \
cd ${PROJECT_DIR}/assets && \
upx --best ${GTA5VIEW_EXECUTABLE} && \
if [ "${PACKAGE_CODE}" == "Dropbox" ]; then
${PROJECT_DIR}/.travis/dropbox_uploader.sh mkdir gta5view-builds/${PACKAGE_VERSION}
${PROJECT_DIR}/.travis/dropbox_uploader.sh upload ${GTA5VIEW_EXECUTABLE} gta5view-builds/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
rm -rf ${GTA5VIEW_EXECUTABLE}
elif [ "${PACKAGE_CODE}" == "gta5-mods" ]; then
${PROJECT_DIR}/.travis/dropbox_uploader.sh mkdir gta5-mods/${PACKAGE_VERSION}
${PROJECT_DIR}/.travis/dropbox_uploader.sh upload ${GTA5VIEW_EXECUTABLE} gta5-mods/${PACKAGE_VERSION}/${GTA5VIEW_EXECUTABLE} && \
rm -rf ${GTA5VIEW_EXECUTABLE}
fi

13
.travis/windows_travis.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
QT_VERSION=5.6.3
DOCKER_IMAGE=syping/qt5-static-mingw:${QT_VERSION}
PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \
docker pull ${DOCKER_IMAGE} && \
docker run --rm \
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
-v "${HOME}/.dropbox_uploader:/root/.dropbox_uploader" \
${DOCKER_IMAGE} \
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .travis/windows_build.sh"

18
.travis/wininstall_build.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
apt-get update -qq && \
apt-get install -qq nsis && \
# Creating folders
cd ${PROJECT_DIR} && \
echo "gta5view build version is ${APPLICATION_VERSION}" && \
mkdir -p build && \
mkdir -p assets && \
# Starting build
cd build && \
qmake ${QMAKE_FLAGS} DEFINES+=GTA5SYNC_BUILDTYPE_REL "DEFINES+=GTA5SYNC_BUILDCODE=\\\\\\\"${PACKAGE_CODE}\\\\\\\"" "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"${APPLICATION_VERSION}\\\\\\\"" DEFINES+=GTA5SYNC_TELEMETRY "DEFINES+=GTA5SYNC_TELEMETRY_WEBURL=\\\\\\\"https://dev.syping.de/gta5view-userstats/\\\\\\\"" DEFINES+=GTA5SYNC_QCONF DEFINES+=GTA5SYNC_INLANG='\\\"RUNDIR:SEPARATOR:lang\\\"' DEFINES+=GTA5SYNC_LANG='\\\"RUNDIR:SEPARATOR:lang\\\"' DEFINES+=GTA5SYNC_PLUG='\\\"RUNDIR:SEPARATOR:plugins\\\"' ../gta5view.pro && \
make -j 4 && \
cd ${PROJECT_DIR}/assets && \
makensis -NOCD ${PROJECT_DIR}/.travis/gta5view.nsi && \
mv -f gta5view_setup.exe gta5view-${EXECUTABLE_VERSION}_setup.exe

12
.travis/wininstall_travis.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
QT_VERSION=5.6.3
DOCKER_IMAGE=syping/qt5-shared-mingw:${QT_VERSION}
PROJECT_DIR_DOCKER=/gta5view
cd ${PROJECT_DIR} && \
docker pull ${DOCKER_IMAGE} && \
docker run --rm \
-v "${PROJECT_DIR}:${PROJECT_DIR_DOCKER}" \
${DOCKER_IMAGE} \
/bin/bash -c "export PROJECT_DIR=${PROJECT_DIR_DOCKER} && export QT_SELECT=${QT_SELECT} && export APPLICATION_VERSION=${APPLICATION_VERSION} && export QMAKE_FLAGS_QT4=${QMAKE_FLAGS_QT4} && export QMAKE_FLAGS_QT5=${QMAKE_FLAGS_QT5} && export PACKAGE_VERSION=${PACKAGE_VERSION} && export PACKAGE_BUILD=${PACKAGE_BUILD} && export PACKAGE_CODE=${PACKAGE_CODE} && export EXECUTABLE_VERSION=${EXECUTABLE_VERSION} && export EXECUTABLE_ARCH=${EXECUTABLE_ARCH} && cd ${PROJECT_DIR_DOCKER} && .travis/wininstall_build.sh"

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
@ -29,47 +29,43 @@ 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;
#ifdef GTA5SYNC_COMMIT
if ((strcmp(literalBuildType, REL_BUILDTYPE) != 0) && !appVersion.contains("-"))
appVersion = appVersion % "-" % GTA5SYNC_COMMIT;
#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 +73,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 +118,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-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
@ -22,19 +22,19 @@
#include "StandardPaths.h" #include "StandardPaths.h"
#include <QtGlobal> #include <QtGlobal>
#include <QStringBuilder> #include <QStringBuilder>
#include <QDesktopWidget>
#include <QApplication> #include <QApplication>
#include <QSettings> #include <QSettings>
#include <QScreen> #include <QScreen>
#include <QDebug> #include <QDebug>
#include <QRect> #include <QRect>
#include <QDir> #include <QDir>
#include <iostream>
#if QT_VERSION < 0x050000 using namespace std;
#include <QDesktopWidget>
#endif
AppEnv::AppEnv() AppEnv::AppEnv()
{ {
} }
// Build Stuff // Build Stuff
@ -55,17 +55,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 +75,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 +132,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,57 +148,18 @@ 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()
{ {
#if QT_VERSION >= 0x050400 return QString("Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 %1/%2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
#ifdef Q_OS_WIN
QString kernelVersion = QSysInfo::kernelVersion();
const QStringList &kernelVersionList = kernelVersion.split(".");
if (kernelVersionList.length() > 2) {
kernelVersion = kernelVersionList.at(0) % "." % kernelVersionList.at(1);
}
QString runArch = QSysInfo::buildCpuArchitecture();
if (runArch == "x86_64") {
runArch = "Win64; x64";
}
else if (runArch == "i686") {
const QString &curArch = QSysInfo::currentCpuArchitecture();
if (curArch == "x86_64") {
runArch = "WOW64";
}
else if (curArch == "i686") {
runArch = "Win32; x86";
}
}
return QString("Mozilla/5.0 (Windows NT %1; %2) %3/%4").arg(kernelVersion, runArch, GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
#else
return QString("Mozilla/5.0 (%1; %2) %3/%4").arg(QSysInfo::kernelType(), QSysInfo::kernelVersion(), GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
#endif
#else
return QString("Mozilla/5.0 %1/%2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER).toUtf8();
#endif
} }
// QUrl AppEnv::getCrewFetchingUrl(QString crewID)
// {
// 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));
@ -203,7 +167,7 @@ QUrl AppEnv::getCrewFetchingUrl(QString crewID)
QUrl AppEnv::getPlayerFetchingUrl(QString crewID, QString pageNumber) QUrl AppEnv::getPlayerFetchingUrl(QString crewID, QString pageNumber)
{ {
return QUrl(QString("https://socialclub.rockstargames.com/crewsapi/GetMembersList?crewId=%1&pageNumber=%2&pageSize=5000").arg(crewID, pageNumber)); return QUrl(QString("https://socialclub.rockstargames.com/crewsapi/GetMembersList?crewId=%1&pageNumber=%2").arg(crewID, pageNumber));
} }
QUrl AppEnv::getPlayerFetchingUrl(QString crewID, int pageNumber) QUrl AppEnv::getPlayerFetchingUrl(QString crewID, int pageNumber)
@ -211,234 +175,12 @@ QUrl AppEnv::getPlayerFetchingUrl(QString crewID, int pageNumber)
return getPlayerFetchingUrl(crewID, QString::number(pageNumber)); return getPlayerFetchingUrl(crewID, QString::number(pageNumber));
} }
// Game Stuff
GameVersion AppEnv::getGameVersion()
{
#ifdef Q_OS_WIN
QString argumentValue;
#ifdef _WIN64
argumentValue = "\\WOW6432Node";
#endif
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
QString installFolderSc = registrySettingsSc.value("InstallFolder", "").toString();
QDir installFolderScDir(installFolderSc);
bool scVersionInstalled = false;
if (!installFolderSc.isEmpty() && installFolderScDir.exists()) {
#ifdef GTA5SYNC_DEBUG
qDebug() << "gameVersionFoundSocialClubVersion";
#endif
scVersionInstalled = true;
}
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\GTAV").arg(argumentValue), QSettings::NativeFormat);
QString installFolderSteam = registrySettingsSteam.value("installfoldersteam", "").toString();
if (installFolderSteam.right(5) == "\\GTAV") {
installFolderSteam = installFolderSteam.remove(installFolderSteam.length() - 5, 5);
}
QDir installFolderSteamDir(installFolderSteam);
bool steamVersionInstalled = false;
if (!installFolderSteam.isEmpty() && installFolderSteamDir.exists()) {
#ifdef GTA5SYNC_DEBUG
qDebug() << "gameVersionFoundSteamVersion";
#endif
steamVersionInstalled = true;
}
if (scVersionInstalled && steamVersionInstalled) {
return GameVersion::BothVersions;
}
else if (scVersionInstalled) {
return GameVersion::SocialClubVersion;
}
else if (steamVersionInstalled) {
return GameVersion::SteamVersion;
}
else {
return GameVersion::NoVersion;
}
#else
return GameVersion::NoVersion;
#endif
}
GameLanguage AppEnv::getGameLanguage(GameVersion gameVersion)
{
if (gameVersion == GameVersion::SocialClubVersion) {
#ifdef Q_OS_WIN
QString argumentValue;
#ifdef _WIN64
argumentValue = "\\WOW6432Node";
#endif
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
QString languageSc = registrySettingsSc.value("Language", "").toString();
return gameLanguageFromString(languageSc);
#else
return GameLanguage::Undefined;
#endif
}
else if (gameVersion == GameVersion::SteamVersion) {
#ifdef Q_OS_WIN
QString argumentValue;
#ifdef _WIN64
argumentValue = "\\WOW6432Node";
#endif
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V Steam").arg(argumentValue), QSettings::NativeFormat);
QString languageSteam = registrySettingsSteam.value("Language", "").toString();
return gameLanguageFromString(languageSteam);
#else
return GameLanguage::Undefined;
#endif
}
return GameLanguage::Undefined;
}
GameLanguage AppEnv::gameLanguageFromString(QString gameLanguage)
{
if (gameLanguage == "en-US") {
return GameLanguage::English;
}
else if (gameLanguage == "fr-FR") {
return GameLanguage::French;
}
else if (gameLanguage == "it-IT") {
return GameLanguage::Italian;
}
else if (gameLanguage == "de-DE") {
return GameLanguage::German;
}
else if (gameLanguage == "es-ES") {
return GameLanguage::Spanish;
}
else if (gameLanguage == "es-MX") {
return GameLanguage::Mexican;
}
else if (gameLanguage == "pt-BR") {
return GameLanguage::Brasilian;
}
else if (gameLanguage == "ru-RU") {
return GameLanguage::Russian;
}
else if (gameLanguage == "pl-PL") {
return GameLanguage::Polish;
}
else if (gameLanguage == "ja-JP") {
return GameLanguage::Japanese;
}
else if (gameLanguage == "zh-CHS") {
return GameLanguage::SChinese;
}
else if (gameLanguage == "zh-CHT") {
return GameLanguage::TChinese;
}
else if (gameLanguage == "ko-KR") {
return GameLanguage::Korean;
}
return GameLanguage::Undefined;
}
QString AppEnv::gameLanguageToString(GameLanguage gameLanguage)
{
switch (gameLanguage) {
case GameLanguage::English:
return "en-US";
case GameLanguage::French:
return "fr-FR";
case GameLanguage::Italian:
return "it-IT";
case GameLanguage::German:
return "de-DE";
case GameLanguage::Spanish:
return "es-ES";
case GameLanguage::Mexican:
return "es-MX";
case GameLanguage::Brasilian:
return "pt-BR";
case GameLanguage::Polish:
return "pl-PL";
case GameLanguage::Japanese:
return "ja-JP";
case GameLanguage::SChinese:
return "zh-CHS";
case GameLanguage::TChinese:
return "zh-CHT";
case GameLanguage::Korean:
return "ko-KR";
default:
return "Undefinied";
}
}
bool AppEnv::setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage)
{
bool socialClubVersion = false;
bool steamVersion = false;
if (gameVersion == GameVersion::SocialClubVersion) {
socialClubVersion = true;
}
else if (gameVersion == GameVersion::SteamVersion) {
steamVersion = true;
}
else if (gameVersion == GameVersion::BothVersions) {
socialClubVersion = true;
steamVersion = true;
}
else {
return false;
}
if (socialClubVersion) {
#ifdef Q_OS_WIN
QString argumentValue;
#ifdef _WIN64
argumentValue = "\\WOW6432Node";
#endif
QSettings registrySettingsSc(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V").arg(argumentValue), QSettings::NativeFormat);
if (gameLanguage != GameLanguage::Undefined) {
registrySettingsSc.setValue("Language", gameLanguageToString(gameLanguage));
}
else {
registrySettingsSc.remove("Language");
}
registrySettingsSc.sync();
if (registrySettingsSc.status() != QSettings::NoError) {
return false;
}
#else
Q_UNUSED(gameLanguage)
#endif
}
if (steamVersion) {
#ifdef Q_OS_WIN
QString argumentValue;
#ifdef _WIN64
argumentValue = "\\WOW6432Node";
#endif
QSettings registrySettingsSteam(QString("HKEY_LOCAL_MACHINE\\SOFTWARE%1\\Rockstar Games\\Grand Theft Auto V Steam").arg(argumentValue), QSettings::NativeFormat);
if (gameLanguage != GameLanguage::Undefined) {
registrySettingsSteam.setValue("Language", gameLanguageToString(gameLanguage));
}
else {
registrySettingsSteam.remove("Language");
}
registrySettingsSteam.sync();
if (registrySettingsSteam.status() != QSettings::NoError) {
return false;
}
#else
Q_UNUSED(gameLanguage)
#endif
}
return true;
}
// Screen Stuff
qreal AppEnv::screenRatio() qreal AppEnv::screenRatio()
{ {
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
qreal dpi = QApplication::primaryScreen()->logicalDotsPerInch(); qreal dpi = QGuiApplication::primaryScreen()->logicalDotsPerInch();
#else #else
qreal dpi = QApplication::desktop()->logicalDpiX(); qreal dpi = qApp->desktop()->logicalDpiX();
#endif #endif
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
return (dpi / 72); return (dpi / 72);
@ -446,12 +188,3 @@ qreal AppEnv::screenRatio()
return (dpi / 96); return (dpi / 96);
#endif #endif
} }
qreal AppEnv::screenRatioPR()
{
#if QT_VERSION >= 0x050600
return QApplication::primaryScreen()->devicePixelRatio();
#else
return 1;
#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-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
@ -22,9 +22,6 @@
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
enum class GameVersion : int { NoVersion = 0, SocialClubVersion = 1, SteamVersion = 2, BothVersions = 3 };
enum class GameLanguage : int { Undefined = 0, English = 1, French = 2, Italian = 3, German = 4, Spanish = 5, Mexican = 6, Brasilian = 7, Russian = 8, Polish = 9, Japanese = 10, SChinese = 11, TChinese = 12, Korean = 13 };
class AppEnv class AppEnv
{ {
public: public:
@ -39,9 +36,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();
@ -49,16 +44,8 @@ public:
static QUrl getPlayerFetchingUrl(QString crewID, QString pageNumber); static QUrl getPlayerFetchingUrl(QString crewID, QString pageNumber);
static QUrl getPlayerFetchingUrl(QString crewID, int pageNumber); static QUrl getPlayerFetchingUrl(QString crewID, int pageNumber);
// Game Stuff
static GameVersion getGameVersion();
static GameLanguage getGameLanguage(GameVersion gameVersion);
static GameLanguage gameLanguageFromString(QString gameLanguage);
static QString gameLanguageToString(GameLanguage gameLanguage);
static bool setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage);
// Screen Stuff // Screen Stuff
static qreal screenRatio(); static qreal screenRatio();
static qreal screenRatioPR();
}; };
#endif // APPENV_H #endif // APPENV_H

View File

@ -1,382 +0,0 @@
cmake_minimum_required(VERSION 3.7)
project(gta5view LANGUAGES C CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(FORCE_QT_VERSION "" CACHE STRING "Force Qt Version")
if(FORCE_QT_VERSION)
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)
list(APPEND GTA5VIEW_LIBS
dwmapi
)
list(APPEND GTA5VIEW_DEFINES
-DUNICODE
-D_UNICODE
-DWIN32
)
list(APPEND GTA5VIEW_RESOURCES
res/app.rc
)
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
-DGTA5SYNC_CMAKE
-DGTA5SYNC_PROJECT
)
set(GTA5VIEW_SOURCES
main.cpp
AboutDialog.cpp
AppEnv.cpp
CrewDatabase.cpp
DatabaseThread.cpp
ExportDialog.cpp
ExportThread.cpp
GlobalString.cpp
IconLoader.cpp
ImportDialog.cpp
JsonEditorDialog.cpp
MapLocationDialog.cpp
OptionsDialog.cpp
PictureDialog.cpp
PictureExport.cpp
PictureWidget.cpp
PlayerListDialog.cpp
ProfileDatabase.cpp
ProfileInterface.cpp
ProfileLoader.cpp
ProfileWidget.cpp
RagePhoto.cpp
SavegameCopy.cpp
SavegameData.cpp
SavegameDialog.cpp
SavegameWidget.cpp
SidebarGenerator.cpp
SnapmaticEditor.cpp
SnapmaticPicture.cpp
SnapmaticWidget.cpp
StandardPaths.cpp
StringParser.cpp
TranslationClass.cpp
UserInterface.cpp
anpro/imagecropper.cpp
pcg/pcg_basic.c
uimod/JSHighlighter.cpp
uimod/UiModLabel.cpp
uimod/UiModWidget.cpp
)
set(GTA5VIEW_HEADERS
config.h
wrapper.h
AboutDialog.h
AppEnv.h
CrewDatabase.h
DatabaseThread.h
ExportDialog.h
ExportThread.h
GlobalString.h
IconLoader.h
ImportDialog.h
JsonEditorDialog.h
MapLocationDialog.h
OptionsDialog.h
PictureDialog.h
PictureExport.h
PictureWidget.h
PlayerListDialog.h
ProfileDatabase.h
ProfileInterface.h
ProfileLoader.h
ProfileWidget.h
RagePhoto.h
SavegameCopy.h
SavegameData.h
SavegameDialog.h
SavegameWidget.h
SidebarGenerator.h
SnapmaticEditor.h
SnapmaticPicture.h
SnapmaticWidget.h
StandardPaths.h
StringParser.h
TranslationClass.h
UserInterface.h
anpro/imagecropper.h
pcg/pcg_basic.h
uimod/JSHighlighter.h
uimod/UiModLabel.h
uimod/UiModWidget.h
)
set(GTA5VIEW_INCLUDEDIR
anpro
pcg
uimod
)
set(GTA5VIEW_FORMS
AboutDialog.ui
ExportDialog.ui
ImportDialog.ui
JsonEditorDialog.ui
MapLocationDialog.ui
OptionsDialog.ui
PictureDialog.ui
PlayerListDialog.ui
ProfileInterface.ui
SavegameDialog.ui
SavegameWidget.ui
SnapmaticEditor.ui
SnapmaticWidget.ui
UserInterface.ui
)
set(GTA5VIEW_TRANSLATIONS
res/gta5sync_de.ts
res/gta5sync_en_US.ts
res/gta5sync_fr.ts
res/gta5sync_ko.ts
res/gta5sync_ru.ts
res/gta5sync_uk.ts
res/gta5sync_zh_TW.ts
)
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()
set(GTA5VIEW_QMFILES
res/gta5sync_de.qm
res/gta5sync_en_US.qm
res/gta5sync_fr.qm
res/gta5sync_ko.qm
res/gta5sync_ru.qm
res/gta5sync_uk.qm
res/gta5sync_zh_TW.qm
res/qt${QT_VERSION_MAJOR}/qtbase_en_GB.qm
)
endif()
option(QCONF_BUILD "System installation intended Qconf build" OFF)
if(QCONF_BUILD)
list(APPEND GTA5VIEW_DEFINES
-DGTA5SYNC_QCONF
)
else()
list(APPEND GTA5VIEW_RESOURCES
res/img.qrc
res/tr_g5p.qrc
res/qt${QT_VERSION_MAJOR}/tr_qt.qrc
)
endif()
option(FLATPAK_BUILD "Flatpak modifications and optimisations" OFF)
if(FLATPAK_BUILD)
list(APPEND GTA5VIEW_DEFINES
-DGTA5SYNC_FLATPAK
)
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)
if(WITH_MOTD)
set(MOTD_WEBURL "" CACHE STRING "Messages WebURL")
list(APPEND GTA5VIEW_HEADERS
MessageThread.h
)
list(APPEND GTA5VIEW_SOURCES
MessageThread.cpp
)
list(APPEND GTA5VIEW_DEFINES
-DGTA5SYNC_MOTD
)
if(MOTD_WEBURL)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_MOTD_WEBURL=\"${MOTD_WEBURL}\""
)
endif()
endif()
option(WITH_TELEMETRY "Hardware survey and basic telemetry system" OFF)
if(WITH_TELEMETRY)
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
TelemetryClass.h
tmext/TelemetryClassAuthenticator.h
)
list(APPEND GTA5VIEW_SOURCES
TelemetryClass.cpp
tmext/TelemetryClassAuthenticator.cpp
)
list(APPEND GTA5VIEW_INCLUDEDIR
tmext
)
list(APPEND GTA5VIEW_DEFINES
-DGTA5SYNC_TELEMETRY
)
if(TELEMETRY_AUTHID AND TELEMETRY_AUTHPW AND TELEMETRY_PUSHURL AND TELEMETRY_REGURL)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_TELEMETRY_AUTHID=\"${TELEMETRY_AUTHID}\""
"-DGTA5SYNC_TELEMETRY_AUTHPW=\"${TELEMETRY_AUTHPW}\""
"-DGTA5SYNC_TELEMETRY_PUSHURL=\"${TELEMETRY_PUSHURL}\""
"-DGTA5SYNC_TELEMETRY_REGURL=\"${TELEMETRY_REGURL}\""
)
endif()
if(TELEMETRY_WEBURL)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_TELEMETRY_WEBURL=\"${TELEMETRY_WEBURL}\""
)
endif()
if(WIN32)
list(APPEND GTA5VIEW_LIBS
d3d9
)
endif()
endif()
if(GTA5VIEW_APPVER)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_APPVER=\"${GTA5VIEW_APPVER}\""
)
endif()
if(GTA5VIEW_BUILDCODE)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_BUILDCODE=\"${GTA5VIEW_BUILDCODE}\""
)
endif()
if(GTA5VIEW_BUILDTYPE)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_BUILDTYPE=\"${GTA5VIEW_BUILDTYPE}\""
)
endif()
if(GTA5VIEW_COMMIT)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_COMMIT=\"${GTA5VIEW_COMMIT}\""
)
endif()
if(GTA5VIEW_INLANG)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_INLANG=\"${GTA5VIEW_INLANG}\""
)
endif()
if(GTA5VIEW_LANG)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_LANG=\"${GTA5VIEW_LANG}\""
)
endif()
if(GTA5VIEW_PLUG)
list(APPEND GTA5VIEW_DEFINES
"-DGTA5SYNC_PLUG=\"${GTA5VIEW_PLUG}\""
)
endif()
add_executable(gta5view
WIN32 MACOSX_BUNDLE
${GTA5VIEW_HEADERS}
${GTA5VIEW_SOURCES}
${GTA5VIEW_FORMS}
${GTA5VIEW_RESOURCES}
)
if(LINGUIST_FOUND AND QCONF_BUILD)
add_custom_target(translations DEPENDS ${GTA5VIEW_QMFILES})
add_dependencies(gta5view translations)
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16.0")
target_precompile_headers(gta5view PRIVATE config.h)
endif()
if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.14.0")
qt5_import_plugins(gta5view INCLUDE Qt5::QSvgPlugin)
endif()
target_compile_definitions(gta5view PRIVATE ${GTA5VIEW_DEFINES})
target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR})
target_link_libraries(gta5view PRIVATE Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Widgets ${GTA5VIEW_LIBS})
install(TARGETS gta5view DESTINATION bin)
install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications)
install(FILES res/de.syping.gta5view.metainfo.xml DESTINATION share/metainfo)
install(FILES res/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-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-32.png DESTINATION share/icons/hicolor/32x32/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-48.png DESTINATION share/icons/hicolor/48x48/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-64.png DESTINATION share/icons/hicolor/64x64/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-96.png DESTINATION share/icons/hicolor/96x96/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-128.png DESTINATION share/icons/hicolor/128x128/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-256.png DESTINATION share/icons/hicolor/256x256/apps RENAME de.syping.gta5view.png)
install(FILES res/gta5view-512.png DESTINATION share/icons/hicolor/512x512/apps RENAME de.syping.gta5view.png)
if(QCONF_BUILD)
include(res/img.cmake)
install(FILES ${GTA5VIEW_IMGFILES} DESTINATION share/gta5view/resources)
install(FILES ${GTA5VIEW_QMFILES} DESTINATION share/gta5view/translations)
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
@ -44,65 +44,137 @@ void DatabaseThread::run()
{ {
QEventLoop threadLoop; QEventLoop threadLoop;
QStringList crewList;
QStringList crewListR;
// Register thread loop end signal
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit())); QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
while (threadRunning) { // Setup crewList for Quick time scan
QTimer::singleShot(300000, &threadLoop, SLOT(quit())); crewList = crewDB->getCrews();
threadLoop.exec(); if (!crewList.isEmpty())
{
crewListR = deleteCompatibleCrews(crewList);
}
else
{
while (crewList.isEmpty() && threadRunning)
{
QTimer::singleShot(1000, &threadLoop, SLOT(quit()));
threadLoop.exec();
if (!crewDB->isAddingCrews())
{
crewList = crewDB->getCrews();
}
}
if (threadRunning)
{
crewListR = deleteCompatibleCrews(crewList);
}
}
// Only do QTS when Thread should be run
if (threadRunning)
{
// Quick time scan
#ifdef GTA5SYNC_DEBUG
qDebug() << "Start QTS";
#endif
if (crewListR.length() <= 5)
{
scanCrewReference(crewListR, 2500);
emit crewNameUpdated();
}
if (crewList.length() <= 3)
{
scanCrewMembersList(crewList, 3, 2500);
emit playerNameUpdated();
}
else if (crewList.length() <= 5)
{
scanCrewMembersList(crewList, 2, 2500);
emit playerNameUpdated();
}
if (threadRunning)
{
QTimer::singleShot(10000, &threadLoop, SLOT(quit()));
threadLoop.exec();
}
}
while (threadRunning)
{
crewList = crewDB->getCrews();
crewListR = deleteCompatibleCrews(crewList);
// Long time scan
#ifdef GTA5SYNC_DEBUG
qDebug() << "Start LTS";
#endif
scanCrewReference(crewListR, 10000);
emit crewNameUpdated();
scanCrewMembersList(crewList, crewMaxPages, 10000);
emit playerNameUpdated();
if (threadRunning)
{
QTimer::singleShot(300000, &threadLoop, SLOT(quit()));
threadLoop.exec();
}
} }
} }
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
#if QT_VERSION < 0x060000
netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
#endif
#endif #endif
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent()); netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
netRequest.setRawHeader("Accept", "text/html"); netRequest.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
netRequest.setRawHeader("Accept-Charset", "utf-8"); netRequest.setRawHeader("Accept-Language", "en-US;q=0.5,en;q=0.3");
netRequest.setRawHeader("Accept-Language", "en-US,en;q=0.9");
netRequest.setRawHeader("Connection", "keep-alive"); netRequest.setRawHeader("Connection", "keep-alive");
QNetworkReply *netReply = netManager->get(netRequest); QNetworkReply *netReply = netManager->get(netRequest);
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 {
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,39 +188,39 @@ 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
#if QT_VERSION < 0x060000
netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); netRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
#endif
#endif #endif
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent()); netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
netRequest.setRawHeader("Accept", "application/json"); netRequest.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
netRequest.setRawHeader("Accept-Charset", "utf-8"); netRequest.setRawHeader("Accept-Language", "en-US;q=0.5,en;q=0.3");
netRequest.setRawHeader("Accept-Language", "en-US,en;q=0.9");
netRequest.setRawHeader("Connection", "keep-alive"); netRequest.setRawHeader("Connection", "keep-alive");
QNetworkReply *netReply = netManager->get(netRequest); QNetworkReply *netReply = netManager->get(netRequest);
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 +228,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 +262,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 +278,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 +290,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

@ -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
@ -22,19 +22,14 @@
#include "ProfileWidget.h" #include "ProfileWidget.h"
#include "ExportThread.h" #include "ExportThread.h"
#include "SavegameData.h" #include "SavegameData.h"
#include "AppEnv.h"
#include "config.h" #include "config.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QDesktopWidget>
#include <QApplication> #include <QApplication>
#include <QFileInfo> #include <QFileInfo>
#include <QDebug>
#include <QFile> #include <QFile>
#if QT_VERSION >= 0x050000
#include <QScreen>
#else
#include <QDesktopWidget>
#endif
ExportThread::ExportThread(QMap<ProfileWidget*,QString> profileMap, QString exportDirectory, bool pictureCopyEnabled, bool pictureExportEnabled, int exportCount, QObject *parent) : QThread(parent), ExportThread::ExportThread(QMap<ProfileWidget*,QString> profileMap, QString exportDirectory, bool pictureCopyEnabled, bool pictureExportEnabled, int exportCount, QObject *parent) : QThread(parent),
profileMap(profileMap), exportDirectory(exportDirectory), pictureCopyEnabled(pictureCopyEnabled), pictureExportEnabled(pictureExportEnabled), exportCount(exportCount) profileMap(profileMap), exportDirectory(exportDirectory), pictureCopyEnabled(pictureCopyEnabled), pictureExportEnabled(pictureExportEnabled), exportCount(exportCount)
{ {
@ -49,7 +44,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)
{ {
@ -106,17 +101,8 @@ void ExportThread::run()
QImage exportPicture = picture->getImage(); QImage exportPicture = picture->getImage();
if (sizeMode == "Desktop") if (sizeMode == "Desktop")
{ {
#if QT_VERSION >= 0x050000 QRect desktopResolution = qApp->desktop()->screenGeometry();
qreal screenRatioPR = AppEnv::screenRatioPR(); exportPicture = exportPicture.scaled(desktopResolution.width(), desktopResolution.height(), aspectRatio, Qt::SmoothTransformation);
QRect desktopResolution = QApplication::primaryScreen()->geometry();
int desktopSizeWidth = qRound((double)desktopResolution.width() * screenRatioPR);
int desktopSizeHeight = qRound((double)desktopResolution.height() * screenRatioPR);
#else
QRect desktopResolution = QApplication::desktop()->screenGeometry();
int desktopSizeWidth = desktopResolution.width();
int desktopSizeHeight = desktopResolution.height();
#endif
exportPicture = exportPicture.scaled(desktopSizeWidth, desktopSizeHeight, aspectRatio, Qt::SmoothTransformation);
} }
else if (sizeMode == "Custom") else if (sizeMode == "Custom")
{ {

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
@ -28,17 +28,17 @@
GlobalString::GlobalString() GlobalString::GlobalString()
{ {
} }
QMap<QString, QString> GlobalString::getGlobalMap() QMap<QString, QString> GlobalString::getGlobalMap()
{ {
QMap<QString, QString> globalMap; QMap<QString, QString> globalMap;
QSettings globalFile(getLanguageFile(), QSettings::IniFormat); QSettings globalFile(getLanguageFile(), QSettings::IniFormat);
#if QT_VERSION < 0x060000
globalFile.setIniCodec("UTF-8"); globalFile.setIniCodec("UTF-8");
#endif
globalFile.beginGroup("Global"); globalFile.beginGroup("Global");
for (const QString &globalStr : globalFile.childKeys()) { for (QString globalStr : globalFile.childKeys())
{
globalMap[globalStr] = globalFile.value(globalStr, globalStr).toString(); globalMap[globalStr] = globalFile.value(globalStr, globalStr).toString();
} }
globalFile.endGroup(); globalFile.endGroup();
@ -49,14 +49,12 @@ QString GlobalString::getString(QString valueStr, bool *ok)
{ {
QString globalString = valueStr; QString globalString = valueStr;
QSettings globalFile(getLanguageFile(), QSettings::IniFormat); QSettings globalFile(getLanguageFile(), QSettings::IniFormat);
#if QT_VERSION < 0x060000
globalFile.setIniCodec("UTF-8"); globalFile.setIniCodec("UTF-8");
#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 +65,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/5sync-16.png", QSize(16, 16));
#ifdef Q_OS_WIN appIcon.addFile(":/img/5sync-24.png", QSize(24, 24));
const QString pattern = AppEnv::getImagesFolder() % QLatin1String("/gta5view-%1.png"); appIcon.addFile(":/img/5sync-32.png", QSize(32, 32));
#else appIcon.addFile(":/img/5sync-40.png", QSize(40, 40));
const QString pattern = AppEnv::getShareFolder() % QLatin1String("/icons/hicolor/%1x%1/apps/de.syping.gta5view.png"); appIcon.addFile(":/img/5sync-48.png", QSize(48, 48));
#endif appIcon.addFile(":/img/5sync-64.png", QSize(64, 64));
#else appIcon.addFile(":/img/5sync-96.png", QSize(96, 96));
const QString pattern = AppEnv::getImagesFolder() % QLatin1String("/gta5view-%1.png"); appIcon.addFile(":/img/5sync-128.png", QSize(128, 128));
#endif appIcon.addFile(":/img/5sync-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;
} }

211
ImageEditorDialog.cpp Normal file
View File

@ -0,0 +1,211 @@
/*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2018 Syping
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "ImageEditorDialog.h"
#include "ui_ImageEditorDialog.h"
#include "ProfileInterface.h"
#include "SidebarGenerator.h"
#include "StandardPaths.h"
#include "ImportDialog.h"
#include "AppEnv.h"
#include "config.h"
#include <QStringBuilder>
#include <QImageReader>
#include <QFileDialog>
#include <QMessageBox>
ImageEditorDialog::ImageEditorDialog(SnapmaticPicture *picture, QString profileName, QWidget *parent) :
QDialog(parent), smpic(picture), profileName(profileName),
ui(new Ui::ImageEditorDialog)
{
// Set Window Flags
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
ui->setupUi(this);
ui->cmdClose->setFocus();
// Set Icon for Close Button
if (QIcon::hasThemeIcon("dialog-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
}
else if (QIcon::hasThemeIcon("gtk-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("gtk-close"));
}
// Set Icon for Import Button
if (QIcon::hasThemeIcon("document-import"))
{
ui->cmdReplace->setIcon(QIcon::fromTheme("document-import"));
}
// Set Icon for Overwrite Button
if (QIcon::hasThemeIcon("document-save"))
{
ui->cmdSave->setIcon(QIcon::fromTheme("document-save"));
}
else if (QIcon::hasThemeIcon("gtk-save"))
{
ui->cmdSave->setIcon(QIcon::fromTheme("gtk-save"));
}
// DPI calculation
qreal screenRatio = AppEnv::screenRatio();
snapmaticResolutionLW = 516 * screenRatio; // 430
snapmaticResolutionLH = 288 * screenRatio; // 240
ui->labPicture->setMinimumSize(snapmaticResolutionLW, snapmaticResolutionLH);
ui->labCapacity->setText(tr("Capacity: %1").arg(QString::number(qRound((double)picture->getContentMaxLength() / 1024)) % " KB"));
imageIsChanged = false;
pictureCache = picture->getImage();
ui->labPicture->setPixmap(QPixmap::fromImage(pictureCache).scaled(snapmaticResolutionLW, snapmaticResolutionLH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
setMaximumSize(sizeHint());
setMinimumSize(sizeHint());
setFixedSize(sizeHint());
}
ImageEditorDialog::~ImageEditorDialog()
{
delete ui;
}
void ImageEditorDialog::on_cmdClose_clicked()
{
close();
}
void ImageEditorDialog::on_cmdReplace_clicked()
{
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("FileDialogs");
bool dontUseNativeDialog = settings.value("DontUseNativeDialog", false).toBool();
settings.beginGroup("ImportReplace");
fileDialogPreOpen: //Work?
QFileDialog fileDialog(this);
fileDialog.setFileMode(QFileDialog::ExistingFile);
fileDialog.setViewMode(QFileDialog::Detail);
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
fileDialog.setWindowTitle(ProfileInterface::tr("Import..."));
fileDialog.setLabelText(QFileDialog::Accept, ProfileInterface::tr("Import"));
// Getting readable Image formats
QString imageFormatsStr = " ";
for (QByteArray imageFormat : QImageReader::supportedImageFormats())
{
imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
}
QStringList filters;
filters << ProfileInterface::tr("All image files (%1)").arg(imageFormatsStr.trimmed());
filters << ProfileInterface::tr("All files (**)");
fileDialog.setNameFilters(filters);
QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
fileDialog.setSidebarUrls(sidebarUrls);
fileDialog.setDirectory(settings.value(profileName % "+Directory", StandardPaths::documentsLocation()).toString());
fileDialog.restoreGeometry(settings.value(profileName % "+Geometry", "").toByteArray());
if (fileDialog.exec())
{
QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1)
{
QString selectedFile = selectedFiles.at(0);
QString selectedFileName = QFileInfo(selectedFile).fileName();
QFile snapmaticFile(selectedFile);
if (!snapmaticFile.open(QFile::ReadOnly))
{
QMessageBox::warning(this, ProfileInterface::tr("Import"), ProfileInterface::tr("Can't import %1 because file can't be open").arg("\""+selectedFileName+"\""));
goto fileDialogPreOpen;
}
QImage *importImage = new QImage();
QImageReader snapmaticImageReader;
snapmaticImageReader.setDecideFormatFromContent(true);
snapmaticImageReader.setDevice(&snapmaticFile);
if (!snapmaticImageReader.read(importImage))
{
QMessageBox::warning(this, ProfileInterface::tr("Import"), ProfileInterface::tr("Can't import %1 because file can't be parsed properly").arg("\""+selectedFileName+"\""));
delete importImage;
goto fileDialogPreOpen;
}
ImportDialog *importDialog = new ImportDialog(this);
importDialog->setImage(importImage);
importDialog->setModal(true);
importDialog->show();
importDialog->exec();
if (importDialog->isImportAgreed())
{
pictureCache = importDialog->image();
ui->labPicture->setPixmap(QPixmap::fromImage(pictureCache).scaled(snapmaticResolutionLW, snapmaticResolutionLH, Qt::KeepAspectRatio, Qt::SmoothTransformation));
imageIsChanged = true;
}
delete importDialog;
}
}
settings.setValue(profileName % "+Geometry", fileDialog.saveGeometry());
settings.setValue(profileName % "+Directory", fileDialog.directory().absolutePath());
settings.endGroup();
settings.endGroup();
}
void ImageEditorDialog::on_cmdSave_clicked()
{
if (imageIsChanged)
{
const QByteArray previousPicture = smpic->getPictureStream();
bool success = smpic->setImage(pictureCache);
if (success)
{
QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName);
}
if (!smpic->exportPicture(currentFilePath))
{
smpic->setPictureStream(previousPicture);
QMessageBox::warning(this, tr("Snapmatic Image Editor"), tr("Patching of Snapmatic Image failed because of I/O Error"));
return;
}
smpic->emitCustomSignal("PictureUpdated");
}
else
{
QMessageBox::warning(this, tr("Snapmatic Image Editor"), tr("Patching of Snapmatic Image failed because of Image Error"));
return;
}
}
close();
}
void ImageEditorDialog::on_cmdQuestion_clicked()
{
QMessageBox::information(this, tr("Snapmatic Image Editor"), tr("Every taken Snapmatic have a different Capacity, a Snapmatic with higher Capacity can store a picture with better quality."));
}

View File

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 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
@ -16,33 +16,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/ *****************************************************************************/
#ifndef MESSAGETHREAD_H #ifndef IMAGEEDITORDIALOG_H
#define MESSAGETHREAD_H #define IMAGEEDITORDIALOG_H
#include <QJsonObject> #include "SnapmaticPicture.h"
#include <QObject> #include <QDialog>
#include <QThread>
class MessageThread : public QThread namespace Ui {
class ImageEditorDialog;
}
class ImageEditorDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public:
explicit MessageThread(uint cacheId, QObject *parent = 0);
public slots: public:
void terminateThread(); explicit ImageEditorDialog(SnapmaticPicture *picture, QString profileName, QWidget *parent = 0);
~ImageEditorDialog();
private slots:
void on_cmdClose_clicked();
void on_cmdReplace_clicked();
void on_cmdSave_clicked();
void on_cmdQuestion_clicked();
private: private:
bool threadRunning; SnapmaticPicture *smpic;
uint cacheId; QString profileName;
Ui::ImageEditorDialog *ui;
protected: int snapmaticResolutionLW;
void run(); int snapmaticResolutionLH;
bool imageIsChanged;
signals: QImage pictureCache;
void messagesArrived(const QJsonObject &messageObject);
void updateCacheId(uint cacheId);
void threadTerminated();
}; };
#endif // MESSAGETHREAD_H #endif // IMAGEEDITORDIALOG_H

130
ImageEditorDialog.ui Normal file
View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImageEditorDialog</class>
<widget class="QDialog" name="ImageEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>516</width>
<height>335</height>
</rect>
</property>
<property name="windowTitle">
<string>Overwrite Image...</string>
</property>
<layout class="QVBoxLayout" name="vlInterface">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labPicture">
<property name="minimumSize">
<size>
<width>516</width>
<height>288</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="buttomFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="vlButtons">
<item>
<layout class="QHBoxLayout" name="hlCapacity">
<item>
<widget class="QLabel" name="labCapacity">
<property name="text">
<string>Capacity: %1</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="cmdQuestion">
<property name="text">
<string>?</string>
</property>
</widget>
</item>
<item>
<spacer name="hsCapacity">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="hlButtons">
<item>
<widget class="QPushButton" name="cmdReplace">
<property name="text">
<string>&amp;Import...</string>
</property>
</widget>
</item>
<item>
<spacer name="hsButtons">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cmdSave">
<property name="text">
<string>&amp;Overwrite</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cmdClose">
<property name="text">
<string>&amp;Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

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-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
@ -16,16 +16,13 @@
* 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 "AppEnv.h" #include "AppEnv.h"
#include "config.h" #include "config.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QInputDialog>
#include <QImageReader> #include <QImageReader>
#include <QColorDialog> #include <QColorDialog>
#include <QFileDialog> #include <QFileDialog>
@ -40,45 +37,42 @@
#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
ImportDialog::ImportDialog(QString profileName, QWidget *parent) : ImportDialog::ImportDialog(QWidget *parent) :
QDialog(parent), profileName(profileName), QDialog(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->setFocus();
importAgreed = false; importAgreed = false;
settingsLocked = false;
watermarkAvatar = true;
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,21 +81,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
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Import");
QString currentProfile = settings.value("Profile", "Default").toString();
settings.endGroup();
processSettings(currentProfile);
// DPI calculation // DPI calculation
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
snapmaticResolutionLW = 516 * screenRatio; // 430 snapmaticResolutionLW = 516 * screenRatio; // 430
@ -112,29 +91,19 @@ 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 setMaximumSize(sizeHint());
optionsMenu.addAction(tr("&Import new Picture..."), this, SLOT(importNewPicture())); setMinimumSize(sizeHint());
optionsMenu.addAction(tr("&Crop Picture..."), this, SLOT(cropPicture())); setFixedSize(sizeHint());
optionsMenu.addSeparator();
optionsMenu.addAction(tr("&Load Settings..."), this, SLOT(loadImportSettings()));
optionsMenu.addAction(tr("&Save Settings..."), this, SLOT(saveImportSettings()));
ui->cmdOptions->setMenu(&optionsMenu);
const QSize windowSize = sizeHint();
setMinimumSize(windowSize);
setMaximumSize(windowSize);
} }
ImportDialog::~ImportDialog() ImportDialog::~ImportDialog()
@ -144,591 +113,134 @@ ImportDialog::~ImportDialog()
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(); 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())
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())
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();
newImage = snapmaticPixmap.toImage(); newImage = snapmaticPixmap.toImage();
#if QT_VERSION >= 0x050600 ui->labPicture->setPixmap(snapmaticPixmap.scaled(snapmaticResolutionLW, snapmaticResolutionLH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
snapmaticPixmap.setDevicePixelRatio(screenRatioPR);
#endif
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)
{
bool blackWatermark = false;
bool redWatermark = false;
if (selectedColour.red() > 127) {
if (selectedColour.green() > 127 || selectedColour.blue() > 127) {
redWatermark = true;
}
}
else {
redWatermark = true;
}
if (selectedColour.lightness() > 127) {
blackWatermark = true;
}
// draw watermark
if (redWatermark) {
const QImage viewWatermark = QImage(AppEnv::getImagesFolder() % "/watermark_2r.png");
snapmaticPainter->drawImage(snapmaticResolution.width() - viewWatermark.width(), 0, viewWatermark);
}
else
{
QImage viewWatermark = QImage(AppEnv::getImagesFolder() % "/watermark_2b.png");
if (!blackWatermark) {
viewWatermark.invertPixels(QImage::InvertRgb);
}
snapmaticPainter->drawImage(snapmaticResolution.width() - viewWatermark.width(), 0, viewWatermark);
}
QImage textWatermark = QImage(AppEnv::getImagesFolder() % "/watermark_1b.png");
if (!blackWatermark) {
textWatermark.invertPixels(QImage::InvertRgb);
}
snapmaticPainter->drawImage(snapmaticResolution.width() - textWatermark.width(), 0, textWatermark);
}
void ImportDialog::processSettings(QString settingsProfile, bool setDefault)
{
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Import");
if (setDefault) {
settings.setValue("Profile", settingsProfile);
}
if (settingsProfile == "Default") {
watermarkAvatar = true;
watermarkPicture = false;
selectedColour = QColor::fromRgb(0, 0, 0, 255);
backImage = QImage();
ui->cbBorderless->setChecked(false);
ui->cbStretch->setChecked(false);
ui->cbForceAvatarColour->setChecked(false);
ui->cbUnlimited->setChecked(false);
ui->cbImportAsIs->setChecked(false);
ui->cbResolution->setCurrentIndex(0);
}
else {
settings.beginGroup(settingsProfile);
watermarkAvatar = settings.value("WatermarkAvatar", true).toBool();
watermarkPicture = settings.value("WatermarkPicture", false).toBool();
backImage = qvariant_cast<QImage>(settings.value("BackgroundImage", QImage()));
selectedColour = qvariant_cast<QColor>(settings.value("SelectedColour", QColor::fromRgb(0, 0, 0, 255)));
ui->cbBorderless->setChecked(settings.value("BorderlessImage", false).toBool());
ui->cbStretch->setChecked(settings.value("BackgroundStretch", 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();
}
if (!workImage.isNull()) {
if (ui->cbAvatar->isChecked()) {
ui->cbWatermark->setChecked(watermarkAvatar);
}
else {
ui->cbWatermark->setChecked(watermarkPicture);
}
}
ui->labColour->setText(tr("Background Colour: <span style=\"color: %1\">%1</span>").arg(selectedColour.name()));
if (!backImage.isNull()) {
ui->labBackgroundImage->setText(tr("Background Image: %1").arg(tr("Storage", "Background Image: Storage")));
ui->cmdBackgroundWipe->setVisible(true);
}
else {
ui->labBackgroundImage->setText(tr("Background Image:"));
ui->cmdBackgroundWipe->setVisible(false);
}
settings.endGroup();
}
void ImportDialog::saveSettings(QString settingsProfile)
{
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Import");
settings.beginGroup(settingsProfile);
settings.setValue("WatermarkAvatar", watermarkAvatar);
settings.setValue("WatermarkPicture", watermarkPicture);
settings.setValue("BackgroundImage", backImage);
settings.setValue("SelectedColour", selectedColour);
settings.setValue("BorderlessImage", ui->cbBorderless->isChecked());
settings.setValue("BackgroundStretch", ui->cbStretch->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.setValue("Profile", settingsProfile);
settings.endGroup();
}
void ImportDialog::cropPicture()
{
qreal screenRatio = AppEnv::screenRatio();
QDialog cropDialog(this);
#if QT_VERSION >= 0x050000
cropDialog.setObjectName(QStringLiteral("CropDialog"));
#else
cropDialog.setObjectName(QString::fromUtf8("CropDialog"));
#endif
cropDialog.setWindowTitle(tr("Crop Picture..."));
cropDialog.setWindowFlags(cropDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
cropDialog.setModal(true);
QVBoxLayout cropLayout;
#if QT_VERSION >= 0x050000
cropLayout.setObjectName(QStringLiteral("CropLayout"));
#else
cropLayout.setObjectName(QString::fromUtf8("CropLayout"));
#endif
cropLayout.setContentsMargins(0, 0, 0, 0);
cropLayout.setSpacing(0);
cropDialog.setLayout(&cropLayout);
ImageCropper imageCropper(&cropDialog);
#if QT_VERSION >= 0x050000
imageCropper.setObjectName(QStringLiteral("ImageCropper"));
#else
imageCropper.setObjectName(QString::fromUtf8("ImageCropper"));
#endif
imageCropper.setBackgroundColor(Qt::black);
imageCropper.setCroppingRectBorderColor(QColor(255, 255, 255, 127));
imageCropper.setImage(QPixmap::fromImage(origImage, Qt::AutoColor));
imageCropper.setProportion(QSize(1, 1));
imageCropper.setFixedSize(workImage.size());
cropLayout.addWidget(&imageCropper);
QHBoxLayout buttonLayout;
#if QT_VERSION >= 0x050000
cropLayout.setObjectName(QStringLiteral("ButtonLayout"));
#else
cropLayout.setObjectName(QString::fromUtf8("ButtonLayout"));
#endif
cropLayout.addLayout(&buttonLayout);
QPushButton cropButton(&cropDialog);
#if QT_VERSION >= 0x050000
cropButton.setObjectName(QStringLiteral("CropButton"));
#else
cropButton.setObjectName(QString::fromUtf8("CropButton"));
#endif
cropButton.setMinimumSize(0, 40 * screenRatio);
cropButton.setText(tr("&Crop"));
cropButton.setToolTip(tr("Crop Picture"));
QObject::connect(&cropButton, SIGNAL(clicked(bool)), &cropDialog, SLOT(accept()));
buttonLayout.addWidget(&cropButton);
cropDialog.show();
cropDialog.setFixedSize(cropDialog.sizeHint());
if (cropDialog.exec() == QDialog::Accepted) {
QImage *croppedImage = new QImage(imageCropper.cropImage().toImage());
setImage(croppedImage);
}
}
void ImportDialog::importNewPicture()
{
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("FileDialogs");
bool dontUseNativeDialog = settings.value("DontUseNativeDialog", false).toBool();
settings.beginGroup("ImportCopy");
fileDialogPreOpen: //Work?
QFileDialog fileDialog(this);
fileDialog.setFileMode(QFileDialog::ExistingFile);
fileDialog.setViewMode(QFileDialog::Detail);
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
fileDialog.setWindowTitle(QApplication::translate("ProfileInterface", "Import..."));
fileDialog.setLabelText(QFileDialog::Accept, QApplication::translate("ProfileInterface", "Import"));
// Getting readable Image formats
QString imageFormatsStr = " ";
for (const QByteArray &imageFormat : QImageReader::supportedImageFormats()) {
imageFormatsStr += QString("*.") % QString::fromUtf8(imageFormat).toLower() % " ";
}
QStringList filters;
filters << QApplication::translate("ProfileInterface", "All image files (%1)").arg(imageFormatsStr.trimmed());
filters << QApplication::translate("ProfileInterface", "All files (**)");
fileDialog.setNameFilters(filters);
QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
fileDialog.setSidebarUrls(sidebarUrls);
fileDialog.setDirectory(settings.value(profileName % "+Directory", StandardPaths::documentsLocation()).toString());
fileDialog.restoreGeometry(settings.value(profileName % "+Geometry", "").toByteArray());
if (fileDialog.exec()) {
QStringList selectedFiles = fileDialog.selectedFiles();
if (selectedFiles.length() == 1) {
QString selectedFile = selectedFiles.at(0);
QString selectedFileName = QFileInfo(selectedFile).fileName();
QFile snapmaticFile(selectedFile);
if (!snapmaticFile.open(QFile::ReadOnly)) {
QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be open").arg("\""+selectedFileName+"\""));
goto fileDialogPreOpen;
}
QImage *importImage = new QImage();
QImageReader snapmaticImageReader;
snapmaticImageReader.setDecideFormatFromContent(true);
snapmaticImageReader.setDevice(&snapmaticFile);
if (!snapmaticImageReader.read(importImage)) {
QMessageBox::warning(this, QApplication::translate("ProfileInterface", "Import"), QApplication::translate("ProfileInterface", "Can't import %1 because file can't be parsed properly").arg("\""+selectedFileName+"\""));
delete importImage;
goto fileDialogPreOpen;
}
setImage(importImage);
}
}
settings.setValue(profileName % "+Geometry", fileDialog.saveGeometry());
settings.setValue(profileName % "+Directory", fileDialog.directory().absolutePath());
settings.endGroup();
settings.endGroup();
}
void ImportDialog::loadImportSettings()
{
if (settingsLocked) {
QMessageBox::information(this, tr("Load Settings..."), tr("Please import a new picture first"));
return;
}
bool ok;
QStringList profileList;
profileList << tr("Default", "Default as Default Profile")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("1")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("2")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("3")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("4")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("5");
QString sProfile = QInputDialog::getItem(this, tr("Load Settings..."), tr("Please select your settings profile"), profileList, 0, false, &ok, windowFlags());
if (ok) {
QString pProfile;
if (sProfile == tr("Default", "Default as Default Profile")) {
pProfile = "Default";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1")) {
pProfile = "Profile 1";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2")) {
pProfile = "Profile 2";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3")) {
pProfile = "Profile 3";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4"))
{
pProfile = "Profile 4";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5")) {
pProfile = "Profile 5";
}
processSettings(pProfile, true);
processImage();
}
}
void ImportDialog::saveImportSettings()
{
if (settingsLocked) {
QMessageBox::information(this, tr("Save Settings..."), tr("Please import a new picture first"));
return;
}
bool ok;
QStringList profileList;
profileList << tr("Profile %1", "Profile %1 as Profile 1").arg("1")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("2")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("3")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("4")
<< tr("Profile %1", "Profile %1 as Profile 1").arg("5");
QString sProfile = QInputDialog::getItem(this, tr("Save Settings..."), tr("Please select your settings profile"), profileList, 0, false, &ok, windowFlags());
if (ok) {
QString pProfile;
if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("1")) {
pProfile = "Profile 1";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("2")) {
pProfile = "Profile 2";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("3")) {
pProfile = "Profile 3";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("4")) {
pProfile = "Profile 4";
}
else if (sProfile == tr("Profile %1", "Profile %1 as Profile 1").arg("5")) {
pProfile = "Profile 5";
}
saveSettings(pProfile);
}
} }
QImage ImportDialog::image() QImage ImportDialog::image()
{ {
if (ui->cbImportAsIs->isChecked()) { return newImage;
return origImage;
}
else {
return newImage;
}
} }
void ImportDialog::setImage(QImage *image_) void ImportDialog::setImage(QImage *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; {
ui->cbAvatar->setChecked(false); workImage = image_->scaledToWidth(snapmaticResolutionW, Qt::SmoothTransformation);
workImage = image_->scaledToWidth(snapmaticResolution.width(), 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; {
ui->cbAvatar->setChecked(false); workImage = image_->scaledToHeight(snapmaticResolutionH, Qt::SmoothTransformation);
workImage = image_->scaledToHeight(snapmaticResolution.height(), Qt::SmoothTransformation);
delete image_; delete image_;
} }
else { else
insideAvatarZone = false; {
ui->cbAvatar->setChecked(false);
workImage = *image_; workImage = *image_;
delete image_; delete image_;
} }
processImage(); processImage();
lockSettings(false);
}
void ImportDialog::lockSettings(bool lock)
{
ui->gbAdvanced->setDisabled(lock);
if (ui->cbImportAsIs->isChecked()) {
ui->gbBackground->setDisabled(true);
ui->gbSettings->setDisabled(true);
}
else {
ui->gbBackground->setDisabled(lock);
ui->gbSettings->setDisabled(lock);
}
ui->cmdOK->setDisabled(lock);
settingsLocked = lock;
}
void ImportDialog::enableOverwriteMode()
{
setWindowTitle(QApplication::translate("ImageEditorDialog", "Overwrite Image..."));
ui->cmdOK->setText(QApplication::translate("ImageEditorDialog", "&Overwrite"));
ui->cmdOK->setToolTip(QApplication::translate("ImageEditorDialog", "Apply changes"));
ui->cmdCancel->setText(QApplication::translate("ImageEditorDialog", "&Close"));
ui->cmdCancel->setToolTip(QApplication::translate("ImageEditorDialog", "Discard changes"));
ui->cmdCancel->setDefault(true);
ui->cmdCancel->setFocus();
lockSettings(true);
} }
bool ImportDialog::isImportAgreed() bool ImportDialog::isImportAgreed()
@ -736,53 +248,29 @@ bool ImportDialog::isImportAgreed()
return importAgreed; return importAgreed;
} }
bool ImportDialog::isUnlimitedBuffer()
{
return ui->cbUnlimited->isChecked();
}
bool ImportDialog::areSettingsLocked()
{
return settingsLocked;
}
QString ImportDialog::getImageTitle() QString ImportDialog::getImageTitle()
{ {
if (ui->cbImportAsIs->isChecked()) { return imageTitle;
return tr("Custom Picture", "Custom Picture Description in SC, don't use Special Character!");
}
else {
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.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;
} }
} }
insideAvatarZone = ui->cbAvatar->isChecked(); insideAvatarZone = ui->cbAvatar->isChecked();
watermarkBlock = true;
if (insideAvatarZone) {
ui->cbWatermark->setChecked(watermarkAvatar);
}
else {
ui->cbWatermark->setChecked(watermarkPicture);
}
watermarkBlock = false;
processImage(); processImage();
} }
@ -799,9 +287,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 +303,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 +330,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 +346,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 +364,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);
@ -906,69 +402,3 @@ void ImportDialog::on_cbForceAvatarColour_toggled(bool checked)
Q_UNUSED(checked) Q_UNUSED(checked)
processImage(); processImage();
} }
void ImportDialog::on_cbWatermark_toggled(bool checked)
{
if (!watermarkBlock) {
if (insideAvatarZone) {
watermarkAvatar = checked;
}
else {
watermarkPicture = checked;
}
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 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,7 +20,6 @@
#define IMPORTDIALOG_H #define IMPORTDIALOG_H
#include <QDialog> #include <QDialog>
#include <QMenu>
namespace Ui { namespace Ui {
class ImportDialog; class ImportDialog;
@ -31,24 +30,15 @@ class ImportDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit ImportDialog(QString profileName, QWidget *parent = 0); explicit ImportDialog(QWidget *parent = 0);
~ImportDialog(); ~ImportDialog();
QImage image(); QImage image();
QString getImageTitle(); QString getImageTitle();
void setImage(QImage *image); void setImage(QImage *image);
void lockSettings(bool lock);
void enableOverwriteMode();
bool isImportAgreed(); bool isImportAgreed();
bool isUnlimitedBuffer();
bool areSettingsLocked();
private slots: private slots:
void processImage(); void processImage();
void reworkImage();
void cropPicture();
void importNewPicture();
void loadImportSettings();
void saveImportSettings();
void on_cbIgnore_toggled(bool checked); void on_cbIgnore_toggled(bool checked);
void on_cbAvatar_toggled(bool checked); void on_cbAvatar_toggled(bool checked);
void on_cmdCancel_clicked(); void on_cmdCancel_clicked();
@ -59,35 +49,20 @@ private slots:
void on_cmdBackgroundWipe_clicked(); void on_cmdBackgroundWipe_clicked();
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_cbBorderless_toggled(bool checked);
void on_cbImportAsIs_toggled(bool checked);
void on_cbResolution_currentIndexChanged(int index);
private: private:
QString profileName;
Ui::ImportDialog *ui; Ui::ImportDialog *ui;
QImage avatarAreaImage; QImage avatarAreaImage;
QString backgroundPath; QString backgroundPath;
QString imageTitle; QString imageTitle;
QImage backImage; QImage backImage;
QImage workImage; QImage workImage;
QImage origImage;
QImage newImage; QImage newImage;
QColor selectedColour; QColor selectedColour;
QMenu optionsMenu;
QSize snapmaticResolution;
bool insideAvatarZone; bool insideAvatarZone;
bool watermarkPicture;
bool watermarkAvatar;
bool watermarkBlock;
bool settingsLocked;
bool importAgreed; bool importAgreed;
int snapmaticResolutionLW; int snapmaticResolutionLW;
int snapmaticResolutionLH; int snapmaticResolutionLH;
void processWatermark(QPainter *snapmaticPainter);
void processSettings(QString settingsProfile, bool setDefault = false);
void saveSettings(QString settingsProfile);
}; };
#endif // IMPORTDIALOG_H #endif // IMPORTDIALOG_H

View File

@ -7,13 +7,13 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>516</width> <width>516</width>
<height>673</height> <height>425</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>516</width> <width>516</width>
<height>512</height> <height>425</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -85,32 +85,30 @@
</property> </property>
<layout class="QVBoxLayout" name="vlSettings"> <layout class="QVBoxLayout" name="vlSettings">
<item> <item>
<layout class="QGridLayout" name="glPicture"> <layout class="QHBoxLayout" name="hlCheckboxes">
<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="text"> <property name="sizePolicy">
<string>Watermark</string> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="cbBorderless">
<property name="text"> <property name="text">
<string>Crop to Aspect Ratio</string> <string>Ignore Aspect Ratio</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -126,8 +124,8 @@
</property> </property>
<layout class="QVBoxLayout" name="vlBackground"> <layout class="QVBoxLayout" name="vlBackground">
<item> <item>
<layout class="QGridLayout" name="glBackground"> <layout class="QHBoxLayout" name="hlColor">
<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">
@ -155,11 +153,8 @@
</property> </property>
<item> <item>
<widget class="QToolButton" name="cmdColourChange"> <widget class="QToolButton" name="cmdColourChange">
<property name="toolTip">
<string>Select background colour</string>
</property>
<property name="text"> <property name="text">
<string notr="true">...</string> <string>...</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -180,24 +175,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">
@ -225,21 +203,15 @@
</property> </property>
<item> <item>
<widget class="QToolButton" name="cmdBackgroundChange"> <widget class="QToolButton" name="cmdBackgroundChange">
<property name="toolTip">
<string>Select background image</string>
</property>
<property name="text"> <property name="text">
<string notr="true">...</string> <string>...</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QToolButton" name="cmdBackgroundWipe"> <widget class="QToolButton" name="cmdBackgroundWipe">
<property name="toolTip">
<string>Remove background image</string>
</property>
<property name="text"> <property name="text">
<string notr="true">X</string> <string>X</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -262,61 +234,25 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbAdvanced">
<property name="title">
<string>Advanced</string>
</property>
<layout class="QVBoxLayout" name="vlAdvanced">
<item> <item>
<layout class="QGridLayout" name="glAdvanced"> <layout class="QHBoxLayout" name="hlBackground">
<item row="1" column="0"> <item>
<widget class="QCheckBox" name="cbUnlimited"> <widget class="QCheckBox" name="cbForceAvatarColour">
<property name="toolTip">
<string>Avoid compression and expand buffer instead, improves picture quality, but may break Snapmatic</string>
</property>
<property name="text"> <property name="text">
<string>Unlimited Buffer</string> <string>Force Colour in Avatar Zone</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item>
<widget class="QCheckBox" name="cbImportAsIs"> <widget class="QCheckBox" name="cbStretch">
<property name="toolTip"> <property name="enabled">
<string>Import as-is, don't change the picture at all, guaranteed to break Snapmatic unless you know what you doing</string> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Import as-is</string> <string>Ignore Aspect Ratio</string>
</property> </property>
</widget> </widget>
</item> </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>
@ -337,19 +273,6 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="hlButtons"> <layout class="QHBoxLayout" name="hlButtons">
<item>
<widget class="QPushButton" name="cmdOptions">
<property name="toolTip">
<string>Import options</string>
</property>
<property name="text">
<string>&amp;Options</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item> <item>
<spacer name="hsButtons"> <spacer name="hsButtons">
<property name="orientation"> <property name="orientation">

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
@ -20,18 +20,13 @@
#include "ui_JsonEditorDialog.h" #include "ui_JsonEditorDialog.h"
#include "SnapmaticEditor.h" #include "SnapmaticEditor.h"
#include "AppEnv.h" #include "AppEnv.h"
#include "config.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox> #include <QMessageBox>
#if QT_VERSION >= 0x050200 #if QT_VERSION >= 0x050200
#include <QFontDatabase> #include <QFontDatabase>
#endif #include <QDebug>
#ifdef GTA5SYNC_TELEMETRY
#include "TelemetryClass.h"
#endif #endif
JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) : JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
@ -39,30 +34,28 @@ 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->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"));
} }
@ -70,18 +63,9 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
#if QT_VERSION >= 0x050200 #if QT_VERSION >= 0x050200
ui->txtJSON->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); ui->txtJSON->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
#else
QFont jsonFont = ui->txtJSON->font();
jsonFont.setStyleHint(QFont::Monospace);
jsonFont.setFixedPitch(true);
ui->txtJSON->setFont(jsonFont);
#endif #endif
QFontMetrics fontMetrics(ui->txtJSON->font()); QFontMetrics fontMetrics(ui->txtJSON->font());
#if QT_VERSION >= 0x050B00
ui->txtJSON->setTabStopDistance(fontMetrics.horizontalAdvance(" "));
#else
ui->txtJSON->setTabStopWidth(fontMetrics.width(" ")); ui->txtJSON->setTabStopWidth(fontMetrics.width(" "));
#endif
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonCode.toUtf8()); QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonCode.toUtf8());
ui->txtJSON->setStyleSheet("QPlainTextEdit{background-color: rgb(46, 47, 48); color: rgb(238, 231, 172);}"); ui->txtJSON->setStyleSheet("QPlainTextEdit{background-color: rgb(46, 47, 48); color: rgb(238, 231, 172);}");
@ -99,10 +83,10 @@ 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));
} }
resize(450 * screenRatio, 550 * screenRatio); resize(450 * screenRatio, 550 * screenRatio);
} }
@ -120,22 +104,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,69 +136,59 @@ 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;
} }
jsonCode = newCode; jsonCode = newCode;
smpic->updateStrings();
smpic->emitUpdate(); smpic->emitUpdate();
#ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) {
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "JSONEdited";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#endif
return true; return true;
} }
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;
} }
@ -216,11 +196,13 @@ bool JsonEditorDialog::saveJsonContent()
void JsonEditorDialog::on_cmdClose_clicked() void JsonEditorDialog::on_cmdClose_clicked()
{ {
close(); this->close();
} }
void JsonEditorDialog::on_cmdSave_clicked() void JsonEditorDialog::on_cmdSave_clicked()
{ {
if (saveJsonContent()) if (saveJsonContent())
close(); {
this->close();
}
} }

View File

@ -112,9 +112,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>Apply changes</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Save</string> <string>&amp;Save</string>
</property> </property>
@ -128,9 +125,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>Discard changes</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Close</string> <string>&amp;Close</string>
</property> </property>

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
@ -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()
@ -62,224 +60,36 @@ MapLocationDialog::~MapLocationDialog()
void MapLocationDialog::drawPointOnMap(double xpos_d, double ypos_d) void MapLocationDialog::drawPointOnMap(double xpos_d, double ypos_d)
{ {
ui->labPos->setText(tr("X: %1\nY: %2", "X and Y position").arg(QString::number(xpos_d), QString::number(ypos_d))); qreal screenRatio = AppEnv::screenRatio();
int pointMakerSize = 8 * screenRatio;
QPixmap pointMakerPixmap = IconLoader::loadingPointmakerIcon().pixmap(QSize(pointMakerSize, pointMakerSize));
QSize mapPixelSize = size();
int pointMakerHalfSize = pointMakerSize / 2;
long xpos_ms = qRound(xpos_d);
long ypos_ms = qRound(ypos_d);
double xpos_ma = xpos_ms + 4000;
double ypos_ma = ypos_ms + 4000;
double xrat = (double)mapPixelSize.width() / 10000;
double yrat = (double)mapPixelSize.height() / 12000;
long xpos_mp = qRound(xpos_ma * xrat);
long ypos_mp = qRound(ypos_ma * yrat);
long xpos_pr = xpos_mp - pointMakerHalfSize;
long ypos_pr = ypos_mp + pointMakerHalfSize;
QPixmap mapPixmap(mapPixelSize);
QPainter mapPainter(&mapPixmap);
mapPainter.drawPixmap(0, 0, mapPixelSize.width(), mapPixelSize.height(), QPixmap(":/img/mappreview.jpg").scaled(mapPixelSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
mapPainter.drawPixmap(xpos_pr, mapPixelSize.height() - ypos_pr, pointMakerSize, pointMakerSize, pointMakerPixmap);
mapPainter.end();
QPalette backgroundPalette;
backgroundPalette.setBrush(backgroundRole(), QBrush(mapPixmap));
setPalette(backgroundPalette);
xpos_new = xpos_d; xpos_new = xpos_d;
ypos_new = ypos_d; ypos_new = ypos_d;
repaint(); ui->labPos->setText(tr("X: %1\nY: %2", "X and Y position").arg(QString::number(xpos_d), QString::number(ypos_d)));
}
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()
@ -301,14 +111,58 @@ 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;
} }
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);
}
void MapLocationDialog::mouseMoveEvent(QMouseEvent *ev)
{
if (!changeMode) { ev->ignore(); }
else if (ev->buttons() & Qt::LeftButton)
{
updatePosFromEvent(ev->x(), ev->y());
ev->accept();
}
else
{
ev->ignore();
}
}
void MapLocationDialog::mouseReleaseEvent(QMouseEvent *ev)
{
if (!changeMode) { ev->ignore(); }
else if (ev->button() == Qt::LeftButton)
{
updatePosFromEvent(ev->x(), ev->y());
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,40 +33,30 @@ 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();
~MapLocationDialog(); ~MapLocationDialog();
protected: protected:
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();
void updatePosFromEvent(double x, double y); void updatePosFromEvent(int x, int y);
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

@ -25,11 +25,6 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Snapmatic Map Viewer</string> <string>Snapmatic Map Viewer</string>
</property> </property>
<property name="styleSheet">
<string notr="true">QDialog#MapLocationDialog {
background-color: transparent;
}</string>
</property>
<layout class="QVBoxLayout" name="vlMapPreview"> <layout class="QVBoxLayout" name="vlMapPreview">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -139,9 +134,6 @@ color: rgb(255, 255, 255);
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>Close viewer</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Close</string> <string>&amp;Close</string>
</property> </property>
@ -168,9 +160,6 @@ color: rgb(255, 255, 255);
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>Apply new position</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Apply</string> <string>&amp;Apply</string>
</property> </property>
@ -184,9 +173,6 @@ color: rgb(255, 255, 255);
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>Revert old position</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Revert</string> <string>&amp;Revert</string>
</property> </property>
@ -200,11 +186,8 @@ color: rgb(255, 255, 255);
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>Select new position</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Select</string> <string>&amp;Set</string>
</property> </property>
<property name="autoDefault"> <property name="autoDefault">
<bool>false</bool> <bool>false</bool>
@ -216,9 +199,6 @@ color: rgb(255, 255, 255);
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip">
<string>Quit select position</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Done</string> <string>&amp;Done</string>
</property> </property>

View File

@ -1,111 +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/>.
*****************************************************************************/
#include "TranslationClass.h"
#include "MessageThread.h"
#include "AppEnv.h"
#include "config.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QEventLoop>
#include <QUrlQuery>
#include <QTimer>
#include <QDebug>
#include <QUrl>
MessageThread::MessageThread(uint cacheId, QObject *parent) : QThread(parent), cacheId(cacheId)
{
threadRunning = true;
}
void MessageThread::run()
{
QEventLoop threadLoop;
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
while (threadRunning) {
{
#ifdef GTA5SYNC_MOTD_WEBURL
QUrl motdWebUrl = QUrl(GTA5SYNC_MOTD_WEBURL);
#else
QUrl motdWebUrl = QUrl("https://motd.syping.de/gta5view-dev/");
#endif
QUrlQuery urlQuery(motdWebUrl);
urlQuery.addQueryItem("code", GTA5SYNC_BUILDCODE);
urlQuery.addQueryItem("cacheid", QString::number(cacheId));
urlQuery.addQueryItem("lang", Translator->getCurrentLanguage());
urlQuery.addQueryItem("version", GTA5SYNC_APPVER);
motdWebUrl.setQuery(urlQuery);
QNetworkAccessManager *netManager = new QNetworkAccessManager();
QNetworkRequest netRequest(motdWebUrl);
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
QNetworkReply *netReply = netManager->get(netRequest);
QEventLoop downloadLoop;
QObject::connect(netManager, SIGNAL(finished(QNetworkReply*)), &downloadLoop, SLOT(quit()));
QObject::connect(this, SIGNAL(threadTerminated()), &threadLoop, SLOT(quit()));
QTimer::singleShot(60000, &downloadLoop, SLOT(quit()));
downloadLoop.exec();
if (netReply->isFinished()) {
QByteArray jsonContent = netReply->readAll();
QString headerData = QString::fromUtf8(netReply->rawHeader("gta5view"));
if (!headerData.isEmpty()) {
QMap<QString,QString> headerMap;
const QStringList headerVarList = headerData.split(';');
for (QString headerVar : headerVarList) {
QStringList varValueList = headerVar.split('=');
if (varValueList.length() >= 2) {
const QString variable = varValueList.at(0).trimmed();
varValueList.removeFirst();
const QString value = varValueList.join('=');
headerMap.insert(variable, value);
}
}
if (headerMap.value("update", "false") == "true") {
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonContent);
emit messagesArrived(jsonDocument.object());
}
if (headerMap.contains("cache")) {
bool uintOk;
uint cacheVal = headerMap.value("cache").toUInt(&uintOk);
if (uintOk) {
cacheId = cacheVal;
emit updateCacheId(cacheId);
}
}
}
}
delete netReply;
delete netManager;
}
QTimer::singleShot(300000, &threadLoop, SLOT(quit()));
threadLoop.exec();
}
}
void MessageThread::terminateThread()
{
threadRunning = false;
emit threadTerminated();
}

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,16 +21,15 @@
#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>
#include <QDesktopWidget>
#include <QJsonDocument> #include <QJsonDocument>
#include <QStyleFactory> #include <QStyleFactory>
#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>
@ -41,12 +40,6 @@
#include <QList> #include <QList>
#include <QDir> #include <QDir>
#if QT_VERSION >= 0x050000
#include <QScreen>
#else
#include <QDesktopWidget>
#endif
#ifdef GTA5SYNC_TELEMETRY #ifdef GTA5SYNC_TELEMETRY
#include "TelemetryClass.h" #include "TelemetryClass.h"
#endif #endif
@ -56,31 +49,19 @@ 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);
ui->tabWidget->setCurrentIndex(0); ui->tabWidget->setCurrentIndex(0);
ui->labPicCustomRes->setVisible(false); ui->labPicCustomRes->setVisible(false);
ui->cmdCancel->setDefault(true);
ui->cmdCancel->setFocus(); ui->cmdCancel->setFocus();
#if QT_VERSION >= 0x050000
qreal screenRatioPR = AppEnv::screenRatioPR();
QRect desktopResolution = QApplication::primaryScreen()->geometry();
int desktopSizeWidth = qRound((double)desktopResolution.width() * screenRatioPR);
int desktopSizeHeight = qRound((double)desktopResolution.height() * screenRatioPR);
#else
QRect desktopResolution = QApplication::desktop()->screenGeometry(this); QRect desktopResolution = QApplication::desktop()->screenGeometry(this);
int desktopSizeWidth = desktopResolution.width(); int desktopSizeWidth = desktopResolution.width();
int desktopSizeHeight = desktopResolution.height(); int desktopSizeHeight = desktopResolution.height();
#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 +74,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();
@ -122,7 +102,6 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
setupInterfaceSettings(); setupInterfaceSettings();
setupStatisticsSettings(); setupStatisticsSettings();
setupSnapmaticPictureViewer(); setupSnapmaticPictureViewer();
setupWindowsGameSettings();
#ifndef Q_QS_ANDROID #ifndef Q_QS_ANDROID
// DPI calculation // DPI calculation
@ -130,9 +109,7 @@ 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)); this->setWindowTitle(windowTitle().arg(GTA5SYNC_APPSTR));
ui->rbClassic->setText(ui->rbClassic->text().arg(GTA5SYNC_APPSTR));
setWindowTitle(windowTitle().arg(GTA5SYNC_APPSTR));
} }
OptionsDialog::~OptionsDialog() OptionsDialog::~OptionsDialog()
@ -145,28 +122,24 @@ OptionsDialog::~OptionsDialog()
void OptionsDialog::setupTreeWidget() void OptionsDialog::setupTreeWidget()
{ {
const QStringList players = profileDB->getPlayers(); for (QString playerIDStr : profileDB->getPlayers())
if (players.length() != 0) { {
for (auto it = players.constBegin(); it != players.constEnd(); it++) { bool ok;
bool ok; int playerID = playerIDStr.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 += playerIDStr;
playerTreeViewList += playerName; playerTreeViewList += playerName;
QTreeWidgetItem *playerItem = new QTreeWidgetItem(playerTreeViewList); QTreeWidgetItem *playerItem = new QTreeWidgetItem(playerTreeViewList);
ui->twPlayers->addTopLevelItem(playerItem); ui->twPlayers->addTopLevelItem(playerItem);
playerItems += playerItem; playerItems += playerItem;
}
} }
ui->twPlayers->sortItems(1, Qt::AscendingOrder);
}
else {
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabPlayers));
} }
ui->twPlayers->sortItems(1, Qt::AscendingOrder);
} }
void OptionsDialog::setupLanguageBox() void OptionsDialog::setupLanguageBox()
@ -176,19 +149,9 @@ 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 (Next Closest Language)", "First language a person can talk with a different person/application. \"Native\" or \"Not Native\".").arg(tr("System",
"System in context of System default")); "System in context of System default"));
#ifdef Q_OS_WIN QString cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
QString cbAutoStr;
if (AppEnv::getGameLanguage(AppEnv::getGameVersion()) != GameLanguage::Undefined) {
cbAutoStr = tr("%1 (Game language)", "Next closest language compared to the Game settings").arg(tr("Auto", "Automatic language choice."));
}
else {
cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
}
#else
const QString cbAutoStr = tr("%1 (Closest to Interface)", "Next closest language compared to the Interface").arg(tr("Auto", "Automatic language choice."));
#endif
ui->cbLanguage->addItem(cbSysStr, "System"); ui->cbLanguage->addItem(cbSysStr, "System");
ui->cbAreaLanguage->addItem(cbAutoStr, "Auto"); ui->cbAreaLanguage->addItem(cbAutoStr, "Auto");
@ -201,18 +164,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 +183,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 +192,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 +223,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 +244,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 +264,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 GTA5SYNC_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();
} }
@ -358,25 +332,26 @@ void OptionsDialog::applySettings()
settings->setValue("Language", ui->cbLanguage->itemData(ui->cbLanguage->currentIndex())); settings->setValue("Language", ui->cbLanguage->itemData(ui->cbLanguage->currentIndex()));
settings->setValue("AreaLanguage", ui->cbAreaLanguage->itemData(ui->cbAreaLanguage->currentIndex())); settings->setValue("AreaLanguage", ui->cbAreaLanguage->itemData(ui->cbAreaLanguage->currentIndex()));
#endif #endif
#ifdef Q_OS_WIN #ifdef GTA5SYNC_WIN
#if QT_VERSION >= 0x050200 #if QT_VERSION >= 0x050200
settings->setValue("NavigationBar", ui->cbSnapmaticNavigationBar->isChecked()); settings->setValue("NavigationBar", ui->cbSnapmaticNavigationBar->isChecked());
#endif #endif
#else
settings->setValue("NavigationBar", ui->cbSnapmaticNavigationBar->isChecked());
#endif #endif
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 +362,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,47 +389,27 @@ 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
settings->beginGroup("Telemetry"); settings->beginGroup("Telemetry");
settings->setValue("PushAppConf", ui->cbAppConfigStats->isChecked()); settings->setValue("PushAppConf", ui->cbAppConfigStats->isChecked());
settings->setValue("PushUsageData", ui->cbUsageData->isChecked());
if (!Telemetry->isStateForced()) { settings->setValue("IsEnabled", ui->cbParticipateStats->isChecked()); } if (!Telemetry->isStateForced()) { settings->setValue("IsEnabled", ui->cbParticipateStats->isChecked()); }
settings->endGroup(); settings->endGroup();
Telemetry->refresh(); Telemetry->refresh();
Telemetry->work(); Telemetry->work();
if (ui->cbUsageData->isChecked() && Telemetry->canPush()) {
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "SettingsUpdated";
#if QT_VERSION >= 0x060000
jsonObject["UpdateTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["UpdateTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#endif #endif
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
@ -461,19 +419,21 @@ 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();
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 +450,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 +492,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 +501,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);
} }
@ -578,20 +549,30 @@ void OptionsDialog::setupStatisticsSettings()
ui->cbParticipateStats->setText(tr("Participate in %1 User Statistics").arg(GTA5SYNC_APPSTR)); ui->cbParticipateStats->setText(tr("Participate in %1 User Statistics").arg(GTA5SYNC_APPSTR));
ui->labUserStats->setText(QString("<a href=\"%2\">%1</a>").arg(tr("View %1 User Statistics Online").arg(GTA5SYNC_APPSTR), TelemetryClass::getWebURL().toString())); ui->labUserStats->setText(QString("<a href=\"%2\">%1</a>").arg(tr("View %1 User Statistics Online").arg(GTA5SYNC_APPSTR), TelemetryClass::getWebURL().toString()));
ui->gbUserFeedback->setVisible(false);
// settings->beginGroup("Startup");
// if (settings->value("IsFirstStart", true).toBool() == true)
// {
// ui->gbUserFeedback->setVisible(false);
// }
// settings->endGroup();
settings->beginGroup("Telemetry"); settings->beginGroup("Telemetry");
ui->cbParticipateStats->setChecked(Telemetry->isEnabled()); ui->cbParticipateStats->setChecked(Telemetry->isEnabled());
ui->cbAppConfigStats->setChecked(settings->value("PushAppConf", false).toBool()); ui->cbAppConfigStats->setChecked(settings->value("PushAppConf", 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);
} }
@ -600,70 +581,14 @@ void OptionsDialog::setupStatisticsSettings()
#endif #endif
} }
void OptionsDialog::setupWindowsGameSettings()
{
#ifdef GTA5SYNC_GAME
GameVersion gameVersion = AppEnv::getGameVersion();
#ifdef Q_OS_WIN
if (gameVersion != GameVersion::NoVersion) {
if (gameVersion == GameVersion::SocialClubVersion) {
ui->gbSteam->setDisabled(true);
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No"))));
if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined) {
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName()));
}
else {
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined")));
}
ui->labSteamLanguage->setVisible(false);
}
else if (gameVersion == GameVersion::SteamVersion) {
ui->gbSocialClub->setDisabled(true);
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: red\">%1</span>").arg(tr("No"))));
ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
ui->labSocialClubLanguage->setVisible(false);
if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined) {
ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName()));
}
else {
ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined")));
}
}
else {
ui->labSocialClubFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
ui->labSteamFound->setText(tr("Found: %1").arg(QString("<span style=\"color: green\">%1</span>").arg(tr("Yes"))));
if (AppEnv::getGameLanguage(GameVersion::SocialClubVersion) != GameLanguage::Undefined) {
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SocialClubVersion))).nativeLanguageName()));
}
else {
ui->labSocialClubLanguage->setText(tr("Language: %1").arg(tr("OS defined")));
}
if (AppEnv::getGameLanguage(GameVersion::SteamVersion) != GameLanguage::Undefined) {
ui->labSteamLanguage->setText(tr("Language: %1").arg(QLocale(AppEnv::gameLanguageToString(AppEnv::getGameLanguage(GameVersion::SteamVersion))).nativeLanguageName()));
}
else {
ui->labSteamLanguage->setText(tr("Language: %1").arg(tr("Steam defined")));
}
}
}
else {
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
}
#else
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
#endif
#else
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabGame));
#endif
}
void OptionsDialog::on_cbIgnoreAspectRatio_toggled(bool checked) 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 +600,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);
@ -685,26 +611,26 @@ void OptionsDialog::setupCustomGTAFolder()
void OptionsDialog::setupSnapmaticPictureViewer() void OptionsDialog::setupSnapmaticPictureViewer()
{ {
#ifdef Q_OS_WIN #ifdef GTA5SYNC_WIN
#if QT_VERSION >= 0x050200 #if QT_VERSION >= 0x050200
settings->beginGroup("Interface"); settings->beginGroup("Interface");
ui->cbSnapmaticNavigationBar->setChecked(settings->value("NavigationBar", true).toBool()); ui->cbSnapmaticNavigationBar->setChecked(settings->value("NavigationBar", false).toBool());
settings->endGroup(); settings->endGroup();
#else #else
ui->cbSnapmaticNavigationBar->setVisible(false); ui->cbSnapmaticNavigationBar->setVisible(false);
ui->gbSnapmaticPictureViewer->setVisible(false); ui->gbSnapmaticPictureViewer->setVisible(false);
#endif #endif
#else #else
settings->beginGroup("Interface"); ui->cbSnapmaticNavigationBar->setVisible(false);
ui->cbSnapmaticNavigationBar->setChecked(settings->value("NavigationBar", true).toBool()); ui->gbSnapmaticPictureViewer->setVisible(false);
settings->endGroup();
#endif #endif
} }
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 +638,25 @@ 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) void OptionsDialog::on_cmdUserFeedbackSend_clicked()
{ {
ui->cbFont->setDisabled(checked); #ifdef GTA5SYNC_TELEMETRY
ui->cmdFont->setDisabled(checked); if (ui->txtUserFeedback->toPlainText().length() < 1024 && ui->txtUserFeedback->toPlainText().length() >= 3)
ui->labFont->setDisabled(checked); {
QJsonDocument feedback;
QJsonObject feedbackObject;
feedbackObject["Message"] = ui->txtUserFeedback->toPlainText();
feedback.setObject(feedbackObject);
Telemetry->push(TelemetryCategory::UserFeedback, feedback);
ui->txtUserFeedback->setPlainText(QString());
}
else
{
QMessageBox::information(this, tr("User Feedback"), tr("A feedback message have to between 3-1024 characters long"));
}
#endif
} }
void OptionsDialog::on_cmdCopyStatsID_clicked() void OptionsDialog::on_cmdCopyStatsID_clicked()
@ -728,18 +665,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,8 @@ 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_cmdUserFeedbackSend_clicked();
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);
@ -82,7 +80,6 @@ private:
void setupInterfaceSettings(); void setupInterfaceSettings();
void setupStatisticsSettings(); void setupStatisticsSettings();
void setupSnapmaticPictureViewer(); void setupSnapmaticPictureViewer();
void setupWindowsGameSettings();
void applySettings(); void applySettings();
}; };

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>
@ -382,72 +382,6 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabGame">
<attribute name="title">
<string>Game</string>
</attribute>
<layout class="QVBoxLayout" name="vlGame">
<item>
<widget class="QGroupBox" name="gbSocialClub">
<property name="title">
<string>Social Club Version</string>
</property>
<layout class="QVBoxLayout" name="vlGameSocialClub">
<item>
<widget class="QLabel" name="labSocialClubFound">
<property name="text">
<string>Found: %1</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labSocialClubLanguage">
<property name="text">
<string>Language: %1</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbSteam">
<property name="title">
<string>Steam Version</string>
</property>
<layout class="QVBoxLayout" name="vlGameSteam">
<item>
<widget class="QLabel" name="labSteamFound">
<property name="text">
<string>Found: %1</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labSteamLanguage">
<property name="text">
<string>Language: %1</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="vsGame">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabStats"> <widget class="QWidget" name="tabStats">
<attribute name="title"> <attribute name="title">
<string>Feedback</string> <string>Feedback</string>
@ -486,11 +420,11 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="gbCategories"> <widget class="QGroupBox" name="gbCategorys">
<property name="title"> <property name="title">
<string>Categories</string> <string>Categories</string>
</property> </property>
<layout class="QVBoxLayout" name="vlCategories"> <layout class="QVBoxLayout" name="vlCategorys">
<item> <item>
<widget class="QCheckBox" name="cbGeneralStats"> <widget class="QCheckBox" name="cbGeneralStats">
<property name="enabled"> <property name="enabled">
@ -524,13 +458,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="cbUsageData">
<property name="text">
<string>Personal Usage Data</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -539,32 +466,74 @@
<property name="title"> <property name="title">
<string>Other</string> <string>Other</string>
</property> </property>
<layout class="QVBoxLayout" name="vlFeedbackOther"> <layout class="QHBoxLayout" name="hlOtherStats">
<item> <item>
<layout class="QHBoxLayout" name="hlParticipation"> <widget class="QLabel" name="labParticipationID">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Participation ID: %1</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cmdCopyStatsID">
<property name="text">
<string>&amp;Copy</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbUserFeedback">
<property name="title">
<string>User Feedback</string>
</property>
<layout class="QVBoxLayout" name="vlUserFeedback">
<item>
<widget class="QPlainTextEdit" name="txtUserFeedback"/>
</item>
<item>
<layout class="QHBoxLayout" name="hlUserFeedbackButtons">
<item> <item>
<widget class="QLabel" name="labParticipationID"> <widget class="QLabel" name="labUserFeedback">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Participation ID: %1</string> <string>Limit: 1 message/day</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="cmdCopyStatsID"> <spacer name="hsUserFeedbackButtons">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cmdUserFeedbackSend">
<property name="text"> <property name="text">
<string>&amp;Copy</string> <string>&amp;Send</string>
</property> </property>
<property name="autoDefault"> <property name="autoDefault">
<bool>false</bool> <bool>false</bool>
@ -660,9 +629,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 +659,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>

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
@ -29,6 +29,14 @@
#include <QEvent> #include <QEvent>
#include <QMenu> #include <QMenu>
#ifdef GTA5SYNC_WIN
#if QT_VERSION >= 0x050200
#ifdef GTA5SYNC_APV
#include <dwmapi.h>
#endif
#endif
#endif
namespace Ui { namespace Ui {
class PictureDialog; class PictureDialog;
} }
@ -48,17 +56,17 @@ public:
void setSnapmaticPicture(SnapmaticPicture *picture, int index); void setSnapmaticPicture(SnapmaticPicture *picture, int index);
void setSnapmaticPicture(SnapmaticPicture *picture); void setSnapmaticPicture(SnapmaticPicture *picture);
void addPreviousNextButtons(); void addPreviousNextButtons();
void styliseDialog(); void stylizeDialog();
bool isIndexed(); bool isIndexed();
int getIndex(); int getIndex();
~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,11 +97,14 @@ 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 #ifdef GTA5SYNC_WIN
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result); #if QT_VERSION >= 0x050200
#elif QT_VERSION >= 0x050000 #ifdef GTA5SYNC_APV
bool nativeEvent(const QByteArray &eventType, void *message, long *result); bool nativeEvent(const QByteArray &eventType, void *message, long *result);
LRESULT HitTestNCA(HWND hWnd, LPARAM lParam);
void resizeEvent(QResizeEvent *event);
#endif
#endif #endif
#endif #endif
@ -125,8 +136,8 @@ private:
int avatarLocY; int avatarLocY;
int avatarSize; int avatarSize;
QMenu *manageMenu; QMenu *manageMenu;
#ifdef Q_OS_WIN #ifdef GTA5SYNC_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

@ -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
@ -17,29 +17,26 @@
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include "AppEnv.h"
#include "PictureExport.h" #include "PictureExport.h"
#include "PictureDialog.h" #include "PictureDialog.h"
#include "StandardPaths.h" #include "StandardPaths.h"
#include "SidebarGenerator.h" #include "SidebarGenerator.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QDesktopWidget>
#include <QApplication> #include <QApplication>
#include <QMessageBox> #include <QMessageBox>
#include <QFileDialog> #include <QFileDialog>
#include <QSettings> #include <QSettings>
#include <QRegExp>
#include <QDebug> #include <QDebug>
#if QT_VERSION < 0x050000
#include <QDesktopWidget>
#endif
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
#include <QSaveFile> #include <QSaveFile>
#include <QScreen>
#endif #endif
PictureExport::PictureExport() PictureExport::PictureExport()
{ {
} }
void PictureExport::exportAsPicture(QWidget *parent, SnapmaticPicture *picture) void PictureExport::exportAsPicture(QWidget *parent, SnapmaticPicture *picture)
@ -50,25 +47,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,55 +109,59 @@ 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 {
qreal screenRatioPR = AppEnv::screenRatioPR();
QRect desktopResolution = QApplication::primaryScreen()->geometry();
int desktopSizeWidth = qRound((double)desktopResolution.width() * screenRatioPR);
int desktopSizeHeight = qRound((double)desktopResolution.height() * screenRatioPR);
#else
QRect desktopResolution = QApplication::desktop()->screenGeometry(); QRect desktopResolution = QApplication::desktop()->screenGeometry();
int desktopSizeWidth = desktopResolution.width(); exportPicture = exportPicture.scaled(desktopResolution.width(), desktopResolution.height(), aspectRatio, Qt::SmoothTransformation);
int desktopSizeHeight = desktopResolution.height();
#endif
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 +172,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 +213,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 +250,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 +261,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,13 @@
#include "PictureDialog.h" #include "PictureDialog.h"
#include "PictureWidget.h" #include "PictureWidget.h"
#include "UiModLabel.h" #include "UiModLabel.h"
#include "AppEnv.h" #include <QDesktopWidget>
#include <QApplication> #include <QApplication>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
#include <QPixmap> #include <QPixmap>
#include <QEvent> #include <QEvent>
#include <QDebug>
PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent) PictureWidget::PictureWidget(QWidget *parent) : QDialog(parent)
{ {
@ -43,6 +44,7 @@ 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)));
QObject::connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(updateWindowSize(int)));
setLayout(widgetLayout); setLayout(widgetLayout);
} }
@ -56,10 +58,12 @@ 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:
emit previousPictureRequested(); emit previousPictureRequested();
break; break;
@ -74,29 +78,32 @@ 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 (screenID == QApplication::desktop()->screenNumber(this))
{
QRect desktopRect = QApplication::desktop()->screenGeometry(this);
this->move(desktopRect.x(), desktopRect.y());
this->resize(desktopRect.width(), desktopRect.height());
this->showFullScreen();
pictureLabel->setPixmap(QPixmap::fromImage(image.scaled(desktopRect.width(), desktopRect.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
}
} }

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-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
@ -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,72 +31,54 @@ 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);
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"));
} }
// 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 {
qreal screenRatio = AppEnv::screenRatio();
if (screenRatio != 1) {
QSize iconSize = ui->cmdMakeAv->iconSize();
iconSize = QSize(iconSize.width() * screenRatio, iconSize.height() * screenRatio);
ui->cmdMakeAv->setIconSize(iconSize);
ui->cmdMakeSe->setIconSize(iconSize);
ui->cmdMakeAd->setIconSize(iconSize);
}
#endif
ui->cmdMakeAv->setIcon(QIcon::fromTheme("go-previous")); ui->cmdMakeAv->setIcon(QIcon::fromTheme("go-previous"));
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 {
qreal screenRatio = AppEnv::screenRatio(); drawSwitchButtons();
if (screenRatio != 1) {
QSize iconSize = ui->cmdMakeAv->iconSize();
iconSize = QSize(iconSize.width() * screenRatio, iconSize.height() * screenRatio);
ui->cmdMakeAv->setIconSize(iconSize);
ui->cmdMakeSe->setIconSize(iconSize);
ui->cmdMakeAd->setIconSize(iconSize);
}
#endif
ui->cmdMakeAv->setIcon(QIcon(AppEnv::getImagesFolder() % "/back.svgz"));
ui->cmdMakeSe->setIcon(QIcon(AppEnv::getImagesFolder() % "/next.svgz"));
ui->cmdMakeAd->setIcon(QIcon(AppEnv::getImagesFolder() % "/add.svgz"));
} }
buildInterface(); buildInterface();
@ -109,15 +89,90 @@ 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;
} }
void PlayerListDialog::drawSwitchButtons()
{
QFont painterFont = ui->cmdApply->font();
QPalette palette;
QFontMetrics fontMetrics(painterFont);
QRect makeAvRect = fontMetrics.boundingRect(QRect(0, 0, 0, 0), Qt::AlignCenter | Qt::TextDontClip, "<");
QRect makeSeRect = fontMetrics.boundingRect(QRect(0, 0, 0, 0), Qt::AlignCenter | Qt::TextDontClip, ">");
QRect makeAdRect = fontMetrics.boundingRect(QRect(0, 0, 0, 0), Qt::AlignCenter | Qt::TextDontClip, "+");
int makeAvSize;
if (makeAvRect.height() > makeAvRect.width())
{
makeAvSize = makeAvRect.height();
}
else
{
makeAvSize = makeAvRect.width();
}
int makeSeSize;
if (makeSeRect.height() > makeSeRect.width())
{
makeSeSize = makeSeRect.height();
}
else
{
makeSeSize = makeSeRect.width();
}
int makeAdSize;
if (makeAdRect.height() > makeAdRect.width())
{
makeAdSize = makeAdRect.height();
}
else
{
makeAdSize = makeAdRect.width();
}
QImage avImage(makeAvSize, makeAvSize, QImage::Format_ARGB32_Premultiplied);
avImage.fill(Qt::transparent);
QImage seImage(makeSeSize, makeSeSize, QImage::Format_ARGB32_Premultiplied);
seImage.fill(Qt::transparent);
QImage adImage(makeAdSize, makeAdSize, QImage::Format_ARGB32_Premultiplied);
adImage.fill(Qt::transparent);
QPainter avPainter(&avImage);
avPainter.setFont(painterFont);
avPainter.setBrush(palette.buttonText());
avPainter.setPen(palette.buttonText().color());
avPainter.drawText(0, 0, makeAvSize, makeAvSize, Qt::AlignCenter | Qt::TextDontClip, "<");
avPainter.end();
QPainter sePainter(&seImage);
sePainter.setFont(painterFont);
sePainter.setBrush(palette.buttonText());
sePainter.setPen(palette.buttonText().color());
sePainter.drawText(0, 0, makeSeSize, makeSeSize, Qt::AlignCenter | Qt::TextDontClip, ">");
sePainter.end();
QPainter adPainter(&adImage);
adPainter.setFont(painterFont);
adPainter.setBrush(palette.buttonText());
adPainter.setPen(palette.buttonText().color());
adPainter.drawText(0, 0, makeAdSize, makeAdSize, Qt::AlignCenter | Qt::TextDontClip, "+");
adPainter.end();
ui->cmdMakeAv->setIconSize(avImage.size());
ui->cmdMakeSe->setIconSize(seImage.size());
ui->cmdMakeAd->setIconSize(adImage.size());
ui->cmdMakeAv->setIcon(QIcon(QPixmap::fromImage(avImage)));
ui->cmdMakeSe->setIcon(QIcon(QPixmap::fromImage(seImage)));
ui->cmdMakeAd->setIcon(QIcon(QPixmap::fromImage(adImage)));
}
void PlayerListDialog::on_cmdCancel_clicked() void PlayerListDialog::on_cmdCancel_clicked()
{ {
close(); close();
@ -126,13 +181,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 +201,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 +216,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 +236,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 +252,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 +271,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);

View File

@ -48,6 +48,7 @@ private:
ProfileDatabase *profileDB; ProfileDatabase *profileDB;
Ui::PlayerListDialog *ui; Ui::PlayerListDialog *ui;
bool listUpdated; bool listUpdated;
void drawSwitchButtons();
void buildInterface(); void buildInterface();
signals: signals:

View File

@ -51,8 +51,8 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="cmdMakeSe"> <widget class="QPushButton" name="cmdMakeSe">
<property name="focusPolicy"> <property name="text">
<enum>Qt::NoFocus</enum> <string/>
</property> </property>
<property name="autoDefault"> <property name="autoDefault">
<bool>false</bool> <bool>false</bool>
@ -61,9 +61,6 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="cmdMakeAv"> <widget class="QPushButton" name="cmdMakeAv">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -74,9 +71,6 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="cmdMakeAd"> <widget class="QPushButton" name="cmdMakeAd">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>

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
@ -29,8 +29,6 @@
#include "ExportThread.h" #include "ExportThread.h"
#include "SavegameData.h" #include "SavegameData.h"
#include "CrewDatabase.h" #include "CrewDatabase.h"
#include "pcg_basic.h"
#include <QFileSystemWatcher>
#include <QProgressDialog> #include <QProgressDialog>
#include <QSpacerItem> #include <QSpacerItem>
#include <QDateTime> #include <QDateTime>
@ -53,6 +51,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 +63,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 +80,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,41 +98,32 @@ 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;
QColor highlightBackColor;
QColor highlightTextColor;
QString enabledPicStr; QString enabledPicStr;
QString profileFolder; QString profileFolder;
QString profileName; QString profileName;
QString loadingStr; QString loadingStr;
QString language; QString language;
pcg32_random_t rng;
bool contextMenuOpened; bool contextMenuOpened;
bool isProfileLoaded; bool isProfileLoaded;
int selectedWidgts; int selectedWidgts;
int contentMode; int contentMode;
bool isSupportedImageFile(QString selectedFileName); bool isSupportedImageFile(QString selectedFileName);
bool importFile(QString selectedFile, QDateTime importDateTime, bool notMultiple); bool importFile(QString selectedFile, QDateTime importDateTime, int *currentTime, bool notMultiple);
bool importUrls(const QMimeData *mimeData); void importFilesProgress(QStringList selectedFiles);
bool importRemote(QUrl remoteUrl);
bool importImage(QImage *snapmaticImage, QDateTime importDateTime);
bool importFilesProgress(QStringList selectedFiles);
bool importSnapmaticPicture(SnapmaticPicture *picture, bool warn = true); bool importSnapmaticPicture(SnapmaticPicture *picture, bool warn = true);
bool importSavegameData(SavegameData *savegame, QString sgdPath, bool warn = true); bool importSavegameData(SavegameData *savegame, QString sgdPath, bool warn = true);
void pictureLoaded(SnapmaticPicture *picture, bool inserted); void pictureLoaded(SnapmaticPicture *picture, bool inserted);
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();
int getRandomUid();
signals: signals:
void profileLoaded(); void profileLoaded();

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,45 +1,42 @@
## 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
- Import/Export Snapmatics, Savegames and pictures - Import/Export Snapmatics, Savegames and pictures
- Choose between multiple Social Club accounts as GTA V profiles IDs - Let choose between multiple Social Club accounts as GTA V profiles IDs
#### Screenshots #### Screenshots
![Snapmatic Picture Viewer](res/src/picture.png) ![Snapmatic Picture Viewer](res/src/picture.png)
![User Interface](res/src/mainui.png) ![User Interface](res/src/mainui.png)
![Snapmatic Properties](res/src/prop.png) ![Snapmatic Properties](res/src/prop.png)
#### Build gta5view for Windows
# Note: Install Docker Community Edition and Git before continuing
docker pull sypingauto/gta5view-build:1.10-static
git clone https://gitlab.com/Syping/gta5view
docker run --rm -v "$PWD/gta5view:/gta5view" -it sypingauto/gta5view-build:1.10-static
mingw64-qt-cmake -B /gta5view/build /gta5view
cmake --build /gta5view/build
#### 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 # Note: You can use 'sudo make install' instead of 'sudo checkinstall'
git clone https://gitlab.com/Syping/gta5view sudo apt-get install git gcc g++ qtbase5-dev qttranslations5-l10n qt5-qmake make checkinstall
cmake -B gta5view-build gta5view git clone https://github.com/SyDevTeam/gta5view && cd gta5view
cmake --build gta5view-build mkdir -p build && cd build
sudo cmake --install gta5view-build qmake -qt=5 GTA5SYNC_PREFIX=/usr ../gta5view.pro # or just qmake GTA5SYNC_PREFIX=/usr ../gta5view.pro
make -j $(nproc --all)
sudo checkinstall --pkgname=gta5view --pkggroup=utility --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5,qttranslations5-l10n
#### Build gta5view for Windows
#### Build gta5view for Arch/Manjaro # Note: Install Docker Community Edition and Git before continuing
git clone https://github.com/SyDevTeam/gta5view && cd gta5view
docker pull syping/qt5-static-mingw
docker run --rm -v ${PWD}:/gta5view -it syping/qt5-static-mingw
cd /gta5view && mkdir -p build && cd build
qmake-static ../gta5view.pro
make -j $(nproc --all)
sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations #### Build gta5view for Windows (Beginner)
git clone https://gitlab.com/Syping/gta5view
cmake -B gta5view-build gta5view
cmake --build gta5view-build
sudo cmake --install gta5view-build
#### Build gta5view for Fedora/RHEL Download the [Qt Framework](https://www.qt.io/) and install the MinGW version.
Download the Source Code over [GitHub](https://github.com/SyDevTeam/gta5view/archive/1.5.x.zip) or with your Git client.
Open the gta5view.pro Project file with Qt Creator and build it over Qt Creator.
sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations #### Download Binary Releases
git clone https://gitlab.com/Syping/gta5view
cmake -B gta5view-build gta5view 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.
cmake --build gta5view-build
sudo cmake --install gta5view-build

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

@ -20,6 +20,7 @@
#include "StringParser.h" #include "StringParser.h"
#include "SavegameData.h" #include "SavegameData.h"
#include <QStringBuilder> #include <QStringBuilder>
#include <QTextCodec>
#include <QByteArray> #include <QByteArray>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>

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-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,8 +24,6 @@
#include "SavegameData.h" #include "SavegameData.h"
#include "SavegameCopy.h" #include "SavegameCopy.h"
#include "AppEnv.h" #include "AppEnv.h"
#include "config.h"
#include <QStringBuilder>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
@ -39,13 +37,6 @@
#include <QMenu> #include <QMenu>
#include <QUrl> #include <QUrl>
#ifdef GTA5SYNC_TELEMETRY
#include "TelemetryClass.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QDateTime>
#endif
SavegameWidget::SavegameWidget(QWidget *parent) : SavegameWidget::SavegameWidget(QWidget *parent) :
ProfileWidget(parent), ProfileWidget(parent),
ui(new Ui::SavegameWidget) ui(new Ui::SavegameWidget)
@ -59,8 +50,9 @@ SavegameWidget::SavegameWidget(QWidget *parent) :
qreal screenRatio = AppEnv::screenRatio(); qreal screenRatio = AppEnv::screenRatio();
ui->labSavegamePic->setFixedSize(48 * screenRatio, 27 * screenRatio); ui->labSavegamePic->setFixedSize(48 * screenRatio, 27 * screenRatio);
ui->labSavegamePic->setScaledContents(true); QPixmap savegamePixmap(":/img/savegame.png");
ui->labSavegamePic->setPixmap(QPixmap(AppEnv::getImagesFolder() % "/savegame.svgz")); if (screenRatio != 1) savegamePixmap = savegamePixmap.scaledToHeight(ui->labSavegamePic->height(), Qt::SmoothTransformation);
ui->labSavegamePic->setPixmap(savegamePixmap);
QString exportSavegameStr = tr("Export Savegame..."); QString exportSavegameStr = tr("Export Savegame...");
Q_UNUSED(exportSavegameStr) Q_UNUSED(exportSavegameStr)
@ -142,49 +134,9 @@ void SavegameWidget::on_cmdDelete_clicked()
if (!QFile::exists(sgdPath)) if (!QFile::exists(sgdPath))
{ {
emit savegameDeleted(); emit savegameDeleted();
#ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "DeleteSuccess";
jsonObject["ExtraFlags"] = "Savegame";
#if QT_VERSION >= 0x060000
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#endif
} }
else if (QFile::remove(sgdPath)) else if(QFile::remove(sgdPath))
{ {
#ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush())
{
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "DeleteSuccess";
jsonObject["ExtraFlags"] = "Savegame";
#if QT_VERSION >= 0x060000
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#endif
emit savegameDeleted(); emit savegameDeleted();
} }
else else
@ -226,8 +178,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 +189,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 +200,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,9 +21,8 @@
#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 <QStringListIterator>
#include <QStringBuilder> #include <QStringBuilder>
#include <QTextDocument> #include <QTextDocument>
#include <QInputDialog> #include <QInputDialog>
@ -31,49 +30,45 @@
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
#ifdef GTA5SYNC_TELEMETRY
#include "TelemetryClass.h"
#include <QJsonDocument>
#include <QJsonObject>
#endif
SnapmaticEditor::SnapmaticEditor(CrewDatabase *crewDB, ProfileDatabase *profileDB, QWidget *parent) : SnapmaticEditor::SnapmaticEditor(CrewDatabase *crewDB, ProfileDatabase *profileDB, QWidget *parent) :
QDialog(parent), crewDB(crewDB), profileDB(profileDB), QDialog(parent), crewDB(crewDB), profileDB(profileDB),
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->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 +89,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 +117,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 +132,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 +142,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 +152,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 +162,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 +182,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 +205,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 +222,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</a>").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</a>").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 +281,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 +297,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,44 +308,28 @@ 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->emitUpdate(); smpic->emitUpdate();
#ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) {
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "PropertyEdited";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#endif
} }
} }
close(); close();
@ -340,7 +345,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 +354,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 +370,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 +383,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,35 +396,37 @@ 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(QRegExp(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)) {
crewDB->addCrew(crewID);
}
crewID = newCrew.toInt(); crewID = newCrew.toInt();
setSnapmaticCrew(returnCrewName(crewID)); setSnapmaticCrew(returnCrewName(crewID));
} }

View File

@ -236,9 +236,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>Apply changes</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Apply</string> <string>&amp;Apply</string>
</property> </property>
@ -252,9 +249,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>Discard changes</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Cancel</string> <string>&amp;Cancel</string>
</property> </property>

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); }
@ -119,7 +120,11 @@ public:
bool setVisible() { return setPictureVisible(); } // Please use setPictureVisible instead bool setVisible() { return setPictureVisible(); } // Please use setPictureVisible instead
// PREDEFINED PROPERTIES // PREDEFINED PROPERTIES
static QSize getSnapmaticResolution(); QSize getSnapmaticResolution();
// SNAPMATIC DEFAULTS
bool isSnapmaticDefaultsEnforced();
void setSnapmaticDefaultsEnforced(bool enforced);
// SNAPMATIC FORMAT // SNAPMATIC FORMAT
SnapmaticFormat getSnapmaticFormat(); SnapmaticFormat getSnapmaticFormat();
@ -134,32 +139,43 @@ 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 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-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
@ -18,6 +18,7 @@
#include "SnapmaticWidget.h" #include "SnapmaticWidget.h"
#include "ui_SnapmaticWidget.h" #include "ui_SnapmaticWidget.h"
#include "ImageEditorDialog.h"
#include "MapLocationDialog.h" #include "MapLocationDialog.h"
#include "JsonEditorDialog.h" #include "JsonEditorDialog.h"
#include "SnapmaticPicture.h" #include "SnapmaticPicture.h"
@ -26,23 +27,16 @@
#include "PictureDialog.h" #include "PictureDialog.h"
#include "PictureExport.h" #include "PictureExport.h"
#include "StringParser.h" #include "StringParser.h"
#include "ImportDialog.h"
#include "AppEnv.h" #include "AppEnv.h"
#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>
#ifdef GTA5SYNC_TELEMETRY
#include "TelemetryClass.h"
#include <QJsonDocument>
#include <QJsonObject>
#endif
SnapmaticWidget::SnapmaticWidget(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QString profileName, QWidget *parent) : SnapmaticWidget::SnapmaticWidget(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QString profileName, QWidget *parent) :
ProfileWidget(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), profileName(profileName), ProfileWidget(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), profileName(profileName),
ui(new Ui::SnapmaticWidget) ui(new Ui::SnapmaticWidget)
@ -76,33 +70,12 @@ 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();
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);
QPixmap renderPixmap(renderResolution);
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
renderPixmap.setDevicePixelRatio(screenRatioPR);
#endif
QPixmap SnapmaticPixmap = QPixmap::fromImage(picture->getImage().scaled(ui->labPicture->width(), ui->labPicture->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::AutoColor);
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 +89,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);
} }
@ -132,7 +106,7 @@ void SnapmaticWidget::on_cmdView_clicked()
{ {
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Interface"); settings.beginGroup("Interface");
bool navigationBar = settings.value("NavigationBar", true).toBool(); bool navigationBar = settings.value("NavigationBar", false).toBool();
settings.endGroup(); settings.endGroup();
PictureDialog *picDialog = new PictureDialog(profileDB, crewDB, profileName, this); PictureDialog *picDialog = new PictureDialog(profileDB, crewDB, profileName, this);
@ -146,8 +120,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
@ -155,7 +128,7 @@ void SnapmaticWidget::on_cmdView_clicked()
picDialog->showMaximized(); picDialog->showMaximized();
#else #else
picDialog->show(); picDialog->show();
if (navigationBar) picDialog->styliseDialog(); if (navigationBar) picDialog->stylizeDialog();
//picDialog->adaptNewDialogSize(); //picDialog->adaptNewDialogSize();
picDialog->setMinimumSize(picDialog->size()); picDialog->setMinimumSize(picDialog->size());
picDialog->setMaximumSize(picDialog->size()); picDialog->setMaximumSize(picDialog->size());
@ -176,38 +149,20 @@ 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()) { {
#ifdef GTA5SYNC_TELEMETRY if (smpic->deletePicFile())
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); {
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) {
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "DeleteSuccess";
jsonObject["ExtraFlags"] = "Snapmatic";
jsonObject["DeletedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#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 +177,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 +208,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 +241,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 +275,8 @@ bool SnapmaticWidget::makePictureHidden()
bool SnapmaticWidget::makePictureVisible() bool SnapmaticWidget::makePictureVisible()
{ {
if (smpic->setPictureVisible()) { if (smpic->setPictureVisible())
{
adjustTextColor(); adjustTextColor();
return true; return true;
} }
@ -319,13 +286,17 @@ 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()
@ -349,107 +320,43 @@ void SnapmaticWidget::editSnapmaticRawJson()
void SnapmaticWidget::editSnapmaticImage() void SnapmaticWidget::editSnapmaticImage()
{ {
QImage *currentImage = new QImage(smpic->getImage()); ImageEditorDialog *imageEditor = new ImageEditorDialog(smpic, profileName, this);
ImportDialog *importDialog = new ImportDialog(profileName, this); imageEditor->setModal(true);
importDialog->setImage(currentImage); imageEditor->show();
importDialog->enableOverwriteMode(); imageEditor->exec();
importDialog->setModal(true); delete imageEditor;
importDialog->exec();
if (importDialog->isImportAgreed()) {
const QByteArray previousPicture = smpic->getPictureStream();
bool success = smpic->setImage(importDialog->image(), importDialog->isUnlimitedBuffer());
if (success) {
QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName)) {
QFile::copy(currentFilePath, backupFileName);
}
if (!smpic->exportPicture(currentFilePath)) {
smpic->setPictureStream(previousPicture);
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of I/O Error"));
return;
}
smpic->emitCustomSignal("PictureUpdated");
#ifdef GTA5SYNC_TELEMETRY
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) {
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "ImageEdited";
jsonObject["ExtraFlags"] = "Interface";
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
#endif
}
else {
QMessageBox::warning(this, QApplication::translate("ImageEditorDialog", "Snapmatic Image Editor"), QApplication::translate("ImageEditorDialog", "Patching of Snapmatic Image failed because of Image Error"));
return;
}
}
delete importDialog;
} }
void SnapmaticWidget::openMapViewer() 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
else {
QSettings telemetrySettings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
telemetrySettings.beginGroup("Telemetry");
bool pushUsageData = telemetrySettings.value("PushUsageData", false).toBool();
telemetrySettings.endGroup();
if (pushUsageData && Telemetry->canPush()) {
QJsonDocument jsonDocument;
QJsonObject jsonObject;
jsonObject["Type"] = "LocationEdited";
jsonObject["ExtraFlags"] = "Interface";
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
#if QT_VERSION >= 0x060000
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
#else
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#endif
jsonDocument.setObject(jsonObject);
Telemetry->push(TelemetryCategory::PersonalData, jsonDocument);
}
}
#endif
} }
delete mapLocDialog; delete mapLocDialog;
} }

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,16 +17,25 @@
*****************************************************************************/ *****************************************************************************/
#include "StringParser.h" #include "StringParser.h"
#include "config.h"
#include <QTextDocument> #include <QTextDocument>
#include <QApplication>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QTextCodec>
#include <QByteArray> #include <QByteArray>
#include <QFileInfo> #include <QFileInfo>
#include <QString> #include <QString>
#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,19 +45,17 @@ 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;
outputStr.replace("APPNAME:", QString::fromUtf8(GTA5SYNC_APPSTR)); QByteArray sharePath = GTA5SYNC_SHARE;
outputStr.replace("SHAREDDIR:", QString::fromUtf8(GTA5SYNC_SHARE)); outputStr.replace("APPNAME:", GTA5SYNC_APPSTR);
outputStr.replace("RUNDIR:", QFileInfo(QApplication::applicationFilePath()).canonicalPath()); outputStr.replace("SHAREDDIR:", QString::fromUtf8(sharePath));
#if QT_VERSION >= 0x060000 outputStr.replace("RUNDIR:", QFileInfo(qApp->applicationFilePath()).absoluteDir().absolutePath());
outputStr.replace("QCONFLANG:", QLibraryInfo::path(QLibraryInfo::TranslationsPath));
outputStr.replace("QCONFPLUG:", QLibraryInfo::path(QLibraryInfo::PluginsPath));
#else
outputStr.replace("QCONFLANG:", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); outputStr.replace("QCONFLANG:", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
outputStr.replace("QCONFPLUG:", QLibraryInfo::location(QLibraryInfo::PluginsPath)); outputStr.replace("QCONFPLUG:", QLibraryInfo::location(QLibraryInfo::PluginsPath));
#endif
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

@ -41,10 +41,9 @@
#define GTA5SYNC_TELEMETRY_WEBURL "" #define GTA5SYNC_TELEMETRY_WEBURL ""
#endif #endif
#ifdef Q_OS_WIN #ifdef GTA5SYNC_WIN
#include "windows.h" #include "windows.h"
#include "intrin.h" #include "intrin.h"
#include "d3d9.h"
#endif #endif
TelemetryClass TelemetryClass::telemetryClassInstance; TelemetryClass TelemetryClass::telemetryClassInstance;
@ -169,8 +168,6 @@ void TelemetryClass::push(TelemetryCategory category)
break; break;
case TelemetryCategory::UserFeedback: case TelemetryCategory::UserFeedback:
break; break;
case TelemetryCategory::PersonalData:
break;
case TelemetryCategory::CustomEmitted: case TelemetryCategory::CustomEmitted:
break; break;
} }
@ -201,7 +198,6 @@ void TelemetryClass::push(TelemetryCategory category, QJsonDocument json)
QNetworkAccessManager *netManager = new QNetworkAccessManager(); QNetworkAccessManager *netManager = new QNetworkAccessManager();
QNetworkRequest netRequest(TelemetryClassAuthenticator::getTrackingPushURL()); QNetworkRequest netRequest(TelemetryClassAuthenticator::getTrackingPushURL());
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
QNetworkReply *netReply = netManager->post(netRequest, httpMultiPart); QNetworkReply *netReply = netManager->post(netRequest, httpMultiPart);
httpMultiPart->setParent(netReply); httpMultiPart->setParent(netReply);
@ -213,10 +209,6 @@ QJsonDocument TelemetryClass::getOperatingSystem()
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
#if QT_VERSION >= 0x050400 #if QT_VERSION >= 0x050400
jsonObject["KernelType"] = QSysInfo::kernelType();
jsonObject["KernelVersion"] = QSysInfo::kernelVersion();
jsonObject["ProductType"] = QSysInfo::productType();
jsonObject["ProductVersion"] = QSysInfo::productVersion();
jsonObject["OSName"] = QSysInfo::prettyProductName(); jsonObject["OSName"] = QSysInfo::prettyProductName();
jsonObject["OSArch"] = QSysInfo::currentCpuArchitecture(); jsonObject["OSArch"] = QSysInfo::currentCpuArchitecture();
#endif #endif
@ -228,21 +220,21 @@ QJsonDocument TelemetryClass::getSystemHardware()
{ {
QJsonDocument jsonDocument; QJsonDocument jsonDocument;
QJsonObject jsonObject; QJsonObject jsonObject;
#ifdef Q_OS_WIN #ifdef GTA5SYNC_WIN
{ {
int CPUInfo[4] = {-1}; int CPUInfo[4] = {-1};
unsigned nExIds, ic = 0; unsigned nExIds, i = 0;
char CPUBrandString[0x40]; char CPUBrandString[0x40];
__cpuid(CPUInfo, 0x80000000); __cpuid(CPUInfo, 0x80000000);
nExIds = CPUInfo[0]; nExIds = CPUInfo[0];
for (ic = 0x80000000; ic <= nExIds; ic++) for (i = 0x80000000; i <= nExIds; ++i)
{ {
__cpuid(CPUInfo, ic); __cpuid(CPUInfo, i);
if (ic == 0x80000002) { memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo)); } if (i == 0x80000002) { memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo)); }
else if (ic == 0x80000003) { memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo)); } else if (i == 0x80000003) { memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo)); }
else if (ic == 0x80000004) { memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); } else if (i == 0x80000004) { memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); }
} }
jsonObject["CPUName"] = QString::fromLatin1(CPUBrandString).simplified(); jsonObject["CPUName"] = QString(CPUBrandString).trimmed();
SYSTEM_INFO sysInfo; SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo); GetSystemInfo(&sysInfo);
jsonObject["CPUThreads"] = QString::number(sysInfo.dwNumberOfProcessors); jsonObject["CPUThreads"] = QString::number(sysInfo.dwNumberOfProcessors);
@ -250,21 +242,6 @@ QJsonDocument TelemetryClass::getSystemHardware()
statex.dwLength = sizeof(statex); statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex); GlobalMemoryStatusEx(&statex);
jsonObject["SystemRAM"] = QString(QString::number((statex.ullTotalPhys / 1024) / 1024) % "MB"); jsonObject["SystemRAM"] = QString(QString::number((statex.ullTotalPhys / 1024) / 1024) % "MB");
QStringList gpusList;
IDirect3D9 *pD3D = Direct3DCreate9(D3D_SDK_VERSION);
int adapters = pD3D->GetAdapterCount();
for (int ia = 0; ia < adapters; ia++)
{
D3DADAPTER_IDENTIFIER9 d3dIdent;
HRESULT result = pD3D->GetAdapterIdentifier(ia, 0, &d3dIdent);
if (result == D3D_OK)
{
QString gpuAdapter = QString::fromLatin1(d3dIdent.Description);
if (!gpusList.contains(gpuAdapter)) { gpusList << gpuAdapter; }
}
}
pD3D->Release();
jsonObject["GPUs"] = QJsonValue::fromVariant(gpusList);
} }
#else #else
QDir procDir("/proc"); QDir procDir("/proc");
@ -283,7 +260,7 @@ QJsonDocument TelemetryClass::getSystemHardware()
QByteArray cpuData = cpuInfoBuffer.readLine(); QByteArray cpuData = cpuInfoBuffer.readLine();
if (cpuData.left(toFind.length()) == toFind) if (cpuData.left(toFind.length()) == toFind)
{ {
jsonObject["CPUName"] = QString::fromUtf8(cpuData).split(':').at(1).simplified(); jsonObject["CPUName"] = QString::fromUtf8(cpuData).split(':').at(1).trimmed();
break; break;
} }
} }
@ -338,9 +315,6 @@ QJsonDocument TelemetryClass::getApplicationSpec()
jsonObject["Arch"] = QSysInfo::buildCpuArchitecture(); jsonObject["Arch"] = QSysInfo::buildCpuArchitecture();
#endif #endif
jsonObject["Name"] = GTA5SYNC_APPSTR; jsonObject["Name"] = GTA5SYNC_APPSTR;
#ifdef GTA5SYNC_COMMIT
jsonObject["Commit"] = GTA5SYNC_COMMIT;
#endif
jsonObject["Version"] = GTA5SYNC_APPVER; jsonObject["Version"] = GTA5SYNC_APPVER;
jsonObject["BuildDateTime"] = AppEnv::getBuildDateTime(); jsonObject["BuildDateTime"] = AppEnv::getBuildDateTime();
jsonObject["BuildType"] = GTA5SYNC_BUILDTYPE; jsonObject["BuildType"] = GTA5SYNC_BUILDTYPE;
@ -395,7 +369,6 @@ QJsonDocument TelemetryClass::getApplicationConf()
QJsonObject startupObject; QJsonObject startupObject;
startupObject["AppStyle"] = settings.value("AppStyle", "System").toString(); startupObject["AppStyle"] = settings.value("AppStyle", "System").toString();
startupObject["CustomStyle"] = settings.value("CustomStyle", false).toBool(); startupObject["CustomStyle"] = settings.value("CustomStyle", false).toBool();
startupObject["StartCount"] = QString::number(settings.value("StartCount", 0).toUInt());
jsonObject["Startup"] = startupObject; jsonObject["Startup"] = startupObject;
settings.endGroup(); settings.endGroup();
@ -437,14 +410,11 @@ QString TelemetryClass::categoryToString(TelemetryCategory category)
case TelemetryCategory::ApplicationConf: case TelemetryCategory::ApplicationConf:
return QString("ApplicationConf"); return QString("ApplicationConf");
break; break;
case TelemetryCategory::ApplicationSpec:
return QString("ApplicationSpec");
break;
case TelemetryCategory::UserFeedback: case TelemetryCategory::UserFeedback:
return QString("UserFeedback"); return QString("UserFeedback");
break; break;
case TelemetryCategory::PersonalData: case TelemetryCategory::ApplicationSpec:
return QString("PersonalData"); return QString("ApplicationSpec");
break; break;
case TelemetryCategory::CustomEmitted: case TelemetryCategory::CustomEmitted:
return QString("CustomEmitted"); return QString("CustomEmitted");
@ -464,7 +434,6 @@ void TelemetryClass::registerClient()
{ {
QNetworkAccessManager *netManager = new QNetworkAccessManager(); QNetworkAccessManager *netManager = new QNetworkAccessManager();
QNetworkRequest netRequest(TelemetryClassAuthenticator::getTrackingRegURL()); QNetworkRequest netRequest(TelemetryClassAuthenticator::getTrackingRegURL());
netRequest.setRawHeader("User-Agent", AppEnv::getUserAgent());
netManager->get(netRequest); netManager->get(netRequest);
connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(registerFinished(QNetworkReply*))); connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(registerFinished(QNetworkReply*)));
@ -495,10 +464,6 @@ void TelemetryClass::work_p(bool doWork)
{ {
push(TelemetryCategory::ApplicationConf); push(TelemetryCategory::ApplicationConf);
} }
else
{
push(TelemetryCategory::ApplicationConf, QJsonDocument());
}
} }
} }

View File

@ -25,7 +25,7 @@
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
enum class TelemetryCategory : int { OperatingSystemSpec = 0, HardwareSpec = 1, UserLocaleData = 2, ApplicationConf = 3, UserFeedback = 4, ApplicationSpec = 5, PersonalData = 6, CustomEmitted = 99 }; enum class TelemetryCategory : int { OperatingSystemSpec = 0, HardwareSpec = 1, UserLocaleData = 2, ApplicationConf = 3, UserFeedback = 4, ApplicationSpec = 5, CustomEmitted = 99};
class TelemetryClass : public QObject class TelemetryClass : public QObject
{ {

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,27 +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
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif
isLangLoaded = true; isLangLoaded = true;
return; return;
} }
@ -78,28 +73,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 +107,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,31 +126,33 @@ 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
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif
isLangLoaded = true; isLangLoaded = true;
} }
} }
if (externalLanguageReady) { if (externalLanguageReady)
{
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "loadInSystemLanguage"; qDebug() << "loadInSystemLanguage";
#endif #endif
@ -158,114 +162,113 @@ 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
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#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
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif
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
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#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
QLocale::setDefault(QLocale(currentLanguage));
#else
QLocale::setDefault(currentLanguage); QLocale::setDefault(currentLanguage);
#endif
isLangLoaded = true; isLangLoaded = true;
} }
} }
#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 +280,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 +293,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 +306,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 +333,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 +345,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 +356,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 +367,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 +399,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 +420,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 +432,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 +457,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 +477,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 +488,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,61 +515,40 @@ 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) {
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageModeInterface"; qDebug() << "autoAreaLanguageMode";
#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("_")) {
langCode = langCode.split("_").at(0);
if (!areaTranslations.contains(langCode))
goto outputDefaultLanguage;
#ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode;
#endif
return langCode;
}
} }
else { else if (langCode.contains("_"))
{
langCode = langCode.split("_").at(0);
if (!areaTranslations.contains(langCode)) goto outputDefaultLanguage;
#ifdef GTA5SYNC_DEBUG #ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageModeGame"; qDebug() << "autoAreaLanguageSelected" << langCode;
#endif #endif
QString langCode = AppEnv::gameLanguageToString(gameLanguage).replace("-", "_"); return langCode;
if (areaTranslations.contains(langCode)) {
#ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode;
#endif
return langCode;
}
else if (langCode.contains("_")) {
langCode = langCode.split("_").at(0);
if (!areaTranslations.contains(langCode))
goto outputDefaultLanguage;
#ifdef GTA5SYNC_DEBUG
qDebug() << "autoAreaLanguageSelected" << langCode;
#endif
return langCode;
}
} }
} }
else if (areaTranslations.contains(userAreaLanguage)) { 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 +573,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 +597,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();
return localeStrList.at(1).toLower(); QStringList localeStrList = locales.at(0).name().split("_");
} if (localeStrList.length() >= 2)
{
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();
} }
return QString(); else
{
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-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
@ -40,31 +40,14 @@
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
#include <QFileInfo> #include <QFileInfo>
#include <QTimer>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
#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
UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, MessageThread *threadMessage, QWidget *parent) :
QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), threadMessage(threadMessage),
ui(new Ui::UserInterface)
#else
UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent) : UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent) :
QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB), QMainWindow(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB),
ui(new Ui::UserInterface) ui(new Ui::UserInterface)
#endif
{ {
ui->setupUi(this); ui->setupUi(this);
contentMode = 0; contentMode = 0;
@ -73,244 +56,107 @@ 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(); ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER));
const char* literalBuildType = GTA5SYNC_BUILDTYPE;
#ifdef GTA5SYNC_COMMIT
if ((strcmp(literalBuildType, REL_BUILDTYPE) != 0) && !appVersion.contains("-"))
appVersion = appVersion % "-" % GTA5SYNC_COMMIT;
#endif
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
@ -320,26 +166,30 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D
ui->vlUserInterface->setContentsMargins(9 * screenRatio, 9 * screenRatio, 9 * screenRatio, 9 * screenRatio); ui->vlUserInterface->setContentsMargins(9 * screenRatio, 9 * screenRatio, 9 * screenRatio, 9 * screenRatio);
} }
void UserInterface::setupDirEnv(bool showFolderDialog) void UserInterface::setupDirEnv()
{ {
// settings init // settings init
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR); QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
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
{
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();
@ -350,15 +200,15 @@ void UserInterface::setupDirEnv(bool showFolderDialog)
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 +216,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 +236,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 +247,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 +268,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 +295,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()
@ -465,18 +322,17 @@ void UserInterface::closeProfile_p()
void UserInterface::closeEvent(QCloseEvent *ev) void UserInterface::closeEvent(QCloseEvent *ev)
{ {
Q_UNUSED(ev) Q_UNUSED(ev)
#ifdef GTA5SYNC_MOTD
threadMessage->terminateThread();
#else
threadDB->terminateThread(); threadDB->terminateThread();
#endif
} }
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 +341,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,25 +379,33 @@ 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,7 +430,9 @@ 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 +446,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 +463,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 +481,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 +553,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,139 +586,24 @@ 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);
} }
} }
#ifdef GTA5SYNC_MOTD
void UserInterface::messagesArrived(const QJsonObject &object)
{
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Messages");
QJsonObject::const_iterator it = object.constBegin();
QJsonObject::const_iterator end = object.constEnd();
QStringList messages;
while (it != end) {
const QString key = it.key();
const QJsonValue value = it.value();
bool uintOk;
uint messageId = key.toUInt(&uintOk);
if (uintOk && value.isString()) {
const QString valueStr = value.toString();
settings.setValue(QString::number(messageId), valueStr);
messages << valueStr;
}
it++;
}
settings.endGroup();
if (!messages.isEmpty())
showMessages(messages);
}
void UserInterface::showMessages(const QStringList messages)
{
QDialog *messageDialog = new QDialog(this);
messageDialog->setWindowTitle(tr("%1 - Messages").arg(GTA5SYNC_APPSTR));
#if QT_VERSION >= 0x050900
messageDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
messageDialog->setWindowFlags(messageDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
QVBoxLayout *messageLayout = new QVBoxLayout;
messageDialog->setLayout(messageLayout);
QStackedWidget *stackWidget = new QStackedWidget(messageDialog);
for (const QString message : messages) {
QLabel *messageLabel = new QLabel(messageDialog);
messageLabel->setText(message);
messageLabel->setWordWrap(true);
stackWidget->addWidget(messageLabel);
}
messageLayout->addWidget(stackWidget);
QHBoxLayout *buttonLayout = new QHBoxLayout;
QPushButton *backButton = new QPushButton(messageDialog);
QPushButton *nextButton = new QPushButton(messageDialog);
if (QIcon::hasThemeIcon("go-previous") && QIcon::hasThemeIcon("go-next") && QIcon::hasThemeIcon("list-add")) {
backButton->setIcon(QIcon::fromTheme("go-previous"));
nextButton->setIcon(QIcon::fromTheme("go-next"));
}
else {
backButton->setIcon(QIcon(AppEnv::getImagesFolder() % "/back.svgz"));
nextButton->setIcon(QIcon(AppEnv::getImagesFolder() % "/next.svgz"));
}
backButton->setEnabled(false);
if (stackWidget->count() <= 1) {
nextButton->setEnabled(false);
}
buttonLayout->addWidget(backButton);
buttonLayout->addWidget(nextButton);
buttonLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
QPushButton *closeButton = new QPushButton(messageDialog);
closeButton->setText(tr("&Close"));
if (QIcon::hasThemeIcon("dialog-close")) {
closeButton->setIcon(QIcon::fromTheme("dialog-close"));
}
else if (QIcon::hasThemeIcon("gtk-close")) {
closeButton->setIcon(QIcon::fromTheme("gtk-close"));
}
buttonLayout->addWidget(closeButton);
messageLayout->addLayout(buttonLayout);
QObject::connect(backButton, &QPushButton::clicked, [stackWidget,backButton,nextButton,closeButton]() {
int index = stackWidget->currentIndex();
if (index > 0) {
index--;
stackWidget->setCurrentIndex(index);
nextButton->setEnabled(true);
if (index > 0) {
backButton->setEnabled(true);
}
else {
backButton->setEnabled(false);
closeButton->setFocus();
}
}
});
QObject::connect(nextButton, &QPushButton::clicked, [stackWidget,backButton,nextButton,closeButton]() {
int index = stackWidget->currentIndex();
if (index < stackWidget->count()-1) {
index++;
stackWidget->setCurrentIndex(index);
backButton->setEnabled(true);
if (index < stackWidget->count()-1) {
nextButton->setEnabled(true);
}
else {
nextButton->setEnabled(false);
closeButton->setFocus();
}
}
});
QObject::connect(closeButton, &QPushButton::clicked, messageDialog, &QDialog::accept);
QObject::connect(messageDialog, &QDialog::finished, messageDialog, &QDialog::deleteLater);
QTimer::singleShot(0, closeButton, [=](){
closeButton->setFocus();
});
messageDialog->show();
}
void UserInterface::updateCacheId(uint cacheId)
{
QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
settings.beginGroup("Messages");
settings.setValue("CacheId", cacheId);
settings.endGroup();
}
#endif
void UserInterface::on_actionSelect_GTA_Folder_triggered() 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 +616,31 @@ 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 ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, GTA5SYNC_APPVER));
QString appVersion = QApplication::applicationVersion(); if (profileOpen)
const char* literalBuildType = GTA5SYNC_BUILDTYPE; {
#ifdef GTA5SYNC_COMMIT this->setWindowTitle(defaultWindowTitle.arg(profileName));
if ((strcmp(literalBuildType, REL_BUILDTYPE) != 0) && !appVersion.contains("-"))
appVersion = appVersion % "-" % GTA5SYNC_COMMIT;
#endif
ui->labVersion->setText(QString("%1 %2").arg(GTA5SYNC_APPSTR, appVersion));
if (profileOpen) {
setWindowTitle(defaultWindowTitle.arg(profileName));
} }
else { else
setWindowTitle(defaultWindowTitle.arg(tr("Select Profile"))); {
this->setWindowTitle(defaultWindowTitle.arg(tr("Select Profile")));
} }
} }

View File

@ -31,10 +31,6 @@
#include <QString> #include <QString>
#include <QMap> #include <QMap>
#ifdef GTA5SYNC_MOTD
#include "MessageThread.h"
#endif
namespace Ui { namespace Ui {
class UserInterface; class UserInterface;
} }
@ -43,12 +39,8 @@ class UserInterface : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
#ifdef GTA5SYNC_MOTD
explicit UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, MessageThread *messageThread, QWidget *parent = 0);
#else
explicit UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent = 0); explicit UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent = 0);
#endif void setupDirEnv();
void setupDirEnv(bool showFolderDialog = true);
~UserInterface(); ~UserInterface();
private slots: private slots:
@ -75,11 +67,6 @@ private slots:
void on_actionSet_Crew_triggered(); void on_actionSet_Crew_triggered();
void on_actionSet_Title_triggered(); void on_actionSet_Title_triggered();
void settingsApplied(int contentMode, bool languageChanged); void settingsApplied(int contentMode, bool languageChanged);
#ifdef GTA5SYNC_MOTD
void messagesArrived(const QJsonObject &object);
void showMessages(const QStringList messages);
void updateCacheId(uint cacheId);
#endif
protected: protected:
void closeEvent(QCloseEvent *ev); void closeEvent(QCloseEvent *ev);
@ -88,14 +75,6 @@ private:
ProfileDatabase *profileDB; ProfileDatabase *profileDB;
CrewDatabase *crewDB; CrewDatabase *crewDB;
DatabaseThread *threadDB; DatabaseThread *threadDB;
#ifdef GTA5SYNC_MOTD
MessageThread *threadMessage;
#endif
#ifdef GTA5SYNC_DONATE
#ifdef GTA5SYNC_DONATE_ADDRESSES
QAction *donateAction;
#endif
#endif
Ui::UserInterface *ui; Ui::UserInterface *ui;
ProfileInterface *profileUI; ProfileInterface *profileUI;
QList<QPushButton*> profileBtns; QList<QPushButton*> profileBtns;

View File

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2020 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
@ -17,6 +17,7 @@
*****************************************************************************/ *****************************************************************************/
#include "JSHighlighter.h" #include "JSHighlighter.h"
#include <QRegExp>
JSHighlighter::JSHighlighter(QTextDocument *parent) : JSHighlighter::JSHighlighter(QTextDocument *parent) :
QSyntaxHighlighter(parent) QSyntaxHighlighter(parent)
@ -30,61 +31,34 @@ JSHighlighter::JSHighlighter(QTextDocument *parent) :
keywordPatterns << "\\btrue\\b" << "\\bfalse\\b"; keywordPatterns << "\\btrue\\b" << "\\bfalse\\b";
for (QString pattern : keywordPatterns) for (QString pattern : keywordPatterns)
{ {
#if QT_VERSION >= 0x050000
rule.pattern = QRegularExpression(pattern);
#else
rule.pattern = QRegExp(pattern); rule.pattern = QRegExp(pattern);
#endif
rule.format = keywordFormat; rule.format = keywordFormat;
highlightingRules.append(rule); highlightingRules.append(rule);
} }
QBrush doubleBrush(QColor::fromRgb(66, 137, 244)); QBrush doubleBrush(QColor::fromRgb(66, 137, 244));
doubleFormat.setForeground(doubleBrush); doubleFormat.setForeground(doubleBrush);
#if QT_VERSION >= 0x050000
rule.pattern = QRegularExpression("[+-]?\\d*\\.?\\d+");
#else
rule.pattern = QRegExp("[+-]?\\d*\\.?\\d+"); rule.pattern = QRegExp("[+-]?\\d*\\.?\\d+");
#endif
rule.format = doubleFormat; rule.format = doubleFormat;
highlightingRules.append(rule); highlightingRules.append(rule);
QBrush quotationBrush(QColor::fromRgb(66, 244, 104)); QBrush quotationBrush(QColor::fromRgb(66, 244, 104));
quotationFormat.setForeground(quotationBrush); quotationFormat.setForeground(quotationBrush);
#if QT_VERSION >= 0x050000
rule.pattern = QRegularExpression("\"[^\"]*\"");
#else
rule.pattern = QRegExp("\"[^\"]*\""); rule.pattern = QRegExp("\"[^\"]*\"");
#endif
rule.format = quotationFormat; rule.format = quotationFormat;
highlightingRules.append(rule); highlightingRules.append(rule);
QBrush objectBrush(QColor::fromRgb(255, 80, 80)); QBrush objectBrush(QColor::fromRgb(255, 80, 80));
objectFormat.setForeground(objectBrush); objectFormat.setForeground(objectBrush);
#if QT_VERSION >= 0x050000
rule.pattern = QRegularExpression("\"[^\"]*\"(?=:)");
#else
rule.pattern = QRegExp("\"[^\"]*\"(?=:)"); rule.pattern = QRegExp("\"[^\"]*\"(?=:)");
#endif
rule.format = objectFormat; rule.format = objectFormat;
highlightingRules.append(rule); highlightingRules.append(rule);
} }
void JSHighlighter::highlightBlock(const QString &text) void JSHighlighter::highlightBlock(const QString &text)
{ {
#if QT_VERSION >= 0x050000 for (HighlightingRule rule : highlightingRules)
for (const HighlightingRule &rule : qAsConst(highlightingRules))
#else
for (const HighlightingRule &rule : highlightingRules)
#endif
{ {
#if QT_VERSION >= 0x050000
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
#else
QRegExp expression(rule.pattern); QRegExp expression(rule.pattern);
int index = expression.indexIn(text); int index = expression.indexIn(text);
while (index >= 0) while (index >= 0)
@ -93,7 +67,6 @@ void JSHighlighter::highlightBlock(const QString &text)
setFormat(index, length, rule.format); setFormat(index, length, rule.format);
index = expression.indexIn(text, index + length); index = expression.indexIn(text, index + length);
} }
#endif
} }
setCurrentBlockState(0); setCurrentBlockState(0);
} }

View File

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* gta5view Grand Theft Auto V Profile Viewer * gta5view Grand Theft Auto V Profile Viewer
* Copyright (C) 2017-2020 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
@ -24,15 +24,10 @@
#include <QTextDocument> #include <QTextDocument>
#include <QTextFormat> #include <QTextFormat>
#include <QStringList> #include <QStringList>
#include <QRegExp>
#include <QVector> #include <QVector>
#include <QHash> #include <QHash>
#if QT_VERSION >= 0x050000
#include <QRegularExpression>
#else
#include <QRegExp>
#endif
class QTextDocument; class QTextDocument;
class JSHighlighter : public QSyntaxHighlighter class JSHighlighter : public QSyntaxHighlighter
@ -42,11 +37,7 @@ class JSHighlighter : public QSyntaxHighlighter
public: public:
struct HighlightingRule struct HighlightingRule
{ {
#if QT_VERSION >= 0x050000
QRegularExpression pattern;
#else
QRegExp pattern; QRegExp pattern;
#endif
QTextCharFormat format; QTextCharFormat format;
}; };
QVector<HighlightingRule> highlightingRules; QVector<HighlightingRule> highlightingRules;

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