diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index ef33068716..4088192f8c 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -517,6 +517,16 @@ true true + + true + true + true + + + true + true + true + true true @@ -742,6 +752,16 @@ true true + + true + true + true + + + true + true + true + true true @@ -987,6 +1007,16 @@ true true + + true + true + true + + + true + true + true + true true @@ -1212,6 +1242,16 @@ true true + + true + true + true + + + true + true + true + true true @@ -1276,6 +1316,8 @@ + + @@ -1932,6 +1974,42 @@ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB "-DBRANCH=$(BRANCH)" -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB "-DBRANCH=$(BRANCH)" -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 472cbd3b55..1ef9787ac5 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -125,6 +125,9 @@ ts false + + {b227bdd4-16f5-4f6e-a8b2-8b1f4bdc606a} + @@ -886,6 +889,36 @@ rpcs3 + + Gui\screenshot manager + + + Generated Files\Release - LLVM + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\Debug - LLVM + + + Gui\screenshot manager + + + Generated Files\Release - LLVM + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\Debug - LLVM + @@ -1169,6 +1202,12 @@ Gui\settings + + Gui\screenshot manager + + + Gui\screenshot manager + diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index 19a5694b85..99fbd7e497 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -42,6 +42,8 @@ save_data_info_dialog.cpp save_data_list_dialog.cpp save_manager_dialog.cpp + screenshot_manager_dialog.cpp + screenshot_preview.cpp settings.cpp settings_dialog.cpp skylander_dialog.cpp diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 61bb0a7862..fe28bc48a9 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -6,6 +6,7 @@ #include "save_manager_dialog.h" #include "trophy_manager_dialog.h" #include "user_manager_dialog.h" +#include "screenshot_manager_dialog.h" #include "kernel_explorer.h" #include "game_list_frame.h" #include "debugger_frame.h" @@ -1518,6 +1519,12 @@ void main_window::CreateConnects() m_game_list_frame->Refresh(true); // New user may have different games unlocked. }); + connect(ui->actionManage_Screenshots, &QAction::triggered, [this] + { + screenshot_manager_dialog* screenshot_manager = new screenshot_manager_dialog(); + screenshot_manager->show(); + }); + connect(ui->toolsCgDisasmAct, &QAction::triggered, [this] { cg_disasm_window* cgdw = new cg_disasm_window(m_gui_settings); diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui index f1ca2ad765..ada8433dd1 100644 --- a/rpcs3/rpcs3qt/main_window.ui +++ b/rpcs3/rpcs3qt/main_window.ui @@ -229,6 +229,7 @@ + @@ -1033,6 +1034,11 @@ English + + + Screenshots + + diff --git a/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp b/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp new file mode 100644 index 0000000000..0f8df5511e --- /dev/null +++ b/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp @@ -0,0 +1,59 @@ +#include "screenshot_manager_dialog.h" +#include "screenshot_preview.h" +#include "qt_utils.h" +#include "Utilities/File.h" + +#include +#include +#include +#include +#include +#include + +screenshot_manager_dialog::screenshot_manager_dialog(QWidget* parent) : QDialog(parent) +{ + setWindowTitle(tr("Screenshots")); + + m_grid = new QListWidget(this); + m_grid->setViewMode(QListWidget::IconMode); + m_grid->setMovement(QListWidget::Static); + m_grid->setResizeMode(QListWidget::Adjust); + m_grid->setIconSize(QSize(160, 90)); + m_grid->setGridSize(m_grid->iconSize() + QSize(10, 10)); + + const std::string screen_path = fs::get_config_dir() + "/screenshots/"; + const QStringList filter{ QStringLiteral("*.png") }; + QDirIterator dir_iter(QString::fromStdString(screen_path), filter, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + + while (dir_iter.hasNext()) + { + const QString filepath = dir_iter.next(); + + QListWidgetItem* item = new QListWidgetItem; + item->setData(Qt::UserRole, filepath); + item->setIcon(QIcon(filepath)); + item->setToolTip(filepath); + + m_grid->addItem(item); + } + + connect(m_grid, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item) + { + if (!item) + { + return; + } + + const QString filepath = item->data(Qt::UserRole).toString(); + + screenshot_preview* preview = new screenshot_preview(filepath); + preview->show(); + }); + + QVBoxLayout* layout = new QVBoxLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_grid); + setLayout(layout); + + resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5); +} diff --git a/rpcs3/rpcs3qt/screenshot_manager_dialog.h b/rpcs3/rpcs3qt/screenshot_manager_dialog.h new file mode 100644 index 0000000000..f5b9e3ba4e --- /dev/null +++ b/rpcs3/rpcs3qt/screenshot_manager_dialog.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +class QListWidget; + +class screenshot_manager_dialog : public QDialog +{ + Q_OBJECT + +public: + screenshot_manager_dialog(QWidget* parent = nullptr); + +private: + QListWidget* m_grid = nullptr; +}; diff --git a/rpcs3/rpcs3qt/screenshot_preview.cpp b/rpcs3/rpcs3qt/screenshot_preview.cpp new file mode 100644 index 0000000000..979f38ebbc --- /dev/null +++ b/rpcs3/rpcs3qt/screenshot_preview.cpp @@ -0,0 +1,64 @@ +#include "screenshot_preview.h" +#include "qt_utils.h" + +#include +#include +#include +#include +#include +#include +#include + +screenshot_preview::screenshot_preview(const QString& filepath, QWidget* parent) + : QLabel(parent) + , m_filepath(filepath) +{ + QImageReader reader(filepath); + reader.setAutoTransform(true); + + m_image = reader.read(); + + setWindowTitle(tr("Screenshot Preview")); + setObjectName("screenshot_preview"); + setContextMenuPolicy(Qt::CustomContextMenu); + setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + setPixmap(QPixmap::fromImage(m_image)); + setMinimumSize(160, 90); + + connect(this, &screenshot_preview::customContextMenuRequested, this, &screenshot_preview::show_context_menu); +} +#include + +void screenshot_preview::show_context_menu(const QPoint & pos) +{ + QMenu* menu = new QMenu(); + menu->addAction(tr("&Copy"), [this]() { QGuiApplication::clipboard()->setImage(m_image); }); + menu->addSeparator(); + + QAction* reset_act = menu->addAction(tr("To &Normal Size"), [this]() { scale(m_image.size()); }); + reset_act->setEnabled(pixmap()->size() != m_image.size()); + + QAction* stretch_act = menu->addAction(tr("&Stretch to size"), [this]() { m_stretch = !m_stretch; scale(size()); }); + stretch_act->setCheckable(true); + stretch_act->setChecked(m_stretch); + + menu->addSeparator(); + menu->addAction(tr("E&xit"), this, &QLabel::close); + menu->exec(mapToGlobal(pos)); +} + +void screenshot_preview::scale(const QSize& new_size) +{ + if (new_size != size()) + { + resize(new_size); + } + + setPixmap(QPixmap::fromImage(m_image.scaled(new_size, m_stretch ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio, Qt::SmoothTransformation))); +} + +void screenshot_preview::resizeEvent(QResizeEvent* event) +{ + scale(event->size()); + event->ignore(); +} diff --git a/rpcs3/rpcs3qt/screenshot_preview.h b/rpcs3/rpcs3qt/screenshot_preview.h new file mode 100644 index 0000000000..f9a813997a --- /dev/null +++ b/rpcs3/rpcs3qt/screenshot_preview.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class screenshot_preview : public QLabel +{ + Q_OBJECT + +public: + screenshot_preview(const QString& filepath, QWidget* parent = nullptr); + +protected: + void resizeEvent(QResizeEvent* event); + +private Q_SLOTS: + void show_context_menu(const QPoint& pos); + +private: + void scale(const QSize& size); + + QString m_filepath; + QImage m_image; + double m_factor = 1.0; + bool m_stretch = false; +};