mirror of https://github.com/RPCS3/rpcs3.git
Qt: refactor curl stuff into a downloader
And add 'Background' updater
This commit is contained in:
parent
c495ef10b0
commit
14200c1a1f
|
@ -393,6 +393,11 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_downloader.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_emu_settings.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_emu_settings.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
@ -678,6 +683,11 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_downloader.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_emu_settings.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_emu_settings.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
@ -983,6 +993,11 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_downloader.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_emu_settings.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_emu_settings.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
@ -1268,6 +1283,11 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Release\moc_downloader.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_emu_settings.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_emu_settings.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
@ -1507,6 +1527,7 @@
|
||||||
<ClCompile Include="rpcs3qt\curl_handle.cpp" />
|
<ClCompile Include="rpcs3qt\curl_handle.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\custom_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\custom_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\debugger_list.cpp" />
|
<ClCompile Include="rpcs3qt\debugger_list.cpp" />
|
||||||
|
<ClCompile Include="rpcs3qt\downloader.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\fatal_error_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\fatal_error_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\gui_application.cpp" />
|
<ClCompile Include="rpcs3qt\gui_application.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\input_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\input_dialog.cpp" />
|
||||||
|
@ -2269,6 +2290,24 @@
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(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"</Command>
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(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"</Command>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="rpcs3qt\downloader.h">
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">Moc%27ing %(Identity)...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|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\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"</Command>
|
||||||
|
<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 -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"</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 -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"</Command>
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">Moc%27ing %(Identity)...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(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"</Command>
|
||||||
|
</CustomBuild>
|
||||||
<ClInclude Include="rpcs3qt\emu_settings_type.h" />
|
<ClInclude Include="rpcs3qt\emu_settings_type.h" />
|
||||||
<CustomBuild Include="rpcs3qt\render_creator.h">
|
<CustomBuild Include="rpcs3qt\render_creator.h">
|
||||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">Moc%27ing %(Identity)...</Message>
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">Moc%27ing %(Identity)...</Message>
|
||||||
|
|
|
@ -131,6 +131,9 @@
|
||||||
<Filter Include="Gui\patch manager">
|
<Filter Include="Gui\patch manager">
|
||||||
<UniqueIdentifier>{e72a0cbe-fbcd-4a0b-8c17-a2a3b7a42258}</UniqueIdentifier>
|
<UniqueIdentifier>{e72a0cbe-fbcd-4a0b-8c17-a2a3b7a42258}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Gui\network">
|
||||||
|
<UniqueIdentifier>{bad5498c-a915-4a96-b0cc-f754c02d8e65}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
|
@ -901,9 +904,6 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_update_manager.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_update_manager.cpp">
|
||||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="rpcs3qt\curl_handle.cpp">
|
|
||||||
<Filter>rpcs3</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp">
|
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp">
|
||||||
<Filter>Gui\screenshot manager</Filter>
|
<Filter>Gui\screenshot manager</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -1057,6 +1057,24 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_patch_manager_dialog.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_patch_manager_dialog.cpp">
|
||||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="rpcs3qt\curl_handle.cpp">
|
||||||
|
<Filter>Gui\network</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="rpcs3qt\downloader.cpp">
|
||||||
|
<Filter>Gui\network</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_downloader.cpp">
|
||||||
|
<Filter>Generated Files\Release - LLVM</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_downloader.cpp">
|
||||||
|
<Filter>Generated Files\Debug</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Release\moc_downloader.cpp">
|
||||||
|
<Filter>Generated Files\Release</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_downloader.cpp">
|
||||||
|
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||||
|
@ -1140,9 +1158,6 @@
|
||||||
<ClInclude Include="rpcs3qt\category.h">
|
<ClInclude Include="rpcs3qt\category.h">
|
||||||
<Filter>Gui\game list</Filter>
|
<Filter>Gui\game list</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="rpcs3qt\curl_handle.h">
|
|
||||||
<Filter>rpcs3</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="rpcs3qt\emu_settings_type.h">
|
<ClInclude Include="rpcs3qt\emu_settings_type.h">
|
||||||
<Filter>Gui\settings</Filter>
|
<Filter>Gui\settings</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1158,6 +1173,9 @@
|
||||||
<ClInclude Include="QTGeneratedFiles\ui_patch_manager_dialog.h">
|
<ClInclude Include="QTGeneratedFiles\ui_patch_manager_dialog.h">
|
||||||
<Filter>Generated Files</Filter>
|
<Filter>Generated Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="rpcs3qt\curl_handle.h">
|
||||||
|
<Filter>Gui\network</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||||
|
@ -1376,6 +1394,9 @@
|
||||||
<CustomBuild Include="rpcs3qt\patch_manager_dialog.ui">
|
<CustomBuild Include="rpcs3qt\patch_manager_dialog.ui">
|
||||||
<Filter>Form Files</Filter>
|
<Filter>Form Files</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="rpcs3qt\downloader.h">
|
||||||
|
<Filter>Gui\network</Filter>
|
||||||
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="rpcs3.ico" />
|
<Image Include="rpcs3.ico" />
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
custom_dialog.cpp
|
custom_dialog.cpp
|
||||||
debugger_frame.cpp
|
debugger_frame.cpp
|
||||||
debugger_list.cpp
|
debugger_list.cpp
|
||||||
|
downloader.cpp
|
||||||
_discord_utils.cpp
|
_discord_utils.cpp
|
||||||
emu_settings.cpp
|
emu_settings.cpp
|
||||||
fatal_error_dialog.cpp
|
fatal_error_dialog.cpp
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "downloader.h"
|
||||||
|
#include "curl_handle.h"
|
||||||
|
#include "progress_dialog.h"
|
||||||
|
|
||||||
|
LOG_CHANNEL(network_log, "NETWORK");
|
||||||
|
|
||||||
|
size_t curl_write_cb_compat(char* ptr, size_t /*size*/, size_t nmemb, void* userdata)
|
||||||
|
{
|
||||||
|
downloader* download = reinterpret_cast<downloader*>(userdata);
|
||||||
|
return download->update_buffer(ptr, nmemb);
|
||||||
|
}
|
||||||
|
|
||||||
|
downloader::downloader(const std::string& thread_name, QWidget* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_parent(parent)
|
||||||
|
, m_thread_name(thread_name)
|
||||||
|
{
|
||||||
|
m_curl = new curl_handle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloader::start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title, bool keep_progress_dialog_open, int exptected_size)
|
||||||
|
{
|
||||||
|
connect(this, &downloader::signal_buffer_update, this, &downloader::handle_buffer_update);
|
||||||
|
|
||||||
|
m_keep_progress_dialog_open = keep_progress_dialog_open;
|
||||||
|
m_curl_buf.clear();
|
||||||
|
m_curl_abort = false;
|
||||||
|
|
||||||
|
curl_easy_setopt(m_curl->get_curl(), CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEFUNCTION, curl_write_cb_compat);
|
||||||
|
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEDATA, this);
|
||||||
|
curl_easy_setopt(m_curl->get_curl(), CURLOPT_FOLLOWLOCATION, follow_location ? 1 : 0);
|
||||||
|
|
||||||
|
const auto thread = QThread::create([this]
|
||||||
|
{
|
||||||
|
const auto result = curl_easy_perform(m_curl->get_curl());
|
||||||
|
m_curl_success = result == CURLE_OK;
|
||||||
|
|
||||||
|
if (!m_curl_success && !m_curl_abort)
|
||||||
|
{
|
||||||
|
const std::string error = "Curl error: " + std::string{ curl_easy_strerror(result) };
|
||||||
|
network_log.error("%s", error);
|
||||||
|
Q_EMIT signal_download_error(QString::fromStdString(error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(thread, &QThread::finished, this, [this]()
|
||||||
|
{
|
||||||
|
if (m_curl_abort)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_progress_dialog && (!m_keep_progress_dialog_open || !m_curl_success))
|
||||||
|
{
|
||||||
|
m_progress_dialog->close();
|
||||||
|
m_progress_dialog = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_curl_success)
|
||||||
|
{
|
||||||
|
Q_EMIT signal_download_finished(m_curl_buf);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (show_progress_dialog)
|
||||||
|
{
|
||||||
|
const int maximum = exptected_size > 0 ? exptected_size : 100;
|
||||||
|
|
||||||
|
if (m_progress_dialog)
|
||||||
|
{
|
||||||
|
m_progress_dialog->setWindowTitle(progress_dialog_title);
|
||||||
|
m_progress_dialog->setAutoClose(!m_keep_progress_dialog_open);
|
||||||
|
m_progress_dialog->setMaximum(maximum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_progress_dialog = new progress_dialog(progress_dialog_title, tr("Please wait..."), tr("Abort"), 0, maximum, true, m_parent);
|
||||||
|
m_progress_dialog->setAutoReset(false);
|
||||||
|
m_progress_dialog->setAutoClose(!m_keep_progress_dialog_open);
|
||||||
|
m_progress_dialog->show();
|
||||||
|
|
||||||
|
// Handle abort
|
||||||
|
connect(m_progress_dialog, &QProgressDialog::canceled, this, [this]()
|
||||||
|
{
|
||||||
|
m_curl_abort = true;
|
||||||
|
close_progress_dialog();
|
||||||
|
});
|
||||||
|
connect(m_progress_dialog, &QProgressDialog::finished, m_progress_dialog, &QProgressDialog::deleteLater);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->setObjectName("Compat Update");
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloader::update_progress_dialog(const QString& title)
|
||||||
|
{
|
||||||
|
if (m_progress_dialog)
|
||||||
|
{
|
||||||
|
m_progress_dialog->setWindowTitle(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloader::close_progress_dialog()
|
||||||
|
{
|
||||||
|
if (m_progress_dialog)
|
||||||
|
{
|
||||||
|
m_progress_dialog->close();
|
||||||
|
m_progress_dialog = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progress_dialog* downloader::get_progress_dialog() const
|
||||||
|
{
|
||||||
|
return m_progress_dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t downloader::update_buffer(char* data, size_t size)
|
||||||
|
{
|
||||||
|
if (m_curl_abort)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto old_size = m_curl_buf.size();
|
||||||
|
const auto new_size = old_size + size;
|
||||||
|
m_curl_buf.resize(static_cast<int>(new_size));
|
||||||
|
memcpy(m_curl_buf.data() + old_size, data, size);
|
||||||
|
|
||||||
|
int max = 0;
|
||||||
|
|
||||||
|
if (m_actual_download_size < 0)
|
||||||
|
{
|
||||||
|
if (curl_easy_getinfo(m_curl->get_curl(), CURLINFO_CONTENT_LENGTH_DOWNLOAD, &m_actual_download_size) == CURLE_OK && m_actual_download_size > 0)
|
||||||
|
{
|
||||||
|
max = static_cast<int>(m_actual_download_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_EMIT signal_buffer_update(static_cast<int>(new_size), max);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void downloader::handle_buffer_update(int size, int max)
|
||||||
|
{
|
||||||
|
if (m_curl_abort)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_progress_dialog)
|
||||||
|
{
|
||||||
|
m_progress_dialog->setMaximum(max > 0 ? max : m_progress_dialog->maximum());
|
||||||
|
m_progress_dialog->setValue(size);
|
||||||
|
QApplication::processEvents();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
class curl_handle;
|
||||||
|
class progress_dialog;
|
||||||
|
|
||||||
|
class downloader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
downloader(const std::string& thread_name, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title = "", bool keep_progress_dialog_open = false, int expected_size = -1);
|
||||||
|
size_t update_buffer(char* data, size_t size);
|
||||||
|
|
||||||
|
void update_progress_dialog(const QString& title);
|
||||||
|
void close_progress_dialog();
|
||||||
|
|
||||||
|
progress_dialog* get_progress_dialog() const;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void handle_buffer_update(int size, int max);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void signal_download_error(const QString& error);
|
||||||
|
void signal_download_finished(const QByteArray& data);
|
||||||
|
void signal_buffer_update(int size, int max);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidget* m_parent = nullptr;
|
||||||
|
std::string m_thread_name;
|
||||||
|
|
||||||
|
curl_handle* m_curl = nullptr;
|
||||||
|
QByteArray m_curl_buf;
|
||||||
|
std::atomic<bool> m_curl_abort = false;
|
||||||
|
std::atomic<bool> m_curl_success = false;
|
||||||
|
double m_actual_download_size = -1.0;
|
||||||
|
|
||||||
|
progress_dialog* m_progress_dialog = nullptr;
|
||||||
|
std::atomic<bool> m_keep_progress_dialog_open = false;
|
||||||
|
QString m_progress_dialog_title;
|
||||||
|
};
|
|
@ -1,77 +1,67 @@
|
||||||
#include "game_compatibility.h"
|
#include "game_compatibility.h"
|
||||||
#include "gui_settings.h"
|
#include "gui_settings.h"
|
||||||
#include "progress_dialog.h"
|
#include "downloader.h"
|
||||||
#include "curl_handle.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
LOG_CHANNEL(compat_log, "Compat");
|
LOG_CHANNEL(compat_log, "Compat");
|
||||||
|
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||||
|
|
||||||
size_t curl_write_cb_compat(char* ptr, size_t /*size*/, size_t nmemb, void* userdata)
|
game_compatibility::game_compatibility(std::shared_ptr<gui_settings> settings, QWidget* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_gui_settings(settings)
|
||||||
{
|
{
|
||||||
game_compatibility* gm_cmp = reinterpret_cast<game_compatibility*>(userdata);
|
m_filepath = m_gui_settings->GetSettingsDir() + "/compat_database.dat";
|
||||||
return gm_cmp->update_buffer(ptr, nmemb);
|
m_downloader = new downloader("Compat Update", parent);
|
||||||
}
|
|
||||||
|
|
||||||
game_compatibility::game_compatibility(std::shared_ptr<gui_settings> settings) : m_xgui_settings(settings)
|
|
||||||
{
|
|
||||||
m_filepath = m_xgui_settings->GetSettingsDir() + "/compat_database.dat";
|
|
||||||
m_url = "https://rpcs3.net/compatibility?api=v1&export";
|
|
||||||
|
|
||||||
m_curl = new curl_handle(this);
|
|
||||||
|
|
||||||
RequestCompatibility();
|
RequestCompatibility();
|
||||||
|
|
||||||
// We need this signal in order to update the GUI from the main thread
|
connect(m_downloader, &downloader::signal_download_error, this, &game_compatibility::handle_download_error);
|
||||||
connect(this, &game_compatibility::signal_buffer_update, this, &game_compatibility::handle_buffer_update);
|
connect(m_downloader, &downloader::signal_download_finished, this, &game_compatibility::handle_download_finished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_compatibility::handle_buffer_update(int size, int max)
|
void game_compatibility::handle_download_error(const QString& error)
|
||||||
{
|
{
|
||||||
if (m_progress_dialog)
|
Q_EMIT DownloadError(error);
|
||||||
{
|
|
||||||
m_progress_dialog->setMaximum(max);
|
|
||||||
m_progress_dialog->setValue(size);
|
|
||||||
QApplication::processEvents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t game_compatibility::update_buffer(char* data, size_t size)
|
void game_compatibility::handle_download_finished(const QByteArray& data)
|
||||||
{
|
{
|
||||||
if (m_curl_abort)
|
compat_log.notice("Database download finished");
|
||||||
|
|
||||||
|
// Create new map from database and write database to file if database was valid
|
||||||
|
if (ReadJSON(QJsonDocument::fromJson(data).object(), true))
|
||||||
{
|
{
|
||||||
return 0;
|
// We have a new database in map, therefore refresh gamelist to new state
|
||||||
|
Q_EMIT DownloadFinished();
|
||||||
|
|
||||||
|
// Write database to file
|
||||||
|
QFile file(m_filepath);
|
||||||
|
|
||||||
|
if (file.exists())
|
||||||
|
{
|
||||||
|
compat_log.notice("Database file found: %s", sstr(m_filepath));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto old_size = m_curl_buf.size();
|
if (!file.open(QIODevice::WriteOnly))
|
||||||
const auto new_size = old_size + size;
|
|
||||||
m_curl_buf.resize(static_cast<int>(new_size));
|
|
||||||
memcpy(m_curl_buf.data() + old_size, data, size);
|
|
||||||
|
|
||||||
int max = m_progress_dialog ? m_progress_dialog->maximum() : 0;
|
|
||||||
|
|
||||||
if (m_actual_dwnld_size < 0)
|
|
||||||
{
|
{
|
||||||
if (curl_easy_getinfo(m_curl->get_curl(), CURLINFO_CONTENT_LENGTH_DOWNLOAD, &m_actual_dwnld_size) == CURLE_OK && m_actual_dwnld_size > 0)
|
compat_log.error("Database Error - Could not write database to file: %s", sstr(m_filepath));
|
||||||
{
|
return;
|
||||||
max = static_cast<int>(m_actual_dwnld_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EMIT signal_buffer_update(static_cast<int>(new_size), max);
|
file.write(data);
|
||||||
|
file.close();
|
||||||
|
|
||||||
return size;
|
compat_log.success("Wrote database to file: %s", sstr(m_filepath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool game_compatibility::ReadJSON(const QJsonObject& json_data, bool after_download)
|
bool game_compatibility::ReadJSON(const QJsonObject& json_data, bool after_download)
|
||||||
{
|
{
|
||||||
int return_code = json_data["return_code"].toInt();
|
const int return_code = json_data["return_code"].toInt();
|
||||||
|
|
||||||
if (return_code < 0)
|
if (return_code < 0)
|
||||||
{
|
{
|
||||||
|
@ -167,77 +157,10 @@ void game_compatibility::RequestCompatibility(bool online)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
compat_log.notice("Beginning compatibility database download from: %s", m_url);
|
const std::string url = "https://rpcs3.net/compatibility?api=v1&export";
|
||||||
|
compat_log.notice("Beginning compatibility database download from: %s", url);
|
||||||
|
|
||||||
// Show Progress
|
m_downloader->start(url, true, true, tr("Downloading Database"));
|
||||||
m_progress_dialog = new progress_dialog(tr("Downloading Database"), tr("Please wait..."), tr("Abort"), 0, 100, true);
|
|
||||||
m_progress_dialog->show();
|
|
||||||
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_URL, m_url.c_str());
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEFUNCTION, curl_write_cb_compat);
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEDATA, this);
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
|
|
||||||
m_curl_buf.clear();
|
|
||||||
m_curl_abort = false;
|
|
||||||
|
|
||||||
// Handle abort
|
|
||||||
connect(m_progress_dialog, &QProgressDialog::canceled, [this] { m_curl_abort = true; });
|
|
||||||
connect(m_progress_dialog, &QProgressDialog::finished, m_progress_dialog, &QProgressDialog::deleteLater);
|
|
||||||
|
|
||||||
auto thread = QThread::create([&]
|
|
||||||
{
|
|
||||||
const auto result = curl_easy_perform(m_curl->get_curl());
|
|
||||||
m_curl_result = result == CURLE_OK;
|
|
||||||
|
|
||||||
if (!m_curl_result)
|
|
||||||
{
|
|
||||||
Q_EMIT DownloadError(qstr("Curl error: ") + qstr(curl_easy_strerror(result)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(thread, &QThread::finished, this, [this, online]()
|
|
||||||
{
|
|
||||||
if (m_progress_dialog)
|
|
||||||
{
|
|
||||||
m_progress_dialog->close();
|
|
||||||
m_progress_dialog = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_curl_result)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
compat_log.notice("Database download finished");
|
|
||||||
|
|
||||||
// Create new map from database and write database to file if database was valid
|
|
||||||
if (ReadJSON(QJsonDocument::fromJson(m_curl_buf).object(), online))
|
|
||||||
{
|
|
||||||
// We have a new database in map, therefore refresh gamelist to new state
|
|
||||||
Q_EMIT DownloadFinished();
|
|
||||||
|
|
||||||
// Write database to file
|
|
||||||
QFile file(m_filepath);
|
|
||||||
|
|
||||||
if (file.exists())
|
|
||||||
{
|
|
||||||
compat_log.notice("Database file found: %s", sstr(m_filepath));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
|
||||||
{
|
|
||||||
compat_log.error("Database Error - Could not write database to file: %s", sstr(m_filepath));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
file.write(m_curl_buf);
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
compat_log.success("Wrote database to file: %s", sstr(m_filepath));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
thread->setObjectName("Compat Update");
|
|
||||||
thread->start();
|
|
||||||
|
|
||||||
// We want to retrieve a new database, therefore refresh gamelist and indicate that
|
// We want to retrieve a new database, therefore refresh gamelist and indicate that
|
||||||
Q_EMIT DownloadStarted();
|
Q_EMIT DownloadStarted();
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
class curl_handle;
|
class downloader;
|
||||||
class gui_settings;
|
class gui_settings;
|
||||||
class progress_dialog;
|
|
||||||
|
|
||||||
struct compat_status
|
struct compat_status
|
||||||
{
|
{
|
||||||
|
@ -35,16 +34,9 @@ private:
|
||||||
{ "NoData", { 6, "", "", tr("Database missing"), tr("Right click here and download the current database.\nMake sure you are connected to the internet.") } },
|
{ "NoData", { 6, "", "", tr("Database missing"), tr("Right click here and download the current database.\nMake sure you are connected to the internet.") } },
|
||||||
{ "Download", { 7, "", "", tr("Retrieving..."), tr("Downloading the compatibility database. Please wait...") } }
|
{ "Download", { 7, "", "", tr("Retrieving..."), tr("Downloading the compatibility database. Please wait...") } }
|
||||||
};
|
};
|
||||||
int m_timer_count = 0;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
QString m_filepath;
|
QString m_filepath;
|
||||||
std::string m_url;
|
downloader* m_downloader = nullptr;
|
||||||
std::atomic<bool> m_curl_result = false;
|
|
||||||
std::atomic<bool> m_curl_abort = false;
|
|
||||||
double m_actual_dwnld_size = -1.0;
|
|
||||||
curl_handle* m_curl = nullptr;
|
|
||||||
QByteArray m_curl_buf;
|
|
||||||
progress_dialog* m_progress_dialog = nullptr;
|
|
||||||
std::shared_ptr<gui_settings> m_xgui_settings;
|
|
||||||
std::map<std::string, compat_status> m_compat_database;
|
std::map<std::string, compat_status> m_compat_database;
|
||||||
|
|
||||||
/** Creates new map from the database */
|
/** Creates new map from the database */
|
||||||
|
@ -52,7 +44,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Handles reads, writes and downloads for the compatibility database */
|
/** Handles reads, writes and downloads for the compatibility database */
|
||||||
game_compatibility(std::shared_ptr<gui_settings> settings);
|
game_compatibility(std::shared_ptr<gui_settings> settings, QWidget* parent);
|
||||||
|
|
||||||
/** Reads database. If online set to true: Downloads and writes the database to file */
|
/** Reads database. If online set to true: Downloads and writes the database to file */
|
||||||
void RequestCompatibility(bool online = false);
|
void RequestCompatibility(bool online = false);
|
||||||
|
@ -63,16 +55,14 @@ public:
|
||||||
/** Returns the data for the requested status */
|
/** Returns the data for the requested status */
|
||||||
compat_status GetStatusData(const QString& status);
|
compat_status GetStatusData(const QString& status);
|
||||||
|
|
||||||
size_t update_buffer(char* data, size_t size);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void DownloadStarted();
|
void DownloadStarted();
|
||||||
void DownloadFinished();
|
void DownloadFinished();
|
||||||
void DownloadError(const QString& error);
|
void DownloadError(const QString& error);
|
||||||
void signal_buffer_update(int size, int max);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void handle_buffer_update(int size, int max);
|
void handle_download_error(const QString& error);
|
||||||
|
void handle_download_finished(const QByteArray& data);
|
||||||
};
|
};
|
||||||
|
|
||||||
class compat_pixmap : public QPixmap
|
class compat_pixmap : public QPixmap
|
||||||
|
|
|
@ -95,7 +95,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
m_game_list->installEventFilter(this);
|
m_game_list->installEventFilter(this);
|
||||||
m_game_list->setColumnCount(gui::column_count);
|
m_game_list->setColumnCount(gui::column_count);
|
||||||
|
|
||||||
m_game_compat = std::make_unique<game_compatibility>(m_gui_settings);
|
m_game_compat = new game_compatibility(m_gui_settings, this);
|
||||||
|
|
||||||
m_central_widget = new QStackedWidget(this);
|
m_central_widget = new QStackedWidget(this);
|
||||||
m_central_widget->addWidget(m_game_list);
|
m_central_widget->addWidget(m_game_list);
|
||||||
|
@ -143,7 +143,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
connect(m_game_grid, &QTableWidget::itemSelectionChanged, this, &game_list_frame::itemSelectionChangedSlot);
|
connect(m_game_grid, &QTableWidget::itemSelectionChanged, this, &game_list_frame::itemSelectionChangedSlot);
|
||||||
connect(m_game_grid, &QTableWidget::itemDoubleClicked, this, &game_list_frame::doubleClickedSlot);
|
connect(m_game_grid, &QTableWidget::itemDoubleClicked, this, &game_list_frame::doubleClickedSlot);
|
||||||
|
|
||||||
connect(m_game_compat.get(), &game_compatibility::DownloadStarted, [this]()
|
connect(m_game_compat, &game_compatibility::DownloadStarted, [this]()
|
||||||
{
|
{
|
||||||
for (const auto& game : m_game_data)
|
for (const auto& game : m_game_data)
|
||||||
{
|
{
|
||||||
|
@ -151,7 +151,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
}
|
}
|
||||||
Refresh();
|
Refresh();
|
||||||
});
|
});
|
||||||
connect(m_game_compat.get(), &game_compatibility::DownloadFinished, [this]()
|
connect(m_game_compat, &game_compatibility::DownloadFinished, [this]()
|
||||||
{
|
{
|
||||||
for (const auto& game : m_game_data)
|
for (const auto& game : m_game_data)
|
||||||
{
|
{
|
||||||
|
@ -159,14 +159,14 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
}
|
}
|
||||||
Refresh();
|
Refresh();
|
||||||
});
|
});
|
||||||
connect(m_game_compat.get(), &game_compatibility::DownloadError, [this](const QString& error)
|
connect(m_game_compat, &game_compatibility::DownloadError, [this](const QString& error)
|
||||||
{
|
{
|
||||||
for (const auto& game : m_game_data)
|
for (const auto& game : m_game_data)
|
||||||
{
|
{
|
||||||
game->compat = m_game_compat->GetCompatibility(game->info.serial);
|
game->compat = m_game_compat->GetCompatibility(game->info.serial);
|
||||||
}
|
}
|
||||||
Refresh();
|
Refresh();
|
||||||
QMessageBox::warning(this, tr("Warning!"), tr("Failed to retrieve the online compatibility database!\nFalling back to local database.\n\n") + tr(qPrintable(error)));
|
QMessageBox::warning(this, tr("Warning!"), tr("Failed to retrieve the online compatibility database!\nFalling back to local database.\n\n%0").arg(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int col = 0; col < m_columnActs.count(); ++col)
|
for (int col = 0; col < m_columnActs.count(); ++col)
|
||||||
|
|
|
@ -128,15 +128,15 @@ private:
|
||||||
game_info GetGameInfoFromItem(const QTableWidgetItem* item);
|
game_info GetGameInfoFromItem(const QTableWidgetItem* item);
|
||||||
|
|
||||||
// Which widget we are displaying depends on if we are in grid or list mode.
|
// Which widget we are displaying depends on if we are in grid or list mode.
|
||||||
QMainWindow* m_game_dock;
|
QMainWindow* m_game_dock = nullptr;
|
||||||
QStackedWidget* m_central_widget;
|
QStackedWidget* m_central_widget = nullptr;
|
||||||
|
|
||||||
// Game Grid
|
// Game Grid
|
||||||
game_list_grid* m_game_grid;
|
game_list_grid* m_game_grid = nullptr;
|
||||||
|
|
||||||
// Game List
|
// Game List
|
||||||
game_list* m_game_list;
|
game_list* m_game_list = nullptr;
|
||||||
std::unique_ptr<game_compatibility> m_game_compat;
|
game_compatibility* m_game_compat = nullptr;
|
||||||
QList<QAction*> m_columnActs;
|
QList<QAction*> m_columnActs;
|
||||||
Qt::SortOrder m_col_sort_order;
|
Qt::SortOrder m_col_sort_order;
|
||||||
int m_sort_column;
|
int m_sort_column;
|
||||||
|
|
|
@ -176,10 +176,35 @@ void main_window::Init()
|
||||||
// Fix possible hidden game list columns. The game list has to be visible already. Use this after show()
|
// Fix possible hidden game list columns. The game list has to be visible already. Use this after show()
|
||||||
m_game_list_frame->FixNarrowColumns();
|
m_game_list_frame->FixNarrowColumns();
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
// RPCS3 Updater
|
||||||
if (m_gui_settings->GetValue(gui::m_check_upd_start).toBool())
|
|
||||||
|
QMenuBar *corner_bar = new QMenuBar(ui->menuBar);
|
||||||
|
|
||||||
|
QMenu *download_menu = new QMenu(tr("Update Available!"), corner_bar);
|
||||||
|
corner_bar->addMenu(download_menu);
|
||||||
|
|
||||||
|
QAction *download_action = new QAction(tr("Download Update"), download_menu);
|
||||||
|
connect(download_action, &QAction::triggered, this, [this]
|
||||||
{
|
{
|
||||||
m_updater.check_for_updates(true, this);
|
m_updater.update(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
download_menu->addAction(download_action);
|
||||||
|
ui->menuBar->setCornerWidget(corner_bar);
|
||||||
|
ui->menuBar->cornerWidget()->setVisible(false);
|
||||||
|
|
||||||
|
connect(&m_updater, &update_manager::signal_update_available, this, [this](bool update_available)
|
||||||
|
{
|
||||||
|
if (ui->menuBar->cornerWidget())
|
||||||
|
{
|
||||||
|
ui->menuBar->cornerWidget()->setVisible(update_available);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__linux__)
|
||||||
|
if (const auto update_value = m_gui_settings->GetValue(gui::m_check_upd_start).toString(); update_value != "false")
|
||||||
|
{
|
||||||
|
m_updater.check_for_updates(true, update_value != "true", this);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1538,7 +1563,7 @@ void main_window::CreateConnects()
|
||||||
std::unordered_map<std::string, std::set<std::string>> games;
|
std::unordered_map<std::string, std::set<std::string>> games;
|
||||||
if (m_game_list_frame)
|
if (m_game_list_frame)
|
||||||
{
|
{
|
||||||
for (const auto game : m_game_list_frame->GetGameInfo())
|
for (const auto& game : m_game_list_frame->GetGameInfo())
|
||||||
{
|
{
|
||||||
if (game)
|
if (game)
|
||||||
{
|
{
|
||||||
|
@ -1675,7 +1700,7 @@ void main_window::CreateConnects()
|
||||||
QMessageBox::warning(this, tr("Auto-updater"), tr("Please stop the emulation before trying to update."));
|
QMessageBox::warning(this, tr("Auto-updater"), tr("Please stop the emulation before trying to update."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_updater.check_for_updates(false, this);
|
m_updater.check_for_updates(false, false, this);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->aboutAct, &QAction::triggered, [this]
|
connect(ui->aboutAct, &QAction::triggered, [this]
|
||||||
|
|
|
@ -341,7 +341,7 @@ namespace gui
|
||||||
{
|
{
|
||||||
bool match = true;
|
bool match = true;
|
||||||
|
|
||||||
for (const auto [role, data] : criteria)
|
for (const auto& [role, data] : criteria)
|
||||||
{
|
{
|
||||||
if (item->data(0, role) != data)
|
if (item->data(0, role) != data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1537,7 +1537,18 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
ui->cb_show_pkg_install->setChecked(m_gui_settings->GetValue(gui::ib_pkg_success).toBool());
|
ui->cb_show_pkg_install->setChecked(m_gui_settings->GetValue(gui::ib_pkg_success).toBool());
|
||||||
ui->cb_show_pup_install->setChecked(m_gui_settings->GetValue(gui::ib_pup_success).toBool());
|
ui->cb_show_pup_install->setChecked(m_gui_settings->GetValue(gui::ib_pup_success).toBool());
|
||||||
|
|
||||||
ui->cb_check_update_start->setChecked(m_gui_settings->GetValue(gui::m_check_upd_start).toBool());
|
const QString updates_yes = tr("Yes", "Updates");
|
||||||
|
const QString updates_background = tr("Background", "Updates");
|
||||||
|
const QString updates_no = tr("No", "Updates");
|
||||||
|
|
||||||
|
ui->combo_updates->addItem(updates_yes, "true");
|
||||||
|
ui->combo_updates->addItem(updates_background, "background");
|
||||||
|
ui->combo_updates->addItem(updates_no, "false");
|
||||||
|
ui->combo_updates->setCurrentIndex(ui->combo_updates->findData(m_gui_settings->GetValue(gui::m_check_upd_start).toString()));
|
||||||
|
connect(ui->combo_updates, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [this](int index)
|
||||||
|
{
|
||||||
|
m_gui_settings->SetValue(gui::m_check_upd_start, ui->combo_updates->itemData(index));
|
||||||
|
});
|
||||||
|
|
||||||
const bool enable_ui_colors = m_gui_settings->GetValue(gui::m_enableUIColors).toBool();
|
const bool enable_ui_colors = m_gui_settings->GetValue(gui::m_enableUIColors).toBool();
|
||||||
ui->cb_custom_colors->setChecked(enable_ui_colors);
|
ui->cb_custom_colors->setChecked(enable_ui_colors);
|
||||||
|
@ -1612,10 +1623,6 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
{
|
{
|
||||||
m_gui_settings->SetValue(gui::ib_pup_success, val);
|
m_gui_settings->SetValue(gui::ib_pup_success, val);
|
||||||
});
|
});
|
||||||
connect(ui->cb_check_update_start, &QCheckBox::clicked, [this](bool val)
|
|
||||||
{
|
|
||||||
m_gui_settings->SetValue(gui::m_check_upd_start, val);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ui->cb_custom_colors, &QCheckBox::clicked, [this](bool val)
|
connect(ui->cb_custom_colors, &QCheckBox::clicked, [this](bool val)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3142,13 +3142,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cb_check_update_start">
|
|
||||||
<property name="text">
|
|
||||||
<string>Check for updates on startup</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="guiTabSpacerRight">
|
<spacer name="guiTabSpacerRight">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -3168,6 +3161,18 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="gb_updates">
|
||||||
|
<property name="title">
|
||||||
|
<string>Check for updates on startup</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="layout_gb_updates">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="combo_updates"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_discord">
|
<widget class="QGroupBox" name="gb_discord">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
|
|
@ -163,7 +163,7 @@ public:
|
||||||
const QString show_boot_game = tr("Shows a confirmation dialog when a game was booted while another game is running.");
|
const QString show_boot_game = tr("Shows a confirmation dialog when a game was booted while another game is running.");
|
||||||
const QString show_pkg_install = tr("Shows a dialog when packages were installed successfully.");
|
const QString show_pkg_install = tr("Shows a dialog when packages were installed successfully.");
|
||||||
const QString show_pup_install = tr("Shows a dialog when firmware was installed successfully.");
|
const QString show_pup_install = tr("Shows a dialog when firmware was installed successfully.");
|
||||||
const QString check_update_start = tr("Check if an update is available on startup.");
|
const QString check_update_start = tr("Checks if an update is available on startup and asks if you want to update.\nIf \"Background\" is selected, the check is done silently in the background and a new download option is shown in the top right corner of the menu if a new version was found.");
|
||||||
const QString use_rich_presence = tr("Enables use of Discord Rich Presence to show what game you are playing on Discord.\nRequires a restart of RPCS3 to completely close the connection.");
|
const QString use_rich_presence = tr("Enables use of Discord Rich Presence to show what game you are playing on Discord.\nRequires a restart of RPCS3 to completely close the connection.");
|
||||||
const QString discord_state = tr("Tell your friends what you are doing.");
|
const QString discord_state = tr("Tell your friends what you are doing.");
|
||||||
const QString custom_colors = tr("Prioritize custom user interface colors over properties set in stylesheet.");
|
const QString custom_colors = tr("Prioritize custom user interface colors over properties set in stylesheet.");
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "progress_dialog.h"
|
#include "progress_dialog.h"
|
||||||
#include "localized.h"
|
#include "localized.h"
|
||||||
#include "rpcs3_version.h"
|
#include "rpcs3_version.h"
|
||||||
#include "curl_handle.h"
|
#include "downloader.h"
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
#include "Crypto/sha256.h"
|
#include "Crypto/sha256.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
|
@ -35,47 +35,11 @@
|
||||||
|
|
||||||
LOG_CHANNEL(update_log, "UPDATER");
|
LOG_CHANNEL(update_log, "UPDATER");
|
||||||
|
|
||||||
size_t curl_write_cb(char* ptr, size_t /*size*/, size_t nmemb, void* userdata)
|
|
||||||
{
|
|
||||||
update_manager* upd_mgr = reinterpret_cast<update_manager*>(userdata);
|
|
||||||
return upd_mgr->update_buffer(ptr, nmemb);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_manager::update_manager()
|
update_manager::update_manager()
|
||||||
{
|
{
|
||||||
m_curl = new curl_handle(this);
|
|
||||||
|
|
||||||
// We need this signal in order to update the GUI from the main thread
|
|
||||||
connect(this, &update_manager::signal_buffer_update, this, &update_manager::handle_buffer_update);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_manager::handle_buffer_update(int size)
|
void update_manager::check_for_updates(bool automatic, bool check_only, QWidget* parent)
|
||||||
{
|
|
||||||
if (m_progress_dialog && m_update_dialog)
|
|
||||||
{
|
|
||||||
m_progress_dialog->setValue(size);
|
|
||||||
QApplication::processEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t update_manager::update_buffer(char* data, size_t size)
|
|
||||||
{
|
|
||||||
if (m_curl_abort)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto old_size = m_curl_buf.size();
|
|
||||||
const auto new_size = old_size + size;
|
|
||||||
m_curl_buf.resize(static_cast<int>(new_size));
|
|
||||||
memcpy(m_curl_buf.data() + old_size, data, size);
|
|
||||||
|
|
||||||
Q_EMIT signal_buffer_update(static_cast<int>(new_size));
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_manager::check_for_updates(bool automatic, QWidget* parent)
|
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (automatic && !::getenv("APPIMAGE"))
|
if (automatic && !::getenv("APPIMAGE"))
|
||||||
|
@ -86,58 +50,41 @@ void update_manager::check_for_updates(bool automatic, QWidget* parent)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
m_curl_abort = false;
|
m_downloader = new downloader("RPCS3 Updater", parent);
|
||||||
m_update_dialog = false;
|
|
||||||
m_curl_buf.clear();
|
|
||||||
|
|
||||||
m_progress_dialog = new progress_dialog(tr("Checking For Updates"), tr("Please wait..."), tr("Abort"), 0, 100, true, parent);
|
connect(m_downloader, &downloader::signal_download_error, this, [this, automatic](const QString& /*error*/)
|
||||||
m_progress_dialog->setAutoClose(false);
|
|
||||||
m_progress_dialog->setAutoReset(false);
|
|
||||||
m_progress_dialog->show();
|
|
||||||
|
|
||||||
connect(m_progress_dialog, &QProgressDialog::canceled, [this]() { m_curl_abort = true; });
|
|
||||||
connect(m_progress_dialog, &QProgressDialog::finished, m_progress_dialog, &QProgressDialog::deleteLater);
|
|
||||||
|
|
||||||
const std::string request_url = "https://update.rpcs3.net/?api=v1&c=" + rpcs3::get_commit_and_hash().second;
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_URL, request_url.c_str());
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEFUNCTION, curl_write_cb);
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEDATA, this);
|
|
||||||
|
|
||||||
auto thread = QThread::create([this]
|
|
||||||
{
|
|
||||||
const auto curl_result = curl_easy_perform(m_curl->get_curl());
|
|
||||||
m_curl_result = curl_result == CURLE_OK;
|
|
||||||
|
|
||||||
if (!m_curl_result)
|
|
||||||
{
|
|
||||||
update_log.error("Curl error(query): %s", curl_easy_strerror(curl_result));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(thread, &QThread::finished, this, [this, automatic]()
|
|
||||||
{
|
|
||||||
const bool result_json = m_curl_result && handle_json(automatic);
|
|
||||||
|
|
||||||
if (!result_json && !m_curl_abort)
|
|
||||||
{
|
{
|
||||||
if (!automatic)
|
if (!automatic)
|
||||||
{
|
{
|
||||||
QMessageBox::warning(m_parent, tr("Auto-updater"), tr("An error occurred during the auto-updating process.\nCheck the log for more information."));
|
QMessageBox::warning(m_parent, tr("Auto-updater"), tr("An error occurred during the auto-updating process.\nCheck the log for more information."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_progress_dialog)
|
|
||||||
{
|
|
||||||
m_progress_dialog->close();
|
|
||||||
m_progress_dialog = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
thread->setObjectName("RPCS3 Update Check");
|
|
||||||
thread->start();
|
connect(m_downloader, &downloader::signal_download_finished, this, [this, automatic, check_only](const QByteArray& data)
|
||||||
|
{
|
||||||
|
const bool result_json = handle_json(automatic, check_only, data);
|
||||||
|
|
||||||
|
if (!result_json)
|
||||||
|
{
|
||||||
|
// The progress dialog is configured to stay open, so we need to close it manually if the download succeeds.
|
||||||
|
m_downloader->close_progress_dialog();
|
||||||
|
|
||||||
|
if (!automatic)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(m_parent, tr("Auto-updater"), tr("An error occurred during the auto-updating process.\nCheck the log for more information."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update_manager::handle_json(bool automatic)
|
Q_EMIT signal_update_available(result_json);
|
||||||
|
});
|
||||||
|
|
||||||
|
const std::string url = "https://update.rpcs3.net/?api=v1&c=" + rpcs3::get_commit_and_hash().second;
|
||||||
|
m_downloader->start(url, true, !automatic, tr("Checking For Updates"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_manager::handle_json(bool automatic, bool check_only, const QByteArray& data)
|
||||||
{
|
{
|
||||||
const QJsonObject json_data = QJsonDocument::fromJson(m_curl_buf).object();
|
const QJsonObject json_data = QJsonDocument::fromJson(data).object();
|
||||||
const int return_code = json_data["return_code"].toInt(-255);
|
const int return_code = json_data["return_code"].toInt(-255);
|
||||||
|
|
||||||
bool hash_found = true;
|
bool hash_found = true;
|
||||||
|
@ -202,7 +149,7 @@ bool update_manager::handle_json(bool automatic)
|
||||||
if (hash_found && return_code == 0)
|
if (hash_found && return_code == 0)
|
||||||
{
|
{
|
||||||
update_log.success("RPCS3 is up to date!");
|
update_log.success("RPCS3 is up to date!");
|
||||||
m_progress_dialog->close();
|
m_downloader->close_progress_dialog();
|
||||||
|
|
||||||
if (!automatic)
|
if (!automatic)
|
||||||
QMessageBox::information(m_parent, tr("Auto-updater"), tr("Your version is already up to date!"));
|
QMessageBox::information(m_parent, tr("Auto-updater"), tr("Your version is already up to date!"));
|
||||||
|
@ -225,11 +172,9 @@ bool update_manager::handle_json(bool automatic)
|
||||||
|
|
||||||
Localized localized;
|
Localized localized;
|
||||||
|
|
||||||
QString message;
|
|
||||||
|
|
||||||
if (hash_found)
|
if (hash_found)
|
||||||
{
|
{
|
||||||
message = tr("A new version of RPCS3 is available!\n\nCurrent version: %0 (%1)\nLatest version: %2 (%3)\nYour version is %4 old.\n\nDo you want to update?")
|
m_update_message = tr("A new version of RPCS3 is available!\n\nCurrent version: %0 (%1)\nLatest version: %2 (%3)\nYour version is %4 old.\n\nDo you want to update?")
|
||||||
.arg(current["version"].toString())
|
.arg(current["version"].toString())
|
||||||
.arg(cur_str)
|
.arg(cur_str)
|
||||||
.arg(latest["version"].toString())
|
.arg(latest["version"].toString())
|
||||||
|
@ -238,73 +183,72 @@ bool update_manager::handle_json(bool automatic)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
message = tr("You're currently using a custom or PR build.\n\nLatest version: %0 (%1)\nThe latest version is %2 old.\n\nDo you want to update to the latest official RPCS3 version?")
|
m_update_message = tr("You're currently using a custom or PR build.\n\nLatest version: %0 (%1)\nThe latest version is %2 old.\n\nDo you want to update to the latest official RPCS3 version?")
|
||||||
.arg(latest["version"].toString())
|
.arg(latest["version"].toString())
|
||||||
.arg(lts_str)
|
.arg(lts_str)
|
||||||
.arg(localized.GetVerboseTimeByMs(std::abs(diff_msec), true));
|
.arg(localized.GetVerboseTimeByMs(std::abs(diff_msec), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QMessageBox::question(m_progress_dialog, tr("Update Available"), message, QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
m_request_url = latest[os]["download"].toString().toStdString();
|
||||||
{
|
|
||||||
m_progress_dialog->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_expected_hash = latest[os]["checksum"].toString().toStdString();
|
m_expected_hash = latest[os]["checksum"].toString().toStdString();
|
||||||
m_expected_size = latest[os]["size"].toInt();
|
m_expected_size = latest[os]["size"].toInt();
|
||||||
|
|
||||||
m_progress_dialog->setWindowTitle(tr("Downloading Update"));
|
if (check_only)
|
||||||
|
|
||||||
// Download RPCS3
|
|
||||||
m_progress_dialog->setMaximum(m_expected_size);
|
|
||||||
m_progress_dialog->setValue(0);
|
|
||||||
m_update_dialog = true;
|
|
||||||
|
|
||||||
const std::string request_url = latest[os]["download"].toString().toStdString();
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_URL, request_url.c_str());
|
|
||||||
curl_easy_setopt(m_curl->get_curl(), CURLOPT_FOLLOWLOCATION, 1);
|
|
||||||
|
|
||||||
m_curl_buf.clear();
|
|
||||||
|
|
||||||
auto thread = QThread::create([this]
|
|
||||||
{
|
{
|
||||||
const auto curl_result = curl_easy_perform(m_curl->get_curl());
|
m_downloader->close_progress_dialog();
|
||||||
m_curl_result = curl_result == CURLE_OK;
|
return true;
|
||||||
|
|
||||||
if (!m_curl_result)
|
|
||||||
{
|
|
||||||
update_log.error("Curl error(download): %s", curl_easy_strerror(curl_result));
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
connect(thread, &QThread::finished, this, [this, automatic]()
|
|
||||||
{
|
|
||||||
const bool result_rpcs3 = m_curl_result && handle_rpcs3();
|
|
||||||
|
|
||||||
if (!result_rpcs3 && !m_curl_abort)
|
update(automatic);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_manager::update(bool automatic)
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(m_downloader->get_progress_dialog(), tr("Update Available"), m_update_message, QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||||
|
{
|
||||||
|
m_downloader->close_progress_dialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_downloader->disconnect();
|
||||||
|
|
||||||
|
connect(m_downloader, &downloader::signal_download_error, this, [this, automatic](const QString& /*error*/)
|
||||||
{
|
{
|
||||||
if (!automatic)
|
if (!automatic)
|
||||||
{
|
{
|
||||||
QMessageBox::warning(m_parent, tr("Auto-updater"), tr("An error occurred during the auto-updating process.\nCheck the log for more information."));
|
QMessageBox::warning(m_parent, tr("Auto-updater"), tr("An error occurred during the auto-updating process.\nCheck the log for more information."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_progress_dialog)
|
|
||||||
{
|
|
||||||
m_progress_dialog->close();
|
|
||||||
m_progress_dialog = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
thread->setObjectName("RPCS3 Updater");
|
|
||||||
thread->start();
|
|
||||||
|
|
||||||
return true;
|
connect(m_downloader, &downloader::signal_download_finished, this, [this, automatic](const QByteArray& data)
|
||||||
|
{
|
||||||
|
const bool result_json = handle_rpcs3(data);
|
||||||
|
|
||||||
|
if (!result_json)
|
||||||
|
{
|
||||||
|
// The progress dialog is configured to stay open, so we need to close it manually if the download succeeds.
|
||||||
|
m_downloader->close_progress_dialog();
|
||||||
|
|
||||||
|
if (!automatic)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(m_parent, tr("Auto-updater"), tr("An error occurred during the auto-updating process.\nCheck the log for more information."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update_manager::handle_rpcs3()
|
Q_EMIT signal_update_available(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_downloader->start(m_request_url, true, true, tr("Downloading Update"), true, m_expected_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool update_manager::handle_rpcs3(const QByteArray& data)
|
||||||
{
|
{
|
||||||
if (m_expected_size != m_curl_buf.size() + 0u)
|
m_downloader->update_progress_dialog(tr("Updating RPCS3"));
|
||||||
|
|
||||||
|
if (m_expected_size != data.size() + 0u)
|
||||||
{
|
{
|
||||||
update_log.error("Download size mismatch: %d expected: %d", m_curl_buf.size(), m_expected_size);
|
update_log.error("Download size mismatch: %d expected: %d", data.size(), m_expected_size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +256,7 @@ bool update_manager::handle_rpcs3()
|
||||||
mbedtls_sha256_context ctx;
|
mbedtls_sha256_context ctx;
|
||||||
mbedtls_sha256_init(&ctx);
|
mbedtls_sha256_init(&ctx);
|
||||||
mbedtls_sha256_starts_ret(&ctx, 0);
|
mbedtls_sha256_starts_ret(&ctx, 0);
|
||||||
mbedtls_sha256_update_ret(&ctx, reinterpret_cast<const unsigned char*>(m_curl_buf.data()), m_curl_buf.size());
|
mbedtls_sha256_update_ret(&ctx, reinterpret_cast<const unsigned char*>(data.data()), data.size());
|
||||||
mbedtls_sha256_finish_ret(&ctx, res_hash);
|
mbedtls_sha256_finish_ret(&ctx, res_hash);
|
||||||
|
|
||||||
std::string res_hash_string("0000000000000000000000000000000000000000000000000000000000000000");
|
std::string res_hash_string("0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
@ -329,9 +273,8 @@ bool update_manager::handle_rpcs3()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string replace_path;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
// Get executable path
|
// Get executable path
|
||||||
const std::string orig_path = Emulator::GetExeDir() + "rpcs3.exe";
|
const std::string orig_path = Emulator::GetExeDir() + "rpcs3.exe";
|
||||||
|
|
||||||
|
@ -340,61 +283,6 @@ bool update_manager::handle_rpcs3()
|
||||||
wchar_orig_path.resize(tmp_size);
|
wchar_orig_path.resize(tmp_size);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, orig_path.c_str(), -1, wchar_orig_path.data(), tmp_size);
|
MultiByteToWideChar(CP_UTF8, 0, orig_path.c_str(), -1, wchar_orig_path.data(), tmp_size);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
|
|
||||||
const char* appimage_path = ::getenv("APPIMAGE");
|
|
||||||
if (appimage_path != nullptr)
|
|
||||||
{
|
|
||||||
replace_path = appimage_path;
|
|
||||||
update_log.notice("Found AppImage path: %s", appimage_path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
update_log.warning("Failed to find AppImage path");
|
|
||||||
char exe_path[PATH_MAX];
|
|
||||||
ssize_t len = ::readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
|
|
||||||
|
|
||||||
if (len == -1)
|
|
||||||
{
|
|
||||||
update_log.error("Failed to find executable path");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
exe_path[len] = '\0';
|
|
||||||
update_log.trace("Found exec path: %s", exe_path);
|
|
||||||
|
|
||||||
replace_path = exe_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_progress_dialog->setWindowTitle(tr("Updating RPCS3"));
|
|
||||||
|
|
||||||
// Move the appimage/exe and replace with new appimage
|
|
||||||
const std::string move_dest = replace_path + "_old";
|
|
||||||
fs::rename(replace_path, move_dest, true);
|
|
||||||
fs::file new_appimage(replace_path, fs::read + fs::write + fs::create + fs::trunc);
|
|
||||||
if (!new_appimage)
|
|
||||||
{
|
|
||||||
update_log.error("Failed to create new AppImage file: %s", replace_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (new_appimage.write(m_curl_buf.data(), m_curl_buf.size()) != m_curl_buf.size() + 0u)
|
|
||||||
{
|
|
||||||
update_log.error("Failed to write new AppImage file: %s", replace_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fchmod(new_appimage.get_handle(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
|
|
||||||
{
|
|
||||||
update_log.error("Failed to chmod rwxrxrx %s", replace_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
new_appimage.close();
|
|
||||||
|
|
||||||
update_log.success("Successfully updated %s!", replace_path);
|
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
|
|
||||||
char temp_path[PATH_MAX];
|
char temp_path[PATH_MAX];
|
||||||
|
|
||||||
GetTempPathA(sizeof(temp_path) - 1, temp_path);
|
GetTempPathA(sizeof(temp_path) - 1, temp_path);
|
||||||
|
@ -409,15 +297,13 @@ bool update_manager::handle_rpcs3()
|
||||||
update_log.error("Failed to create temporary file: %s", tmpfile_path);
|
update_log.error("Failed to create temporary file: %s", tmpfile_path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (tmpfile.write(m_curl_buf.data(), m_curl_buf.size()) != m_curl_buf.size())
|
if (tmpfile.write(data.data(), data.size()) != data.size())
|
||||||
{
|
{
|
||||||
update_log.error("Failed to write temporary file: %s", tmpfile_path);
|
update_log.error("Failed to write temporary file: %s", tmpfile_path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tmpfile.close();
|
tmpfile.close();
|
||||||
|
|
||||||
m_progress_dialog->setWindowTitle(tr("Updating RPCS3"));
|
|
||||||
|
|
||||||
// 7z stuff (most of this stuff is from 7z Util sample and has been reworked to be more stl friendly)
|
// 7z stuff (most of this stuff is from 7z Util sample and has been reworked to be more stl friendly)
|
||||||
|
|
||||||
ISzAlloc allocImp;
|
ISzAlloc allocImp;
|
||||||
|
@ -596,8 +482,62 @@ bool update_manager::handle_rpcs3()
|
||||||
error_free7z();
|
error_free7z();
|
||||||
if (res)
|
if (res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
std::string replace_path;
|
||||||
|
|
||||||
|
const char* appimage_path = ::getenv("APPIMAGE");
|
||||||
|
if (appimage_path != nullptr)
|
||||||
|
{
|
||||||
|
replace_path = appimage_path;
|
||||||
|
update_log.notice("Found AppImage path: %s", appimage_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update_log.warning("Failed to find AppImage path");
|
||||||
|
char exe_path[PATH_MAX];
|
||||||
|
ssize_t len = ::readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
|
||||||
|
|
||||||
|
if (len == -1)
|
||||||
|
{
|
||||||
|
update_log.error("Failed to find executable path");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
exe_path[len] = '\0';
|
||||||
|
update_log.trace("Found exec path: %s", exe_path);
|
||||||
|
|
||||||
|
replace_path = exe_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the appimage/exe and replace with new appimage
|
||||||
|
const std::string move_dest = replace_path + "_old";
|
||||||
|
fs::rename(replace_path, move_dest, true);
|
||||||
|
fs::file new_appimage(replace_path, fs::read + fs::write + fs::create + fs::trunc);
|
||||||
|
if (!new_appimage)
|
||||||
|
{
|
||||||
|
update_log.error("Failed to create new AppImage file: %s", replace_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (new_appimage.write(data.data(), data.size()) != data.size() + 0u)
|
||||||
|
{
|
||||||
|
update_log.error("Failed to write new AppImage file: %s", replace_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fchmod(new_appimage.get_handle(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
|
||||||
|
{
|
||||||
|
update_log.error("Failed to chmod rwxrxrx %s", replace_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
new_appimage.close();
|
||||||
|
|
||||||
|
update_log.success("Successfully updated %s!", replace_path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_downloader->close_progress_dialog();
|
||||||
|
|
||||||
QMessageBox::information(m_parent, tr("Auto-updater"), tr("Update successful!\nRPCS3 will now restart."));
|
QMessageBox::information(m_parent, tr("Auto-updater"), tr("Update successful!\nRPCS3 will now restart."));
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -4,37 +4,30 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
class curl_handle;
|
class downloader;
|
||||||
class progress_dialog;
|
|
||||||
|
|
||||||
class update_manager final : public QObject
|
class update_manager final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> m_update_dialog = false;
|
downloader* m_downloader = nullptr;
|
||||||
progress_dialog* m_progress_dialog = nullptr;
|
|
||||||
QWidget* m_parent = nullptr;
|
QWidget* m_parent = nullptr;
|
||||||
|
|
||||||
curl_handle* m_curl = nullptr;
|
QString m_update_message;
|
||||||
QByteArray m_curl_buf;
|
|
||||||
std::atomic<bool> m_curl_abort = false;
|
|
||||||
std::atomic<bool> m_curl_result = false;
|
|
||||||
|
|
||||||
|
std::string m_request_url;
|
||||||
std::string m_expected_hash;
|
std::string m_expected_hash;
|
||||||
u64 m_expected_size = 0;
|
u64 m_expected_size = 0;
|
||||||
|
|
||||||
bool handle_json(bool automatic);
|
bool handle_json(bool automatic, bool check_only, const QByteArray& data);
|
||||||
bool handle_rpcs3();
|
bool handle_rpcs3(const QByteArray& data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
update_manager();
|
update_manager();
|
||||||
void check_for_updates(bool automatic, QWidget* parent = nullptr);
|
void check_for_updates(bool automatic, bool check_only, QWidget* parent = nullptr);
|
||||||
size_t update_buffer(char* data, size_t size);
|
void update(bool automatic);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void signal_buffer_update(int size);
|
void signal_update_available(bool update_available);
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void handle_buffer_update(int size);
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue