Open Source Snapmatic picture and Savegame viewer/editor for GTA V https://gta5view.syping.de/

PictureExport.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*****************************************************************************
  2. * gta5view Grand Theft Auto V Profile Viewer
  3. * Copyright (C) 2016-2017 Syping
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *****************************************************************************/
  18. #include "config.h"
  19. #include "PictureExport.h"
  20. #include "PictureDialog.h"
  21. #include "StandardPaths.h"
  22. #include "SidebarGenerator.h"
  23. #include <QStringBuilder>
  24. #include <QDesktopWidget>
  25. #include <QApplication>
  26. #include <QMessageBox>
  27. #include <QFileDialog>
  28. #include <QSettings>
  29. #include <QRegExp>
  30. #include <QDebug>
  31. #if QT_VERSION >= 0x050000
  32. #include <QSaveFile>
  33. #endif
  34. PictureExport::PictureExport()
  35. {
  36. }
  37. void PictureExport::exportAsPicture(QWidget *parent, SnapmaticPicture *picture)
  38. {
  39. QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
  40. // Picture Settings
  41. // Quality Settings
  42. settings.beginGroup("Pictures");
  43. int defaultQuality = 100;
  44. QSize defExportSize = QSize(960, 536);
  45. int customQuality = settings.value("CustomQuality", defaultQuality).toInt();
  46. if (customQuality < 1 || customQuality > 100)
  47. {
  48. customQuality = 100;
  49. }
  50. bool useCustomQuality = settings.value("CustomQualityEnabled", false).toBool();
  51. // Size Settings
  52. QSize cusExportSize = settings.value("CustomSize", defExportSize).toSize();
  53. if (cusExportSize.width() > 3840)
  54. {
  55. cusExportSize.setWidth(3840);
  56. }
  57. else if (cusExportSize.height() > 2160)
  58. {
  59. cusExportSize.setHeight(2160);
  60. }
  61. if (cusExportSize.width() < 1)
  62. {
  63. cusExportSize.setWidth(1);
  64. }
  65. else if (cusExportSize.height() < 1)
  66. {
  67. cusExportSize.setHeight(1);
  68. }
  69. QString sizeMode = settings.value("ExportSizeMode", "Default").toString();
  70. Qt::AspectRatioMode aspectRatio = (Qt::AspectRatioMode)settings.value("AspectRatio", Qt::KeepAspectRatio).toInt();
  71. QString defaultExportFormat = settings.value("DefaultExportFormat", ".jpg").toString();
  72. settings.endGroup();
  73. // End Picture Settings
  74. settings.beginGroup("FileDialogs");
  75. bool dontUseNativeDialog = settings.value("DontUseNativeDialog", false).toBool();
  76. settings.beginGroup("ExportAsPicture");
  77. fileDialogPreSave: //Work?
  78. QFileDialog fileDialog(parent);
  79. fileDialog.setFileMode(QFileDialog::AnyFile);
  80. fileDialog.setViewMode(QFileDialog::Detail);
  81. fileDialog.setAcceptMode(QFileDialog::AcceptSave);
  82. fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
  83. fileDialog.setOption(QFileDialog::DontConfirmOverwrite, true);
  84. fileDialog.setDefaultSuffix("suffix");
  85. fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
  86. fileDialog.setWindowTitle(PictureDialog::tr("Export as Picture..."));
  87. fileDialog.setLabelText(QFileDialog::Accept, PictureDialog::tr("Export"));
  88. QStringList filters;
  89. filters << PictureDialog::tr("JPEG Graphics (*.jpg *.jpeg)");
  90. filters << PictureDialog::tr("Portable Network Graphics (*.png)");
  91. fileDialog.setNameFilters(filters);
  92. QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
  93. fileDialog.setSidebarUrls(sidebarUrls);
  94. fileDialog.setDirectory(settings.value("Directory", StandardPaths::picturesLocation()).toString());
  95. fileDialog.restoreGeometry(settings.value(parent->objectName() % "+Geometry", "").toByteArray());
  96. QString newPictureFileName = getPictureFileName(picture) % defaultExportFormat;
  97. fileDialog.selectFile(newPictureFileName);
  98. if (fileDialog.exec())
  99. {
  100. QStringList selectedFiles = fileDialog.selectedFiles();
  101. if (selectedFiles.length() == 1)
  102. {
  103. QString saveFileFormat;
  104. QString selectedFile = selectedFiles.at(0);
  105. if (selectedFile.right(4) == ".jpg")
  106. {
  107. saveFileFormat = "JPEG";
  108. }
  109. else if (selectedFile.right(4) == ".jpeg")
  110. {
  111. saveFileFormat = "JPEG";
  112. }
  113. else if (selectedFile.right(4) == ".png")
  114. {
  115. saveFileFormat = "PNG";
  116. }
  117. else if (selectedFile.right(7) == ".suffix")
  118. {
  119. if (fileDialog.selectedNameFilter() == "JPEG picture (*.jpg)")
  120. {
  121. selectedFile.replace(".suffix", ".jpg");
  122. }
  123. else if (fileDialog.selectedNameFilter() == "Portable Network Graphics (*.png)")
  124. {
  125. selectedFile.replace(".suffix", ".png");
  126. }
  127. else
  128. {
  129. selectedFile.replace(".suffix", ".jpg");
  130. }
  131. }
  132. if (QFile::exists(selectedFile))
  133. {
  134. if (QMessageBox::No == QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Overwrite %1 with current Snapmatic picture?").arg("\""+selectedFile+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
  135. {
  136. goto fileDialogPreSave; //Work?
  137. }
  138. }
  139. // Scale Picture
  140. QImage exportPicture = picture->getImage();
  141. if (sizeMode == "Desktop")
  142. {
  143. QRect desktopResolution = QApplication::desktop()->screenGeometry();
  144. exportPicture = exportPicture.scaled(desktopResolution.width(), desktopResolution.height(), aspectRatio, Qt::SmoothTransformation);
  145. }
  146. else if (sizeMode == "Custom")
  147. {
  148. exportPicture = exportPicture.scaled(cusExportSize, aspectRatio, Qt::SmoothTransformation);
  149. }
  150. int errorId = 0;
  151. bool isSaved = false;
  152. #if QT_VERSION >= 0x050000
  153. QSaveFile *picFile = new QSaveFile(selectedFile);
  154. #else
  155. QFile *picFile = new QFile(selectedFile);
  156. #endif
  157. if (picFile->open(QIODevice::WriteOnly))
  158. {
  159. isSaved = exportPicture.save(picFile, saveFileFormat.toStdString().c_str(), useCustomQuality ? customQuality : defaultQuality);
  160. #if QT_VERSION >= 0x050000
  161. if (isSaved)
  162. {
  163. isSaved = picFile->commit();
  164. }
  165. else
  166. {
  167. errorId = 1;
  168. }
  169. #else
  170. picFile->close();
  171. #endif
  172. }
  173. else
  174. {
  175. errorId = 2;
  176. }
  177. delete picFile;
  178. if (!isSaved)
  179. {
  180. switch (errorId)
  181. {
  182. case 0:
  183. QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Failed to export the picture because the system occurred a write failure"));
  184. break;
  185. case 1:
  186. QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Failed to export the picture because the format detection failures"));
  187. break;
  188. case 2:
  189. QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Failed to export the picture because the file can't be written"));
  190. break;
  191. default:
  192. QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("Failed to export the picture because of an unknown reason"));
  193. }
  194. goto fileDialogPreSave; //Work?
  195. }
  196. }
  197. else
  198. {
  199. QMessageBox::warning(parent, PictureDialog::tr("Export as Picture"), PictureDialog::tr("No valid file is selected"));
  200. goto fileDialogPreSave; //Work?
  201. }
  202. }
  203. settings.setValue(parent->objectName() % "+Geometry", fileDialog.saveGeometry());
  204. settings.setValue("Directory", fileDialog.directory().absolutePath());
  205. settings.endGroup();
  206. settings.endGroup();
  207. }
  208. void PictureExport::exportAsSnapmatic(QWidget *parent, SnapmaticPicture *picture)
  209. {
  210. QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
  211. settings.beginGroup("FileDialogs");
  212. bool dontUseNativeDialog = settings.value("DontUseNativeDialog", false).toBool();
  213. settings.beginGroup("ExportAsSnapmatic");
  214. QString adjustedPicPath = picture->getOriginalPictureFileName();
  215. fileDialogPreSave: //Work?
  216. QFileInfo sgdFileInfo(adjustedPicPath);
  217. QFileDialog fileDialog(parent);
  218. fileDialog.setFileMode(QFileDialog::AnyFile);
  219. fileDialog.setViewMode(QFileDialog::Detail);
  220. fileDialog.setAcceptMode(QFileDialog::AcceptSave);
  221. fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
  222. fileDialog.setOption(QFileDialog::DontConfirmOverwrite, true);
  223. fileDialog.setDefaultSuffix(".rem");
  224. fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
  225. fileDialog.setWindowTitle(PictureDialog::tr("Export as Snapmatic..."));
  226. fileDialog.setLabelText(QFileDialog::Accept, PictureDialog::tr("Export"));
  227. QStringList filters;
  228. filters << PictureDialog::tr("GTA V Export (*.g5e)");
  229. filters << PictureDialog::tr("GTA V Raw Export (*.auto)");
  230. filters << PictureDialog::tr("Snapmatic pictures (PGTA*)");
  231. fileDialog.setNameFilters(filters);
  232. QList<QUrl> sidebarUrls = SidebarGenerator::generateSidebarUrls(fileDialog.sidebarUrls());
  233. fileDialog.setSidebarUrls(sidebarUrls);
  234. fileDialog.setDirectory(settings.value("Directory", StandardPaths::documentsLocation()).toString());
  235. fileDialog.restoreGeometry(settings.value(parent->objectName() % "+Geometry", "").toByteArray());
  236. fileDialog.selectFile(QString(picture->getExportPictureFileName() % ".g5e"));
  237. if (fileDialog.exec())
  238. {
  239. QStringList selectedFiles = fileDialog.selectedFiles();
  240. if (selectedFiles.length() == 1)
  241. {
  242. QString selectedFile = selectedFiles.at(0);
  243. bool isAutoExt = false;
  244. if (selectedFile.right(5) == ".auto")
  245. {
  246. isAutoExt = true;
  247. QString dirPath = QFileInfo(selectedFile).dir().path();
  248. QString stockFileName = sgdFileInfo.fileName();
  249. selectedFile = dirPath % "/" % stockFileName;
  250. }
  251. else if (selectedFile.right(4) == ".rem")
  252. {
  253. selectedFile.remove(selectedFile.length() - 4, 4);
  254. }
  255. if (QFile::exists(selectedFile))
  256. {
  257. if (QMessageBox::No == QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Overwrite %1 with current Snapmatic picture?").arg("\""+selectedFile+"\""), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
  258. {
  259. goto fileDialogPreSave; //Work?
  260. }
  261. }
  262. if (selectedFile.right(4) == ".g5e")
  263. {
  264. bool isExported = picture->exportPicture(selectedFile, SnapmaticFormat::G5E_Format);
  265. if (!isExported)
  266. {
  267. QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Failed to export current Snapmatic picture"));
  268. goto fileDialogPreSave; //Work?
  269. }
  270. }
  271. else
  272. {
  273. bool isCopied = picture->exportPicture(selectedFile, SnapmaticFormat::PGTA_Format);
  274. if (!isCopied)
  275. {
  276. QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Failed to export current Snapmatic picture"));
  277. goto fileDialogPreSave; //Work?
  278. }
  279. else
  280. {
  281. if (isAutoExt) QMessageBox::information(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("Exported Snapmatic to \"%1\" because of using the .auto extension.").arg(selectedFile));
  282. }
  283. }
  284. }
  285. else
  286. {
  287. QMessageBox::warning(parent, PictureDialog::tr("Export as Snapmatic"), PictureDialog::tr("No valid file is selected"));
  288. goto fileDialogPreSave; //Work?
  289. }
  290. }
  291. settings.setValue(parent->objectName() % "+Geometry", fileDialog.saveGeometry());
  292. settings.setValue("Directory", fileDialog.directory().absolutePath());
  293. settings.endGroup();
  294. }
  295. QString PictureExport::getPictureFileName(SnapmaticPicture *picture)
  296. {
  297. return picture->getExportPictureFileName();
  298. }