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
This commit is contained in:
parent
e463d2d22c
commit
050a281be8
23 changed files with 472 additions and 1302 deletions
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[submodule "src/libragephoto"]
|
||||||
|
path = src/libragephoto
|
||||||
|
url = https://github.com/Syping/libragephoto.git
|
||||||
|
branch = 0.2.0
|
|
@ -20,6 +20,9 @@ endif()
|
||||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network Svg Widgets REQUIRED)
|
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network Svg Widgets REQUIRED)
|
||||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools QUIET)
|
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)
|
if(WIN32)
|
||||||
list(APPEND GTA5VIEW_LIBS
|
list(APPEND GTA5VIEW_LIBS
|
||||||
dwmapi
|
dwmapi
|
||||||
|
@ -71,7 +74,6 @@ set(GTA5VIEW_SOURCES
|
||||||
src/ProfileInterface.cpp
|
src/ProfileInterface.cpp
|
||||||
src/ProfileLoader.cpp
|
src/ProfileLoader.cpp
|
||||||
src/ProfileWidget.cpp
|
src/ProfileWidget.cpp
|
||||||
src/RagePhoto.cpp
|
|
||||||
src/SavegameCopy.cpp
|
src/SavegameCopy.cpp
|
||||||
src/SavegameData.cpp
|
src/SavegameData.cpp
|
||||||
src/SavegameDialog.cpp
|
src/SavegameDialog.cpp
|
||||||
|
@ -114,7 +116,6 @@ set(GTA5VIEW_HEADERS
|
||||||
src/ProfileInterface.h
|
src/ProfileInterface.h
|
||||||
src/ProfileLoader.h
|
src/ProfileLoader.h
|
||||||
src/ProfileWidget.h
|
src/ProfileWidget.h
|
||||||
src/RagePhoto.h
|
|
||||||
src/SavegameCopy.h
|
src/SavegameCopy.h
|
||||||
src/SavegameData.h
|
src/SavegameData.h
|
||||||
src/SavegameDialog.h
|
src/SavegameDialog.h
|
||||||
|
@ -360,8 +361,8 @@ if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.14.0")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(gta5view PRIVATE ${GTA5VIEW_DEFINES})
|
target_compile_definitions(gta5view PRIVATE ${GTA5VIEW_DEFINES})
|
||||||
target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR})
|
target_include_directories(gta5view PRIVATE ${GTA5VIEW_INCLUDEDIR} ${RAGEPHOTO_INCLUDE_DIRS})
|
||||||
target_link_libraries(gta5view PRIVATE Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Widgets ${GTA5VIEW_LIBS})
|
target_link_libraries(gta5view PRIVATE Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Widgets ragephoto ${GTA5VIEW_LIBS})
|
||||||
|
|
||||||
install(TARGETS gta5view DESTINATION bin)
|
install(TARGETS gta5view DESTINATION bin)
|
||||||
install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications)
|
install(FILES res/de.syping.gta5view.desktop DESTINATION share/applications)
|
||||||
|
|
|
@ -15,7 +15,7 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V
|
||||||
|
|
||||||
# Note: Install Docker Community Edition and Git before continuing
|
# Note: Install Docker Community Edition and Git before continuing
|
||||||
docker pull sypingauto/gta5view-build:1.10-static
|
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
|
docker run --rm -v "$PWD/gta5view:/gta5view" -it sypingauto/gta5view-build:1.10-static
|
||||||
mingw64-qt-cmake -B /gta5view/build /gta5view
|
mingw64-qt-cmake -B /gta5view/build /gta5view
|
||||||
cmake --build /gta5view/build
|
cmake --build /gta5view/build
|
||||||
|
@ -23,7 +23,7 @@ Open Source Snapmatic and Savegame viewer/editor for GTA V
|
||||||
#### Build gta5view for Debian/Ubuntu
|
#### Build gta5view for Debian/Ubuntu
|
||||||
|
|
||||||
sudo apt-get install cmake git gcc g++ libqt5svg5-dev make qtbase5-dev qttranslations5-l10n
|
sudo apt-get install cmake git gcc g++ libqt5svg5-dev make qtbase5-dev qttranslations5-l10n
|
||||||
git clone https://gitlab.com/Syping/gta5view
|
git clone --recurse-submodules https://gitlab.com/Syping/gta5view
|
||||||
cmake -B gta5view-build gta5view
|
cmake -B gta5view-build gta5view
|
||||||
cmake --build gta5view-build
|
cmake --build gta5view-build
|
||||||
sudo cmake --install 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
|
#### Build gta5view for Arch/Manjaro
|
||||||
|
|
||||||
sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations
|
sudo pacman -S cmake gcc git make qt5-base qt5-svg qt5-tools qt5-translations
|
||||||
git clone https://gitlab.com/Syping/gta5view
|
git clone --recurse-submodules https://gitlab.com/Syping/gta5view
|
||||||
cmake -B gta5view-build gta5view
|
cmake -B gta5view-build gta5view
|
||||||
cmake --build gta5view-build
|
cmake --build gta5view-build
|
||||||
sudo cmake --install 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
|
#### Build gta5view for Fedora/RHEL
|
||||||
|
|
||||||
sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations
|
sudo dnf install cmake git gcc gcc-c++ make qt5-qtbase-devel qt5-qtsvg-devel qt5-qttranslations
|
||||||
git clone https://gitlab.com/Syping/gta5view
|
git clone --recurse-submodules https://gitlab.com/Syping/gta5view
|
||||||
cmake -B gta5view-build gta5view
|
cmake -B gta5view-build gta5view
|
||||||
cmake --build gta5view-build
|
cmake --build gta5view-build
|
||||||
sudo cmake --install gta5view-build
|
sudo cmake --install gta5view-build
|
||||||
|
|
|
@ -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-2023 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,11 +29,7 @@ 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);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Build Strings
|
// Build Strings
|
||||||
QString appVersion = QApplication::applicationVersion();
|
QString appVersion = QApplication::applicationVersion();
|
||||||
|
|
|
@ -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-2023 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
|
||||||
|
@ -435,11 +435,7 @@ bool AppEnv::setGameLanguage(GameVersion gameVersion, GameLanguage gameLanguage)
|
||||||
|
|
||||||
qreal AppEnv::screenRatio()
|
qreal AppEnv::screenRatio()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050000
|
|
||||||
qreal dpi = QApplication::primaryScreen()->logicalDotsPerInch();
|
qreal dpi = QApplication::primaryScreen()->logicalDotsPerInch();
|
||||||
#else
|
|
||||||
qreal dpi = QApplication::desktop()->logicalDpiX();
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
return (dpi / 72);
|
return (dpi / 72);
|
||||||
#else
|
#else
|
||||||
|
@ -449,9 +445,5 @@ qreal AppEnv::screenRatio()
|
||||||
|
|
||||||
qreal AppEnv::screenRatioPR()
|
qreal AppEnv::screenRatioPR()
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050600
|
|
||||||
return QApplication::primaryScreen()->devicePixelRatio();
|
return QApplication::primaryScreen()->devicePixelRatio();
|
||||||
#else
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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-2023 Syping
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -49,11 +49,7 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
|
||||||
ui(new Ui::ImportDialog)
|
ui(new Ui::ImportDialog)
|
||||||
{
|
{
|
||||||
// Set Window Flags
|
// Set Window Flags
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->cmdOK->setDefault(true);
|
ui->cmdOK->setDefault(true);
|
||||||
|
|
|
@ -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-2023 Syping
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -39,12 +39,8 @@ 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::WindowContextHelpButtonHint, false);
|
||||||
setWindowFlag(Qt::WindowMinMaxButtonsHint, true);
|
setWindowFlag(Qt::WindowMinMaxButtonsHint, true);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowMinMaxButtonsHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->cmdClose->setDefault(true);
|
ui->cmdClose->setDefault(true);
|
||||||
|
@ -194,7 +190,7 @@ bool JsonEditorDialog::saveJsonContent()
|
||||||
QJsonDocument jsonDocument;
|
QJsonDocument jsonDocument;
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "JSONEdited";
|
jsonObject["Type"] = "JSONEdited";
|
||||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -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-2023 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,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);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->cmdDone->setVisible(false);
|
ui->cmdDone->setVisible(false);
|
||||||
|
|
|
@ -56,11 +56,7 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
|
||||||
ui(new Ui::OptionsDialog)
|
ui(new Ui::OptionsDialog)
|
||||||
{
|
{
|
||||||
// Set Window Flags
|
// Set Window Flags
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Setup User Interface
|
// Setup User Interface
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
|
@ -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-2023 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,11 +20,9 @@
|
||||||
#include "PictureWidget.h"
|
#include "PictureWidget.h"
|
||||||
#include "ProfileDatabase.h"
|
#include "ProfileDatabase.h"
|
||||||
#include "ui_PictureDialog.h"
|
#include "ui_PictureDialog.h"
|
||||||
#include "SidebarGenerator.h"
|
|
||||||
#include "MapLocationDialog.h"
|
#include "MapLocationDialog.h"
|
||||||
#include "JsonEditorDialog.h"
|
#include "JsonEditorDialog.h"
|
||||||
#include "SnapmaticEditor.h"
|
#include "SnapmaticEditor.h"
|
||||||
#include "StandardPaths.h"
|
|
||||||
#include "PictureExport.h"
|
#include "PictureExport.h"
|
||||||
#include "ImportDialog.h"
|
#include "ImportDialog.h"
|
||||||
#include "StringParser.h"
|
#include "StringParser.h"
|
||||||
|
@ -127,21 +125,8 @@ PictureDialog::PictureDialog(bool primaryWindow, ProfileDatabase *profileDB, Cre
|
||||||
void PictureDialog::setupPictureDialog()
|
void PictureDialog::setupPictureDialog()
|
||||||
{
|
{
|
||||||
// Set Window Flags
|
// Set Window Flags
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
setWindowFlag(Qt::CustomizeWindowHint, true);
|
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
|
// Setup User Interface
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
@ -234,13 +219,6 @@ void PictureDialog::closeEvent(QCloseEvent *ev)
|
||||||
void PictureDialog::addPreviousNextButtons()
|
void PictureDialog::addPreviousNextButtons()
|
||||||
{
|
{
|
||||||
QToolBar *uiToolbar = new QToolBar("Picture Toolbar", this);
|
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->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
uiToolbar->setObjectName("UiToolbar");
|
uiToolbar->setObjectName("UiToolbar");
|
||||||
uiToolbar->addAction(QIcon(AppEnv::getImagesFolder() % "/back.svgz"), "", this, SLOT(previousPictureRequestedSlot()));
|
uiToolbar->addAction(QIcon(AppEnv::getImagesFolder() % "/back.svgz"), "", this, SLOT(previousPictureRequestedSlot()));
|
||||||
|
@ -689,14 +667,8 @@ void PictureDialog::on_labPicture_mouseDoubleClicked(Qt::MouseButton button)
|
||||||
#endif
|
#endif
|
||||||
PictureWidget *pictureWidget = new PictureWidget(this); // Work!
|
PictureWidget *pictureWidget = new PictureWidget(this); // Work!
|
||||||
pictureWidget->setObjectName("PictureWidget");
|
pictureWidget->setObjectName("PictureWidget");
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
pictureWidget->setWindowFlag(Qt::FramelessWindowHint, true);
|
pictureWidget->setWindowFlag(Qt::FramelessWindowHint, true);
|
||||||
pictureWidget->setWindowFlag(Qt::MaximizeUsingFullscreenGeometryHint, 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->setWindowTitle(windowTitle());
|
||||||
pictureWidget->setStyleSheet("QLabel#pictureLabel{background-color:black;}");
|
pictureWidget->setStyleSheet("QLabel#pictureLabel{background-color:black;}");
|
||||||
pictureWidget->setImage(smpic->getImage(), desktopRect);
|
pictureWidget->setImage(smpic->getImage(), desktopRect);
|
||||||
|
@ -785,7 +757,7 @@ void PictureDialog::openPreviewMap()
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "LocationEdited";
|
jsonObject["Type"] = "LocationEdited";
|
||||||
jsonObject["ExtraFlags"] = "Viewer";
|
jsonObject["ExtraFlags"] = "Viewer";
|
||||||
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
|
jsonObject["EditedSize"] = QString::number(picture->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
@ -863,7 +835,7 @@ void PictureDialog::editSnapmaticImage()
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "ImageEdited";
|
jsonObject["Type"] = "ImageEdited";
|
||||||
jsonObject["ExtraFlags"] = "Viewer";
|
jsonObject["ExtraFlags"] = "Viewer";
|
||||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -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-2023 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,7 +18,6 @@
|
||||||
|
|
||||||
#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 <QStringBuilder>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
@ -33,11 +32,7 @@ PlayerListDialog::PlayerListDialog(QStringList players, ProfileDatabase *profile
|
||||||
ui(new Ui::PlayerListDialog)
|
ui(new Ui::PlayerListDialog)
|
||||||
{
|
{
|
||||||
// Set Window Flags
|
// Set Window Flags
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
listUpdated = false;
|
listUpdated = false;
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
|
@ -24,14 +24,12 @@
|
||||||
#include "DatabaseThread.h"
|
#include "DatabaseThread.h"
|
||||||
#include "SavegameWidget.h"
|
#include "SavegameWidget.h"
|
||||||
#include "PictureDialog.h"
|
#include "PictureDialog.h"
|
||||||
#include "PictureExport.h"
|
|
||||||
#include "StandardPaths.h"
|
#include "StandardPaths.h"
|
||||||
#include "ProfileLoader.h"
|
#include "ProfileLoader.h"
|
||||||
#include "ExportThread.h"
|
#include "ExportThread.h"
|
||||||
#include "ImportDialog.h"
|
#include "ImportDialog.h"
|
||||||
#include "UiModLabel.h"
|
#include "UiModLabel.h"
|
||||||
#include "pcg_basic.h"
|
#include "pcg_basic.h"
|
||||||
#include "wrapper.h"
|
|
||||||
#include "AppEnv.h"
|
#include "AppEnv.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
@ -544,7 +542,7 @@ fileDialogPreOpen: //Work?
|
||||||
fileDialog.setViewMode(QFileDialog::Detail);
|
fileDialog.setViewMode(QFileDialog::Detail);
|
||||||
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
|
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||||
fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
|
fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
|
||||||
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
|
fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
fileDialog.setWindowTitle(tr("Import..."));
|
fileDialog.setWindowTitle(tr("Import..."));
|
||||||
fileDialog.setLabelText(QFileDialog::Accept, tr("Import..."));
|
fileDialog.setLabelText(QFileDialog::Accept, tr("Import..."));
|
||||||
|
|
||||||
|
@ -604,7 +602,8 @@ bool ProfileInterface::importFilesProgress(QStringList selectedFiles)
|
||||||
|
|
||||||
// Progress dialog
|
// Progress dialog
|
||||||
QProgressDialog pbDialog(this);
|
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.setWindowTitle(tr("Import..."));
|
||||||
pbDialog.setLabelText(tr("Import file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
pbDialog.setLabelText(tr("Import file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
||||||
pbDialog.setRange(1, maximumId);
|
pbDialog.setRange(1, maximumId);
|
||||||
|
@ -661,7 +660,7 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime
|
||||||
QJsonDocument jsonDocument;
|
QJsonDocument jsonDocument;
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "ImportSuccess";
|
jsonObject["Type"] = "ImportSuccess";
|
||||||
jsonObject["ImportSize"] = QString::number(picture->getContentMaxLength());
|
jsonObject["ImportSize"] = QString::number(picture->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
@ -873,7 +872,7 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "ImportSuccess";
|
jsonObject["Type"] = "ImportSuccess";
|
||||||
jsonObject["ExtraFlag"] = "Dialog";
|
jsonObject["ExtraFlag"] = "Dialog";
|
||||||
jsonObject["ImportSize"] = QString::number(picture->getContentMaxLength());
|
jsonObject["ImportSize"] = QString::number(picture->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
@ -920,7 +919,7 @@ bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime
|
||||||
QJsonDocument jsonDocument;
|
QJsonDocument jsonDocument;
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "ImportSuccess";
|
jsonObject["Type"] = "ImportSuccess";
|
||||||
jsonObject["ImportSize"] = QString::number(picture->getContentMaxLength());
|
jsonObject["ImportSize"] = QString::number(picture->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["ImportTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
@ -1002,27 +1001,16 @@ bool ProfileInterface::importRemote(QUrl remoteUrl)
|
||||||
{
|
{
|
||||||
bool retValue = false;
|
bool retValue = false;
|
||||||
QDialog urlPasteDialog(this);
|
QDialog urlPasteDialog(this);
|
||||||
#if QT_VERSION >= 0x050000
|
|
||||||
urlPasteDialog.setObjectName(QStringLiteral("UrlPasteDialog"));
|
urlPasteDialog.setObjectName(QStringLiteral("UrlPasteDialog"));
|
||||||
#else
|
urlPasteDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
urlPasteDialog.setObjectName(QString::fromUtf8("UrlPasteDialog"));
|
urlPasteDialog.setWindowFlag(Qt::WindowCloseButtonHint, false);
|
||||||
#endif
|
|
||||||
urlPasteDialog.setWindowFlags(urlPasteDialog.windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowCloseButtonHint);
|
|
||||||
urlPasteDialog.setWindowTitle(tr("Import..."));
|
urlPasteDialog.setWindowTitle(tr("Import..."));
|
||||||
urlPasteDialog.setModal(true);
|
urlPasteDialog.setModal(true);
|
||||||
QVBoxLayout urlPasteLayout(&urlPasteDialog);
|
QVBoxLayout urlPasteLayout(&urlPasteDialog);
|
||||||
#if QT_VERSION >= 0x050000
|
|
||||||
urlPasteLayout.setObjectName(QStringLiteral("UrlPasteLayout"));
|
urlPasteLayout.setObjectName(QStringLiteral("UrlPasteLayout"));
|
||||||
#else
|
|
||||||
urlPasteLayout.setObjectName(QString::fromUtf8("UrlPasteLayout"));
|
|
||||||
#endif
|
|
||||||
urlPasteDialog.setLayout(&urlPasteLayout);
|
urlPasteDialog.setLayout(&urlPasteLayout);
|
||||||
UiModLabel urlPasteLabel(&urlPasteDialog);
|
UiModLabel urlPasteLabel(&urlPasteDialog);
|
||||||
#if QT_VERSION >= 0x050000
|
|
||||||
urlPasteLabel.setObjectName(QStringLiteral("UrlPasteLabel"));
|
urlPasteLabel.setObjectName(QStringLiteral("UrlPasteLabel"));
|
||||||
#else
|
|
||||||
urlPasteLabel.setObjectName(QString::fromUtf8("UrlPasteLabel"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
urlPasteLabel.setText(tr("Prepare Content for Import..."));
|
urlPasteLabel.setText(tr("Prepare Content for Import..."));
|
||||||
urlPasteLayout.addWidget(&urlPasteLabel);
|
urlPasteLayout.addWidget(&urlPasteLabel);
|
||||||
|
@ -1401,7 +1389,8 @@ void ProfileInterface::exportSelected()
|
||||||
}
|
}
|
||||||
|
|
||||||
QProgressDialog pbDialog(this);
|
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.setWindowTitle(tr("Export selected..."));
|
||||||
pbDialog.setLabelText(tr("Initialising export..."));
|
pbDialog.setLabelText(tr("Initialising export..."));
|
||||||
pbDialog.setRange(0, exportCount);
|
pbDialog.setRange(0, exportCount);
|
||||||
|
@ -2030,7 +2019,8 @@ void ProfileInterface::massTool(MassTool tool)
|
||||||
int overallId = 0;
|
int overallId = 0;
|
||||||
|
|
||||||
QProgressDialog pbDialog(this);
|
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.setWindowTitle(tr("Patch selected..."));
|
||||||
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
||||||
pbDialog.setRange(1, maximumId);
|
pbDialog.setRange(1, maximumId);
|
||||||
|
@ -2123,7 +2113,8 @@ void ProfileInterface::massTool(MassTool tool)
|
||||||
int overallId = 0;
|
int overallId = 0;
|
||||||
|
|
||||||
QProgressDialog pbDialog(this);
|
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.setWindowTitle(tr("Patch selected..."));
|
||||||
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
||||||
pbDialog.setRange(1, maximumId);
|
pbDialog.setRange(1, maximumId);
|
||||||
|
@ -2238,7 +2229,8 @@ preSelectionCrewID:
|
||||||
int overallId = 0;
|
int overallId = 0;
|
||||||
|
|
||||||
QProgressDialog pbDialog(this);
|
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.setWindowTitle(tr("Patch selected..."));
|
||||||
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(1), QString::number(maximumId)));
|
||||||
pbDialog.setRange(1, maximumId);
|
pbDialog.setRange(1, maximumId);
|
||||||
|
@ -2333,7 +2325,8 @@ preSelectionTitle:
|
||||||
int overallId = 0;
|
int overallId = 0;
|
||||||
|
|
||||||
QProgressDialog pbDialog(this);
|
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.setWindowTitle(tr("Patch selected..."));
|
||||||
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(overallId), QString::number(maximumId)));
|
pbDialog.setLabelText(tr("Patch file %1 of %2 files").arg(QString::number(overallId), QString::number(maximumId)));
|
||||||
pbDialog.setRange(1, maximumId);
|
pbDialog.setRange(1, maximumId);
|
||||||
|
|
|
@ -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 <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
|
|
||||||
|
|
||||||
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_jsonData = t_jsonDocument.toJson(QJsonDocument::Compact);
|
|
||||||
p_jsonObject = t_jsonDocument.object();
|
|
||||||
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;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RagePhoto::setPhotoData(const char *data, int size)
|
|
||||||
{
|
|
||||||
if (static_cast<quint32>(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<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
|
|
||||||
}
|
|
110
src/RagePhoto.h
110
src/RagePhoto.h
|
@ -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
|
|
|
@ -17,7 +17,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "SnapmaticPicture.h"
|
#include "SnapmaticPicture.h"
|
||||||
#include "StringParser.h"
|
|
||||||
#include "SavegameData.h"
|
#include "SavegameData.h"
|
||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
@ -78,7 +77,7 @@ QString SavegameData::getSavegameDataString(const QByteArray &savegameHeader)
|
||||||
QList<QByteArray> savegameBytesList = savegameBytes.split(char(0x01));
|
QList<QByteArray> savegameBytesList = savegameBytes.split(char(0x01));
|
||||||
savegameBytes = savegameBytesList.at(1);
|
savegameBytes = savegameBytesList.at(1);
|
||||||
savegameBytesList.clear();
|
savegameBytesList.clear();
|
||||||
return SnapmaticPicture::parseTitleString(savegameBytes, savegameBytes.length());
|
return SnapmaticPicture::parseTitleString(savegameBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SavegameData::readingSavegameFromFile(const QString &fileName)
|
bool SavegameData::readingSavegameFromFile(const QString &fileName)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* gta5view Grand Theft Auto V Profile Viewer
|
* 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
|
* 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,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);
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Setup User Interface
|
// Setup User Interface
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
|
@ -315,7 +315,7 @@ void SnapmaticEditor::on_cmdApply_clicked()
|
||||||
QJsonDocument jsonDocument;
|
QJsonDocument jsonDocument;
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "PropertyEdited";
|
jsonObject["Type"] = "PropertyEdited";
|
||||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* gta5spv Grand Theft Auto Snapmatic Picture Viewer
|
* 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
|
* 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
|
||||||
|
@ -37,18 +37,287 @@
|
||||||
#else
|
#else
|
||||||
#include <QStringDecoder>
|
#include <QStringDecoder>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION >= 0x050000
|
|
||||||
#include <QSaveFile>
|
#include <QSaveFile>
|
||||||
#else
|
|
||||||
#include "StandardPaths.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// IMAGES VALUES
|
// IMAGES VALUES
|
||||||
#define snapmaticResolutionW 960
|
#define snapmaticResolutionW 960
|
||||||
#define snapmaticResolutionH 536
|
#define snapmaticResolutionH 536
|
||||||
#define snapmaticResolution QSize(snapmaticResolutionW, snapmaticResolutionH)
|
#define snapmaticResolution QSize(snapmaticResolutionW, snapmaticResolutionH)
|
||||||
|
|
||||||
|
// GTA5VIEW RELATED INTERNAL FUNCTIONS
|
||||||
|
inline quint32 gta5view_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]));
|
||||||
|
}
|
||||||
|
|
||||||
|
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<char*>(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<char*>(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<char*>(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<char*>(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<char*>(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<int>(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)
|
SnapmaticPicture::SnapmaticPicture(const QString &fileName, QObject *parent) : QObject(parent), picFilePath(fileName)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
@ -68,8 +337,12 @@ void SnapmaticPicture::reset()
|
||||||
lastStep = QString();
|
lastStep = QString();
|
||||||
sortStr = QString();
|
sortStr = QString();
|
||||||
|
|
||||||
|
// INIT PIC FORMAT
|
||||||
|
picFormat = 0;
|
||||||
|
|
||||||
// INIT PIC BOOLS
|
// INIT PIC BOOLS
|
||||||
isFormatSwitch = false;
|
isFormatSwitch = false;
|
||||||
|
isPreLoaded = false;
|
||||||
picOk = false;
|
picOk = false;
|
||||||
|
|
||||||
// INIT JSON
|
// INIT JSON
|
||||||
|
@ -77,32 +350,45 @@ void SnapmaticPicture::reset()
|
||||||
|
|
||||||
// SNAPMATIC PROPERTIES
|
// SNAPMATIC PROPERTIES
|
||||||
localProperties = {};
|
localProperties = {};
|
||||||
|
|
||||||
|
// JSON OBJECT
|
||||||
|
jsonObject = QJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnapmaticPicture::preloadFile()
|
bool SnapmaticPicture::preloadFile()
|
||||||
{
|
{
|
||||||
QFile *picFile = new QFile(picFilePath);
|
QFile picFile(picFilePath);
|
||||||
picFileName = QFileInfo(picFilePath).fileName();
|
picFileName = QFileInfo(picFilePath).fileName();
|
||||||
|
|
||||||
isFormatSwitch = false;
|
isFormatSwitch = false;
|
||||||
|
|
||||||
if (!picFile->open(QFile::ReadOnly)) {
|
if (!picFile.open(QIODevice::ReadOnly)) {
|
||||||
lastStep = "1;/1,OpenFile," % convertDrawStringForLog(picFilePath);
|
lastStep = "1;/1,OpenFile," % convertDrawStringForLog(picFilePath);
|
||||||
delete picFile;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_ragePhoto.setIODevice(picFile);
|
const qint64 fileMaxSize = (1024 * 1024 * 64);
|
||||||
bool ok = p_ragePhoto.load();
|
const QByteArray fileData = picFile.read(fileMaxSize);
|
||||||
picFile->close();
|
|
||||||
delete picFile;
|
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)
|
if (!ok)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (picFilePath.right(4) != QLatin1String(".g5e")) {
|
const QJsonDocument t_jsonDocument = QJsonDocument::fromJson(p_ragePhoto.json());
|
||||||
if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX)
|
if (t_jsonDocument.isNull())
|
||||||
|
return false;
|
||||||
|
jsonObject = t_jsonDocument.object();
|
||||||
|
|
||||||
|
if (!picFilePath.endsWith(".g5e", Qt::CaseInsensitive)) {
|
||||||
|
if (picFormat == G5EPhotoFormat::G5EX)
|
||||||
isFormatSwitch = true;
|
isFormatSwitch = true;
|
||||||
}
|
}
|
||||||
|
isPreLoaded = true;
|
||||||
emit preloaded();
|
emit preloaded();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -116,17 +402,17 @@ bool SnapmaticPicture::readingPicture(bool cacheEnabled_)
|
||||||
cacheEnabled = cacheEnabled_;
|
cacheEnabled = cacheEnabled_;
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (!p_ragePhoto.isLoaded())
|
if (!isPreLoaded)
|
||||||
ok = preloadFile();
|
ok = preloadFile();
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (cacheEnabled)
|
if (cacheEnabled)
|
||||||
picOk = cachePicture.loadFromData(p_ragePhoto.photoData(), "JPEG");
|
picOk = cachePicture.loadFromData(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()), "JPEG");
|
||||||
if (!cacheEnabled) {
|
if (!cacheEnabled) {
|
||||||
QImage tempPicture;
|
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
|
parseJsonContent(); // JSON parsing is own function
|
||||||
|
@ -138,7 +424,7 @@ bool SnapmaticPicture::readingPicture(bool cacheEnabled_)
|
||||||
|
|
||||||
void SnapmaticPicture::updateStrings()
|
void SnapmaticPicture::updateStrings()
|
||||||
{
|
{
|
||||||
QString cmpPicTitl = p_ragePhoto.title();
|
QString cmpPicTitl(p_ragePhoto.title());
|
||||||
cmpPicTitl.replace('\"', "''");
|
cmpPicTitl.replace('\"', "''");
|
||||||
cmpPicTitl.replace(' ', '_');
|
cmpPicTitl.replace(' ', '_');
|
||||||
cmpPicTitl.replace(':', '-');
|
cmpPicTitl.replace(':', '-');
|
||||||
|
@ -153,7 +439,7 @@ void SnapmaticPicture::updateStrings()
|
||||||
cmpPicTitl.remove('.');
|
cmpPicTitl.remove('.');
|
||||||
pictureStr = tr("PHOTO - %1").arg(localProperties.createdDateTime.toString("MM/dd/yy HH:mm:ss"));
|
pictureStr = tr("PHOTO - %1").arg(localProperties.createdDateTime.toString("MM/dd/yy HH:mm:ss"));
|
||||||
sortStr = localProperties.createdDateTime.toString("yyMMddHHmmss") % QString::number(localProperties.uid);
|
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)
|
if (getSnapmaticFormat() == SnapmaticFormat::G5E_Format)
|
||||||
picFileName = "PGTA5" % QString::number(localProperties.uid);
|
picFileName = "PGTA5" % QString::number(localProperties.uid);
|
||||||
picExportFileName = exportStr % "_" % cmpPicTitl;
|
picExportFileName = exportStr % "_" % cmpPicTitl;
|
||||||
|
@ -165,17 +451,16 @@ bool SnapmaticPicture::readingPictureFromFile(const QString &fileName, bool cach
|
||||||
picFilePath = fileName;
|
picFilePath = fileName;
|
||||||
return readingPicture(cacheEnabled_);
|
return readingPicture(cacheEnabled_);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode)
|
bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode)
|
||||||
{
|
{
|
||||||
#ifdef GTA5SYNC_DYNAMIC_PHOTOBUFFER
|
#ifdef GTA5SYNC_DYNAMIC_PHOTOBUFFER // It's not properly implemented yet, please don't define
|
||||||
quint32 jpegPicStreamLength = p_ragePhoto.photoBuffer();
|
quint32 jpegPicStreamLength = p_ragePhoto.data()->photoBuffer();
|
||||||
#else
|
#else
|
||||||
quint32 jpegPicStreamLength = 524288U;
|
quint32 jpegPicStreamLength = RagePhoto::DEFAULT_GTA5_PHOTOBUFFER;
|
||||||
#endif
|
#endif
|
||||||
QByteArray picByteArray;
|
QByteArray picByteArray;
|
||||||
int comLvl = 100;
|
int comLvl = 100;
|
||||||
|
@ -193,19 +478,11 @@ bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode)
|
||||||
comLvl--;
|
comLvl--;
|
||||||
saveSuccess = false;
|
saveSuccess = false;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
p_ragePhoto.setPhotoBuffer(size, true);
|
|
||||||
picByteArray = picByteArrayT;
|
picByteArray = picByteArrayT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
#ifndef GTA5SYNC_DYNAMIC_PHOTOBUFFER
|
|
||||||
if (p_ragePhoto.photoBuffer() != jpegPicStreamLength)
|
|
||||||
p_ragePhoto.setPhotoData(QByteArray()); // avoid buffer set fail
|
|
||||||
p_ragePhoto.setPhotoBuffer(jpegPicStreamLength, true);
|
|
||||||
#endif
|
|
||||||
picByteArray = picByteArrayT;
|
picByteArray = picByteArrayT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (saveSuccess)
|
if (saveSuccess)
|
||||||
|
@ -215,7 +492,18 @@ bool SnapmaticPicture::setImage(const QImage &picture, bool eXtendMode)
|
||||||
|
|
||||||
bool SnapmaticPicture::setPictureStream(const QByteArray &streamArray) // clean method
|
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 (success) {
|
||||||
if (cacheEnabled) {
|
if (cacheEnabled) {
|
||||||
QImage replacedPicture;
|
QImage replacedPicture;
|
||||||
|
@ -224,26 +512,19 @@ bool SnapmaticPicture::setPictureStream(const QByteArray &streamArray) // clean
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnapmaticPicture::setPictureTitl(const QString &newTitle_)
|
bool SnapmaticPicture::setPictureTitl(const QString &newTitle_)
|
||||||
{
|
{
|
||||||
QString newTitle = newTitle_;
|
QString newTitle = newTitle_;
|
||||||
if (newTitle.length() > 39) {
|
if (newTitle.length() > 39)
|
||||||
newTitle = newTitle.left(39);
|
newTitle = newTitle.left(39);
|
||||||
}
|
p_ragePhoto.setTitle(newTitle.toStdString().c_str());
|
||||||
p_ragePhoto.setTitle(newTitle);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SnapmaticPicture::getContentMaxLength()
|
|
||||||
{
|
|
||||||
return p_ragePhoto.photoBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SnapmaticPicture::getExportPictureFileName()
|
QString SnapmaticPicture::getExportPictureFileName()
|
||||||
{
|
{
|
||||||
return picExportFileName;
|
return picExportFileName;
|
||||||
|
@ -252,24 +533,20 @@ QString SnapmaticPicture::getExportPictureFileName()
|
||||||
QString SnapmaticPicture::getOriginalPictureFileName()
|
QString SnapmaticPicture::getOriginalPictureFileName()
|
||||||
{
|
{
|
||||||
QString newPicFileName = picFileName;
|
QString newPicFileName = picFileName;
|
||||||
if (picFileName.right(4) == ".bak") {
|
if (picFileName.right(4) == ".bak")
|
||||||
newPicFileName = QString(picFileName).remove(picFileName.length() - 4, 4);
|
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);
|
newPicFileName = QString(picFileName).remove(picFileName.length() - 7, 7);
|
||||||
}
|
|
||||||
return newPicFileName;
|
return newPicFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SnapmaticPicture::getOriginalPictureFilePath()
|
QString SnapmaticPicture::getOriginalPictureFilePath()
|
||||||
{
|
{
|
||||||
QString newPicFilePath = picFilePath;
|
QString newPicFilePath = picFilePath;
|
||||||
if (picFilePath.right(4) == ".bak") {
|
if (picFilePath.right(4) == ".bak")
|
||||||
newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 4, 4);
|
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);
|
newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 7, 7);
|
||||||
}
|
|
||||||
return newPicFilePath;
|
return newPicFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,13 +586,13 @@ QString SnapmaticPicture::getLastStep(bool readable)
|
||||||
if (descStepList.length() < 1)
|
if (descStepList.length() < 1)
|
||||||
return lastStep;
|
return lastStep;
|
||||||
int argsCount = descStepList.at(0).toInt(&intOk);
|
int argsCount = descStepList.at(0).toInt(&intOk);
|
||||||
if (!intOk) { return lastStep; }
|
if (!intOk)
|
||||||
|
return lastStep;
|
||||||
if (argsCount == 1) {
|
if (argsCount == 1) {
|
||||||
QString currentAction = descStepList.at(1);
|
QString currentAction = descStepList.at(1);
|
||||||
QString actionFile = descStepList.at(2);
|
QString actionFile = descStepList.at(2);
|
||||||
if (currentAction == "OpenFile") {
|
if (currentAction == "OpenFile")
|
||||||
return tr("open file %1").arg(actionFile);
|
return tr("open file %1").arg(actionFile);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (argsCount == 3 || argsCount == 4) {
|
else if (argsCount == 3 || argsCount == 4) {
|
||||||
QString currentAction = descStepList.at(1);
|
QString currentAction = descStepList.at(1);
|
||||||
|
@ -325,42 +602,31 @@ QString SnapmaticPicture::getLastStep(bool readable)
|
||||||
if (argsCount == 4) { actionError2 = descStepList.at(5); }
|
if (argsCount == 4) { actionError2 = descStepList.at(5); }
|
||||||
if (currentAction == "ReadingFile") {
|
if (currentAction == "ReadingFile") {
|
||||||
QString readableError = actionError;
|
QString readableError = actionError;
|
||||||
if (actionError == "NOHEADER") {
|
if (actionError == "NOHEADER")
|
||||||
readableError = tr("header not exists");
|
readableError = tr("header not exists");
|
||||||
}
|
else if (actionError == "MALFORMEDHEADER")
|
||||||
else if (actionError == "MALFORMEDHEADER") {
|
|
||||||
readableError = tr("header is malformed");
|
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);
|
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);
|
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);
|
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);
|
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");
|
readableError = tr("JSON is incomplete and malformed");
|
||||||
}
|
else if (actionError == "JSONINCOMPLETE")
|
||||||
else if (actionError == "JSONINCOMPLETE") {
|
|
||||||
readableError = tr("JSON is incomplete");
|
readableError = tr("JSON is incomplete");
|
||||||
}
|
else if (actionError == "JSONERROR")
|
||||||
else if (actionError == "JSONERROR") {
|
|
||||||
readableError = tr("JSON is malformed");
|
readableError = tr("JSON is malformed");
|
||||||
}
|
|
||||||
return tr("reading file %1 because of %2", "Example for %2: JSON is malformed error").arg(actionFile, readableError);
|
return tr("reading file %1 because of %2", "Example for %2: JSON is malformed error").arg(actionFile, readableError);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
return lastStep;
|
return lastStep;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
return lastStep;
|
return lastStep;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return lastStep;
|
return lastStep;
|
||||||
|
|
||||||
|
@ -368,18 +634,16 @@ QString SnapmaticPicture::getLastStep(bool readable)
|
||||||
|
|
||||||
QImage SnapmaticPicture::getImage()
|
QImage SnapmaticPicture::getImage()
|
||||||
{
|
{
|
||||||
if (cacheEnabled) {
|
if (cacheEnabled)
|
||||||
return cachePicture;
|
return cachePicture;
|
||||||
}
|
else
|
||||||
else {
|
return QImage::fromData(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()), "JPEG");
|
||||||
return QImage::fromData(p_ragePhoto.photoData(), "JPEG");
|
|
||||||
}
|
|
||||||
return QImage();
|
return QImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SnapmaticPicture::getPictureStream()
|
QByteArray SnapmaticPicture::getPictureStream()
|
||||||
{
|
{
|
||||||
return p_ragePhoto.photoData();
|
return QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnapmaticPicture::isPicOk()
|
bool SnapmaticPicture::isPicOk()
|
||||||
|
@ -412,7 +676,7 @@ bool SnapmaticPicture::isJsonOk()
|
||||||
|
|
||||||
QString SnapmaticPicture::getJsonStr()
|
QString SnapmaticPicture::getJsonStr()
|
||||||
{
|
{
|
||||||
return QString::fromUtf8(p_ragePhoto.jsonData());
|
return QString::fromUtf8(p_ragePhoto.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
SnapmaticProperties SnapmaticPicture::getSnapmaticProperties()
|
SnapmaticProperties SnapmaticPicture::getSnapmaticProperties()
|
||||||
|
@ -422,7 +686,6 @@ SnapmaticProperties SnapmaticPicture::getSnapmaticProperties()
|
||||||
|
|
||||||
void SnapmaticPicture::parseJsonContent()
|
void SnapmaticPicture::parseJsonContent()
|
||||||
{
|
{
|
||||||
QJsonObject jsonObject = p_ragePhoto.jsonObject();
|
|
||||||
QVariantMap jsonMap = jsonObject.toVariantMap();
|
QVariantMap jsonMap = jsonObject.toVariantMap();
|
||||||
|
|
||||||
bool jsonIncomplete = false;
|
bool jsonIncomplete = false;
|
||||||
|
@ -540,28 +803,28 @@ void SnapmaticPicture::parseJsonContent()
|
||||||
|
|
||||||
bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties)
|
bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties)
|
||||||
{
|
{
|
||||||
QJsonObject jsonObject = p_ragePhoto.jsonObject();
|
QJsonObject t_jsonObject = jsonObject;
|
||||||
|
|
||||||
QJsonObject locObject;
|
QJsonObject locObject;
|
||||||
locObject["x"] = properties.location.x;
|
locObject["x"] = properties.location.x;
|
||||||
locObject["y"] = properties.location.y;
|
locObject["y"] = properties.location.y;
|
||||||
locObject["z"] = properties.location.z;
|
locObject["z"] = properties.location.z;
|
||||||
|
|
||||||
jsonObject["loc"] = locObject;
|
t_jsonObject["loc"] = locObject;
|
||||||
jsonObject["uid"] = properties.uid;
|
t_jsonObject["uid"] = properties.uid;
|
||||||
jsonObject["area"] = properties.location.area;
|
t_jsonObject["area"] = properties.location.area;
|
||||||
jsonObject["crewid"] = properties.crewID;
|
t_jsonObject["crewid"] = properties.crewID;
|
||||||
jsonObject["street"] = properties.streetID;
|
t_jsonObject["street"] = properties.streetID;
|
||||||
jsonObject["creat"] = QJsonValue::fromVariant(properties.createdTimestamp);
|
t_jsonObject["creat"] = QJsonValue::fromVariant(properties.createdTimestamp);
|
||||||
jsonObject["plyrs"] = QJsonValue::fromVariant(properties.playersList);
|
t_jsonObject["plyrs"] = QJsonValue::fromVariant(properties.playersList);
|
||||||
jsonObject["meme"] = properties.isMeme;
|
t_jsonObject["meme"] = properties.isMeme;
|
||||||
jsonObject["mug"] = properties.isMug;
|
t_jsonObject["mug"] = properties.isMug;
|
||||||
jsonObject["slf"] = properties.isSelfie;
|
t_jsonObject["slf"] = properties.isSelfie;
|
||||||
jsonObject["drctr"] = properties.isFromDirector;
|
t_jsonObject["drctr"] = properties.isFromDirector;
|
||||||
jsonObject["rsedtr"] = properties.isFromRSEditor;
|
t_jsonObject["rsedtr"] = properties.isFromRSEditor;
|
||||||
jsonObject["onislandx"] = properties.location.isCayoPerico;
|
t_jsonObject["onislandx"] = properties.location.isCayoPerico;
|
||||||
|
|
||||||
QJsonDocument jsonDocument(jsonObject);
|
const QJsonDocument jsonDocument(t_jsonObject);
|
||||||
if (setJsonStr(QString::fromUtf8(jsonDocument.toJson(QJsonDocument::Compact)))) {
|
if (setJsonStr(QString::fromUtf8(jsonDocument.toJson(QJsonDocument::Compact)))) {
|
||||||
localProperties = properties;
|
localProperties = properties;
|
||||||
return true;
|
return true;
|
||||||
|
@ -571,14 +834,16 @@ bool SnapmaticPicture::setSnapmaticProperties(SnapmaticProperties properties)
|
||||||
|
|
||||||
bool SnapmaticPicture::setJsonStr(const QString &newJsonStr, bool updateProperties)
|
bool SnapmaticPicture::setJsonStr(const QString &newJsonStr, bool updateProperties)
|
||||||
{
|
{
|
||||||
if (p_ragePhoto.setJsonData(newJsonStr.toUtf8())) {
|
const QJsonDocument t_jsonDocument = QJsonDocument::fromJson(newJsonStr.toStdString().c_str());
|
||||||
if (updateProperties)
|
if (t_jsonDocument.isNull())
|
||||||
parseJsonContent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
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
|
// FILE MANAGEMENT
|
||||||
|
@ -588,7 +853,7 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, SnapmaticFormat fo
|
||||||
// Keep current format when Auto_Format is used
|
// Keep current format when Auto_Format is used
|
||||||
SnapmaticFormat format = format_;
|
SnapmaticFormat format = format_;
|
||||||
if (format_ == SnapmaticFormat::Auto_Format) {
|
if (format_ == SnapmaticFormat::Auto_Format) {
|
||||||
if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) {
|
if (p_ragePhoto.format() == G5EPhotoFormat::G5EX) {
|
||||||
format = SnapmaticFormat::G5E_Format;
|
format = SnapmaticFormat::G5E_Format;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -597,68 +862,27 @@ bool SnapmaticPicture::exportPicture(const QString &fileName, SnapmaticFormat fo
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saveSuccess = false;
|
bool saveSuccess = false;
|
||||||
#if QT_VERSION >= 0x050000
|
QSaveFile picFile(fileName);
|
||||||
QSaveFile *picFile = new QSaveFile(fileName);
|
if (picFile.open(QIODevice::WriteOnly)) {
|
||||||
#else
|
|
||||||
QFile *picFile = new QFile(StandardPaths::tempLocation() % "/" % QFileInfo(fileName).fileName() % ".tmp");
|
|
||||||
#endif
|
|
||||||
if (picFile->open(QIODevice::WriteOnly)) {
|
|
||||||
if (format == SnapmaticFormat::G5E_Format) {
|
if (format == SnapmaticFormat::G5E_Format) {
|
||||||
p_ragePhoto.save(picFile, RagePhoto::PhotoFormat::G5EX);
|
gta5view_export_save(&picFile, p_ragePhoto.data());
|
||||||
#if QT_VERSION >= 0x050000
|
saveSuccess = picFile.commit();
|
||||||
saveSuccess = picFile->commit();
|
|
||||||
#else
|
|
||||||
saveSuccess = true;
|
|
||||||
picFile->close();
|
|
||||||
#endif
|
|
||||||
delete picFile;
|
|
||||||
}
|
}
|
||||||
else if (format == SnapmaticFormat::JPEG_Format) {
|
else if (format == SnapmaticFormat::JPEG_Format) {
|
||||||
picFile->write(p_ragePhoto.photoData());
|
picFile.write(QByteArray::fromRawData(p_ragePhoto.photoData(), p_ragePhoto.photoSize()));
|
||||||
#if QT_VERSION >= 0x050000
|
saveSuccess = picFile.commit();
|
||||||
saveSuccess = picFile->commit();
|
|
||||||
#else
|
|
||||||
saveSuccess = true;
|
|
||||||
picFile->close();
|
|
||||||
#endif
|
|
||||||
delete picFile;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p_ragePhoto.save(picFile, RagePhoto::PhotoFormat::GTA5);
|
bool ok;
|
||||||
#if QT_VERSION >= 0x050000
|
const std::string photo = p_ragePhoto.save(&ok);
|
||||||
saveSuccess = picFile->commit();
|
if (ok)
|
||||||
#else
|
picFile.write(photo.data(), photo.size());
|
||||||
saveSuccess = true;
|
saveSuccess = picFile.commit();
|
||||||
picFile->close();
|
|
||||||
#endif
|
|
||||||
delete picFile;
|
|
||||||
}
|
}
|
||||||
#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;
|
return saveSuccess;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
delete picFile;
|
|
||||||
return saveSuccess;
|
return saveSuccess;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnapmaticPicture::setPicFileName(const QString &picFileName_)
|
void SnapmaticPicture::setPicFileName(const QString &picFileName_)
|
||||||
|
@ -674,19 +898,19 @@ void SnapmaticPicture::setPicFilePath(const QString &picFilePath_)
|
||||||
bool SnapmaticPicture::deletePicFile()
|
bool SnapmaticPicture::deletePicFile()
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (!QFile::exists(picFilePath)) {
|
if (!QFile::exists(picFilePath))
|
||||||
success = true;
|
success = true;
|
||||||
}
|
else if (QFile::remove(picFilePath))
|
||||||
else if (QFile::remove(picFilePath)) {
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
|
||||||
if (isHidden()) {
|
if (isHidden()) {
|
||||||
const QString picBakPath = QString(picFilePath).remove(picFilePath.length() - 7, 7) % ".bak";
|
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 {
|
else {
|
||||||
const QString picBakPath = picFilePath % ".bak";
|
const QString picBakPath = picFilePath % ".bak";
|
||||||
if (QFile::exists(picBakPath)) QFile::remove(picBakPath);
|
if (QFile::exists(picBakPath))
|
||||||
|
QFile::remove(picBakPath);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -695,23 +919,21 @@ bool SnapmaticPicture::deletePicFile()
|
||||||
|
|
||||||
bool SnapmaticPicture::isHidden()
|
bool SnapmaticPicture::isHidden()
|
||||||
{
|
{
|
||||||
if (picFilePath.right(7) == QLatin1String(".hidden")) {
|
if (picFilePath.right(7) == QLatin1String(".hidden"))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnapmaticPicture::isVisible()
|
bool SnapmaticPicture::isVisible()
|
||||||
{
|
{
|
||||||
if (picFilePath.right(7) == QLatin1String(".hidden")) {
|
if (picFilePath.right(7) == QLatin1String(".hidden"))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnapmaticPicture::setPictureHidden()
|
bool SnapmaticPicture::setPictureHidden()
|
||||||
{
|
{
|
||||||
if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) {
|
if (picFormat == G5EPhotoFormat::G5EX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!isHidden()) {
|
if (!isHidden()) {
|
||||||
|
@ -727,9 +949,8 @@ bool SnapmaticPicture::setPictureHidden()
|
||||||
|
|
||||||
bool SnapmaticPicture::setPictureVisible()
|
bool SnapmaticPicture::setPictureVisible()
|
||||||
{
|
{
|
||||||
if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) {
|
if (picFormat == G5EPhotoFormat::G5EX)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
if (isHidden()) {
|
if (isHidden()) {
|
||||||
QString newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 7, 7);
|
QString newPicFilePath = QString(picFilePath).remove(picFilePath.length() - 7, 7);
|
||||||
if (QFile::rename(picFilePath, newPicFilePath)) {
|
if (QFile::rename(picFilePath, newPicFilePath)) {
|
||||||
|
@ -752,20 +973,19 @@ QSize SnapmaticPicture::getSnapmaticResolution()
|
||||||
|
|
||||||
SnapmaticFormat SnapmaticPicture::getSnapmaticFormat()
|
SnapmaticFormat SnapmaticPicture::getSnapmaticFormat()
|
||||||
{
|
{
|
||||||
if (p_ragePhoto.photoFormat() == RagePhoto::PhotoFormat::G5EX) {
|
if (picFormat == G5EPhotoFormat::G5EX)
|
||||||
return SnapmaticFormat::G5E_Format;
|
return SnapmaticFormat::G5E_Format;
|
||||||
}
|
|
||||||
return SnapmaticFormat::PGTA_Format;
|
return SnapmaticFormat::PGTA_Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnapmaticPicture::setSnapmaticFormat(SnapmaticFormat format)
|
void SnapmaticPicture::setSnapmaticFormat(SnapmaticFormat format)
|
||||||
{
|
{
|
||||||
if (format == SnapmaticFormat::G5E_Format) {
|
if (format == SnapmaticFormat::G5E_Format) {
|
||||||
p_ragePhoto.setPhotoFormat(RagePhoto::PhotoFormat::G5EX);
|
picFormat = G5EPhotoFormat::G5EX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (format == SnapmaticFormat::PGTA_Format) {
|
else if (format == SnapmaticFormat::PGTA_Format) {
|
||||||
p_ragePhoto.setPhotoFormat(RagePhoto::PhotoFormat::GTA5);
|
picFormat = RagePhoto::PhotoFormat::GTA5;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << "setSnapmaticFormat: Invalid SnapmaticFormat defined, valid SnapmaticFormats are G5E_Format and PGTA_Format";
|
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
|
// VERIFY CHAR FOR BE A VALID SNAPMATIC CHARACTER
|
||||||
if (titleChar.isLetterOrNumber() || titleChar.isPrint()) {
|
if (titleChar.isLetterOrNumber() || titleChar.isPrint()) {
|
||||||
if (titleChar == '<' || titleChar == '>' || titleChar == '\\') return false;
|
if (titleChar == '<' || titleChar == '>' || titleChar == '\\')
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -802,9 +1023,8 @@ bool SnapmaticPicture::verifyTitleChar(const QChar &titleChar)
|
||||||
|
|
||||||
// STRING OPERATIONS
|
// STRING OPERATIONS
|
||||||
|
|
||||||
QString SnapmaticPicture::parseTitleString(const QByteArray &commitBytes, int maxLength)
|
QString SnapmaticPicture::parseTitleString(const QByteArray &commitBytes)
|
||||||
{
|
{
|
||||||
Q_UNUSED(maxLength)
|
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
QStringDecoder strDecoder = QStringDecoder(QStringDecoder::Utf16LE);
|
QStringDecoder strDecoder = QStringDecoder(QStringDecoder::Utf16LE);
|
||||||
QString retStr = strDecoder(commitBytes);
|
QString retStr = strDecoder(commitBytes);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* gta5spv Grand Theft Auto Snapmatic Picture Viewer
|
* gta5view Grand Theft Auto V Profile Viewer
|
||||||
* Copyright (C) 2016-2020 Syping
|
* Copyright (C) 2016-2023 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,6 +21,7 @@
|
||||||
|
|
||||||
#include "RagePhoto.h"
|
#include "RagePhoto.h"
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
@ -28,6 +29,16 @@
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
enum class SnapmaticFormat : int { Auto_Format = 0, PGTA_Format = 1, JPEG_Format = 2, G5E_Format = 3 };
|
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 SnapmaticProperties {
|
||||||
struct SnapmaticLocation {
|
struct SnapmaticLocation {
|
||||||
|
@ -74,7 +85,6 @@ public:
|
||||||
QString getExportPictureFileName();
|
QString getExportPictureFileName();
|
||||||
QString getOriginalPictureFileName();
|
QString getOriginalPictureFileName();
|
||||||
QString getOriginalPictureFilePath();
|
QString getOriginalPictureFilePath();
|
||||||
int getContentMaxLength();
|
|
||||||
bool setImage(const QImage &picture, bool eXtendMode = false);
|
bool setImage(const QImage &picture, bool eXtendMode = false);
|
||||||
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);
|
||||||
|
@ -130,7 +140,7 @@ public:
|
||||||
static bool verifyTitle(const QString &title);
|
static bool verifyTitle(const QString &title);
|
||||||
|
|
||||||
// STRING OPERATIONS
|
// STRING OPERATIONS
|
||||||
static QString parseTitleString(const QByteArray &commitBytes, int maxLength);
|
static QString parseTitleString(const QByteArray &commitBytes);
|
||||||
static QString convertDrawStringForLog(const QString &inputStr);
|
static QString convertDrawStringForLog(const QString &inputStr);
|
||||||
static QString convertLogStringForDraw(const QString &inputStr);
|
static QString convertLogStringForDraw(const QString &inputStr);
|
||||||
|
|
||||||
|
@ -145,14 +155,17 @@ private:
|
||||||
QString pictureStr;
|
QString pictureStr;
|
||||||
QString lastStep;
|
QString lastStep;
|
||||||
QString sortStr;
|
QString sortStr;
|
||||||
|
uint32_t picFormat;
|
||||||
bool picOk;
|
bool picOk;
|
||||||
bool cacheEnabled;
|
bool cacheEnabled;
|
||||||
bool isFormatSwitch;
|
bool isFormatSwitch;
|
||||||
|
bool isPreLoaded;
|
||||||
|
|
||||||
// JSON
|
// JSON
|
||||||
void parseJsonContent();
|
void parseJsonContent();
|
||||||
bool jsonOk;
|
bool jsonOk;
|
||||||
SnapmaticProperties localProperties;
|
SnapmaticProperties localProperties;
|
||||||
|
QJsonObject jsonObject;
|
||||||
|
|
||||||
// VERIFY CONTENT
|
// VERIFY CONTENT
|
||||||
static bool verifyTitleChar(const QChar &titleChar);
|
static bool verifyTitleChar(const QChar &titleChar);
|
||||||
|
|
|
@ -195,7 +195,7 @@ bool SnapmaticWidget::deletePicture()
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "DeleteSuccess";
|
jsonObject["Type"] = "DeleteSuccess";
|
||||||
jsonObject["ExtraFlags"] = "Snapmatic";
|
jsonObject["ExtraFlags"] = "Snapmatic";
|
||||||
jsonObject["DeletedSize"] = QString::number(smpic->getContentMaxLength());
|
jsonObject["DeletedSize"] = QString::number(smpic->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["DeletedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
@ -381,7 +381,7 @@ void SnapmaticWidget::editSnapmaticImage()
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "ImageEdited";
|
jsonObject["Type"] = "ImageEdited";
|
||||||
jsonObject["ExtraFlags"] = "Interface";
|
jsonObject["ExtraFlags"] = "Interface";
|
||||||
jsonObject["EditedSize"] = QString::number(smpic->getContentMaxLength());
|
jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
@ -439,7 +439,7 @@ void SnapmaticWidget::openMapViewer()
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject["Type"] = "LocationEdited";
|
jsonObject["Type"] = "LocationEdited";
|
||||||
jsonObject["ExtraFlags"] = "Interface";
|
jsonObject["ExtraFlags"] = "Interface";
|
||||||
jsonObject["EditedSize"] = QString::number(picture->getContentMaxLength());
|
jsonObject["EditedSize"] = QString::number(smpic->ragePhoto()->photoSize());
|
||||||
#if QT_VERSION >= 0x060000
|
#if QT_VERSION >= 0x060000
|
||||||
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
jsonObject["EditedTime"] = QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -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-2023 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
|
||||||
|
@ -184,11 +184,7 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D
|
||||||
QObject::connect(donateAction, &QAction::triggered, this, [=](){
|
QObject::connect(donateAction, &QAction::triggered, this, [=](){
|
||||||
QDialog *donateDialog = new QDialog(this);
|
QDialog *donateDialog = new QDialog(this);
|
||||||
donateDialog->setWindowTitle(QString("%1 - %2").arg(GTA5SYNC_APPSTR, tr("Donate")));
|
donateDialog->setWindowTitle(QString("%1 - %2").arg(GTA5SYNC_APPSTR, tr("Donate")));
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
donateDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
donateDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
donateDialog->setWindowFlags(donateDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
QVBoxLayout *donateLayout = new QVBoxLayout;
|
QVBoxLayout *donateLayout = new QVBoxLayout;
|
||||||
donateDialog->setLayout(donateLayout);
|
donateDialog->setLayout(donateLayout);
|
||||||
QLabel *methodsLabel = new QLabel(QString("<b>%1</b>").arg(tr("Donation methods").toHtmlEscaped()), donateDialog);
|
QLabel *methodsLabel = new QLabel(QString("<b>%1</b>").arg(tr("Donation methods").toHtmlEscaped()), donateDialog);
|
||||||
|
@ -222,11 +218,7 @@ UserInterface::UserInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, D
|
||||||
QObject::connect(currencyButton, &QPushButton::pressed, donateDialog, [=](){
|
QObject::connect(currencyButton, &QPushButton::pressed, donateDialog, [=](){
|
||||||
QDialog *addressDialog = new QDialog(donateDialog);
|
QDialog *addressDialog = new QDialog(donateDialog);
|
||||||
addressDialog->setWindowTitle(currencyStr);
|
addressDialog->setWindowTitle(currencyStr);
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
addressDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
addressDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
addressDialog->setWindowFlags(donateDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
QVBoxLayout *addressLayout = new QVBoxLayout;
|
QVBoxLayout *addressLayout = new QVBoxLayout;
|
||||||
addressDialog->setLayout(addressLayout);
|
addressDialog->setLayout(addressLayout);
|
||||||
QLabel *addressLabel = new QLabel(address, addressDialog);
|
QLabel *addressLabel = new QLabel(address, addressDialog);
|
||||||
|
@ -580,11 +572,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);
|
fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
fileDialog.setWindowTitle(tr("Open File..."));
|
fileDialog.setWindowTitle(tr("Open File..."));
|
||||||
|
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
|
@ -754,11 +742,7 @@ void UserInterface::showMessages(const QStringList messages)
|
||||||
{
|
{
|
||||||
QDialog *messageDialog = new QDialog(this);
|
QDialog *messageDialog = new QDialog(this);
|
||||||
messageDialog->setWindowTitle(tr("%1 - Messages").arg(GTA5SYNC_APPSTR));
|
messageDialog->setWindowTitle(tr("%1 - Messages").arg(GTA5SYNC_APPSTR));
|
||||||
#if QT_VERSION >= 0x050900
|
|
||||||
messageDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
messageDialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
#else
|
|
||||||
messageDialog->setWindowFlags(messageDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
|
|
||||||
#endif
|
|
||||||
QVBoxLayout *messageLayout = new QVBoxLayout;
|
QVBoxLayout *messageLayout = new QVBoxLayout;
|
||||||
messageDialog->setLayout(messageLayout);
|
messageDialog->setLayout(messageLayout);
|
||||||
QStackedWidget *stackWidget = new QStackedWidget(messageDialog);
|
QStackedWidget *stackWidget = new QStackedWidget(messageDialog);
|
||||||
|
|
1
src/libragephoto
Submodule
1
src/libragephoto
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 8e732195493c4a4d5f120f290e77524645d8772e
|
|
@ -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-2023 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,15 +21,12 @@
|
||||||
#include "ProfileDatabase.h"
|
#include "ProfileDatabase.h"
|
||||||
#include "DatabaseThread.h"
|
#include "DatabaseThread.h"
|
||||||
#include "SavegameDialog.h"
|
#include "SavegameDialog.h"
|
||||||
#include "OptionsDialog.h"
|
|
||||||
#include "PictureDialog.h"
|
#include "PictureDialog.h"
|
||||||
#include "UserInterface.h"
|
#include "UserInterface.h"
|
||||||
#include "CrewDatabase.h"
|
#include "CrewDatabase.h"
|
||||||
#include "SavegameData.h"
|
#include "SavegameData.h"
|
||||||
#include "UiModWidget.h"
|
|
||||||
#include "UiModLabel.h"
|
#include "UiModLabel.h"
|
||||||
#include "IconLoader.h"
|
#include "IconLoader.h"
|
||||||
#include "AppEnv.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <QSignalMapper>
|
#include <QSignalMapper>
|
||||||
|
@ -227,7 +224,6 @@ int main(int argc, char *argv[])
|
||||||
bool readOk = picture.readingPictureFromFile(arg1);
|
bool readOk = picture.readingPictureFromFile(arg1);
|
||||||
picDialog.setWindowIcon(IconLoader::loadingAppIcon());
|
picDialog.setWindowIcon(IconLoader::loadingAppIcon());
|
||||||
picDialog.setSnapmaticPicture(&picture, readOk);
|
picDialog.setSnapmaticPicture(&picture, readOk);
|
||||||
picDialog.setWindowFlags(picDialog.windowFlags()^Qt::Dialog^Qt::Window);
|
|
||||||
|
|
||||||
int crewID = picture.getSnapmaticProperties().crewID;
|
int crewID = picture.getSnapmaticProperties().crewID;
|
||||||
if (crewID != 0)
|
if (crewID != 0)
|
||||||
|
@ -254,7 +250,6 @@ int main(int argc, char *argv[])
|
||||||
bool readOk = savegame.readingSavegameFromFile(arg1);
|
bool readOk = savegame.readingSavegameFromFile(arg1);
|
||||||
savegameDialog.setWindowIcon(IconLoader::loadingAppIcon());
|
savegameDialog.setWindowIcon(IconLoader::loadingAppIcon());
|
||||||
savegameDialog.setSavegameData(&savegame, arg1, readOk);
|
savegameDialog.setSavegameData(&savegame, arg1, readOk);
|
||||||
savegameDialog.setWindowFlags(savegameDialog.windowFlags()^Qt::Dialog^Qt::Window);
|
|
||||||
|
|
||||||
if (!readOk)
|
if (!readOk)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in a new issue