Qt: add shortcut manager

This commit is contained in:
Megamouse 2019-10-04 16:14:05 +02:00
parent 9ee7d04560
commit 43288a6760
18 changed files with 908 additions and 172 deletions

View file

@ -302,7 +302,7 @@ u32 music_selection_context::step_track(bool next)
// Play the previous track. Start with the last track if we reached the start of the playlist.
if (current_track == 0)
{
current_track = playlist.size() - 1;
current_track = ::narrow<u32>(playlist.size() - 1);
}
else
{

View file

@ -65,7 +65,7 @@ std::string cfg_rpcn::generate_npid()
const char list_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
std::srand(time(nullptr));
std::srand(static_cast<u32>(time(nullptr)));
for (int i = 0; i < 10; i++)
{

View file

@ -362,6 +362,15 @@
<ClCompile Include="QTGeneratedFiles\Debug\moc_settings_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_shortcut_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_shortcut_handler.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_shortcut_settings.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_skylander_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
@ -587,6 +596,15 @@
<ClCompile Include="QTGeneratedFiles\Release\moc_settings_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_shortcut_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_shortcut_handler.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_shortcut_settings.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_skylander_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
@ -665,6 +683,9 @@
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp" />
<ClCompile Include="rpcs3qt\settings.cpp" />
<ClCompile Include="rpcs3qt\shortcut_dialog.cpp" />
<ClCompile Include="rpcs3qt\shortcut_handler.cpp" />
<ClCompile Include="rpcs3qt\shortcut_settings.cpp" />
<ClCompile Include="rpcs3qt\shortcut_utils.cpp" />
<ClCompile Include="rpcs3qt\skylander_dialog.cpp" />
<ClCompile Include="rpcs3qt\tooltips.cpp" />
@ -903,6 +924,7 @@
<ClInclude Include="QTGeneratedFiles\ui_patch_creator_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_patch_manager_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_settings_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_shortcut_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_welcome_dialog.h" />
<CustomBuild Include="rpcs3qt\about_dialog.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
@ -1237,6 +1259,36 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(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\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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"</Command>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_handler.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_settings.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_dialog.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\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" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\shortcut_utils.h" />
<ClInclude Include="rpcs3qt\stylesheets.h" />
<CustomBuild Include="rpcs3qt\skylander_dialog.h">
@ -1651,6 +1703,16 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_dialog.ui">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Uic%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Uic%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />

View file

@ -145,6 +145,9 @@
<Filter Include="Io\SDL">
<UniqueIdentifier>{00fa44cd-ccae-48d9-8541-5f3b2b26a845}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\shortcuts">
<UniqueIdentifier>{1b83df2f-bb74-4bc9-87f1-ab2f3889bcc9}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
@ -891,6 +894,33 @@
<ClCompile Include="QTGeneratedFiles\Release\moc_config_checker.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\shortcut_handler.cpp">
<Filter>Gui\shortcuts</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_shortcut_handler.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_shortcut_handler.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\shortcut_settings.cpp">
<Filter>Gui\shortcuts</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_shortcut_settings.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_shortcut_settings.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\shortcut_dialog.cpp">
<Filter>Gui\shortcuts</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_shortcut_dialog.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_shortcut_dialog.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Input\ds4_pad_handler.h">
@ -1058,6 +1088,9 @@
<ClInclude Include="Input\sdl_pad_handler.h">
<Filter>Io\SDL</Filter>
</ClInclude>
<ClInclude Include="QTGeneratedFiles\ui_shortcut_dialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
@ -1318,6 +1351,18 @@
<CustomBuild Include="rpcs3qt\config_checker.h">
<Filter>Gui\log</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_handler.h">
<Filter>Gui\shortcuts</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_settings.h">
<Filter>Gui\shortcuts</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_dialog.h">
<Filter>Gui\shortcuts</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\shortcut_dialog.ui">
<Filter>Form Files</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Image Include="rpcs3.ico" />

View file

@ -74,6 +74,9 @@ set(SRC_FILES
settings.cpp
settings_dialog.cpp
shortcut_utils.cpp
shortcut_dialog.cpp
shortcut_handler.cpp
shortcut_settings.cpp
skylander_dialog.cpp
syntax_highlighter.cpp
tooltips.cpp
@ -102,6 +105,7 @@ set(UI_FILES
patch_creator_dialog.ui
patch_manager_dialog.ui
settings_dialog.ui
shortcut_dialog.ui
welcome_dialog.ui
)

View file

@ -124,6 +124,10 @@ gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon,
setVisibility(startup_visibility);
create();
// TODO: enable in Qt6
//m_shortcut_handler = new shortcut_handler(gui::shortcuts::shortcut_handler_id::game_window, this, m_gui_settings);
//connect(m_shortcut_handler, &shortcut_handler::shortcut_activated, this, &gs_frame::handle_shortcut);
// Change cursor when in fullscreen.
connect(this, &QWindow::visibilityChanged, this, [this](QWindow::Visibility visibility)
{
@ -138,7 +142,7 @@ gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon,
});
// Configure the mouse hide on idle timer
connect(&m_mousehide_timer, &QTimer::timeout, this, &gs_frame::MouseHideTimeout);
connect(&m_mousehide_timer, &QTimer::timeout, this, &gs_frame::mouse_hide_timeout);
m_mousehide_timer.setSingleShot(true);
#ifdef _WIN32
@ -220,6 +224,7 @@ void gs_frame::showEvent(QShowEvent *event)
QWindow::showEvent(event);
}
// TODO: remove when shortcuts are properly hooked up (also check keyboard_pad_handler::processKeyEvent)
void gs_frame::keyPressEvent(QKeyEvent *keyEvent)
{
if (keyEvent->isAutoRepeat())
@ -236,38 +241,117 @@ void gs_frame::keyPressEvent(QKeyEvent *keyEvent)
{
if (keyEvent->modifiers() == Qt::AltModifier)
{
static int count = 0;
mark_log.success("Made forced mark %d in log", ++count);
return;
handle_shortcut(gui::shortcuts::shortcut::gw_log_mark, {});
break;
}
else if (keyEvent->modifiers() == Qt::ControlModifier)
{
toggle_mouselock();
return;
handle_shortcut(gui::shortcuts::shortcut::gw_mouse_lock, {});
break;
}
break;
}
case Qt::Key_Return:
{
if (keyEvent->modifiers() == Qt::AltModifier)
{
toggle_fullscreen();
return;
}
handle_shortcut(gui::shortcuts::shortcut::gw_toggle_fullscreen, {});
break;
}
case Qt::Key_Escape:
{
if (visibility() == FullScreen && !m_disable_kb_hotkeys)
{
toggle_fullscreen();
return;
}
handle_shortcut(gui::shortcuts::shortcut::gw_exit_fullscreen, {});
break;
}
case Qt::Key_P:
{
if (keyEvent->modifiers() == Qt::ControlModifier && !m_disable_kb_hotkeys)
if (keyEvent->modifiers() == Qt::ControlModifier)
handle_shortcut(gui::shortcuts::shortcut::gw_pause_play, {});
break;
}
case Qt::Key_S:
{
if (keyEvent->modifiers() == Qt::ControlModifier)
handle_shortcut(gui::shortcuts::shortcut::gw_savestate, {});
break;
}
case Qt::Key_R:
{
if (keyEvent->modifiers() == Qt::ControlModifier)
handle_shortcut(gui::shortcuts::shortcut::gw_restart, {});
break;
}
case Qt::Key_C:
{
if (keyEvent->modifiers() == Qt::AltModifier)
handle_shortcut(gui::shortcuts::shortcut::gw_rsx_capture, {});
break;
}
case Qt::Key_F10:
{
if (keyEvent->modifiers() == Qt::ControlModifier)
handle_shortcut(gui::shortcuts::shortcut::gw_frame_limit, {});
break;
}
case Qt::Key_F11:
{
handle_shortcut(gui::shortcuts::shortcut::gw_toggle_recording, {});
break;
}
case Qt::Key_F12:
{
handle_shortcut(gui::shortcuts::shortcut::gw_screenshot, {});
break;
}
default:
{
break;
}
}
}
void gs_frame::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence)
{
gui_log.notice("Game window registered shortcut: %s (%s)", shortcut_key, key_sequence.toString().toStdString());
switch (shortcut_key)
{
case gui::shortcuts::shortcut::gw_toggle_fullscreen:
{
toggle_fullscreen();
break;
}
case gui::shortcuts::shortcut::gw_exit_fullscreen:
{
if (visibility() == FullScreen && !m_disable_kb_hotkeys)
{
toggle_fullscreen();
}
break;
}
case gui::shortcuts::shortcut::gw_log_mark:
{
static int count = 0;
mark_log.success("Made forced mark %d in log", ++count);
break;
}
case gui::shortcuts::shortcut::gw_mouse_lock:
{
toggle_mouselock();
break;
}
case gui::shortcuts::shortcut::gw_screenshot:
{
screenshot_toggle = true;
break;
}
case gui::shortcuts::shortcut::gw_toggle_recording:
{
toggle_recording();
break;
}
case gui::shortcuts::shortcut::gw_pause_play:
{
if (!m_disable_kb_hotkeys)
{
switch (Emu.GetStatus())
{
@ -290,18 +374,9 @@ void gs_frame::keyPressEvent(QKeyEvent *keyEvent)
}
break;
}
case Qt::Key_S:
case gui::shortcuts::shortcut::gw_restart:
{
if (keyEvent->modifiers() == Qt::ControlModifier && !m_disable_kb_hotkeys)
{
Emu.Kill(false, true);
return;
}
break;
}
case Qt::Key_R:
{
if (keyEvent->modifiers() == Qt::ControlModifier && !m_disable_kb_hotkeys)
if (!m_disable_kb_hotkeys)
{
if (Emu.IsStopped())
{
@ -314,133 +389,34 @@ void gs_frame::keyPressEvent(QKeyEvent *keyEvent)
}
break;
}
case Qt::Key_C:
case gui::shortcuts::shortcut::gw_savestate:
{
if (keyEvent->modifiers() == Qt::AltModifier && !m_disable_kb_hotkeys)
if (!m_disable_kb_hotkeys)
{
Emu.Kill(false, true);
return;
}
break;
}
case gui::shortcuts::shortcut::gw_rsx_capture:
{
if (!m_disable_kb_hotkeys)
{
g_user_asked_for_frame_capture = true;
return;
}
break;
}
case Qt::Key_F10:
case gui::shortcuts::shortcut::gw_frame_limit:
{
if (keyEvent->modifiers() == Qt::ControlModifier)
{
g_disable_frame_limit = !g_disable_frame_limit;
gui_log.warning("%s boost mode", g_disable_frame_limit.load() ? "Enabled" : "Disabled");
return;
}
break;
}
case Qt::Key_F11:
{
utils::video_provider& video_provider = g_fxo->get<utils::video_provider>();
if (g_recording_mode == recording_mode::cell)
{
gui_log.warning("A video recorder is already in use by cell. Regular recording can not proceed.");
m_video_encoder->stop();
break;
}
if (g_recording_mode.exchange(recording_mode::stopped) == recording_mode::rpcs3)
{
m_video_encoder->stop();
if (!video_provider.set_image_sink(nullptr, recording_mode::rpcs3))
{
gui_log.warning("The video provider could not release the image sink. A sink with higher priority must have been set.");
}
// Play a sound
if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_recording.wav"; fs::is_file(sound_path))
{
QSound::play(qstr(sound_path));
}
else
{
QApplication::beep();
}
ensure(m_video_encoder->path().starts_with(fs::get_config_dir()));
const std::string shortpath = m_video_encoder->path().substr(fs::get_config_dir().size() - 1); // -1 for /
rsx::overlays::queue_message(tr("Recording saved: %0").arg(QString::fromStdString(shortpath)).toStdString());
}
else
{
m_video_encoder->stop();
const std::string& id = Emu.GetTitleID();
std::string video_path = fs::get_config_dir() + "recordings/";
if (!id.empty())
{
video_path += id + "/";
}
if (!fs::create_path(video_path) && fs::g_tls_error != fs::error::exist)
{
screenshot_log.error("Failed to create recordings path \"%s\" : %s", video_path, fs::g_tls_error);
break;
}
if (!id.empty())
{
video_path += id + "_";
}
video_path += "recording_" + date_time::current_time_narrow<'_'>() + ".mp4";
utils::video_encoder::frame_format output_format{};
output_format.av_pixel_format = static_cast<AVPixelFormat>(g_cfg_recording.pixel_format.get());
output_format.width = g_cfg_recording.width;
output_format.height = g_cfg_recording.height;
output_format.pitch = g_cfg_recording.width * 4;
m_video_encoder->set_path(video_path);
m_video_encoder->set_framerate(g_cfg_recording.framerate);
m_video_encoder->set_video_bitrate(g_cfg_recording.video_bps);
m_video_encoder->set_video_codec(g_cfg_recording.video_codec);
m_video_encoder->set_max_b_frames(g_cfg_recording.max_b_frames);
m_video_encoder->set_gop_size(g_cfg_recording.gop_size);
m_video_encoder->set_output_format(output_format);
m_video_encoder->set_sample_rate(0); // TODO
m_video_encoder->set_audio_bitrate(0); // TODO
m_video_encoder->set_audio_codec(0); // TODO
m_video_encoder->encode();
if (m_video_encoder->has_error)
{
rsx::overlays::queue_message(tr("Recording not possible").toStdString());
m_video_encoder->stop();
break;
}
if (!video_provider.set_image_sink(m_video_encoder, recording_mode::rpcs3))
{
gui_log.warning("The video provider could not set the image sink. A sink with higher priority must have been set.");
rsx::overlays::queue_message(tr("Recording not possible").toStdString());
m_video_encoder->stop();
break;
}
video_provider.set_pause_time(0);
g_recording_mode = recording_mode::rpcs3;
rsx::overlays::queue_message(tr("Recording started").toStdString());
}
break;
}
case Qt::Key_F12:
{
screenshot_toggle = true;
g_disable_frame_limit = !g_disable_frame_limit;
gui_log.warning("%s boost mode", g_disable_frame_limit.load() ? "Enabled" : "Disabled");
break;
}
default:
{
break;
}
}
}
void gs_frame::toggle_fullscreen()
@ -466,6 +442,105 @@ void gs_frame::toggle_fullscreen()
});
}
void gs_frame::toggle_recording()
{
utils::video_provider& video_provider = g_fxo->get<utils::video_provider>();
if (g_recording_mode == recording_mode::cell)
{
gui_log.warning("A video recorder is already in use by cell. Regular recording can not proceed.");
m_video_encoder->stop();
return;
}
if (g_recording_mode.exchange(recording_mode::stopped) == recording_mode::rpcs3)
{
m_video_encoder->stop();
if (!video_provider.set_image_sink(nullptr, recording_mode::rpcs3))
{
gui_log.warning("The video provider could not release the image sink. A sink with higher priority must have been set.");
}
// Play a sound
if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_recording.wav"; fs::is_file(sound_path))
{
QSound::play(qstr(sound_path));
}
else
{
QApplication::beep();
}
ensure(m_video_encoder->path().starts_with(fs::get_config_dir()));
const std::string shortpath = m_video_encoder->path().substr(fs::get_config_dir().size() - 1); // -1 for /
rsx::overlays::queue_message(tr("Recording saved: %0").arg(QString::fromStdString(shortpath)).toStdString());
}
else
{
m_video_encoder->stop();
const std::string& id = Emu.GetTitleID();
std::string video_path = fs::get_config_dir() + "recordings/";
if (!id.empty())
{
video_path += id + "/";
}
if (!fs::create_path(video_path) && fs::g_tls_error != fs::error::exist)
{
screenshot_log.error("Failed to create recordings path \"%s\" : %s", video_path, fs::g_tls_error);
return;
}
if (!id.empty())
{
video_path += id + "_";
}
video_path += "recording_" + date_time::current_time_narrow<'_'>() + ".mp4";
utils::video_encoder::frame_format output_format{};
output_format.av_pixel_format = static_cast<AVPixelFormat>(g_cfg_recording.pixel_format.get());
output_format.width = g_cfg_recording.width;
output_format.height = g_cfg_recording.height;
output_format.pitch = g_cfg_recording.width * 4;
m_video_encoder->set_path(video_path);
m_video_encoder->set_framerate(g_cfg_recording.framerate);
m_video_encoder->set_video_bitrate(g_cfg_recording.video_bps);
m_video_encoder->set_video_codec(g_cfg_recording.video_codec);
m_video_encoder->set_max_b_frames(g_cfg_recording.max_b_frames);
m_video_encoder->set_gop_size(g_cfg_recording.gop_size);
m_video_encoder->set_output_format(output_format);
m_video_encoder->set_sample_rate(0); // TODO
m_video_encoder->set_audio_bitrate(0); // TODO
m_video_encoder->set_audio_codec(0); // TODO
m_video_encoder->encode();
if (m_video_encoder->has_error)
{
rsx::overlays::queue_message(tr("Recording not possible").toStdString());
m_video_encoder->stop();
return;
}
if (!video_provider.set_image_sink(m_video_encoder, recording_mode::rpcs3))
{
gui_log.warning("The video provider could not set the image sink. A sink with higher priority must have been set.");
rsx::overlays::queue_message(tr("Recording not possible").toStdString());
m_video_encoder->stop();
return;
}
video_provider.set_pause_time(0);
g_recording_mode = recording_mode::rpcs3;
rsx::overlays::queue_message(tr("Recording started").toStdString());
}
}
void gs_frame::toggle_mouselock()
{
// first we toggle the value
@ -985,7 +1060,7 @@ void gs_frame::handle_cursor(QWindow::Visibility visibility, bool from_event, bo
update_cursor();
}
void gs_frame::MouseHideTimeout()
void gs_frame::mouse_hide_timeout()
{
// Our idle timeout occured, so we update the cursor
if (m_hide_mouse_after_idletime && m_show_mouse)

View file

@ -1,5 +1,6 @@
#pragma once
#include "shortcut_handler.h"
#include "util/types.hpp"
#include "util/atomic.hpp"
#include "util/media_utils.h"
@ -105,10 +106,12 @@ protected:
private:
void hide_on_close();
void toggle_recording();
void toggle_mouselock();
void update_cursor();
void handle_cursor(QWindow::Visibility visibility, bool from_event, bool start_idle_timer);
private Q_SLOTS:
void MouseHideTimeout();
void mouse_hide_timeout();
void handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence);
};

View file

@ -116,6 +116,7 @@ namespace gui
const QString pad_settings = "PadSettings";
const QString config = "Config";
const QString log_viewer = "LogViewer";
const QString sc = "Shortcuts";
const QString update_on = "true";
const QString update_off = "false";
@ -258,6 +259,8 @@ namespace gui
const gui_save lv_show_timestamps = gui_save(log_viewer, "show_timestamps", true);
const gui_save lv_show_threads = gui_save(log_viewer, "show_threads", true);
const gui_save lv_log_levels = gui_save(log_viewer, "log_levels", 0b11111111u);
const gui_save sc_shortcuts = gui_save(sc, "shortcuts", QVariantMap());
}
/** Class for GUI settings..

View file

@ -32,6 +32,7 @@
#include "ipc_settings_dialog.h"
#include "shortcut_utils.h"
#include "config_checker.h"
#include "shortcut_dialog.h"
#include <thread>
#include <charconv>
@ -159,6 +160,9 @@ bool main_window::Init([[maybe_unused]] bool with_cli_boot)
}
}
m_shortcut_handler = new shortcut_handler(gui::shortcuts::shortcut_handler_id::main_window, this, m_gui_settings);
connect(m_shortcut_handler, &shortcut_handler::shortcut_activated, this, &main_window::handle_shortcut);
show(); // needs to be done before creating the thumbnail toolbar
// enable play options if a recent game exists
@ -329,6 +333,63 @@ void main_window::ResizeIcons(int index)
m_game_list_frame->ResizeIcons(index);
}
void main_window::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence)
{
gui_log.notice("Main window registered shortcut: %s (%s)", shortcut_key, key_sequence.toString().toStdString());
const system_state status = Emu.GetStatus();
switch (shortcut_key)
{
case gui::shortcuts::shortcut::mw_toggle_fullscreen:
{
ui->toolbar_fullscreen->trigger();
break;
}
case gui::shortcuts::shortcut::mw_exit_fullscreen:
{
if (isFullScreen())
ui->toolbar_fullscreen->trigger();
break;
}
case gui::shortcuts::shortcut::mw_refresh:
{
m_game_list_frame->Refresh(true);
break;
}
case gui::shortcuts::shortcut::mw_pause:
{
if (status == system_state::running)
Emu.Pause();
break;
}
case gui::shortcuts::shortcut::mw_restart:
{
if (status == system_state::paused)
Emu.Resume();
else if (status == system_state::ready)
Emu.Run(true);
break;
}
case gui::shortcuts::shortcut::mw_start:
{
if (!Emu.GetBoot().empty())
Emu.Restart();
break;
}
case gui::shortcuts::shortcut::mw_stop:
{
if (status != system_state::stopped)
Emu.GracefulShutdown(false, true);
break;
}
default:
{
break;
}
}
}
void main_window::OnPlayOrPause()
{
gui_log.notice("User triggered OnPlayOrPause");
@ -941,7 +1002,6 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
pdlg.SetValue(pdlg.maximum());
std::this_thread::sleep_for(100ms);
if (true)
{
m_game_list_frame->Refresh(true);
@ -962,7 +1022,6 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
bootable_paths_installed[bootable_paths[index]] = packages[index].title_id;
}
if (true)
{
pdlg.hide();
@ -1684,7 +1743,6 @@ void main_window::OnEmuRun(bool /*start_playtime*/) const
m_thumb_playPause->setIcon(m_icon_thumb_pause);
#endif
ui->sysPauseAct->setText(tr("&Pause"));
ui->sysPauseAct->setShortcut(QKeySequence("Ctrl+P"));
ui->sysPauseAct->setIcon(m_icon_pause);
ui->toolbar_start->setIcon(m_icon_pause);
ui->toolbar_start->setText(tr("Pause"));
@ -1708,7 +1766,6 @@ void main_window::OnEmuResume() const
m_thumb_playPause->setIcon(m_icon_thumb_pause);
#endif
ui->sysPauseAct->setText(tr("&Pause"));
ui->sysPauseAct->setShortcut(QKeySequence("Ctrl+P"));
ui->sysPauseAct->setIcon(m_icon_pause);
ui->toolbar_start->setIcon(m_icon_pause);
ui->toolbar_start->setText(tr("Pause"));
@ -1726,7 +1783,6 @@ void main_window::OnEmuPause() const
m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif
ui->sysPauseAct->setText(tr("&Resume"));
ui->sysPauseAct->setShortcut(QKeySequence("Ctrl+R"));
ui->sysPauseAct->setIcon(m_icon_play);
ui->toolbar_start->setIcon(m_icon_play);
ui->toolbar_start->setText(tr("Play"));
@ -1747,7 +1803,6 @@ void main_window::OnEmuStop()
m_debugger_frame->UpdateUI();
ui->sysPauseAct->setText(Emu.IsReady() ? tr("&Play") : tr("&Resume"));
ui->sysPauseAct->setShortcut(QKeySequence("Ctrl+R"));
ui->sysPauseAct->setIcon(m_icon_play);
#ifdef _WIN32
m_thumb_playPause->setToolTip(play_tooltip);
@ -1808,7 +1863,6 @@ void main_window::OnEmuReady() const
m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif
ui->sysPauseAct->setText(Emu.IsReady() ? tr("&Play") : tr("&Resume"));
ui->sysPauseAct->setShortcut(QKeySequence("Ctrl+R"));
ui->sysPauseAct->setIcon(m_icon_play);
ui->toolbar_start->setIcon(m_icon_play);
ui->toolbar_start->setText(tr("Play"));
@ -2286,6 +2340,13 @@ void main_window::CreateConnects()
connect(ui->confEmuAct, &QAction::triggered, this, [open_settings]() { open_settings(7); });
connect(ui->confGuiAct, &QAction::triggered, this, [open_settings]() { open_settings(8); });
connect(ui->confShortcutsAct, &QAction::triggered, [this]()
{
shortcut_dialog dlg(m_gui_settings, this);
connect(&dlg, &shortcut_dialog::saved, m_shortcut_handler, &shortcut_handler::update);
dlg.exec();
});
const auto open_pad_settings = [this]
{
pad_settings_dialog dlg(m_gui_settings, this);
@ -2996,23 +3057,6 @@ void main_window::CreateFirmwareCache()
}
}
void main_window::keyPressEvent(QKeyEvent *keyEvent)
{
if (keyEvent->isAutoRepeat())
{
return;
}
if (((keyEvent->modifiers() & Qt::AltModifier) && keyEvent->key() == Qt::Key_Return) || (isFullScreen() && keyEvent->key() == Qt::Key_Escape))
{
ui->toolbar_fullscreen->trigger();
}
else if ((keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key() == Qt::Key_F5)
{
m_game_list_frame->Refresh(true);
}
}
void main_window::mouseDoubleClickEvent(QMouseEvent *event)
{
if (isFullScreen())

View file

@ -12,6 +12,7 @@
#include "update_manager.h"
#include "settings.h"
#include "shortcut_handler.h"
#include "Emu/System.h"
#include <memory>
@ -127,9 +128,10 @@ private Q_SLOTS:
void RemoveFirmwareCache();
void CreateFirmwareCache();
void handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence);
protected:
void closeEvent(QCloseEvent *event) override;
void keyPressEvent(QKeyEvent *keyEvent) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
@ -187,4 +189,6 @@ private:
update_manager m_updater;
QAction* m_download_menu_action = nullptr;
shortcut_handler* m_shortcut_handler = nullptr;
};

View file

@ -246,6 +246,9 @@
<addaction name="separator"/>
<addaction name="confRPCNAct"/>
<addaction name="confIPCAct"/>
<addaction name="separator"/>
<addaction name="confShortcutsAct"/>
<addaction name="separator"/>
<addaction name="confAutopauseManagerAct"/>
</widget>
<widget class="QMenu" name="menuManage">
@ -1239,11 +1242,15 @@
<string>Check Config</string>
</property>
</action>
<action name="confShortcutsAct">
<property name="text">
<string>Shortcuts</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="../resources.qrc"/>
<include location="../resources.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -0,0 +1,103 @@
#include "shortcut_dialog.h"
#include "ui_shortcut_dialog.h"
#include "shortcut_settings.h"
#include <QDialogButtonBox>
#include <QPushButton>
#include <QKeySequenceEdit>
#include <QLabel>
#include <QHBoxLayout>
shortcut_dialog::shortcut_dialog(const std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
: QDialog(parent), ui(new Ui::shortcut_dialog), m_gui_settings(gui_settings)
{
ui->setupUi(this);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &shortcut_dialog::reject);
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
{
if (button == ui->buttonBox->button(QDialogButtonBox::Save))
{
save();
accept();
}
else if (button == ui->buttonBox->button(QDialogButtonBox::Apply))
{
save();
}
});
shortcut_settings sc_settings{};
for (const auto& [shortcut_key, shortcut] : sc_settings.shortcut_map)
{
const QKeySequence key_sequence = sc_settings.get_key_sequence(shortcut, gui_settings);
QLabel* label = new QLabel(shortcut.localized_name);
QKeySequenceEdit* key_sequence_edit = new QKeySequenceEdit;
key_sequence_edit->setObjectName(shortcut.name);
key_sequence_edit->setMinimumWidth(label->sizeHint().width());
key_sequence_edit->setKeySequence(key_sequence);
m_values[shortcut.name] = key_sequence.toString();
connect(key_sequence_edit, &QKeySequenceEdit::keySequenceChanged, this, &shortcut_dialog::handle_change);
QHBoxLayout* shortcut_layout = new QHBoxLayout;
shortcut_layout->addWidget(label);
shortcut_layout->addWidget(key_sequence_edit);
shortcut_layout->setStretch(0, 1);
shortcut_layout->setStretch(1, 1);
const auto add_layout = [](QVBoxLayout* layout, QHBoxLayout* shortcut_layout)
{
layout->insertLayout(layout->count() - 1, shortcut_layout); // count() - 1 to ignore the vertical spacer
};
switch (shortcut.handler_id)
{
case gui::shortcuts::shortcut_handler_id::game_window:
{
add_layout(ui->game_window_layout, shortcut_layout);
break;
}
case gui::shortcuts::shortcut_handler_id::main_window:
{
add_layout(ui->main_window_layout, shortcut_layout);
break;
}
}
}
const int min_width = std::max(
{
ui->main_window_group_box->sizeHint().width(),
ui->game_window_group_box->sizeHint().width(),
});
ui->main_window_group_box->setMinimumWidth(min_width);
ui->game_window_group_box->setMinimumWidth(min_width);
}
shortcut_dialog::~shortcut_dialog()
{
delete ui;
}
void shortcut_dialog::save()
{
shortcut_settings sc_settings{};
for (const auto& entry : m_values)
{
m_gui_settings->SetValue(sc_settings.get_shortcut_gui_save(entry.first), entry.second);
}
Q_EMIT saved();
}
void shortcut_dialog::handle_change(const QKeySequence& keySequence)
{
m_values[sender()->objectName()] = keySequence.toString();
}

View file

@ -0,0 +1,32 @@
#pragma once
#include "gui_settings.h"
#include <QDialog>
namespace Ui
{
class shortcut_dialog;
}
class shortcut_dialog : public QDialog
{
Q_OBJECT
public:
explicit shortcut_dialog(const std::shared_ptr<gui_settings> gui_settings, QWidget* parent = nullptr);
~shortcut_dialog();
Q_SIGNALS:
void saved();
private:
void save();
Ui::shortcut_dialog* ui;
std::shared_ptr<gui_settings> m_gui_settings;
std::map<QString, QString> m_values;
private Q_SLOTS:
void handle_change(const QKeySequence& keySequence);
};

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>shortcut_dialog</class>
<widget class="QDialog" name="shortcut_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>822</width>
<height>364</height>
</rect>
</property>
<property name="windowTitle">
<string>Shortcuts</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
<item>
<widget class="QGroupBox" name="main_window_group_box">
<property name="title">
<string>Main Window Shortcuts</string>
</property>
<layout class="QVBoxLayout" name="main_window_layout">
<item>
<spacer name="verticalSpacer_main_window">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="game_window_group_box">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Game Window Shortcuts</string>
</property>
<layout class="QVBoxLayout" name="game_window_layout">
<item>
<spacer name="verticalSpacer_game_window">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,77 @@
#include "stdafx.h"
#include "shortcut_handler.h"
#include "Emu/System.h"
LOG_CHANNEL(shortcut_log, "Shortcuts");
shortcut_handler::shortcut_handler(gui::shortcuts::shortcut_handler_id handler_id, QWidget* parent, const std::shared_ptr<gui_settings>& gui_settings)
: QObject(parent), m_handler_id(handler_id), m_gui_settings(gui_settings)
{
// Initialize shortcuts
shortcut_settings sc_settings{};
for (const auto& [shortcut_key, info] : sc_settings.shortcut_map)
{
// Skip shortcuts that weren't meant for this handler
if (handler_id != info.handler_id)
{
continue;
}
const QKeySequence key_sequence = sc_settings.get_key_sequence(info, gui_settings);
QShortcut* shortcut = new QShortcut(key_sequence, parent);
shortcut->setAutoRepeat(false);
shortcut_key_info key_info{};
key_info.shortcut = shortcut;
key_info.info = info;
key_info.key_sequence = key_sequence;
m_shortcuts[shortcut_key] = key_info;
connect(shortcut, &QShortcut::activated, this, [this, key = shortcut_key]()
{
handle_shortcut(key, m_shortcuts[key].key_sequence);
});
connect(shortcut, &QShortcut::activatedAmbiguously, this, [this, key = shortcut_key]()
{
// TODO: do not allow same shortcuts and remove this connect
// activatedAmbiguously will trigger if you have the same key sequence for several shortcuts
const QKeySequence& key_sequence = m_shortcuts[key].key_sequence;
shortcut_log.error("Shortcut activated ambiguously: %s (%s)", key, key_sequence.toString().toStdString());
handle_shortcut(key, key_sequence);
});
}
}
void shortcut_handler::update()
{
shortcut_log.notice("Updating shortcuts");
shortcut_settings sc_settings{};
for (const auto& [shortcut_key, info] : sc_settings.shortcut_map)
{
// Skip shortcuts that weren't meant for this handler
if (m_handler_id != info.handler_id || !m_shortcuts.contains(shortcut_key))
{
continue;
}
const QKeySequence key_sequence = sc_settings.get_key_sequence(info, m_gui_settings);
shortcut_key_info& key_info = m_shortcuts[shortcut_key];
key_info.key_sequence = key_sequence;
if (key_info.shortcut)
{
key_info.shortcut->setKey(key_sequence);
}
}
}
void shortcut_handler::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence)
{
shortcut_log.notice("Shortcut pressed: %s (%s)", shortcut_key, key_sequence.toString().toStdString());
Q_EMIT shortcut_activated(shortcut_key, key_sequence);
}

View file

@ -0,0 +1,37 @@
#pragma once
#include "gui_settings.h"
#include "shortcut_settings.h"
#include <QShortcut>
#include <QWidget>
#include <map>
class shortcut_handler : public QObject
{
Q_OBJECT
public:
shortcut_handler(gui::shortcuts::shortcut_handler_id handler_id, QWidget* parent, const std::shared_ptr<gui_settings>& gui_settings);
Q_SIGNALS:
void shortcut_activated(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence);
public Q_SLOTS:
void update();
private:
void handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKeySequence& key_sequence);
gui::shortcuts::shortcut_handler_id m_handler_id;
std::shared_ptr<gui_settings> m_gui_settings;
struct shortcut_key_info
{
QShortcut* shortcut = nullptr;
QKeySequence key_sequence{};
shortcut_info info{};
};
std::map<gui::shortcuts::shortcut, shortcut_key_info> m_shortcuts;
};

View file

@ -0,0 +1,90 @@
#include "shortcut_settings.h"
using namespace gui::shortcuts;
template <>
void fmt_class_string<gui::shortcuts::shortcut>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](gui::shortcuts::shortcut value)
{
switch (value)
{
case shortcut::mw_start: return "mw_start";
case shortcut::mw_stop: return "mw_stop";
case shortcut::mw_pause: return "mw_pause";
case shortcut::mw_restart: return "mw_restart";
case shortcut::mw_toggle_fullscreen: return "mw_toggle_fullscreen";
case shortcut::mw_exit_fullscreen: return "mw_exit_fullscreen";
case shortcut::mw_refresh: return "mw_refresh";
case shortcut::gw_toggle_fullscreen: return "gw_toggle_fullscreen";
case shortcut::gw_exit_fullscreen: return "gw_exit_fullscreen";
case shortcut::gw_log_mark: return "gw_log_mark";
case shortcut::gw_mouse_lock: return "gw_mouse_lock";
case shortcut::gw_screenshot: return "gw_screenshot";
case shortcut::gw_toggle_recording: return "gw_toggle_recording";
case shortcut::gw_pause_play: return "gw_pause_play";
case shortcut::gw_savestate: return "gw_savestate";
case shortcut::gw_restart: return "gw_restart";
case shortcut::gw_rsx_capture: return "gw_rsx_capture";
case shortcut::gw_frame_limit: return "gw_frame_limit";
case shortcut::count: return "count";
};
return unknown;
});
}
shortcut_settings::shortcut_settings()
: shortcut_map({
{ shortcut::mw_start, shortcut_info{ "main_window_start", tr("Start"), "Ctrl+E", shortcut_handler_id::main_window } },
{ shortcut::mw_stop, shortcut_info{ "main_window_stop", tr("Stop"), "Ctrl+S", shortcut_handler_id::main_window } },
{ shortcut::mw_pause, shortcut_info{ "main_window_pause", tr("Pause"), "Ctrl+P", shortcut_handler_id::main_window } },
{ shortcut::mw_restart, shortcut_info{ "main_window_restart", tr("Restart"), "Ctrl+R", shortcut_handler_id::main_window } },
{ shortcut::mw_toggle_fullscreen, shortcut_info{ "main_window_toggle_fullscreen", tr("Toggle Fullscreen"), "Alt+Return", shortcut_handler_id::main_window } },
{ shortcut::mw_exit_fullscreen, shortcut_info{ "main_window_exit_fullscreen", tr("Exit Fullscreen"), "Esc", shortcut_handler_id::main_window } },
{ shortcut::mw_refresh, shortcut_info{ "main_window_refresh", tr("Refresh"), "Ctrl+F5", shortcut_handler_id::main_window } },
{ shortcut::gw_toggle_fullscreen, shortcut_info{ "game_window_toggle_fullscreen", tr("Toggle Fullscreen"), "Alt+Return", shortcut_handler_id::game_window } },
{ shortcut::gw_exit_fullscreen, shortcut_info{ "game_window_exit_fullscreen", tr("Exit Fullscreen"), "Esc", shortcut_handler_id::game_window } },
{ shortcut::gw_log_mark, shortcut_info{ "game_window_log_mark", tr("Add Log Mark"), "Alt+L", shortcut_handler_id::game_window } },
{ shortcut::gw_mouse_lock, shortcut_info{ "game_window_mouse_lock", tr("Mouse lock"), "Ctrl+L", shortcut_handler_id::game_window } },
{ shortcut::gw_toggle_recording, shortcut_info{ "game_window_toggle_recording", tr("Start/Stop Recording"), "F11", shortcut_handler_id::game_window } },
{ shortcut::gw_screenshot, shortcut_info{ "game_window_screenshot", tr("Screenshot"), "F12", shortcut_handler_id::game_window } },
{ shortcut::gw_pause_play, shortcut_info{ "game_window_pause_play", tr("Pause/Play"), "Ctrl+P", shortcut_handler_id::game_window } },
{ shortcut::gw_savestate, shortcut_info{ "game_window_savestate", tr("Savestate"), "Ctrl+S", shortcut_handler_id::game_window } },
{ shortcut::gw_restart, shortcut_info{ "game_window_restart", tr("Restart"), "Ctrl+R", shortcut_handler_id::game_window } },
{ shortcut::gw_rsx_capture, shortcut_info{ "game_window_rsx_capture", tr("RSX Capture"), "Alt+C", shortcut_handler_id::game_window } },
{ shortcut::gw_frame_limit, shortcut_info{ "game_window_gw_frame_limit", tr("Toggle Framelimit"), "Ctrl+F10", shortcut_handler_id::game_window } },
})
{
}
shortcut_settings::~shortcut_settings()
{
}
gui_save shortcut_settings::get_shortcut_gui_save(const QString& shortcut_name)
{
const auto it = std::find_if(shortcut_map.begin(), shortcut_map.end(), [&](const auto& entry) { return entry.second.name == shortcut_name; });
if (it != shortcut_map.cend())
{
return gui_save(gui::sc, it->second.name, it->second.key_sequence);
}
return gui_save();
}
QKeySequence shortcut_settings::get_key_sequence(const shortcut_info& entry, const std::shared_ptr<gui_settings>& gui_settings)
{
const QString saved_value = gui_settings->GetValue(get_shortcut_gui_save(entry.name)).toString();
QKeySequence key_sequence = QKeySequence::fromString(saved_value);
if (key_sequence.isEmpty())
{
// Use the default shortcut if no shortcut was configured
key_sequence = QKeySequence::fromString(entry.key_sequence);
}
return key_sequence;
}

View file

@ -0,0 +1,65 @@
#pragma once
#include "gui_settings.h"
#include <QKeySequence>
namespace gui
{
namespace shortcuts
{
enum class shortcut_handler_id : int
{
main_window,
game_window,
};
enum class shortcut : int
{
mw_start,
mw_stop,
mw_pause,
mw_restart,
mw_toggle_fullscreen,
mw_exit_fullscreen,
mw_refresh,
gw_toggle_fullscreen,
gw_exit_fullscreen,
gw_log_mark,
gw_mouse_lock,
gw_screenshot,
gw_toggle_recording,
gw_pause_play,
gw_savestate,
gw_restart,
gw_rsx_capture,
gw_frame_limit,
count
};
}
}
struct shortcut_info
{
QString name;
QString localized_name;
QString key_sequence;
gui::shortcuts::shortcut_handler_id handler_id{};
};
class shortcut_settings : public QObject
{
Q_OBJECT
public:
shortcut_settings();
~shortcut_settings();
const std::map<const gui::shortcuts::shortcut, const shortcut_info> shortcut_map;
gui_save get_shortcut_gui_save(const QString& shortcut_name);
QKeySequence get_key_sequence(const shortcut_info& entry, const std::shared_ptr<gui_settings>& gui_settings);
};