Browse Source

add JSON Editor + Interface improvements

1.5.x
Syping 5 years ago
parent
commit
f9eee75757
  1. 8
      .travis.yml
  2. 11
      CrewDatabase.cpp
  3. 1
      CrewDatabase.h
  4. 164
      JsonEditorDialog.cpp
  5. 56
      JsonEditorDialog.h
  6. 124
      JsonEditorDialog.ui
  7. 1
      MapLocationDialog.cpp
  8. 2
      MapLocationDialog.h
  9. 86
      OptionsDialog.cpp
  10. 3
      OptionsDialog.h
  11. 73
      OptionsDialog.ui
  12. 117
      PictureDialog.cpp
  13. 12
      PictureDialog.h
  14. 57
      ProfileInterface.cpp
  15. 3
      ProfileInterface.h
  16. 13
      SnapmaticEditor.cpp
  17. 95
      SnapmaticPicture.cpp
  18. 3
      SnapmaticPicture.h
  19. 48
      SnapmaticWidget.cpp
  20. 2
      SnapmaticWidget.h
  21. 72
      anpro/JSHighlighter.cpp
  22. 56
      anpro/JSHighlighter.h
  23. 2
      config.h
  24. 7
      gta5view.pro
  25. 467
      lang/gta5sync_no.ts
  26. 38
      main.cpp
  27. 4
      res/app.rc
  28. BIN
      res/gta5sync_de.qm
  29. 378
      res/gta5sync_de.ts
  30. BIN
      res/gta5sync_en_US.qm
  31. 362
      res/gta5sync_en_US.ts
  32. BIN
      res/gta5sync_fr.qm
  33. 368
      res/gta5sync_fr.ts
  34. BIN
      res/gta5sync_ru.qm
  35. 366
      res/gta5sync_ru.ts

8
.travis.yml

@ -32,14 +32,14 @@ before_script:
script:
- cd qt5
- qmake -qt=5 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=c++11 DEFINES+=GTA5SYNC_BUILDTYPE_DEV "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"$PACKAGE_VERSION-dev3\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro
- qmake -qt=5 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=c++11 DEFINES+=GTA5SYNC_BUILDTYPE_DEV "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"$PACKAGE_VERSION-dev4\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro
- make -j 4
- sudo checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt5 --pkgversion=$PACKAGE_VERSION --pkgrelease=dev3 --pkggroup=utility --maintainer="Syping on Travis \<[email protected]\>" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5,qttranslations5-l10n --conflicts=gta5view,gta5view-qt4 --replaces=gta5view,gta5view-qt4 --pakdir=../../package
- sudo checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt5 --pkgversion=$PACKAGE_VERSION --pkgrelease=dev4 --pkggroup=utility --maintainer="Syping on Travis \<[email protected]\>" --requires=libqt5core5a,libqt5gui5,libqt5network5,libqt5widgets5,qttranslations5-l10n --conflicts=gta5view,gta5view-qt4 --replaces=gta5view,gta5view-qt4 --pakdir=../../package
- cd ..
- cd qt4
- qmake -qt=4 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=c++11 DEFINES+=GTA5SYNC_BUILDTYPE_DEV "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"$PACKAGE_VERSION-dev3\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro
- qmake -qt=4 GTA5SYNC_PREFIX=/usr QMAKE_CXXFLAGS+=-std=c++11 DEFINES+=GTA5SYNC_BUILDTYPE_DEV "DEFINES+=GTA5SYNC_APPVER=\\\\\\\"$PACKAGE_VERSION-dev4\\\\\\\"" DEFINES+=GTA5SYNC_QCONF ../../gta5view.pro
- make -j 4
- sudo checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt4 --pkgversion=$PACKAGE_VERSION --pkgrelease=dev3 --pkggroup=utility --maintainer="Syping on Travis \<[email protected]\>" --requires=libqtcore4,libqtgui4,libqt4-network,qtcore4-l10n --conflicts=gta5view,gta5view-qt5 --replaces=gta5view,gta5view-qt5 --pakdir=../../package
- sudo checkinstall -D --default --nodoc --install=no --pkgname=gta5view-qt4 --pkgversion=$PACKAGE_VERSION --pkgrelease=dev4 --pkggroup=utility --maintainer="Syping on Travis \<[email protected]\>" --requires=libqtcore4,libqtgui4,libqt4-network,qtcore4-l10n --conflicts=gta5view,gta5view-qt5 --replaces=gta5view,gta5view-qt5 --pakdir=../../package
- cd ..
deploy:

11
CrewDatabase.cpp

@ -92,6 +92,17 @@ QStringList CrewDatabase::getCompatibleCrews_p()
return crewDB->childKeys();
}
QString CrewDatabase::getCrewName(QString crewID)
{
QMutexLocker locker(&mutex);
#ifdef GTA5SYNC_DEBUG
qDebug() << "getCrewName" << crewID;
#endif
QString crewStr = crewDB->value(crewID, crewID).toString();
if (crewID == "0") crewStr = tr("No Crew", "");
return crewStr;
}
QString CrewDatabase::getCrewName(int crewID)
{
QMutexLocker locker(&mutex);

1
CrewDatabase.h

@ -29,6 +29,7 @@ class CrewDatabase : public QObject
Q_OBJECT
public:
explicit CrewDatabase(QObject *parent = 0);
QString getCrewName(QString crewID);
QString getCrewName(int crewID);
QStringList getCompatibleCrews();
QStringList getCrews();

164
JsonEditorDialog.cpp

@ -0,0 +1,164 @@
/*****************************************************************************
* gta5sync GRAND THEFT AUTO V SYNC
* Copyright (C) 2017 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 "JsonEditorDialog.h"
#include "ui_JsonEditorDialog.h"
#include "SnapmaticEditor.h"
#include "AppEnv.h"
#include <QStringBuilder>
#include <QJsonDocument>
#include <QMessageBox>
#if QT_VERSION >= 0x050200
#include <QFontDatabase>
#include <QDebug>
#endif
JsonEditorDialog::JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent) :
QDialog(parent), smpic(picture),
ui(new Ui::JsonEditorDialog)
{
// Set Window Flags
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint^Qt::WindowMinMaxButtonsHint);
ui->setupUi(this);
if (QIcon::hasThemeIcon("dialog-close"))
{
ui->cmdClose->setIcon(QIcon::fromTheme("dialog-close"));
}
jsonCode = picture->getJsonStr();
#if QT_VERSION >= 0x050200
ui->txtJSON->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
#endif
QFontMetrics fm(ui->txtJSON->font());
ui->txtJSON->setTabStopWidth(fm.width(" "));
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonCode.toUtf8());
ui->txtJSON->setStyleSheet("QPlainTextEdit{background-color: rgb(46, 47, 48); color: rgb(238, 231, 172);}");
ui->txtJSON->setPlainText(QString::fromUtf8(jsonDocument.toJson(QJsonDocument::Indented)).trimmed());
jsonHl = new JSHighlighter(ui->txtJSON->document());
// DPI calculation
qreal screenRatio = AppEnv::screenRatio();
ui->hlButtons->setContentsMargins(9 * screenRatio, 0, 9 * screenRatio, 0);
if (screenRatio > 1)
{
ui->lineJSON->setMinimumHeight(qRound(1 * screenRatio));
ui->lineJSON->setMaximumHeight(qRound(1 * screenRatio));
}
resize(450 * screenRatio, 550 * screenRatio);
}
JsonEditorDialog::~JsonEditorDialog()
{
delete jsonHl;
delete ui;
}
void JsonEditorDialog::closeEvent(QCloseEvent *ev)
{
QString jsonPatched = QString(ui->txtJSON->toPlainText()).replace("\t", " ");
QJsonDocument jsonNew = QJsonDocument::fromJson(jsonPatched.toUtf8());
QJsonDocument jsonOriginal = QJsonDocument::fromJson(jsonCode.toUtf8());
QString originalCode = QString::fromUtf8(jsonOriginal.toJson(QJsonDocument::Compact));
QString newCode = QString::fromUtf8(jsonNew.toJson(QJsonDocument::Compact));
if (newCode != originalCode)
{
QMessageBox::StandardButton button = QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("<h4>Unsaved changes detected</h4>You want to save the JSON content before you quit?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel);
if (button == QMessageBox::Yes)
{
if (saveJsonContent())
{
ev->accept();
}
else
{
ev->ignore();
}
return;
}
else if (button == QMessageBox::No)
{
ev->accept();
return;
}
else
{
ev->ignore();
return;
}
}
}
bool JsonEditorDialog::saveJsonContent()
{
QString jsonPatched = QString(ui->txtJSON->toPlainText()).replace("\t", " ");
QJsonDocument jsonNew = QJsonDocument::fromJson(jsonPatched.toUtf8());
if (!jsonNew.isEmpty())
{
QJsonDocument jsonOriginal = QJsonDocument::fromJson(jsonCode.toUtf8());
QString originalCode = QString::fromUtf8(jsonOriginal.toJson(QJsonDocument::Compact));
QString newCode = QString::fromUtf8(jsonNew.toJson(QJsonDocument::Compact));
if (newCode != originalCode)
{
QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName);
}
smpic->setJsonStr(newCode, true);
if (!smpic->isJsonOk())
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of JSON Error"));
smpic->setJsonStr(originalCode, true);
return false;
}
if (!smpic->exportPicture(currentFilePath))
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error"));
smpic->setJsonStr(originalCode, true);
return false;
}
jsonCode = newCode;
smpic->emitUpdate();
return true;
}
return true;
}
else
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of JSON Error"));
return false;
}
}
void JsonEditorDialog::on_cmdClose_clicked()
{
this->close();
}
void JsonEditorDialog::on_cmdSave_clicked()
{
if (saveJsonContent())
{
this->close();
}
}

56
JsonEditorDialog.h

@ -0,0 +1,56 @@
/*****************************************************************************
* gta5sync GRAND THEFT AUTO V SYNC
* Copyright (C) 2017 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 JSONEDITORDIALOG_H
#define JSONEDITORDIALOG_H
#include "SnapmaticPicture.h"
#include "JSHighlighter.h"
#include <QDialog>
namespace Ui {
class JsonEditorDialog;
}
class JsonEditorDialog : public QDialog
{
Q_OBJECT
public:
explicit JsonEditorDialog(SnapmaticPicture *picture, QWidget *parent = 0);
bool saveJsonContent();
~JsonEditorDialog();
protected:
void closeEvent(QCloseEvent *ev);
private slots:
void on_cmdClose_clicked();
void on_cmdSave_clicked();
signals:
void codeUpdated(QString jsonCode);
private:
QString jsonCode;
JSHighlighter *jsonHl;
SnapmaticPicture *smpic;
Ui::JsonEditorDialog *ui;
};
#endif // JSONEDITORDIALOG_H

124
JsonEditorDialog.ui

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>JsonEditorDialog</class>
<widget class="QDialog" name="JsonEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>550</width>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
<string>Snapmatic JSON Editor</string>
</property>
<layout class="QVBoxLayout" name="vlInterface">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="vlJSON">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPlainTextEdit" name="txtJSON">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="Line" name="lineJSON">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QFrame[frameShape=&quot;4&quot;]
{
color: black;
}</string>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="hlButtons">
<item>
<spacer name="hsButtons">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cmdSave">
<property name="text">
<string>&amp;Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cmdClose">
<property name="text">
<string>&amp;Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

1
MapLocationDialog.cpp

@ -34,6 +34,7 @@ MapLocationDialog::MapLocationDialog(double x, double y, QWidget *parent) :
ui->cmdApply->setVisible(false);
ui->cmdRevert->setVisible(false);
ui->cmdDone->setCursor(Qt::ArrowCursor);
ui->cmdClose->setCursor(Qt::ArrowCursor);
// DPI calculation
qreal screenRatio = AppEnv::screenRatio();

2
MapLocationDialog.h

@ -51,13 +51,13 @@ private slots:
void on_cmdClose_clicked();
private:
Ui::MapLocationDialog *ui;
double xpos_old;
double ypos_old;
double xpos_new;
double ypos_new;
bool propUpdate;
bool changeMode;
Ui::MapLocationDialog *ui;
};
#endif // MAPLOCATIONDIALOG_H

86
OptionsDialog.cpp

@ -25,6 +25,7 @@
#include "config.h"
#include <QStringBuilder>
#include <QDesktopWidget>
#include <QStyleFactory>
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
@ -72,18 +73,19 @@ OptionsDialog::OptionsDialog(ProfileDatabase *profileDB, QWidget *parent) :
ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
}
// DPI calculation
qreal screenRatio = AppEnv::screenRatio();
resize(435 * screenRatio, 405 * screenRatio);
setupTreeWidget();
setupLanguageBox();
setupRadioButtons();
setupDefaultProfile();
setupPictureSettings();
setupCustomGTAFolder();
setupInterfaceSettings();
setupSnapmaticPictureViewer();
// DPI calculation
qreal screenRatio = AppEnv::screenRatio();
resize(435 * screenRatio, 405 * screenRatio);
#ifdef GTA5SYNC_DISABLED
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabSync));
#endif
@ -239,6 +241,61 @@ void OptionsDialog::setupRadioButtons()
}
}
void OptionsDialog::setupInterfaceSettings()
{
settings->beginGroup("Startup");
bool alwaysUseMessageFont = settings->value("AlwaysUseMessageFont", false).toBool();
ui->cbAlwaysUseMessageFont->setChecked(alwaysUseMessageFont);
#ifdef GTA5SYNC_WIN
if (QSysInfo::windowsVersion() >= 0x0080)
{
ui->gbFont->setVisible(false);
ui->cbAlwaysUseMessageFont->setVisible(false);
}
#else
ui->gbFont->setVisible(false);
ui->cbAlwaysUseMessageFont->setVisible(false);
#endif
QString currentStyle = qApp->style()->objectName();
QString appStyle = settings->value("AppStyle", currentStyle).toString();
bool customStyle = settings->value("CustomStyle", false).toBool();
const QStringList availableStyles = QStyleFactory::keys();
ui->cbStyleList->addItems(availableStyles);
if (availableStyles.contains(appStyle, Qt::CaseInsensitive))
{
// use 'for' for select to be sure it's case insensitive
int currentIndex = 0;
for (QString currentStyleFF : availableStyles)
{
if (currentStyleFF.toLower() == appStyle.toLower())
{
ui->cbStyleList->setCurrentIndex(currentIndex);
}
currentIndex++;
}
}
else
{
if (availableStyles.contains(currentStyle, Qt::CaseInsensitive))
{
int currentIndex = 0;
for (QString currentStyleFF : availableStyles)
{
if (currentStyleFF.toLower() == currentStyle.toLower())
{
ui->cbStyleList->setCurrentIndex(currentIndex);
}
currentIndex++;
}
}
}
if (customStyle)
{
ui->cbDefaultStyle->setChecked(false);
}
settings->endGroup();
}
void OptionsDialog::on_cmdOK_clicked()
{
applySettings();
@ -310,6 +367,22 @@ void OptionsDialog::applySettings()
settings->setValue("force", forceCustomFolder);
settings->endGroup();
bool defaultStyle = ui->cbDefaultStyle->isChecked();
settings->beginGroup("Startup");
if (!defaultStyle)
{
QString newStyle = ui->cbStyleList->currentText();
settings->setValue("CustomStyle", true);
settings->setValue("AppStyle", newStyle);
qApp->setStyle(QStyleFactory::create(newStyle));
}
else
{
settings->setValue("CustomStyle", false);
}
settings->setValue("AlwaysUseMessageFont", ui->cbAlwaysUseMessageFont->isChecked());
settings->endGroup();
#if QT_VERSION >= 0x050000
bool languageChanged = ui->cbLanguage->currentData().toString() != currentLanguage;
bool languageAreaChanged = ui->cbAreaLanguage->currentData().toString() != currentAreaLanguage;
@ -494,3 +567,8 @@ void OptionsDialog::on_cmdExploreFolder_clicked()
ui->txtFolder->setText(GTAV_Folder);
}
}
void OptionsDialog::on_cbDefaultStyle_toggled(bool checked)
{
ui->cbStyleList->setDisabled(checked);
}

3
OptionsDialog.h

@ -46,6 +46,7 @@ private slots:
void on_hsPicQuality_valueChanged(int value);
void on_cbIgnoreAspectRatio_toggled(bool checked);
void on_cmdExploreFolder_clicked();
void on_cbDefaultStyle_toggled(bool checked);
signals:
void settingsApplied(int contentMode, bool languageChanged);
@ -61,6 +62,7 @@ private:
QString defaultProfile;
QString percentString;
QSettings *settings;
bool withoutPlayers;
bool currentFFolder;
int contentMode;
int customQuality;
@ -73,6 +75,7 @@ private:
void setupDefaultProfile();
void setupPictureSettings();
void setupCustomGTAFolder();
void setupInterfaceSettings();
void setupSnapmaticPictureViewer();
void applySettings();
};

73
OptionsDialog.ui

@ -314,7 +314,7 @@
</widget>
</item>
<item>
<spacer name="vsTabPictures">
<spacer name="vsPictures">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -382,15 +382,15 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabLocalization">
<widget class="QWidget" name="tabInterface">
<attribute name="title">
<string>Language</string>
<string>Interface</string>
</attribute>
<layout class="QVBoxLayout" name="vlLocalization">
<layout class="QVBoxLayout" name="vlInterface">
<item>
<widget class="QGroupBox" name="gbLanguage">
<property name="title">
<string>Interface</string>
<string>Language for Interface</string>
</property>
<layout class="QVBoxLayout" name="vlLanguage">
<item>
@ -409,9 +409,9 @@
<item>
<widget class="QGroupBox" name="gbAreas">
<property name="title">
<string>Areas</string>
<string>Language for Areas</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="vlAreas">
<item>
<widget class="QComboBox" name="cbAreaLanguage"/>
</item>
@ -425,6 +425,65 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbStyle">
<property name="title">
<string>Style</string>
</property>
<layout class="QVBoxLayout" name="vlStyle">
<item>
<widget class="QCheckBox" name="cbDefaultStyle">
<property name="text">
<string>Use Default Style (Restart)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="hlStyle">
<item>
<widget class="QLabel" name="labStyle">
<property name="text">
<string>Style:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbStyleList">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbFont">
<property name="title">
<string>Font</string>
</property>
<layout class="QVBoxLayout" name="vlFont">
<item>
<widget class="QCheckBox" name="cbAlwaysUseMessageFont">
<property name="text">
<string>Always use Message Font (Windows 2003 and earlier)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="vsInterface">
<property name="orientation">

117
PictureDialog.cpp

@ -22,6 +22,7 @@
#include "ui_PictureDialog.h"
#include "SidebarGenerator.h"
#include "MapLocationDialog.h"
#include "JsonEditorDialog.h"
#include "SnapmaticEditor.h"
#include "StandardPaths.h"
#include "PictureExport.h"
@ -62,6 +63,17 @@
#include <QUrl>
#include <QDir>
// Macros for better Overview + RAM
#define locX QString::number(picture->getSnapmaticProperties().location.x)
#define locY QString::number(picture->getSnapmaticProperties().location.y)
#define locZ QString::number(picture->getSnapmaticProperties().location.z)
#define crewID QString::number(picture->getSnapmaticProperties().crewID)
#define picArea picture->getSnapmaticProperties().location.area
#define picPath picture->getPictureFilePath()
#define picTitl StringParser::escapeString(picture->getPictureTitle())
#define plyrsList picture->getSnapmaticProperties().playersList
#define created picture->getSnapmaticProperties().createdDateTime.toString(Qt::DefaultLocaleShortDate)
PictureDialog::PictureDialog(ProfileDatabase *profileDB, CrewDatabase *crewDB, QWidget *parent) :
QDialog(parent), profileDB(profileDB), crewDB(crewDB),
ui(new Ui::PictureDialog)
@ -102,22 +114,13 @@ void PictureDialog::setupPictureDialog(bool withDatabase_)
windowTitleStr = this->windowTitle();
jsonDrawString = ui->labJSON->text();
ui->cmdManage->setEnabled(false);
plyrsList = QStringList();
fullscreenWidget = nullptr;
rqFullscreen = false;
previewMode = false;
naviEnabled = false;
indexed = false;
picArea = "";
picTitl = "";
picPath = "";
created = "";
crewStr = "";
crewID = "";
locX = "";
locY = "";
locZ = "";
smpic = nullptr;
crewStr = "";
// With datebase
withDatabase = withDatabase_;
@ -145,9 +148,11 @@ void PictureDialog::setupPictureDialog(bool withDatabase_)
jpegExportAction = manageMenu->addAction(tr("Export as &Picture..."), this, SLOT(exportSnapmaticPicture()));
pgtaExportAction = manageMenu->addAction(tr("Export as &Snapmatic..."), this, SLOT(copySnapmaticPicture()));
manageMenuSep1 = manageMenu->addSeparator();
openViewerAction = manageMenu->addAction(tr("Open &Map View..."), this, SLOT(openPreviewMap()));
openViewerAction->setShortcut(Qt::Key_M);
propEditorAction = manageMenu->addAction(tr("&Edit Properties..."), this, SLOT(editSnapmaticProperties()));
manageMenuSep2 = manageMenu->addSeparator();
openViewerAction = manageMenu->addAction(tr("Open &Map Viewer..."), this, SLOT(openPreviewMap()));
openViewerAction->setShortcut(Qt::Key_M);
jsonEditorAction = manageMenu->addAction(tr("Open &JSON Editor..."), this, SLOT(editSnapmaticRawJson()));
ui->cmdManage->setMenu(manageMenu);
// Global map
@ -176,9 +181,11 @@ PictureDialog::~PictureDialog()
{
delete propEditorAction;
delete openViewerAction;
delete jsonEditorAction;
delete jpegExportAction;
delete pgtaExportAction;
delete manageMenuSep1;
delete manageMenuSep2;
delete manageMenu;
delete ui;
}
@ -426,7 +433,6 @@ void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture, bool readOk,
snapmaticPicture = QImage();
indexed = _indexed;
index = _index;
picPath = picture->getPictureFilePath();
smpic = picture;
if (!readOk)
{
@ -441,23 +447,14 @@ void PictureDialog::setSnapmaticPicture(SnapmaticPicture *picture, bool readOk,
}
if (picture->isJsonOk())
{
locX = QString::number(picture->getSnapmaticProperties().location.x);
locY = QString::number(picture->getSnapmaticProperties().location.y);
locZ = QString::number(picture->getSnapmaticProperties().location.z);
if (withDatabase)
{
crewID = QString::number(picture->getSnapmaticProperties().crewID);
crewStr = crewDB->getCrewName(picture->getSnapmaticProperties().crewID);
crewStr = crewDB->getCrewName(crewID);
}
else
{
crewID = QString::number(picture->getSnapmaticProperties().crewID);
crewStr = QString::number(picture->getSnapmaticProperties().crewID);
crewStr = crewID;
}
created = picture->getSnapmaticProperties().createdDateTime.toString(Qt::DefaultLocaleShortDate);
plyrsList = picture->getSnapmaticProperties().playersList;
picTitl = StringParser::escapeString(picture->getPictureTitle());
picArea = picture->getSnapmaticProperties().location.area;
if (globalMap.contains(picArea))
{
picAreaStr = globalMap[picArea];
@ -565,15 +562,18 @@ void PictureDialog::renderPicture()
void PictureDialog::crewNameUpdated()
{
if (withDatabase && crewID == crewStr)
SnapmaticPicture *picture = smpic; // used by macro
QString crewIDStr = crewID;
if (withDatabase && crewIDStr == crewStr)
{
crewStr = crewDB->getCrewName(crewID.toInt());
crewStr = crewDB->getCrewName(crewIDStr);
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
}
}
void PictureDialog::playerNameUpdated()
{
SnapmaticPicture *picture = smpic; // used by macro
if (plyrsList.count() >= 1)
{
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
@ -582,19 +582,23 @@ void PictureDialog::playerNameUpdated()
QString PictureDialog::generateCrewString()
{
if (crewID != "0" && !crewID.isEmpty())
SnapmaticPicture *picture = smpic; // used by macro
QString crewIDStr = crewID; // save operation time
if (crewIDStr != "0" && !crewIDStr.isEmpty())
{
return QString("<a href=\"https://socialclub.rockstargames.com/crew/" % QString(crewStr).replace(" ", "_") % "/" % crewID % "\">" % crewStr % "</a>");
return QString("<a href=\"https://socialclub.rockstargames.com/crew/" % QString(crewStr).replace(" ", "_") % "/" % crewIDStr % "\">" % crewStr % "</a>");
}
return tr("No Crew");
}
QString PictureDialog::generatePlayersString()
{
SnapmaticPicture *picture = smpic; // used by macro
const QStringList playersList = plyrsList; // save operation time
QString plyrsStr;
if (plyrsList.length() >= 1)
if (playersList.length() >= 1)
{
for (QString player : plyrsList)
for (QString player : playersList)
{
QString playerName;
if (withDatabase)
@ -691,14 +695,15 @@ int PictureDialog::getIndex()
void PictureDialog::openPreviewMap()
{
SnapmaticPicture *picture = smpic;
MapLocationDialog *mapLocDialog;
if (rqFullscreen && fullscreenWidget != nullptr)
{
mapLocDialog = new MapLocationDialog(smpic->getSnapmaticProperties().location.x, smpic->getSnapmaticProperties().location.y, fullscreenWidget);
mapLocDialog = new MapLocationDialog(picture->getSnapmaticProperties().location.x, picture->getSnapmaticProperties().location.y, fullscreenWidget);
}
else
{
mapLocDialog = new MapLocationDialog(smpic->getSnapmaticProperties().location.x, smpic->getSnapmaticProperties().location.y, this);
mapLocDialog = new MapLocationDialog(picture->getSnapmaticProperties().location.x, picture->getSnapmaticProperties().location.y, this);
}
mapLocDialog->setWindowIcon(windowIcon());
mapLocDialog->setModal(true);
@ -707,25 +712,25 @@ void PictureDialog::openPreviewMap()
if (mapLocDialog->propUpdated())
{
// Update Snapmatic Properties
SnapmaticProperties localSpJson = smpic->getSnapmaticProperties();
SnapmaticProperties localSpJson = picture->getSnapmaticProperties();
localSpJson.location.x = mapLocDialog->getXpos();
localSpJson.location.y = mapLocDialog->getYpos();
localSpJson.location.z = 0;
// Update Snapmatic Picture
QString currentFilePath = smpic->getPictureFilePath();
QString originalFilePath = smpic->getOriginalPictureFilePath();
QString currentFilePath = picture->getPictureFilePath();
QString originalFilePath = picture->getOriginalPictureFilePath();
QString backupFileName = originalFilePath % ".bak";
if (!QFile::exists(backupFileName))
{
QFile::copy(currentFilePath, backupFileName);
}
SnapmaticProperties fallbackProperties = smpic->getSnapmaticProperties();
smpic->setSnapmaticProperties(localSpJson);
if (!smpic->exportPicture(currentFilePath))
SnapmaticProperties fallbackProperties = picture->getSnapmaticProperties();
picture->setSnapmaticProperties(localSpJson);
if (!picture->exportPicture(currentFilePath))
{
QMessageBox::warning(this, SnapmaticEditor::tr("Snapmatic Properties"), SnapmaticEditor::tr("Patching of Snapmatic Properties failed because of I/O Error"));
smpic->setSnapmaticProperties(fallbackProperties);
picture->setSnapmaticProperties(fallbackProperties);
}
else
{
@ -737,6 +742,7 @@ void PictureDialog::openPreviewMap()
void PictureDialog::editSnapmaticProperties()
{
SnapmaticPicture *picture = smpic;
SnapmaticEditor *snapmaticEditor;
if (rqFullscreen && fullscreenWidget != nullptr)
{
@ -746,29 +752,42 @@ void PictureDialog::editSnapmaticProperties()
{
snapmaticEditor = new SnapmaticEditor(crewDB, this);
}
snapmaticEditor->setWindowFlags(snapmaticEditor->windowFlags()^Qt::WindowContextHelpButtonHint);
snapmaticEditor->setWindowIcon(windowIcon());
snapmaticEditor->setSnapmaticPicture(smpic);
snapmaticEditor->setSnapmaticPicture(picture);
snapmaticEditor->setModal(true);
snapmaticEditor->show();
snapmaticEditor->exec();
delete snapmaticEditor;
}
void PictureDialog::editSnapmaticRawJson()
{
SnapmaticPicture *picture = smpic;
JsonEditorDialog *jsonEditor = new JsonEditorDialog(picture, this);
jsonEditor->setModal(true);
jsonEditor->show();
jsonEditor->exec();
delete jsonEditor;
}
void PictureDialog::updated()
{
SnapmaticPicture *picture = smpic; // used by macro
if (withDatabase)
{
crewID = QString::number(smpic->getSnapmaticProperties().crewID);
crewStr = crewDB->getCrewName(smpic->getSnapmaticProperties().crewID);
crewStr = crewDB->getCrewName(crewID);
}
else
{
crewStr = crewID;
}
if (globalMap.contains(picArea))
{
picAreaStr = globalMap[picArea];
}
else
{
crewID = QString::number(smpic->getSnapmaticProperties().crewID);
crewStr = QString::number(smpic->getSnapmaticProperties().crewID);
picAreaStr = picArea;
}
locX = QString::number(smpic->getSnapmaticProperties().location.x);
locY = QString::number(smpic->getSnapmaticProperties().location.y);
locZ = QString::number(smpic->getSnapmaticProperties().location.z);
picTitl = StringParser::escapeString(smpic->getPictureTitle());
ui->labJSON->setText(jsonDrawString.arg(locX, locY, locZ, generatePlayersString(), generateCrewString(), picTitl, picAreaStr, created));
}

12
PictureDialog.h

@ -69,6 +69,7 @@ private slots:
void nextPictureRequestedSlot();
void previousPictureRequestedSlot();
void editSnapmaticProperties();
void editSnapmaticRawJson();
void renderOverlayPicture();
void renderPicture();
void openPreviewMap();
@ -100,23 +101,16 @@ private:
QAction *pgtaExportAction;
QAction *propEditorAction;
QAction *openViewerAction;
QAction *jsonEditorAction;
QAction *manageMenuSep1;
QAction *manageMenuSep2;
QImage avatarAreaPicture;
QImage snapmaticPicture;
QImage overlayTempImage;
QString jsonDrawString;
QString windowTitleStr;
QStringList plyrsList;
QString picAreaStr;
QString picArea;
QString picTitl;
QString picPath;
QString created;
QString crewStr;
QString crewID;
QString locX;
QString locY;
QString locZ;
bool overlayEnabled;
bool withDatabase;
bool rqFullscreen;

57
ProfileInterface.cpp

@ -54,6 +54,9 @@
#include <QUrl>
#include <QDir>
#define importTimeFormat "HHmmss"
#define findRetryLimit 500
ProfileInterface::ProfileInterface(ProfileDatabase *profileDB, CrewDatabase *crewDB, DatabaseThread *threadDB, QWidget *parent) :
QWidget(parent), profileDB(profileDB), crewDB(crewDB), threadDB(threadDB),
ui(new Ui::ProfileInterface)
@ -446,7 +449,9 @@ fileDialogPreOpen: //Work?
if (selectedFiles.length() == 1)
{
QString selectedFile = selectedFiles.at(0);
if (!importFile(selectedFile, true)) goto fileDialogPreOpen; //Work?
QDateTime importDateTime = QDateTime::currentDateTime();
int currentTime = importDateTime.toString(importTimeFormat).toInt();
if (!importFile(selectedFile, importDateTime, &currentTime, true)) goto fileDialogPreOpen; //Work?
}
else if (selectedFiles.length() > 1)
{
@ -486,13 +491,14 @@ void ProfileInterface::importFilesProgress(QStringList selectedFiles)
pbBar.at(0)->setTextVisible(false);
pbDialog.show();
QTime t;
t.start();
QDateTime importDateTime = QDateTime::currentDateTime();
int currentTime = importDateTime.time().toString(importTimeFormat).toInt();
for (QString selectedFile : selectedFiles)
{
pbDialog.setValue(overallId);
pbDialog.setLabelText(tr("Import file %1 of %2 files").arg(QString::number(overallId), QString::number(maximumId)));
if (!importFile(selectedFile, false))
importDateTime = QDateTime::currentDateTime();
if (!importFile(selectedFile, importDateTime, &currentTime, false))
{
failedFiles << QFileInfo(selectedFile).fileName();
}
@ -510,7 +516,7 @@ void ProfileInterface::importFilesProgress(QStringList selectedFiles)
}
}
bool ProfileInterface::importFile(QString selectedFile, bool notMultiple)
bool ProfileInterface::importFile(QString selectedFile, QDateTime importDateTime, int *currentTime, bool notMultiple)
{
QString selectedFileName = QFileInfo(selectedFile).fileName();
if (QFile::exists(selectedFile))
@ -590,7 +596,7 @@ bool ProfileInterface::importFile(QString selectedFile, bool notMultiple)
diffWidth = diffWidth / 2;
}
snapmaticPainter.drawImage(145 + diffWidth, 66 + diffHeight, snapmaticImage);
customImageTitle = "Custom Avatar";
customImageTitle = ImportDialog::tr("Custom Avatar", "Custom Avatar Description in SC, don't use Special Character!");
}
else
{
@ -609,7 +615,7 @@ bool ProfileInterface::importFile(QString selectedFile, bool notMultiple)
diffHeight = diffHeight / 2;
}
snapmaticPainter.drawImage(0 + diffWidth, 0 + diffHeight, snapmaticImage);
customImageTitle = "Custom Picture";
customImageTitle = ImportDialog::tr("Custom Picture", "Custom Picture Description in SC, don't use Special Character!");
}
snapmaticPainter.end();
if (!picture->setImage(snapmaticPixmap.toImage()))
@ -617,23 +623,22 @@ bool ProfileInterface::importFile(QString selectedFile, bool notMultiple)
delete picture;
return false;
}
QString currentTime = QTime::currentTime().toString("HHmmss");
SnapmaticProperties spJson = picture->getSnapmaticProperties();
spJson.uid = QString(currentTime %
QString::number(QDate::currentDate().dayOfYear())).toInt();
spJson.uid = QString(QString::number(*currentTime) %
QString::number(importDateTime.date().dayOfYear())).toInt();
bool fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid));
bool fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid) % ".hidden");
int cEnough = 0;
while ((fExists || fExistsHidden) && cEnough < 5000)
while ((fExists || fExistsHidden) && cEnough < findRetryLimit)
{
currentTime = QString::number(currentTime.toInt() - 1);
spJson.uid = QString(currentTime %
QString::number(QDate::currentDate().dayOfYear())).toInt();
*currentTime = *currentTime - 1;
spJson.uid = QString(QString::number(*currentTime) %
QString::number(importDateTime.date().dayOfYear())).toInt();
fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid));
fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid) % ".hidden");
cEnough++;
}
spJson.createdDateTime = QDateTime::currentDateTime();
spJson.createdDateTime = importDateTime;
spJson.createdTimestamp = spJson.createdDateTime.toTime_t();
picture->setSnapmaticProperties(spJson);
picture->setPicFileName(QString("PGTA5%1").arg(QString::number(spJson.uid)));
@ -672,23 +677,22 @@ bool ProfileInterface::importFile(QString selectedFile, bool notMultiple)
{
if (picture->setImage(importDialog->image()))
{
QString currentTime = QTime::currentTime().toString("HHmmss");
SnapmaticProperties spJson = picture->getSnapmaticProperties();
spJson.uid = QString(currentTime +
QString::number(QDate::currentDate().dayOfYear())).toInt();
spJson.uid = QString(QString::number(*currentTime) %
QString::number(importDateTime.date().dayOfYear())).toInt();
bool fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid));
bool fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid) % ".hidden");
int cEnough = 0;
while ((fExists || fExistsHidden) && cEnough < 25)
while ((fExists || fExistsHidden) && cEnough < findRetryLimit)
{
currentTime = QString::number(currentTime.toInt() - 1);
spJson.uid = QString(currentTime %
QString::number(QDate::currentDate().dayOfYear())).toInt();
*currentTime = *currentTime - 1;
spJson.uid = QString(QString::number(*currentTime) %
QString::number(importDateTime.date().dayOfYear())).toInt();
fExists = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid));
fExistsHidden = QFile::exists(profileFolder % "/PGTA5" % QString::number(spJson.uid) % ".hidden");
cEnough++;
}
spJson.createdDateTime = QDateTime::currentDateTime();
spJson.createdDateTime = importDateTime;
spJson.createdTimestamp = spJson.createdDateTime.toTime_t();
picture->setSnapmaticProperties(spJson);
picture->setPicFileName(QString("PGTA5%1").arg(QString::number(spJson.uid)));
@ -1158,6 +1162,9 @@ void ProfileInterface::contextMenuTriggeredPIC(QContextMenuEvent *ev)
editMenu.addAction(SnapmaticWidget::tr("Hide &In-game"), picWidget, SLOT(makePictureHiddenSlot()));
}
editMenu.addAction(PictureDialog::tr("&Edit Properties..."), picWidget, SLOT(editSnapmaticProperties()));
editMenu.addSeparator();
editMenu.addAction(PictureDialog::tr("Open &Map Viewer..."), picWidget, SLOT(openMapViewer()));
editMenu.addAction(PictureDialog::tr("Open &JSON Editor..."), picWidget, SLOT(editSnapmaticRawJson()));
QMenu exportMenu(SnapmaticWidget::tr("&Export"), this);
exportMenu.addAction(PictureDialog::tr("Export as &Picture..."), picWidget, SLOT(on_cmdExport_clicked()));
exportMenu.addAction(PictureDialog::tr("Export as &Snapmatic..."), picWidget, SLOT(on_cmdCopy_clicked()));
@ -1231,7 +1238,9 @@ void ProfileInterface::on_saProfileContent_dropped(const QMimeData *mimeData)
if (pathList.length() == 1)
{
QString selectedFile = pathList.at(0);
importFile(selectedFile, true);
QDateTime importDateTime = QDateTime::currentDateTime();
int currentTime = importDateTime.toString(importTimeFormat).toInt();
importFile(selectedFile, QDateTime::currentDateTime(), &currentTime, true);
}
else if (pathList.length() > 1)
{

3
ProfileInterface.h

@ -31,6 +31,7 @@
#include "CrewDatabase.h"
#include <QProgressDialog>
#include <QSpacerItem>
#include <QDateTime>
#include <QWidget>
#include <QList>
#include <QMap>
@ -107,7 +108,7 @@ private:
int contentMode;
bool isSupportedImageFile(QString selectedFileName);
bool importFile(QString selectedFile, bool notMultiple);
bool importFile(QString selectedFile, QDateTime importDateTime, int *currentTime, bool notMultiple);
void importFilesProgress(QStringList selectedFiles);
bool importSnapmaticPicture(SnapmaticPicture *picture, bool warn = true);
bool importSavegameData(SavegameData *savegame, QString sgdPath, bool warn = true);

13
SnapmaticEditor.cpp

@ -32,13 +32,24 @@ SnapmaticEditor::SnapmaticEditor(CrewDatabase *crewDB, QWidget *parent) :
QDialog(parent), crewDB(crewDB),
ui(new Ui::SnapmaticEditor)
{
// Set Window Flags
setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
ui->setupUi(this);
ui->cmdApply->setDefault(true);
if (QIcon::hasThemeIcon("dialog-apply"))
if (QIcon::hasThemeIcon("dialog-ok-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok-apply"));
}
else if (QIcon::hasThemeIcon("dialog-apply"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-apply"));
}
else if (QIcon::hasThemeIcon("dialog-ok"))
{
ui->cmdApply->setIcon(QIcon::fromTheme("dialog-ok"));
}
if (QIcon::hasThemeIcon("dialog-cancel"))
{
ui->cmdCancel->setIcon(QIcon::fromTheme("dialog-cancel"));

95
SnapmaticPicture.cpp

@ -774,60 +774,119 @@ void SnapmaticPicture::parseJsonContent()
{
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonStr.toUtf8());
QJsonObject jsonObject = jsonDocument.object();
QVariantMap jsonMap = jsonObject.toVariantMap(); // backward compatibility
QVariantMap jsonMap = jsonObject.toVariantMap();
bool jsonIncomplete = false;
bool jsonError = false;
if (jsonObject.contains("loc"))
{
QJsonObject locObject = jsonObject["loc"].toObject();
if (locObject.contains("x")) { localSpJson.location.x = locObject["x"].toDouble(); }
if (locObject.contains("y")) { localSpJson.location.y = locObject["y"].toDouble(); }
if (locObject.contains("z")) { localSpJson.location.z = locObject["z"].toDouble(); }
if (jsonObject["loc"].isObject())
{
QJsonObject locObject = jsonObject["loc"].toObject();
if (locObject.contains("x"))
{
if (locObject["x"].isDouble()) { localSpJson.location.x = locObject["x"].toDouble(); }
else { jsonError = true; }
}
else { jsonIncomplete = true; }
if (locObject.contains("y"))
{
if (locObject["y"].isDouble()) { localSpJson.location.y = locObject["y"].toDouble(); }
else { jsonError = true; }
}
else { jsonIncomplete = true; }
if (locObject.contains("z"))
{