From 050a281be83f562a3b3e1039c1501fbb6efaaf9e Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 27 Jan 2023 20:09:43 +0100 Subject: [PATCH] replace internal RagePhoto with libragephoto, few other changes - remove more Qt4 compatibility stuff - replaced internal RagePhoto with libragephoto 0.2 - some minor UI changes - year 2023 updates --- .gitmodules | 4 + CMakeLists.txt | 9 +- README.md | 8 +- src/AboutDialog.cpp | 6 +- src/AppEnv.cpp | 10 +- src/ImportDialog.cpp | 6 +- src/JsonEditorDialog.cpp | 8 +- src/MapLocationDialog.cpp | 6 +- src/OptionsDialog.cpp | 4 - src/PictureDialog.cpp | 34 +- src/PlayerListDialog.cpp | 7 +- src/ProfileInterface.cpp | 43 +- src/RagePhoto.cpp | 865 -------------------------------------- src/RagePhoto.h | 110 ----- src/SavegameData.cpp | 3 +- src/SavegameDialog.cpp | 6 +- src/SnapmaticEditor.cpp | 2 +- src/SnapmaticPicture.cpp | 590 ++++++++++++++++++-------- src/SnapmaticPicture.h | 21 +- src/SnapmaticWidget.cpp | 6 +- src/UserInterface.cpp | 18 +- src/libragephoto | 1 + src/main.cpp | 7 +- 23 files changed, 472 insertions(+), 1302 deletions(-) create mode 100644 .gitmodules delete mode 100644 src/RagePhoto.cpp delete mode 100644 src/RagePhoto.h create mode 160000 src/libragephoto diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5517ee2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "src/libragephoto"] +path = src/libragephoto +url = https://github.com/Syping/libragephoto.git +branch = 0.2.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 73d6c73..3057f85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,9 @@ endif() find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network Svg Widgets REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools QUIET) +set(RAGEPHOTO_STATIC ON CACHE BOOL "Build libragephoto as static library") +add_subdirectory(src/libragephoto) + if(WIN32) list(APPEND GTA5VIEW_LIBS dwmapi @@ -71,7 +74,6 @@ set(GTA5VIEW_SOURCES src/ProfileInterface.cpp src/ProfileLoader.cpp src/ProfileWidget.cpp - src/RagePhoto.cpp src/SavegameCopy.cpp src/SavegameData.cpp src/SavegameDialog.cpp @@ -114,7 +116,6 @@ set(GTA5VIEW_HEADERS src/ProfileInterface.h src/ProfileLoader.h src/ProfileWidget.h - src/RagePhoto.h src/SavegameCopy.h src/SavegameData.h src/SavegameDialog.h @@ -360,8 +361,8 @@ if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.14.0") 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}) +target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR} ${RAGEPHOTO_INCLUDE_DIRS}) +target_link_libraries(gta5view PRIVATE Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Widgets ragephoto ${GTA5VIEW_LIBS}) install(TARGETS gta5view DESTINATION bin) install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications) diff --git a/README.md b/README.md index 8831699..e5372a3 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V # Note: Install Docker Community Edition and Git before continuing docker pull sypingauto/gta5view-build:1.10-static - git clone https://gitlab.com/Syping/gta5view + git clone --recurse-submodules 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 @@ -23,7 +23,7 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V #### Build gta5view for Debian/Ubuntu sudo apt-get install cmake git gcc g++ libqt5svg5-dev make qtbase5-dev qttranslations5-l10n - git clone https://gitlab.com/Syping/gta5view + git clone --recurse-submodules https://gitlab.com/Syping/gta5view cmake -B gta5view-build gta5view cmake --build gta5view-build sudo cmake --install gta5view-build @@ -31,7 +31,7 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V #### Build gta5view for Arch/Manjaro sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations - git clone https://gitlab.com/Syping/gta5view + git clone --recurse-submodules https://gitlab.com/Syping/gta5view cmake -B gta5view-build gta5view cmake --build gta5view-build sudo cmake --install gta5view-build @@ -39,7 +39,7 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V #### Build gta5view for Fedora/RHEL sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations - git clone https://gitlab.com/Syping/gta5view + git clone --recurse-submodules https://gitlab.com/Syping/gta5view cmake -B gta5view-build gta5view cmake --build gta5view-build sudo cmake --install gta5view-build diff --git a/src/AboutDialog.cpp b/src/AboutDialog.cpp index 12852cf..192e4e7 100644 --- a/src/AboutDialog.cpp +++ b/src/AboutDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2021 Syping +* Copyright (C) 2016-2023 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 @@ -29,11 +29,7 @@ AboutDialog::AboutDialog(QWidget *parent) : ui(new Ui::AboutDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); -#endif // Build Strings QString appVersion = QApplication::applicationVersion(); diff --git a/src/AppEnv.cpp b/src/AppEnv.cpp index 9d112a5..38bb630 100644 --- a/src/AppEnv.cpp +++ b/src/AppEnv.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2021 Syping +* Copyright (C) 2016-2023 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 @@ -435,11 +435,7 @@ bool AppEnv::setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage) qreal AppEnv::screenRatio() { -#if QT_VERSION >= 0x050000 qreal dpi = QApplication::primaryScreen()->logicalDotsPerInch(); -#else - qreal dpi = QApplication::desktop()->logicalDpiX(); -#endif #ifdef Q_OS_MAC return (dpi / 72); #else @@ -449,9 +445,5 @@ qreal AppEnv::screenRatio() qreal AppEnv::screenRatioPR() { -#if QT_VERSION >= 0x050600 return QApplication::primaryScreen()->devicePixelRatio(); -#else - return 1; -#endif } diff --git a/src/ImportDialog.cpp b/src/ImportDialog.cpp index 594cbf8..68c3ab0 100644 --- a/src/ImportDialog.cpp +++ b/src/ImportDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2017-2022 Syping +* Copyright (C) 2017-2023 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 @@ -49,11 +49,7 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) : ui(new Ui::ImportDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); -#endif ui->setupUi(this); ui->cmdOK->setDefault(true); diff --git a/src/JsonEditorDialog.cpp b/src/JsonEditorDialog.cpp index ae13966..2153216 100644 --- a/src/JsonEditorDialog.cpp +++ b/src/JsonEditorDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2017-2021 Syping +* Copyright (C) 2017-2023 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 @@ -39,12 +39,8 @@ JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) : ui(new Ui::JsonEditorDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); setWindowFlag(Qt::WindowMinMaxButtonsHint, true); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowMinMaxButtonsHint); -#endif ui->setupUi(this); ui->cmdClose->setDefault(true); @@ -194,7 +190,7 @@ bool JsonEditorDialog::saveJsonContent() QJsonDocument jsonDocument; QJsonObject jsonObject; jsonObject["Type"] = "JSONEdited"; - jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); + jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else diff --git a/src/MapLocationDialog.cpp b/src/MapLocationDialog.cpp index b233a28..b161999 100644 --- a/src/MapLocationDialog.cpp +++ b/src/MapLocationDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2017-2021 Syping +* Copyright (C) 2017-2023 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 @@ -29,11 +29,7 @@ MapLocationDialog::MapLocationDialog(double x, double y, QWidget *parent) : ui(new Ui::MapLocationDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); -#endif ui->setupUi(this); ui->cmdDone->setVisible(false); diff --git a/src/OptionsDialog.cpp b/src/OptionsDialog.cpp index d096383..eddf145 100644 --- a/src/OptionsDialog.cpp +++ b/src/OptionsDialog.cpp @@ -56,11 +56,7 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) : ui(new Ui::OptionsDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); -#endif // Setup User Interface ui->setupUi(this); diff --git a/src/PictureDialog.cpp b/src/PictureDialog.cpp index 99850f8..2d4ca6a 100644 --- a/src/PictureDialog.cpp +++ b/src/PictureDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2021 Syping +* Copyright (C) 2016-2023 Syping * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,11 +20,9 @@ #include "PictureWidget.h" #include "ProfileDatabase.h" #include "ui_PictureDialog.h" -#include "SidebarGenerator.h" #include "MapLocationDialog.h" #include "JsonEditorDialog.h" #include "SnapmaticEditor.h" -#include "StandardPaths.h" #include "PictureExport.h" #include "ImportDialog.h" #include "StringParser.h" @@ -127,21 +125,8 @@ PictureDialog::PictureDialog(bool primaryWindow, ProfileDatabase *profileDB, Cre void PictureDialog::setupPictureDialog() { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); setWindowFlag(Qt::CustomizeWindowHint, true); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::CustomizeWindowHint); -#endif -#ifdef Q_OS_LINUX - // for stupid Window Manager like GNOME -#if QT_VERSION >= 0x050900 - setWindowFlag(Qt::Dialog, false); - setWindowFlag(Qt::Window, true); -#else - setWindowFlags(windowFlags()^Qt::Dialog^Qt::Window); -#endif -#endif // Setup User Interface ui->setupUi(this); @@ -234,13 +219,6 @@ void PictureDialog::closeEvent(QCloseEvent *ev) void PictureDialog::addPreviousNextButtons() { QToolBar *uiToolbar = new QToolBar("Picture Toolbar", this); -#if QT_VERSION < 0x050600 - qreal screenRatio = AppEnv::screenRatio(); - if (screenRatio != 1) { - QSize iconSize = uiToolbar->iconSize(); - uiToolbar->setIconSize(QSize(iconSize.width() * screenRatio, iconSize.height() * screenRatio)); - } -#endif uiToolbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); uiToolbar->setObjectName("UiToolbar"); uiToolbar->addAction(QIcon(AppEnv::getImagesFolder() % "/back.svgz"), "", this, SLOT(previousPictureRequestedSlot())); @@ -689,14 +667,8 @@ void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button) #endif PictureWidget *pictureWidget = new PictureWidget(this); // Work! pictureWidget->setObjectName("PictureWidget"); -#if QT_VERSION >= 0x050900 pictureWidget->setWindowFlag(Qt::FramelessWindowHint, true); pictureWidget->setWindowFlag(Qt::MaximizeUsingFullscreenGeometryHint, true); -#elif QT_VERSION >= 0x050600 - pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint^Qt::MaximizeUsingFullscreenGeometryHint); -#else - pictureWidget->setWindowFlags(pictureWidget->windowFlags()^Qt::FramelessWindowHint); -#endif pictureWidget->setWindowTitle(windowTitle()); pictureWidget->setStyleSheet("QLabel#pictureLabel{background-color:black;}"); pictureWidget->setImage(smpic->getImage(), desktopRect); @@ -785,7 +757,7 @@ void PictureDialog::openPreviewMap() QJsonObject jsonObject; jsonObject["Type"] = "LocationEdited"; jsonObject["ExtraFlags"] = "Viewer"; - jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength()); + jsonObject["EditedSize"] = QString::number(picture->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else @@ -863,7 +835,7 @@ void PictureDialog::editSnapmaticImage() QJsonObject jsonObject; jsonObject["Type"] = "ImageEdited"; jsonObject["ExtraFlags"] = "Viewer"; - jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); + jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else diff --git a/src/PlayerListDialog.cpp b/src/PlayerListDialog.cpp index 7c1b9a3..ecb6fa1 100644 --- a/src/PlayerListDialog.cpp +++ b/src/PlayerListDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2021 Syping +* Copyright (C) 2016-2023 Syping * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +18,6 @@ #include "PlayerListDialog.h" #include "ui_PlayerListDialog.h" -#include "wrapper.h" #include "AppEnv.h" #include #include @@ -33,11 +32,7 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile ui(new Ui::PlayerListDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); -#endif listUpdated = false; ui->setupUi(this); diff --git a/src/ProfileInterface.cpp b/src/ProfileInterface.cpp index ce87356..63f66f6 100644 --- a/src/ProfileInterface.cpp +++ b/src/ProfileInterface.cpp @@ -24,14 +24,12 @@ #include "DatabaseThread.h" #include "SavegameWidget.h" #include "PictureDialog.h" -#include "PictureExport.h" #include "StandardPaths.h" #include "ProfileLoader.h" #include "ExportThread.h" #include "ImportDialog.h" #include "UiModLabel.h" #include "pcg_basic.h" -#include "wrapper.h" #include "AppEnv.h" #include "config.h" #include @@ -544,7 +542,7 @@ fileDialogPreOpen: //Work? fileDialog.setViewMode(QFileDialog::Detail); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog); - fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint); + fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); fileDialog.setWindowTitle(tr("Import...")); fileDialog.setLabelText(QFileDialog::Accept, tr("Import...")); @@ -604,7 +602,8 @@ bool ProfileInterface::importFilesProgress(QStringList selectedFiles) // Progress dialog QProgressDialog pbDialog(this); - pbDialog.setWindowFlags(pbDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + pbDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + pbDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); pbDialog.setWindowTitle(tr("Import...")); pbDialog.setLabelText(tr("Import file %1 of %2 files").arg(QString::number(1), QString::number(maximumId))); pbDialog.setRange(1, maximumId); @@ -661,7 +660,7 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime QJsonDocument jsonDocument; QJsonObject jsonObject; jsonObject["Type"] = "ImportSuccess"; - jsonObject["ImportSize"] = QString::number(picture->getContentMaxLength()); + jsonObject["ImportSize"] = QString::number(picture->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else @@ -873,7 +872,7 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime QJsonObject jsonObject; jsonObject["Type"] = "ImportSuccess"; jsonObject["ExtraFlag"] = "Dialog"; - jsonObject["ImportSize"] = QString::number(picture->getContentMaxLength()); + jsonObject["ImportSize"] = QString::number(picture->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else @@ -920,7 +919,7 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime QJsonDocument jsonDocument; QJsonObject jsonObject; jsonObject["Type"] = "ImportSuccess"; - jsonObject["ImportSize"] = QString::number(picture->getContentMaxLength()); + jsonObject["ImportSize"] = QString::number(picture->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else @@ -1002,27 +1001,16 @@ bool ProfileInterface::importRemote(QUrl remoteUrl) { bool retValue = false; QDialog urlPasteDialog(this); -#if QT_VERSION >= 0x050000 urlPasteDialog.setObjectName(QStringLiteral("UrlPasteDialog")); -#else - urlPasteDialog.setObjectName(QString::fromUtf8("UrlPasteDialog")); -#endif - urlPasteDialog.setWindowFlags(urlPasteDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + urlPasteDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + urlPasteDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); urlPasteDialog.setWindowTitle(tr("Import...")); urlPasteDialog.setModal(true); QVBoxLayout urlPasteLayout(&urlPasteDialog); -#if QT_VERSION >= 0x050000 urlPasteLayout.setObjectName(QStringLiteral("UrlPasteLayout")); -#else - urlPasteLayout.setObjectName(QString::fromUtf8("UrlPasteLayout")); -#endif urlPasteDialog.setLayout(&urlPasteLayout); UiModLabel urlPasteLabel(&urlPasteDialog); -#if QT_VERSION >= 0x050000 urlPasteLabel.setObjectName(QStringLiteral("UrlPasteLabel")); -#else - urlPasteLabel.setObjectName(QString::fromUtf8("UrlPasteLabel")); -#endif urlPasteLabel.setText(tr("Prepare Content for Import...")); urlPasteLayout.addWidget(&urlPasteLabel); @@ -1401,7 +1389,8 @@ void ProfileInterface::exportSelected() } QProgressDialog pbDialog(this); - pbDialog.setWindowFlags(pbDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + pbDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + pbDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); pbDialog.setWindowTitle(tr("Export selected...")); pbDialog.setLabelText(tr("Initialising export...")); pbDialog.setRange(0, exportCount); @@ -2030,7 +2019,8 @@ void ProfileInterface::massTool(MassTool tool) int overallId = 0; QProgressDialog pbDialog(this); - pbDialog.setWindowFlags(pbDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + pbDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + pbDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); pbDialog.setWindowTitle(tr("Patch selected...")); pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId))); pbDialog.setRange(1, maximumId); @@ -2123,7 +2113,8 @@ void ProfileInterface::massTool(MassTool tool) int overallId = 0; QProgressDialog pbDialog(this); - pbDialog.setWindowFlags(pbDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + pbDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + pbDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); pbDialog.setWindowTitle(tr("Patch selected...")); pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId))); pbDialog.setRange(1, maximumId); @@ -2238,7 +2229,8 @@ preSelectionCrewID: int overallId = 0; QProgressDialog pbDialog(this); - pbDialog.setWindowFlags(pbDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + pbDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + pbDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); pbDialog.setWindowTitle(tr("Patch selected...")); pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId))); pbDialog.setRange(1, maximumId); @@ -2333,7 +2325,8 @@ preSelectionTitle: int overallId = 0; QProgressDialog pbDialog(this); - pbDialog.setWindowFlags(pbDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint); + pbDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); + pbDialog.setWindowFlag(Qt::WindowCloseButtonHint, false); pbDialog.setWindowTitle(tr("Patch selected...")); pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(overallId), QString::number(maximumId))); pbDialog.setRange(1, maximumId); diff --git a/src/RagePhoto.cpp b/src/RagePhoto.cpp deleted file mode 100644 index 293d4a8..0000000 --- a/src/RagePhoto.cpp +++ /dev/null @@ -1,865 +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 . -*****************************************************************************/ - -#include "RagePhoto.h" -#include -#include -#include -#if QT_VERSION < 0x060000 -#include -#else -#include -#include -#endif -#ifdef RAGEPHOTO_BENCHMARK -#include -#include -#endif - -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(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(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(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(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(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(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(PhotoFormat::G5EX)) { - size = dataBuffer.read(uInt32Buffer, 4); - if (size != 4) - return false; - format = charToUInt32LE(uInt32Buffer); - if (format == static_cast(ExportFormat::G5E3P)) { - size = dataBuffer.read(uInt32Buffer, 4); - if (size != 4) - return false; - quint32 compressedSize = charToUInt32LE(uInt32Buffer); - - char *compressedPhotoHeader = static_cast(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(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(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(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(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(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(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(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(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_jsonData = t_jsonDocument.toJson(QJsonDocument::Compact); - p_jsonObject = t_jsonDocument.object(); - return true; -} - -bool RagePhoto::setPhotoBuffer(quint32 size, bool moveOffsets) -{ - if (size < static_cast(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; - return true; -} - -bool RagePhoto::setPhotoData(const char *data, int size) -{ - if (static_cast(size) > p_photoBuffer) - return false; - p_photoData = QByteArray(data, size); - 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) -{ - if (photoFormat == PhotoFormat::G5EX) { - char uInt32Buffer[4]; - quint32 format = static_cast(PhotoFormat::G5EX); - uInt32ToCharLE(format, uInt32Buffer); - ioDevice->write(uInt32Buffer, 4); - format = static_cast(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(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(x[0]) << 24 | - static_cast(x[1]) << 16 | - static_cast(x[2]) << 8 | - static_cast(x[3])); -} - -quint32 RagePhoto::charToUInt32LE(char *x) -{ - return (static_cast(x[3]) << 24 | - static_cast(x[2]) << 16 | - static_cast(x[1]) << 8 | - static_cast(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 -} diff --git a/src/RagePhoto.h b/src/RagePhoto.h deleted file mode 100644 index 4f7a5ba..0000000 --- a/src/RagePhoto.h +++ /dev/null @@ -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 . -*****************************************************************************/ - -#ifndef RAGEPHOTO_H -#define RAGEPHOTO_H - -#include -#include -#include - -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 diff --git a/src/SavegameData.cpp b/src/SavegameData.cpp index 42a9ae3..c83fcf3 100644 --- a/src/SavegameData.cpp +++ b/src/SavegameData.cpp @@ -17,7 +17,6 @@ *****************************************************************************/ #include "SnapmaticPicture.h" -#include "StringParser.h" #include "SavegameData.h" #include #include @@ -78,7 +77,7 @@ QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader) QList savegameBytesList = savegameBytes.split(char(0x01)); savegameBytes = savegameBytesList.at(1); savegameBytesList.clear(); - return SnapmaticPicture::parseTitleString(savegameBytes, savegameBytes.length()); + return SnapmaticPicture::parseTitleString(savegameBytes); } bool SavegameData::readingSavegameFromFile(const QString &fileName) diff --git a/src/SavegameDialog.cpp b/src/SavegameDialog.cpp index 27b0229..d0317c2 100644 --- a/src/SavegameDialog.cpp +++ b/src/SavegameDialog.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2018 Syping +* Copyright (C) 2016-2023 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 @@ -28,11 +28,7 @@ SavegameDialog::SavegameDialog(QWidget *parent) : ui(new Ui::SavegameDialog) { // Set Window Flags -#if QT_VERSION >= 0x050900 setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint); -#endif // Setup User Interface ui->setupUi(this); diff --git a/src/SnapmaticEditor.cpp b/src/SnapmaticEditor.cpp index f07346e..3ce3f4c 100644 --- a/src/SnapmaticEditor.cpp +++ b/src/SnapmaticEditor.cpp @@ -315,7 +315,7 @@ void SnapmaticEditor::on_cmdApply_clicked() QJsonDocument jsonDocument; QJsonObject jsonObject; jsonObject["Type"] = "PropertyEdited"; - jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); + jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else diff --git a/src/SnapmaticPicture.cpp b/src/SnapmaticPicture.cpp index c3664fd..5846d72 100644 --- a/src/SnapmaticPicture.cpp +++ b/src/SnapmaticPicture.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -* gta5spv Grand Theft Auto Snapmatic Picture Viewer -* Copyright (C) 2016-2021 Syping +* gta5view Grand Theft Auto V Profile Viewer +* Copyright (C) 2016-2023 Syping * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,18 +37,287 @@ #else #include #endif - -#if QT_VERSION >= 0x050000 #include -#else -#include "StandardPaths.h" -#endif // IMAGES VALUES #define snapmaticResolutionW 960 #define snapmaticResolutionH 536 #define snapmaticResolution QSize(snapmaticResolutionW, snapmaticResolutionH) +// GTA5VIEW RELATED INTERNAL FUNCTIONS +inline quint32 gta5view_charToUInt32LE(char *x) +{ + return (static_cast(x[3]) << 24 | + static_cast(x[2]) << 16 | + static_cast(x[1]) << 8 | + static_cast(x[0])); +} + +inline void gta5view_uInt32ToCharLE(quint32 x, char *y) +{ + y[0] = x; + y[1] = x >> 8; + y[2] = x >> 16; + y[3] = x >> 24; +} + +inline bool gta5view_export_load(const QByteArray &fileData, RagePhoto *ragePhoto) +{ + QBuffer dataBuffer; + dataBuffer.setData(fileData); + if (!dataBuffer.open(QIODevice::ReadOnly)) + return false; + dataBuffer.seek(4); + + char uInt32Buffer[4]; + qint64 size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + + quint32 format = gta5view_charToUInt32LE(uInt32Buffer); + if (format == G5EExportFormat::G5E3P) { + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + quint32 compressedSize = gta5view_charToUInt32LE(uInt32Buffer); + + char *compressedPhotoHeader = static_cast(std::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; + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + quint32 t_headerSum = gta5view_charToUInt32LE(uInt32Buffer); + ragePhoto->setHeader(t_photoHeader.constData(), t_headerSum); + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + quint32 t_photoBuffer = gta5view_charToUInt32LE(uInt32Buffer); + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + compressedSize = gta5view_charToUInt32LE(uInt32Buffer); + + char *compressedPhoto = static_cast(std::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); + t_photoData = qUncompress(t_photoData); + free(compressedPhoto); + ragePhoto->setPhoto(t_photoData.constData(), t_photoData.size(), t_photoBuffer); + + // JSON offset will be calculated later, offsets will be removed in G5E4P + size = dataBuffer.skip(4); + if (size != 4) + return false; + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + quint32 t_jsonBuffer = gta5view_charToUInt32LE(uInt32Buffer); + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + compressedSize = gta5view_charToUInt32LE(uInt32Buffer); + + char *compressedJson = static_cast(std::malloc(compressedSize)); + if (!compressedJson) + return false; + size = dataBuffer.read(compressedJson, compressedSize); + if (size != compressedSize) { + free(compressedJson); + return false; + } + QByteArray t_jsonData = QByteArray::fromRawData(compressedJson, compressedSize); + t_jsonData = qUncompress(t_jsonData); + free(compressedJson); + if (t_jsonData.isEmpty()) + return false; + ragePhoto->setJson(t_jsonData.constData(), t_jsonBuffer); + + // TITL offset will be calculated later, offsets will be removed in G5E4P + size = dataBuffer.skip(4); + if (size != 4) + return false; + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + quint32 t_titlBuffer = gta5view_charToUInt32LE(uInt32Buffer); + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + compressedSize = gta5view_charToUInt32LE(uInt32Buffer); + + char *compressedTitl = static_cast(std::malloc(compressedSize)); + if (!compressedTitl) + return false; + size = dataBuffer.read(compressedTitl, compressedSize); + if (size != compressedSize) { + free(compressedTitl); + return false; + } + QByteArray t_titlData = QByteArray::fromRawData(compressedTitl, compressedSize); + t_titlData = qUncompress(t_titlData); + free(compressedTitl); + ragePhoto->setTitle(t_titlData.constData(), t_titlBuffer); + + // DESC offset will be calculated later, offsets will be removed in G5E4P + size = dataBuffer.skip(4); + if (size != 4) + return false; + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + quint32 t_descBuffer = gta5view_charToUInt32LE(uInt32Buffer); + + size = dataBuffer.read(uInt32Buffer, 4); + if (size != 4) + return false; + compressedSize = gta5view_charToUInt32LE(uInt32Buffer); + + char *compressedDesc = static_cast(std::malloc(compressedSize)); + if (!compressedDesc) + return false; + size = dataBuffer.read(compressedDesc, compressedSize); + if (size != compressedSize) { + free(compressedDesc); + return false; + } + QByteArray t_descData = QByteArray::fromRawData(compressedDesc, compressedSize); + t_descData = qUncompress(t_descData); + free(compressedDesc); + ragePhoto->setDescription(t_descData.constData(), t_descBuffer); + + // EOF will be calculated later, EOF marker will be removed in G5E4P + size = dataBuffer.skip(4); + if (size != 4) + return false; + + // libragephoto needs to know we gave it a GTA V Snapmatic + ragePhoto->setFormat(RagePhoto::GTA5); + + return true; + } + else if (format == G5EExportFormat::G5E2P) { + const QByteArray t_fileData = qUncompress(dataBuffer.readAll()); + if (t_fileData.isEmpty()) + return false; + return ragePhoto->load(t_fileData.constData(), t_fileData.size()); + } + else if (format == G5EExportFormat::G5E1P) { + size = dataBuffer.skip(1); + if (size != 1) + return false; + + char length[1]; + size = dataBuffer.read(length, 1); + if (size != 1) + return false; + int i_length = QByteArray::number(static_cast(length[0]), 16).toInt() + 6; + + size = dataBuffer.skip(i_length); + if (size != i_length) + return false; + + const QByteArray t_fileData = qUncompress(dataBuffer.readAll()); + if (t_fileData.isEmpty()) + return false; + return ragePhoto->load(t_fileData.constData(), t_fileData.size()); + } + return false; +} + +inline void gta5view_export_save(QIODevice *ioDevice, RagePhotoData *data) +{ + char uInt32Buffer[4]; + quint32 format = G5EPhotoFormat::G5EX; + gta5view_uInt32ToCharLE(format, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + format = G5EExportFormat::G5E3P; + gta5view_uInt32ToCharLE(format, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + QByteArray compressedData = qCompress(QByteArray::fromRawData(data->header, strlen(data->header)), 9); + quint32 compressedSize = compressedData.size(); + gta5view_uInt32ToCharLE(compressedSize, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + ioDevice->write(compressedData); + + gta5view_uInt32ToCharLE(data->headerSum, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + gta5view_uInt32ToCharLE(data->photoBuffer, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + compressedData = qCompress(QByteArray::fromRawData(data->jpeg, data->jpegSize), 9); + compressedSize = compressedData.size(); + gta5view_uInt32ToCharLE(compressedSize, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + ioDevice->write(compressedData); + + gta5view_uInt32ToCharLE(data->jsonOffset, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + gta5view_uInt32ToCharLE(data->jsonBuffer, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + compressedData = qCompress(QByteArray::fromRawData(data->json, strlen(data->json)), 9); + compressedSize = compressedData.size(); + gta5view_uInt32ToCharLE(compressedSize, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + ioDevice->write(compressedData); + + gta5view_uInt32ToCharLE(data->titlOffset, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + gta5view_uInt32ToCharLE(data->titlBuffer, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + compressedData = qCompress(QByteArray::fromRawData(data->title, strlen(data->title)), 9); + compressedSize = compressedData.size(); + gta5view_uInt32ToCharLE(compressedSize, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + ioDevice->write(compressedData); + + gta5view_uInt32ToCharLE(data->descOffset, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + gta5view_uInt32ToCharLE(data->descBuffer, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + + compressedData = qCompress(QByteArray::fromRawData(data->description, strlen(data->description)), 9); + compressedSize = compressedData.size(); + gta5view_uInt32ToCharLE(compressedSize, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); + ioDevice->write(compressedData); + + gta5view_uInt32ToCharLE(data->endOfFile, uInt32Buffer); + ioDevice->write(uInt32Buffer, 4); +} + +// SNAPMATIC PICTURE CLASS SnapmaticPicture::SnapmaticPicture(const QString &fileName, QObject *parent) : QObject(parent), picFilePath(fileName) { reset(); @@ -68,8 +337,12 @@ void SnapmaticPicture::reset() lastStep = QString(); sortStr = QString(); + // INIT PIC FORMAT + picFormat = 0; + // INIT PIC BOOLS isFormatSwitch = false; + isPreLoaded = false; picOk = false; // INIT JSON @@ -77,32 +350,45 @@ void SnapmaticPicture::reset() // SNAPMATIC PROPERTIES localProperties = {}; + + // JSON OBJECT + jsonObject = QJsonObject(); } bool SnapmaticPicture::preloadFile() { - QFile *picFile = new QFile(picFilePath); + QFile picFile(picFilePath); picFileName = QFileInfo(picFilePath).fileName(); - isFormatSwitch = false; - if (!picFile->open(QFile::ReadOnly)) { + if (!picFile.open(QIODevice::ReadOnly)) { lastStep = "1;/1,OpenFile," % convertDrawStringForLog(picFilePath); - delete picFile; return false; } - p_ragePhoto.setIODevice(picFile); - bool ok = p_ragePhoto.load(); - picFile->close(); - delete picFile; + const qint64 fileMaxSize = (1024 * 1024 * 64); + const QByteArray fileData = picFile.read(fileMaxSize); + + bool ok = p_ragePhoto.load(fileData.constData(), fileData.size()); + picFormat = p_ragePhoto.format(); + + // libragephoto doesn't support modules yet + if (picFormat == G5EPhotoFormat::G5EX) + ok = gta5view_export_load(fileData, &p_ragePhoto); + if (!ok) return false; - if (picFilePath.right(4) != QLatin1String(".g5e")) { - if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) + const QJsonDocument t_jsonDocument = QJsonDocument::fromJson(p_ragePhoto.json()); + if (t_jsonDocument.isNull()) + return false; + jsonObject = t_jsonDocument.object(); + + if (!picFilePath.endsWith(".g5e", Qt::CaseInsensitive)) { + if (picFormat == G5EPhotoFormat::G5EX) isFormatSwitch = true; } + isPreLoaded = true; emit preloaded(); return ok; } @@ -116,17 +402,17 @@ bool SnapmaticPicture::readingPicture(bool cacheEnabled_) cacheEnabled = cacheEnabled_; bool ok = true; - if (!p_ragePhoto.isLoaded()) + if (!isPreLoaded) ok = preloadFile(); if (!ok) return false; if (cacheEnabled) - picOk = cachePicture.loadFromData(p_ragePhoto.photoData(), "JPEG"); + picOk = cachePicture.loadFromData(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()), "JPEG"); if (!cacheEnabled) { QImage tempPicture; - picOk = tempPicture.loadFromData(p_ragePhoto.photoData(), "JPEG"); + picOk = tempPicture.loadFromData(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()), "JPEG"); } parseJsonContent(); // JSON parsing is own function @@ -138,7 +424,7 @@ bool SnapmaticPicture::readingPicture(bool cacheEnabled_) void SnapmaticPicture::updateStrings() { - QString cmpPicTitl = p_ragePhoto.title(); + QString cmpPicTitl(p_ragePhoto.title()); cmpPicTitl.replace('\"', "''"); cmpPicTitl.replace(' ', '_'); cmpPicTitl.replace(':', '-'); @@ -153,7 +439,7 @@ void SnapmaticPicture::updateStrings() cmpPicTitl.remove('.'); pictureStr = tr("PHOTO - %1").arg(localProperties.createdDateTime.toString("MM/dd/yy HH:mm:ss")); sortStr = localProperties.createdDateTime.toString("yyMMddHHmmss") % QString::number(localProperties.uid); - QString exportStr = localProperties.createdDateTime.toString("yyyyMMdd") % "-" % QString::number(localProperties.uid); + const QString exportStr = localProperties.createdDateTime.toString("yyyyMMdd") % "-" % QString::number(localProperties.uid); if (getSnapmaticFormat() == SnapmaticFormat::G5E_Format) picFileName = "PGTA5" % QString::number(localProperties.uid); picExportFileName = exportStr % "_" % cmpPicTitl; @@ -165,17 +451,16 @@ bool SnapmaticPicture::readingPictureFromFile(const QString &fileName, bool cach picFilePath = fileName; return readingPicture(cacheEnabled_); } - else { + else return false; - } } bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode) { -#ifdef GTA5SYNC_DYNAMIC_PHOTOBUFFER - quint32 jpegPicStreamLength = p_ragePhoto.photoBuffer(); +#ifdef GTA5SYNC_DYNAMIC_PHOTOBUFFER // It's not properly implemented yet, please don't define + quint32 jpegPicStreamLength = p_ragePhoto.data()->photoBuffer(); #else - quint32 jpegPicStreamLength = 524288U; + quint32 jpegPicStreamLength = RagePhoto::DEFAULT_GTA5_PHOTOBUFFER; #endif QByteArray picByteArray; int comLvl = 100; @@ -193,19 +478,11 @@ bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode) comLvl--; saveSuccess = false; } - else { - p_ragePhoto.setPhotoBuffer(size, true); + else picByteArray = picByteArrayT; - } } - else { -#ifndef GTA5SYNC_DYNAMIC_PHOTOBUFFER - if (p_ragePhoto.photoBuffer() != jpegPicStreamLength) - p_ragePhoto.setPhotoData(QByteArray()); // avoid buffer set fail - p_ragePhoto.setPhotoBuffer(jpegPicStreamLength, true); -#endif + else picByteArray = picByteArrayT; - } } } if (saveSuccess) @@ -215,7 +492,18 @@ bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode) bool SnapmaticPicture::setPictureStream(const QByteArray &streamArray) // clean method { - bool success = p_ragePhoto.setPhotoData(streamArray); +#ifdef GTA5SYNC_DYNAMIC_PHOTOBUFFER // It's not properly implemented yet, please don't define + quint32 jpegPicStreamLength = p_ragePhoto.data()->photoBuffer(); +#else + quint32 jpegPicStreamLength = RagePhoto::DEFAULT_GTA5_PHOTOBUFFER; +#endif + if (streamArray.size() > jpegPicStreamLength) + jpegPicStreamLength = streamArray.size(); +#ifdef GTA5SYNC_COMPACT_PHOTOBUFFER // Experiment to save less than the default photo buffer + if (streamArray.size() < jpegPicStreamLength) + jpegPicStreamLength = streamArray.size(); +#endif + bool success = p_ragePhoto.setPhoto(streamArray.data(), streamArray.size(), jpegPicStreamLength); if (success) { if (cacheEnabled) { QImage replacedPicture; @@ -224,26 +512,19 @@ bool SnapmaticPicture::setPictureStream(const QByteArray &streamArray) // clean } return true; } - else { + else return false; - } } bool SnapmaticPicture::setPictureTitl(const QString &newTitle_) { QString newTitle = newTitle_; - if (newTitle.length() > 39) { + if (newTitle.length() > 39) newTitle = newTitle.left(39); - } - p_ragePhoto.setTitle(newTitle); + p_ragePhoto.setTitle(newTitle.toStdString().c_str()); return true; } -int SnapmaticPicture::getContentMaxLength() -{ - return p_ragePhoto.photoBuffer(); -} - QString SnapmaticPicture::getExportPictureFileName() { return picExportFileName; @@ -252,24 +533,20 @@ QString SnapmaticPicture::getExportPictureFileName() QString SnapmaticPicture::getOriginalPictureFileName() { QString newPicFileName = picFileName; - if (picFileName.right(4) == ".bak") { + if (picFileName.right(4) == ".bak") newPicFileName = QString(picFileName).remove(picFileName.length() - 4, 4); - } - if (picFileName.right(7) == ".hidden") { + if (picFileName.right(7) == ".hidden") newPicFileName = QString(picFileName).remove(picFileName.length() - 7, 7); - } return newPicFileName; } QString SnapmaticPicture::getOriginalPictureFilePath() { QString newPicFilePath = picFilePath; - if (picFilePath.right(4) == ".bak") { + if (picFilePath.right(4) == ".bak") newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 4, 4); - } - if (picFilePath.right(7) == ".hidden") { + if (picFilePath.right(7) == ".hidden") newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 7, 7); - } return newPicFilePath; } @@ -309,13 +586,13 @@ QString SnapmaticPicture::getLastStep(bool readable) if (descStepList.length() < 1) return lastStep; int argsCount = descStepList.at(0).toInt(&intOk); - if (!intOk) { return lastStep; } + if (!intOk) + return lastStep; if (argsCount == 1) { QString currentAction = descStepList.at(1); QString actionFile = descStepList.at(2); - if (currentAction == "OpenFile") { + if (currentAction == "OpenFile") return tr("open file %1").arg(actionFile); - } } else if (argsCount == 3 || argsCount == 4) { QString currentAction = descStepList.at(1); @@ -325,42 +602,31 @@ QString SnapmaticPicture::getLastStep(bool readable) if (argsCount == 4) { actionError2 = descStepList.at(5); } if (currentAction == "ReadingFile") { QString readableError = actionError; - if (actionError == "NOHEADER") { + if (actionError == "NOHEADER") readableError = tr("header not exists"); - } - else if (actionError == "MALFORMEDHEADER") { + else if (actionError == "MALFORMEDHEADER") readableError = tr("header is malformed"); - } - else if (actionError == "NOJPEG" || actionError == "NOPIC") { + else if (actionError == "NOJPEG" || actionError == "NOPIC") readableError = tr("picture not exists (%1)").arg(actionError); - } - else if (actionError == "NOJSON" || actionError == "CTJSON") { + else if (actionError == "NOJSON" || actionError == "CTJSON") readableError = tr("JSON not exists (%1)").arg(actionError); - } - else if (actionError == "NOTITL" || actionError == "CTTITL") { + else if (actionError == "NOTITL" || actionError == "CTTITL") readableError = tr("title not exists (%1)").arg(actionError); - } - else if (actionError == "NODESC" || actionError == "CTDESC") { + else if (actionError == "NODESC" || actionError == "CTDESC") readableError = tr("description not exists (%1)").arg(actionError); - } - else if (actionError == "JSONINCOMPLETE" && actionError2 == "JSONERROR") { + else if (actionError == "JSONINCOMPLETE" && actionError2 == "JSONERROR") readableError = tr("JSON is incomplete and malformed"); - } - else if (actionError == "JSONINCOMPLETE") { + else if (actionError == "JSONINCOMPLETE") readableError = tr("JSON is incomplete"); - } - else if (actionError == "JSONERROR") { + else if (actionError == "JSONERROR") readableError = tr("JSON is malformed"); - } return tr("reading file %1 because of %2", "Example for %2: JSON is malformed error").arg(actionFile, readableError); } - else { + else return lastStep; - } } - else { + else return lastStep; - } } return lastStep; @@ -368,18 +634,16 @@ QString SnapmaticPicture::getLastStep(bool readable) QImage SnapmaticPicture::getImage() { - if (cacheEnabled) { + if (cacheEnabled) return cachePicture; - } - else { - return QImage::fromData(p_ragePhoto.photoData(), "JPEG"); - } + else + return QImage::fromData(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()), "JPEG"); return QImage(); } QByteArray SnapmaticPicture::getPictureStream() { - return p_ragePhoto.photoData(); + return QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()); } bool SnapmaticPicture::isPicOk() @@ -412,7 +676,7 @@ bool SnapmaticPicture::isJsonOk() QString SnapmaticPicture::getJsonStr() { - return QString::fromUtf8(p_ragePhoto.jsonData()); + return QString::fromUtf8(p_ragePhoto.json()); } SnapmaticProperties SnapmaticPicture::getSnapmaticProperties() @@ -422,7 +686,6 @@ SnapmaticProperties SnapmaticPicture::getSnapmaticProperties() void SnapmaticPicture::parseJsonContent() { - QJsonObject jsonObject = p_ragePhoto.jsonObject(); QVariantMap jsonMap = jsonObject.toVariantMap(); bool jsonIncomplete = false; @@ -540,28 +803,28 @@ void SnapmaticPicture::parseJsonContent() bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties) { - QJsonObject jsonObject = p_ragePhoto.jsonObject(); + QJsonObject t_jsonObject = jsonObject; QJsonObject locObject; locObject["x"] = properties.location.x; locObject["y"] = properties.location.y; locObject["z"] = properties.location.z; - jsonObject["loc"] = locObject; - jsonObject["uid"] = properties.uid; - jsonObject["area"] = properties.location.area; - jsonObject["crewid"] = properties.crewID; - jsonObject["street"] = properties.streetID; - jsonObject["creat"] = QJsonValue::fromVariant(properties.createdTimestamp); - jsonObject["plyrs"] = QJsonValue::fromVariant(properties.playersList); - jsonObject["meme"] = properties.isMeme; - jsonObject["mug"] = properties.isMug; - jsonObject["slf"] = properties.isSelfie; - jsonObject["drctr"] = properties.isFromDirector; - jsonObject["rsedtr"] = properties.isFromRSEditor; - jsonObject["onislandx"] = properties.location.isCayoPerico; + t_jsonObject["loc"] = locObject; + t_jsonObject["uid"] = properties.uid; + t_jsonObject["area"] = properties.location.area; + t_jsonObject["crewid"] = properties.crewID; + t_jsonObject["street"] = properties.streetID; + t_jsonObject["creat"] = QJsonValue::fromVariant(properties.createdTimestamp); + t_jsonObject["plyrs"] = QJsonValue::fromVariant(properties.playersList); + t_jsonObject["meme"] = properties.isMeme; + t_jsonObject["mug"] = properties.isMug; + t_jsonObject["slf"] = properties.isSelfie; + t_jsonObject["drctr"] = properties.isFromDirector; + t_jsonObject["rsedtr"] = properties.isFromRSEditor; + t_jsonObject["onislandx"] = properties.location.isCayoPerico; - QJsonDocument jsonDocument(jsonObject); + const QJsonDocument jsonDocument(t_jsonObject); if (setJsonStr(QString::fromUtf8(jsonDocument.toJson(QJsonDocument::Compact)))) { localProperties = properties; return true; @@ -571,14 +834,16 @@ bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties) bool SnapmaticPicture::setJsonStr(const QString &newJsonStr, bool updateProperties) { - if (p_ragePhoto.setJsonData(newJsonStr.toUtf8())) { - if (updateProperties) - parseJsonContent(); - return true; - } - else { + const QJsonDocument t_jsonDocument = QJsonDocument::fromJson(newJsonStr.toStdString().c_str()); + if (t_jsonDocument.isNull()) return false; - } + const QByteArray t_jsonData = t_jsonDocument.toJson(QJsonDocument::Compact); + jsonObject = t_jsonDocument.object(); + + p_ragePhoto.setJson(t_jsonData.constData()); + if (updateProperties) + parseJsonContent(); + return true; } // FILE MANAGEMENT @@ -588,7 +853,7 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, SnapmaticFormat fo // Keep current format when Auto_Format is used SnapmaticFormat format = format_; if (format_ == SnapmaticFormat::Auto_Format) { - if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { + if (p_ragePhoto.format() == G5EPhotoFormat::G5EX) { format = SnapmaticFormat::G5E_Format; } else { @@ -597,68 +862,27 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, SnapmaticFormat fo } bool saveSuccess = false; -#if QT_VERSION >= 0x050000 - QSaveFile *picFile = new QSaveFile(fileName); -#else - QFile *picFile = new QFile(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); -#endif - if (picFile->open(QIODevice::WriteOnly)) { + QSaveFile picFile(fileName); + if (picFile.open(QIODevice::WriteOnly)) { if (format == SnapmaticFormat::G5E_Format) { - p_ragePhoto.save(picFile, RagePhoto::PhotoFormat::G5EX); -#if QT_VERSION >= 0x050000 - saveSuccess = picFile->commit(); -#else - saveSuccess = true; - picFile->close(); -#endif - delete picFile; + gta5view_export_save(&picFile, p_ragePhoto.data()); + saveSuccess = picFile.commit(); } else if (format == SnapmaticFormat::JPEG_Format) { - picFile->write(p_ragePhoto.photoData()); -#if QT_VERSION >= 0x050000 - saveSuccess = picFile->commit(); -#else - saveSuccess = true; - picFile->close(); -#endif - delete picFile; + picFile.write(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize())); + saveSuccess = picFile.commit(); } else { - p_ragePhoto.save(picFile, RagePhoto::PhotoFormat::GTA5); -#if QT_VERSION >= 0x050000 - saveSuccess = picFile->commit(); -#else - saveSuccess = true; - picFile->close(); -#endif - delete picFile; + bool ok; + const std::string photo = p_ragePhoto.save(&ok); + if (ok) + picFile.write(photo.data(), photo.size()); + saveSuccess = picFile.commit(); } -#if QT_VERSION <= 0x050000 - if (saveSuccess) { - bool tempBakCreated = false; - if (QFile::exists(fileName)) { - if (!QFile::rename(fileName, fileName % ".tmp")) { - QFile::remove(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); - return false; - } - tempBakCreated = true; - } - if (!QFile::rename(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp", fileName)) { - QFile::remove(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp"); - if (tempBakCreated) - QFile::rename(fileName % ".tmp", fileName); - return false; - } - if (tempBakCreated) - QFile::remove(fileName % ".tmp"); - } -#endif return saveSuccess; } - else { - delete picFile; + else return saveSuccess; - } } void SnapmaticPicture::setPicFileName(const QString &picFileName_) @@ -674,19 +898,19 @@ void SnapmaticPicture::setPicFilePath(const QString &picFilePath_) bool SnapmaticPicture::deletePicFile() { bool success = false; - if (!QFile::exists(picFilePath)) { + if (!QFile::exists(picFilePath)) success = true; - } - else if (QFile::remove(picFilePath)) { + else if (QFile::remove(picFilePath)) success = true; - } if (isHidden()) { const QString picBakPath = QString(picFilePath).remove(picFilePath.length() - 7, 7) % ".bak"; - if (QFile::exists(picBakPath)) QFile::remove(picBakPath); + if (QFile::exists(picBakPath)) + QFile::remove(picBakPath); } else { const QString picBakPath = picFilePath % ".bak"; - if (QFile::exists(picBakPath)) QFile::remove(picBakPath); + if (QFile::exists(picBakPath)) + QFile::remove(picBakPath); } return success; } @@ -695,23 +919,21 @@ bool SnapmaticPicture::deletePicFile() bool SnapmaticPicture::isHidden() { - if (picFilePath.right(7) == QLatin1String(".hidden")) { + if (picFilePath.right(7) == QLatin1String(".hidden")) return true; - } return false; } bool SnapmaticPicture::isVisible() { - if (picFilePath.right(7) == QLatin1String(".hidden")) { + if (picFilePath.right(7) == QLatin1String(".hidden")) return false; - } return true; } bool SnapmaticPicture::setPictureHidden() { - if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { + if (picFormat == G5EPhotoFormat::G5EX) { return false; } if (!isHidden()) { @@ -727,9 +949,8 @@ bool SnapmaticPicture::setPictureHidden() bool SnapmaticPicture::setPictureVisible() { - if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { + if (picFormat == G5EPhotoFormat::G5EX) return false; - } if (isHidden()) { QString newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 7, 7); if (QFile::rename(picFilePath, newPicFilePath)) { @@ -752,20 +973,19 @@ QSize SnapmaticPicture::getSnapmaticResolution() SnapmaticFormat SnapmaticPicture::getSnapmaticFormat() { - if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) { + if (picFormat == G5EPhotoFormat::G5EX) return SnapmaticFormat::G5E_Format; - } return SnapmaticFormat::PGTA_Format; } void SnapmaticPicture::setSnapmaticFormat(SnapmaticFormat format) { if (format == SnapmaticFormat::G5E_Format) { - p_ragePhoto.setPhotoFormat(RagePhoto::PhotoFormat::G5EX); + picFormat = G5EPhotoFormat::G5EX; return; } else if (format == SnapmaticFormat::PGTA_Format) { - p_ragePhoto.setPhotoFormat(RagePhoto::PhotoFormat::GTA5); + picFormat = RagePhoto::PhotoFormat::GTA5; return; } qDebug() << "setSnapmaticFormat: Invalid SnapmaticFormat defined, valid SnapmaticFormats are G5E_Format and PGTA_Format"; @@ -794,7 +1014,8 @@ bool SnapmaticPicture::verifyTitleChar(const QChar &titleChar) { // VERIFY CHAR FOR BE A VALID SNAPMATIC CHARACTER if (titleChar.isLetterOrNumber() || titleChar.isPrint()) { - if (titleChar == '<' || titleChar == '>' || titleChar == '\\') return false; + if (titleChar == '<' || titleChar == '>' || titleChar == '\\') + return false; return true; } return false; @@ -802,9 +1023,8 @@ bool SnapmaticPicture::verifyTitleChar(const QChar &titleChar) // STRING OPERATIONS -QString SnapmaticPicture::parseTitleString(const QByteArray &commitBytes, int maxLength) +QString SnapmaticPicture::parseTitleString(const QByteArray &commitBytes) { - Q_UNUSED(maxLength) #if QT_VERSION >= 0x060000 QStringDecoder strDecoder = QStringDecoder(QStringDecoder::Utf16LE); QString retStr = strDecoder(commitBytes); diff --git a/src/SnapmaticPicture.h b/src/SnapmaticPicture.h index 8113cdc..66ef16c 100644 --- a/src/SnapmaticPicture.h +++ b/src/SnapmaticPicture.h @@ -1,6 +1,6 @@ /***************************************************************************** -* gta5spv Grand Theft Auto Snapmatic Picture Viewer -* Copyright (C) 2016-2020 Syping +* gta5view Grand Theft Auto V Profile Viewer +* Copyright (C) 2016-2023 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 @@ -21,6 +21,7 @@ #include "RagePhoto.h" #include +#include #include #include #include @@ -28,6 +29,16 @@ #include enum class SnapmaticFormat : int { Auto_Format = 0, PGTA_Format = 1, JPEG_Format = 2, G5E_Format = 3 }; +enum G5EExportFormat : uint32_t { + G5E1P = 0x454C0010UL, + G5E2P = 0x01000032UL, + G5E2S = 0x02000032UL, + G5E3P = 0x01000033UL, + G5E3S = 0x02000033UL, +}; +enum G5EPhotoFormat : uint32_t { + G5EX = 0x45354700UL, +}; struct SnapmaticProperties { struct SnapmaticLocation { @@ -74,7 +85,6 @@ public: QString getExportPictureFileName(); QString getOriginalPictureFileName(); QString getOriginalPictureFilePath(); - int getContentMaxLength(); bool setImage(const QImage &picture, bool eXtendMode = false); bool setPictureTitl(const QString &newTitle); // Please use setPictureTitle instead bool setPictureStream(const QByteArray &streamArray); @@ -130,7 +140,7 @@ public: static bool verifyTitle(const QString &title); // STRING OPERATIONS - static QString parseTitleString(const QByteArray &commitBytes, int maxLength); + static QString parseTitleString(const QByteArray &commitBytes); static QString convertDrawStringForLog(const QString &inputStr); static QString convertLogStringForDraw(const QString &inputStr); @@ -145,14 +155,17 @@ private: QString pictureStr; QString lastStep; QString sortStr; + uint32_t picFormat; bool picOk; bool cacheEnabled; bool isFormatSwitch; + bool isPreLoaded; // JSON void parseJsonContent(); bool jsonOk; SnapmaticProperties localProperties; + QJsonObject jsonObject; // VERIFY CONTENT static bool verifyTitleChar(const QChar &titleChar); diff --git a/src/SnapmaticWidget.cpp b/src/SnapmaticWidget.cpp index db718a7..b3c4498 100644 --- a/src/SnapmaticWidget.cpp +++ b/src/SnapmaticWidget.cpp @@ -195,7 +195,7 @@ bool SnapmaticWidget::deletePicture() QJsonObject jsonObject; jsonObject["Type"] = "DeleteSuccess"; jsonObject["ExtraFlags"] = "Snapmatic"; - jsonObject["DeletedSize"] = QString::number(smpic->getContentMaxLength()); + jsonObject["DeletedSize"] = QString::number(smpic->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else @@ -381,7 +381,7 @@ void SnapmaticWidget::editSnapmaticImage() QJsonObject jsonObject; jsonObject["Type"] = "ImageEdited"; jsonObject["ExtraFlags"] = "Interface"; - jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength()); + jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else @@ -439,7 +439,7 @@ void SnapmaticWidget::openMapViewer() QJsonObject jsonObject; jsonObject["Type"] = "LocationEdited"; jsonObject["ExtraFlags"] = "Interface"; - jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength()); + jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize()); #if QT_VERSION >= 0x060000 jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); #else diff --git a/src/UserInterface.cpp b/src/UserInterface.cpp index a990b51..e65b852 100644 --- a/src/UserInterface.cpp +++ b/src/UserInterface.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2021 Syping +* Copyright (C) 2016-2023 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 @@ -184,11 +184,7 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D 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("%1").arg(tr("Donation methods").toHtmlEscaped()), donateDialog); @@ -222,11 +218,7 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D 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); @@ -580,11 +572,7 @@ fileDialogPreOpen: fileDialog.setViewMode(QFileDialog::Detail); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setOption(QFileDialog::DontUseNativeDialog, false); -#if QT_VERSION >= 0x050900 fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false); -#else - fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint); -#endif fileDialog.setWindowTitle(tr("Open File...")); QStringList filters; @@ -754,11 +742,7 @@ 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); diff --git a/src/libragephoto b/src/libragephoto new file mode 160000 index 0000000..8e73219 --- /dev/null +++ b/src/libragephoto @@ -0,0 +1 @@ +Subproject commit 8e732195493c4a4d5f120f290e77524645d8772e diff --git a/src/main.cpp b/src/main.cpp index 350d430..e84c61a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ /***************************************************************************** * gta5view Grand Theft Auto V Profile Viewer -* Copyright (C) 2016-2021 Syping +* Copyright (C) 2016-2023 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 @@ -21,15 +21,12 @@ #include "ProfileDatabase.h" #include "DatabaseThread.h" #include "SavegameDialog.h" -#include "OptionsDialog.h" #include "PictureDialog.h" #include "UserInterface.h" #include "CrewDatabase.h" #include "SavegameData.h" -#include "UiModWidget.h" #include "UiModLabel.h" #include "IconLoader.h" -#include "AppEnv.h" #include "config.h" #include #include @@ -227,7 +224,6 @@ int main(int argc, char *argv[]) bool readOk = picture.readingPictureFromFile(arg1); picDialog.setWindowIcon(IconLoader::loadingAppIcon()); picDialog.setSnapmaticPicture(&picture, readOk); - picDialog.setWindowFlags(picDialog.windowFlags()^Qt::Dialog^Qt::Window); int crewID = picture.getSnapmaticProperties().crewID; if (crewID != 0) @@ -254,7 +250,6 @@ int main(int argc, char *argv[]) bool readOk = savegame.readingSavegameFromFile(arg1); savegameDialog.setWindowIcon(IconLoader::loadingAppIcon()); savegameDialog.setSavegameData(&savegame, arg1, readOk); - savegameDialog.setWindowFlags(savegameDialog.windowFlags()^Qt::Dialog^Qt::Window); if (!readOk) return 1;