mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-06 07:12:28 +01:00
Compare commits
No commits in common. "d00d29ba90bf04c4919d01d2dfb1d4cce84739e1" and "1a991b244f308faabed63c60cd18a54c6b63f805" have entirely different histories.
d00d29ba90
...
1a991b244f
|
|
@ -38,14 +38,17 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
|||
git clone https://github.com/engnr/qt-downloader.git
|
||||
cd qt-downloader
|
||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||
sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
# nested Qt 6.10.1 URL workaround
|
||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
# archived Qt 6.7.3 URL workaround
|
||||
sed -i '' "s/official_releases/archive/g" qt-downloader
|
||||
cd "/tmp/Qt"
|
||||
"$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml
|
||||
"$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache
|
||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||
sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader"
|
||||
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats -o "$QT_VER/clang_64"
|
||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.1 workaround
|
||||
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
||||
fi
|
||||
|
||||
cd "$WORKDIR"
|
||||
|
|
|
|||
|
|
@ -38,13 +38,16 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
|||
git clone https://github.com/engnr/qt-downloader.git
|
||||
cd qt-downloader
|
||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||
sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
# nested Qt 6.10.1 URL workaround
|
||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
# archived Qt 6.7.3 URL workaround
|
||||
sed -i '' "s/official_releases/archive/g" qt-downloader
|
||||
cd "/tmp/Qt"
|
||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml
|
||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||
sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader"
|
||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats -o "$QT_VER/clang_64"
|
||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.1 workaround
|
||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
||||
fi
|
||||
|
||||
cd "$WORKDIR"
|
||||
|
|
|
|||
2
.github/workflows/rpcs3.yml
vendored
2
.github/workflows/rpcs3.yml
vendored
|
|
@ -134,7 +134,7 @@ jobs:
|
|||
runs-on: macos-14
|
||||
env:
|
||||
CCACHE_DIR: /tmp/ccache_dir
|
||||
QT_VER: '6.10.1'
|
||||
QT_VER: '6.7.3'
|
||||
QT_VER_MAIN: '6'
|
||||
LLVM_COMPILER_VER: '21'
|
||||
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt
|
||||
|
|
|
|||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -21,7 +21,7 @@
|
|||
ignore = dirty
|
||||
[submodule "3rdparty/hidapi"]
|
||||
path = 3rdparty/hidapi/hidapi
|
||||
url = ../../libusb/hidapi.git
|
||||
url = ../../RPCS3/hidapi.git
|
||||
branch = master
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/pugixml"]
|
||||
|
|
|
|||
2
3rdparty/FAudio
vendored
2
3rdparty/FAudio
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 4ea8afea6ba857c24e40877f487d000d559b196d
|
||||
Subproject commit 8de3616b5b204260fe639e76587731d8a73b8d2c
|
||||
2
3rdparty/hidapi/hidapi
vendored
2
3rdparty/hidapi/hidapi
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit d6b2a974608dec3b76fb1e36c189f22b9cf3650c
|
||||
Subproject commit f42423643ec9011c98cccc0bb790722bbbd3f30b
|
||||
2
3rdparty/libsdl-org/SDL
vendored
2
3rdparty/libsdl-org/SDL
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 7f3ae3d57459e59943a4ecfefc8f6277ec6bf540
|
||||
Subproject commit badbf8da4ee72b3ef599c721ffc9899e8d7c8d90
|
||||
|
|
@ -201,7 +201,7 @@ QPushButton::disabled {
|
|||
/* QSpinBox (Settings -> Emulator -> width/height) */
|
||||
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
|
||||
QSpinBox, QDoubleSpinBox {
|
||||
height: 1.50em;
|
||||
height: 0.1em;
|
||||
background-color: #b3ac98;
|
||||
}
|
||||
QSpinBox::disabled, QDoubleSpinBox::disabled {
|
||||
|
|
|
|||
|
|
@ -1051,15 +1051,7 @@ error_code cellPadSetPortSetting(u32 port_no, u32 port_setting)
|
|||
if (port_no >= CELL_PAD_MAX_PORT_NUM)
|
||||
return CELL_OK;
|
||||
|
||||
if (port_setting & CELL_PAD_SETTING_PRESS_ON)
|
||||
config.port_setting[port_no] |= CELL_PAD_SETTING_PRESS_ON;
|
||||
else
|
||||
config.port_setting[port_no] &= ~CELL_PAD_SETTING_PRESS_ON;
|
||||
|
||||
if (port_setting & CELL_PAD_SETTING_SENSOR_ON)
|
||||
config.port_setting[port_no] |= CELL_PAD_SETTING_SENSOR_ON;
|
||||
else
|
||||
config.port_setting[port_no] &= ~CELL_PAD_SETTING_SENSOR_ON;
|
||||
config.port_setting[port_no] = port_setting;
|
||||
|
||||
// can also return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD <- Update: seems to be just internal and ignored
|
||||
|
||||
|
|
@ -1131,7 +1123,7 @@ error_code cellPadSetPressMode(u32 port_no, u32 mode)
|
|||
if (!config.max_connect)
|
||||
return CELL_PAD_ERROR_UNINITIALIZED;
|
||||
|
||||
if (port_no >= CELL_MAX_PADS || mode > 1)
|
||||
if (port_no >= CELL_PAD_MAX_PORT_NUM)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
|
||||
|
|
@ -1165,7 +1157,7 @@ error_code cellPadSetSensorMode(u32 port_no, u32 mode)
|
|||
if (!config.max_connect)
|
||||
return CELL_PAD_ERROR_UNINITIALIZED;
|
||||
|
||||
if (port_no >= CELL_MAX_PADS || mode > 1)
|
||||
if (port_no >= CELL_MAX_PADS)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
|
||||
|
|
|
|||
|
|
@ -12,45 +12,28 @@ namespace rsx
|
|||
namespace aligned_allocator
|
||||
{
|
||||
template <size_t Align>
|
||||
requires (Align != 0) && ((Align & (Align - 1)) == 0)
|
||||
size_t align_up(size_t size)
|
||||
{
|
||||
return (size + (Align - 1)) & ~(Align - 1);
|
||||
}
|
||||
|
||||
template <size_t Align>
|
||||
requires (Align != 0) && ((Align & (Align - 1)) == 0)
|
||||
void* malloc(size_t size)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#ifdef _WIN32
|
||||
return _aligned_malloc(size, Align);
|
||||
#elif defined(__APPLE__)
|
||||
constexpr size_t NativeAlign = std::max(Align, sizeof(void*));
|
||||
return std::aligned_alloc(NativeAlign, align_up<NativeAlign>(size));
|
||||
#else
|
||||
return std::aligned_alloc(Align, align_up<Align>(size));
|
||||
return std::aligned_alloc(Align, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <size_t Align>
|
||||
requires (Align != 0) && ((Align & (Align - 1)) == 0)
|
||||
void* realloc(void* prev_ptr, [[maybe_unused]] size_t prev_size, size_t new_size)
|
||||
{
|
||||
if (align_up<Align>(prev_size) >= new_size)
|
||||
if (prev_size >= new_size)
|
||||
{
|
||||
return prev_ptr;
|
||||
}
|
||||
|
||||
ensure(reinterpret_cast<usz>(prev_ptr) % Align == 0, "Pointer not aligned to Align");
|
||||
#if defined(_WIN32)
|
||||
#ifdef _WIN32
|
||||
return _aligned_realloc(prev_ptr, new_size, Align);
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
constexpr size_t NativeAlign = std::max(Align, sizeof(void*));
|
||||
void* ret = std::aligned_alloc(NativeAlign, align_up<NativeAlign>(new_size));
|
||||
#else
|
||||
void* ret = std::aligned_alloc(Align, align_up<Align>(new_size));
|
||||
#endif
|
||||
void* ret = std::aligned_alloc(Align, new_size);
|
||||
std::memcpy(ret, prev_ptr, std::min(prev_size, new_size));
|
||||
std::free(prev_ptr);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -266,6 +266,14 @@ void ds3_pad_handler::check_add_device(hid_device* hidDevice, hid_enumerated_dev
|
|||
}
|
||||
|
||||
device->report_id = buf[0];
|
||||
#elif defined (__APPLE__)
|
||||
int res = hid_init_sixaxis_usb(hidDevice);
|
||||
if (res < 0)
|
||||
{
|
||||
ds3_log.error("check_add_device: hid_init_sixaxis_usb failed! (result=%d, error=%s)", res, hid_error(hidDevice));
|
||||
HidDevice::close(hidDevice);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (wchar_t ch : wide_serial)
|
||||
|
|
|
|||
|
|
@ -435,12 +435,6 @@ QCoreApplication* create_application(std::span<char* const> qt_argv)
|
|||
{
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0");
|
||||
}
|
||||
#elif __APPLE__
|
||||
// set the QT_MTL_NO_TRANSACTION variable in order to prevent Qt GUI freeze
|
||||
qputenv("QT_MTL_NO_TRANSACTION", "1");
|
||||
|
||||
// set the QT_MAC_NO_CONTAINER_LAYER variable in order to prevent swapchain crash
|
||||
qputenv("QT_MAC_NO_CONTAINER_LAYER", "1");
|
||||
#endif
|
||||
|
||||
bool use_high_dpi = true;
|
||||
|
|
|
|||
|
|
@ -117,8 +117,7 @@ void game_list::fix_narrow_columns()
|
|||
|
||||
void game_list::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
// Handle deselction when clicking on empty space in the table
|
||||
if (!itemAt(event->pos()))
|
||||
if (QTableWidgetItem* item = itemAt(event->pos()); !item || !item->data(Qt::UserRole).isValid())
|
||||
{
|
||||
clearSelection();
|
||||
setCurrentItem(nullptr); // Needed for currentItemChanged
|
||||
|
|
|
|||
|
|
@ -230,32 +230,42 @@ bool main_window::Init([[maybe_unused]] bool with_cli_boot)
|
|||
|
||||
// RPCS3 Updater
|
||||
|
||||
connect(ui->actionDownload_Update, &QAction::triggered, this, [this]
|
||||
QMenu* download_menu = new QMenu(tr("Update Available!"));
|
||||
|
||||
QAction* download_action = new QAction(tr("Download Update"), download_menu);
|
||||
connect(download_action, &QAction::triggered, this, [this]
|
||||
{
|
||||
m_updater.update(false);
|
||||
});
|
||||
|
||||
download_menu->addAction(download_action);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Use a menu at the top right corner to indicate the new version.
|
||||
// Some distros just can't handle corner widgets at the moment.
|
||||
QMenuBar* corner_bar = new QMenuBar(ui->menuBar);
|
||||
corner_bar->addMenu(ui->menuUpdate_Available);
|
||||
QMenuBar *corner_bar = new QMenuBar(ui->menuBar);
|
||||
m_download_menu_action = corner_bar->addMenu(download_menu);
|
||||
ui->menuBar->setCornerWidget(corner_bar);
|
||||
ui->menuBar->cornerWidget()->setVisible(false);
|
||||
ui->menuBar->removeAction(ui->menuUpdate_Available->menuAction());
|
||||
|
||||
connect(&m_updater, &update_manager::signal_update_available, this, [this](bool update_available)
|
||||
{
|
||||
ui->menuBar->cornerWidget()->setVisible(update_available);
|
||||
});
|
||||
#else
|
||||
ui->menuUpdate_Available->menuAction()->setVisible(false);
|
||||
// Append a menu to the right of the regular menus to indicate the new version.
|
||||
// Some distros just can't handle corner widgets at the moment.
|
||||
m_download_menu_action = ui->menuBar->addMenu(download_menu);
|
||||
#endif
|
||||
|
||||
ensure(m_download_menu_action);
|
||||
m_download_menu_action->setVisible(false);
|
||||
|
||||
connect(&m_updater, &update_manager::signal_update_available, this, [this](bool update_available)
|
||||
{
|
||||
ui->menuUpdate_Available->menuAction()->setVisible(update_available);
|
||||
if (m_download_menu_action)
|
||||
{
|
||||
m_download_menu_action->setVisible(update_available);
|
||||
}
|
||||
if (ui->menuBar && ui->menuBar->cornerWidget())
|
||||
{
|
||||
ui->menuBar->cornerWidget()->setVisible(update_available);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifdef RPCS3_UPDATE_SUPPORTED
|
||||
if (const auto update_value = m_gui_settings->GetValue(gui::m_check_upd_start).toString(); update_value != gui::update_off)
|
||||
|
|
@ -1923,11 +1933,9 @@ void main_window::OnEmuRun(bool /*start_playtime*/)
|
|||
EnableMenus(true);
|
||||
|
||||
update_gui_pad_thread();
|
||||
|
||||
m_system_state = system_state::running;
|
||||
}
|
||||
|
||||
void main_window::OnEmuResume()
|
||||
void main_window::OnEmuResume() const
|
||||
{
|
||||
const QString title = GetCurrentTitle();
|
||||
const QString restart_tooltip = tr("Restart %0").arg(title);
|
||||
|
|
@ -1940,11 +1948,9 @@ void main_window::OnEmuResume()
|
|||
ui->toolbar_start->setText(tr("Pause"));
|
||||
ui->toolbar_start->setToolTip(pause_tooltip);
|
||||
ui->toolbar_stop->setToolTip(stop_tooltip);
|
||||
|
||||
m_system_state = system_state::starting; // Let's just use this state to distinguish between resumed and running
|
||||
}
|
||||
|
||||
void main_window::OnEmuPause()
|
||||
void main_window::OnEmuPause() const
|
||||
{
|
||||
const QString title = GetCurrentTitle();
|
||||
const QString resume_tooltip = tr("Resume %0").arg(title);
|
||||
|
|
@ -1960,8 +1966,6 @@ void main_window::OnEmuPause()
|
|||
{
|
||||
m_game_list_frame->Refresh();
|
||||
}
|
||||
|
||||
m_system_state = system_state::paused;
|
||||
}
|
||||
|
||||
void main_window::OnEmuStop()
|
||||
|
|
@ -2022,11 +2026,9 @@ void main_window::OnEmuStop()
|
|||
}
|
||||
|
||||
update_gui_pad_thread();
|
||||
|
||||
m_system_state = system_state::stopped;
|
||||
}
|
||||
|
||||
void main_window::OnEmuReady()
|
||||
void main_window::OnEmuReady() const
|
||||
{
|
||||
const QString title = GetCurrentTitle();
|
||||
const QString play_tooltip = tr("Play %0").arg(title);
|
||||
|
|
@ -2052,8 +2054,6 @@ void main_window::OnEmuReady()
|
|||
ui->removeAllCachesAct->setEnabled(false);
|
||||
ui->removeSavestatesAct->setEnabled(false);
|
||||
ui->cleanUpGameListAct->setEnabled(false);
|
||||
|
||||
m_system_state = system_state::ready;
|
||||
}
|
||||
|
||||
void main_window::EnableMenus(bool enabled) const
|
||||
|
|
@ -2340,26 +2340,11 @@ void main_window::RetranslateUI(const QStringList& language_codes, const QString
|
|||
|
||||
ui->retranslateUi(this);
|
||||
|
||||
// Refresh game list first to prevent localization mismatches in further Refresh calls
|
||||
if (m_game_list_frame)
|
||||
{
|
||||
m_game_list_frame->Refresh(true);
|
||||
}
|
||||
|
||||
// Update menu bar size (needed if the corner widget changes its size)
|
||||
ui->menuBar->adjustSize();
|
||||
|
||||
// Update toolbar elements
|
||||
switch (m_system_state)
|
||||
{
|
||||
case system_state::running: OnEmuRun(false); break;
|
||||
case system_state::stopped: OnEmuStop(); break;
|
||||
case system_state::paused: OnEmuPause(); break;
|
||||
case system_state::starting: OnEmuResume(); break;
|
||||
case system_state::ready: OnEmuReady(); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
Q_EMIT RequestDialogRepaint();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include "settings.h"
|
||||
#include "shortcut_handler.h"
|
||||
#include "Emu/config_mode.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -89,9 +88,9 @@ Q_SIGNALS:
|
|||
public Q_SLOTS:
|
||||
void OnEmuStop();
|
||||
void OnEmuRun(bool start_playtime);
|
||||
void OnEmuResume();
|
||||
void OnEmuPause();
|
||||
void OnEmuReady();
|
||||
void OnEmuResume() const;
|
||||
void OnEmuPause() const;
|
||||
void OnEmuReady() const;
|
||||
void OnEnableDiscEject(bool enabled) const;
|
||||
void OnEnableDiscInsert(bool enabled) const;
|
||||
void OnAddBreakpoint(u32 addr) const;
|
||||
|
|
@ -194,10 +193,9 @@ private:
|
|||
std::shared_ptr<persistent_settings> m_persistent_settings;
|
||||
|
||||
update_manager m_updater;
|
||||
QAction* m_download_menu_action = nullptr;
|
||||
|
||||
shortcut_handler* m_shortcut_handler = nullptr;
|
||||
|
||||
std::unique_ptr<gui_pad_thread> m_gui_pad_thread;
|
||||
|
||||
system_state m_system_state = system_state::stopped;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -412,12 +412,6 @@
|
|||
<addaction name="aboutAct"/>
|
||||
<addaction name="aboutQtAct"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuUpdate_Available">
|
||||
<property name="title">
|
||||
<string>Update Available!</string>
|
||||
</property>
|
||||
<addaction name="actionDownload_Update"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEmulation"/>
|
||||
<addaction name="menuConfiguration"/>
|
||||
|
|
@ -425,7 +419,6 @@
|
|||
<addaction name="menuUtilities"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuHelp"/>
|
||||
<addaction name="menuUpdate_Available"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -1455,11 +1448,6 @@
|
|||
<string>Sound Effects</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDownload_Update">
|
||||
<property name="text">
|
||||
<string>Download Update</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@
|
|||
|
||||
movie_item::movie_item() : QTableWidgetItem(), movie_item_base()
|
||||
{
|
||||
setData(Qt::UserRole, {}); // Set any value to UserRole for proper indexing (e.g. for multiselection)
|
||||
}
|
||||
|
||||
movie_item::movie_item(const QString& text, int type) : QTableWidgetItem(text, type), movie_item_base()
|
||||
{
|
||||
setData(Qt::UserRole, {}); // Set any value to UserRole for proper indexing (e.g. for multiselection)
|
||||
}
|
||||
|
||||
movie_item::movie_item(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type), movie_item_base()
|
||||
{
|
||||
setData(Qt::UserRole, {}); // Set any value to UserRole for proper indexing (e.g. for multiselection)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,10 +71,14 @@ bool qt_camera_video_sink::present(const QVideoFrame& frame)
|
|||
// Flip image if necessary
|
||||
if (flip_horizontally || flip_vertically)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
Qt::Orientations orientation {};
|
||||
orientation.setFlag(Qt::Orientation::Horizontal, flip_horizontally);
|
||||
orientation.setFlag(Qt::Orientation::Vertical, flip_vertically);
|
||||
image.flip(orientation);
|
||||
#else
|
||||
image.mirror(flip_horizontally, flip_vertically);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (image.format() != QImage::Format_RGBA8888)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ void update_manager::check_for_updates(bool automatic, bool check_only, bool aut
|
|||
{
|
||||
update_log.notice("Checking for updates: automatic=%d, check_only=%d, auto_accept=%d", automatic, check_only, auto_accept);
|
||||
|
||||
m_update_info = {};
|
||||
m_update_message.clear();
|
||||
m_changelog.clear();
|
||||
|
||||
if (automatic)
|
||||
{
|
||||
|
|
@ -102,7 +103,7 @@ void update_manager::check_for_updates(bool automatic, bool check_only, bool aut
|
|||
}
|
||||
}
|
||||
|
||||
Q_EMIT signal_update_available(result_json && m_update_info.update_found);
|
||||
Q_EMIT signal_update_available(result_json && !m_update_message.isEmpty());
|
||||
});
|
||||
|
||||
const utils::OS_version os = utils::get_OS_version();
|
||||
|
|
@ -120,7 +121,7 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
const QJsonObject json_data = QJsonDocument::fromJson(data).object();
|
||||
const int return_code = json_data["return_code"].toInt(-255);
|
||||
|
||||
m_update_info.hash_found = true;
|
||||
bool hash_found = true;
|
||||
|
||||
if (return_code < 0)
|
||||
{
|
||||
|
|
@ -142,7 +143,7 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
// If a user clicks "Check for Updates" with a custom build ask him if he's sure he wants to update to latest version
|
||||
if (!automatic && return_code == -1)
|
||||
{
|
||||
m_update_info.hash_found = false;
|
||||
hash_found = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -186,7 +187,7 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
check_json(latest["version"].isString(), "Node 'latest_build: version' not found or not a string") &&
|
||||
check_json(latest["datetime"].isString(), "Node 'latest_build: datetime' not found or not a string")
|
||||
) ||
|
||||
(m_update_info.hash_found && !(
|
||||
(hash_found && !(
|
||||
check_json(current.isObject(), "JSON doesn't contain current_build section") &&
|
||||
check_json(current["version"].isString(), "Node 'current_build: datetime' not found or not a string") &&
|
||||
check_json(current["datetime"].isString(), "Node 'current_build: version' not found or not a string")
|
||||
|
|
@ -195,7 +196,7 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_update_info.hash_found && return_code == 0)
|
||||
if (hash_found && return_code == 0)
|
||||
{
|
||||
update_log.success("RPCS3 is up to date!");
|
||||
m_downloader->close_progress_dialog();
|
||||
|
|
@ -209,25 +210,58 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
// Calculate how old the build is
|
||||
const QString date_fmt = QStringLiteral("yyyy-MM-dd hh:mm:ss");
|
||||
|
||||
const QDateTime cur_date = m_update_info.hash_found ? QDateTime::fromString(current["datetime"].toString(), date_fmt) : QDateTime::currentDateTimeUtc();
|
||||
const QDateTime cur_date = hash_found ? QDateTime::fromString(current["datetime"].toString(), date_fmt) : QDateTime::currentDateTimeUtc();
|
||||
const QDateTime lts_date = QDateTime::fromString(latest["datetime"].toString(), date_fmt);
|
||||
|
||||
m_update_info.update_found = true;
|
||||
m_update_info.cur_date = cur_date.toString(date_fmt);
|
||||
m_update_info.lts_date = lts_date.toString(date_fmt);
|
||||
m_update_info.diff_msec = cur_date.msecsTo(lts_date);
|
||||
m_update_info.new_version = latest["version"].toString();
|
||||
const QString cur_str = cur_date.toString(date_fmt);
|
||||
const QString lts_str = lts_date.toString(date_fmt);
|
||||
|
||||
if (m_update_info.hash_found)
|
||||
const qint64 diff_msec = cur_date.msecsTo(lts_date);
|
||||
|
||||
update_log.notice("Current: %s, latest: %s, difference: %lld ms", cur_str, lts_str, diff_msec);
|
||||
|
||||
const Localized localized;
|
||||
|
||||
const QString new_version = latest["version"].toString();
|
||||
m_new_version = new_version.toStdString();
|
||||
const QString support_message = tr("<br>You can empower our project at <a href=\"https://rpcs3.net/patreon\">RPCS3 Patreon</a>.<br>");
|
||||
|
||||
if (hash_found)
|
||||
{
|
||||
m_update_info.old_version = current["version"].toString();
|
||||
const QString old_version = current["version"].toString();
|
||||
m_old_version = old_version.toStdString();
|
||||
|
||||
if (diff_msec < 0)
|
||||
{
|
||||
// This usually means that the current version was marked as broken and won't be shipped anymore, so we need to downgrade to avoid certain bugs.
|
||||
m_update_message = tr("A better version of RPCS3 is available!<br><br>Current version: %0 (%1)<br>Better version: %2 (%3)<br>%4<br>Do you want to update?")
|
||||
.arg(old_version)
|
||||
.arg(cur_str)
|
||||
.arg(new_version)
|
||||
.arg(lts_str)
|
||||
.arg(support_message);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_update_message = tr("A new version of RPCS3 is available!<br><br>Current version: %0 (%1)<br>Latest version: %2 (%3)<br>Your version is %4 behind.<br>%5<br>Do you want to update?")
|
||||
.arg(old_version)
|
||||
.arg(cur_str)
|
||||
.arg(new_version)
|
||||
.arg(lts_str)
|
||||
.arg(localized.GetVerboseTimeByMs(diff_msec, true))
|
||||
.arg(support_message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_update_info.old_version = QString::fromStdString(fmt::format("%s-%s-%s", rpcs3::get_full_branch(), rpcs3::get_branch(), rpcs3::get_version().to_string()));
|
||||
}
|
||||
m_old_version = fmt::format("%s-%s-%s", rpcs3::get_full_branch(), rpcs3::get_branch(), rpcs3::get_version().to_string());
|
||||
|
||||
update_log.notice("Current: %s, latest: %s, difference: %lld ms", m_update_info.cur_date, m_update_info.lts_date, m_update_info.diff_msec);
|
||||
m_update_message = tr("You're currently using a custom or PR build.<br><br>Latest version: %0 (%1)<br>The latest version is %2 old.<br>%3<br>Do you want to update to the latest official RPCS3 version?")
|
||||
.arg(new_version)
|
||||
.arg(lts_str)
|
||||
.arg(localized.GetVerboseTimeByMs(std::abs(diff_msec), true))
|
||||
.arg(support_message);
|
||||
}
|
||||
|
||||
m_request_url = latest[os]["download"].toString().toStdString();
|
||||
m_expected_hash = latest[os]["checksum"].toString().toStdString();
|
||||
|
|
@ -243,9 +277,9 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
|
||||
if (!auto_accept)
|
||||
{
|
||||
if (automatic && m_gui_settings->GetValue(gui::ib_skip_version).toString() == m_update_info.new_version)
|
||||
if (automatic && m_gui_settings->GetValue(gui::ib_skip_version).toString() == new_version)
|
||||
{
|
||||
update_log.notice("Skipping automatic update notification for version '%s' due to user preference", m_update_info.new_version);
|
||||
update_log.notice("Skipping automatic update notification for version '%s' due to user preference", new_version);
|
||||
m_downloader->close_progress_dialog();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -266,6 +300,7 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
}
|
||||
else
|
||||
{
|
||||
entry.version = tr("N/A");
|
||||
update_log.notice("JSON changelog entry does not contain a version string.");
|
||||
}
|
||||
|
||||
|
|
@ -275,10 +310,11 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce
|
|||
}
|
||||
else
|
||||
{
|
||||
entry.title = tr("N/A");
|
||||
update_log.notice("JSON changelog entry does not contain a title string.");
|
||||
}
|
||||
|
||||
m_update_info.changelog.push_back(std::move(entry));
|
||||
m_changelog.push_back(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -315,61 +351,25 @@ void update_manager::update(bool auto_accept)
|
|||
|
||||
if (!auto_accept)
|
||||
{
|
||||
if (!m_update_info.update_found)
|
||||
if (m_update_message.isEmpty())
|
||||
{
|
||||
// This can happen if we abort the check_for_updates download. Just check again in this case.
|
||||
update_log.notice("Aborting update: Update not found. Trying again...");
|
||||
update_log.notice("Aborting update: Update message is empty. Trying again...");
|
||||
m_downloader->close_progress_dialog();
|
||||
check_for_updates(false, false, false, m_parent);
|
||||
return;
|
||||
}
|
||||
|
||||
const Localized localized;
|
||||
const QString support_message = tr("<br>You can empower our project at <a href=\"https://rpcs3.net/patreon\">RPCS3 Patreon</a>.<br>");
|
||||
QString update_message;
|
||||
|
||||
if (m_update_info.hash_found)
|
||||
{
|
||||
if (m_update_info.diff_msec < 0)
|
||||
{
|
||||
// This usually means that the current version was marked as broken and won't be shipped anymore, so we need to downgrade to avoid certain bugs.
|
||||
update_message = tr("A better version of RPCS3 is available!<br><br>Current version: %0 (%1)<br>Better version: %2 (%3)<br>%4<br>Do you want to update?")
|
||||
.arg(m_update_info.old_version)
|
||||
.arg(m_update_info.cur_date)
|
||||
.arg(m_update_info.new_version)
|
||||
.arg(m_update_info.lts_date)
|
||||
.arg(support_message);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_message = tr("A new version of RPCS3 is available!<br><br>Current version: %0 (%1)<br>Latest version: %2 (%3)<br>Your version is %4 behind.<br>%5<br>Do you want to update?")
|
||||
.arg(m_update_info.old_version)
|
||||
.arg(m_update_info.cur_date)
|
||||
.arg(m_update_info.new_version)
|
||||
.arg(m_update_info.lts_date)
|
||||
.arg(localized.GetVerboseTimeByMs(m_update_info.diff_msec, true))
|
||||
.arg(support_message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
update_message = tr("You're currently using a custom or PR build.<br><br>Latest version: %0 (%1)<br>The latest version is %2 old.<br>%3<br>Do you want to update to the latest official RPCS3 version?")
|
||||
.arg(m_update_info.new_version)
|
||||
.arg(m_update_info.lts_date)
|
||||
.arg(localized.GetVerboseTimeByMs(std::abs(m_update_info.diff_msec), true))
|
||||
.arg(support_message);
|
||||
}
|
||||
|
||||
QString changelog_content;
|
||||
|
||||
for (const changelog_data& entry : m_update_info.changelog)
|
||||
for (const changelog_data& entry : m_changelog)
|
||||
{
|
||||
if (!changelog_content.isEmpty())
|
||||
changelog_content.append('\n');
|
||||
changelog_content.append(tr("• %0: %1").arg(entry.version.isEmpty() ? tr("N/A") : entry.version, entry.title.isEmpty() ? tr("N/A") : entry.title));
|
||||
changelog_content.append(tr("• %0: %1").arg(entry.version, entry.title));
|
||||
}
|
||||
|
||||
QMessageBox mb(QMessageBox::Icon::Question, tr("Update Available"), update_message, QMessageBox::Yes | QMessageBox::No, m_downloader->get_progress_dialog() ? m_downloader->get_progress_dialog() : m_parent);
|
||||
QMessageBox mb(QMessageBox::Icon::Question, tr("Update Available"), m_update_message, QMessageBox::Yes | QMessageBox::No, m_downloader->get_progress_dialog() ? m_downloader->get_progress_dialog() : m_parent);
|
||||
mb.setTextFormat(Qt::RichText);
|
||||
mb.setCheckBox(new QCheckBox(tr("Don't show again for this version")));
|
||||
|
||||
|
|
@ -380,16 +380,16 @@ void update_manager::update(bool auto_accept)
|
|||
|
||||
// Smartass hack to make the unresizeable message box wide enough for the changelog
|
||||
const int changelog_width = QLabel(changelog_content).sizeHint().width();
|
||||
if (QLabel(update_message).sizeHint().width() < changelog_width)
|
||||
if (QLabel(m_update_message).sizeHint().width() < changelog_width)
|
||||
{
|
||||
update_message += " ";
|
||||
while (QLabel(update_message).sizeHint().width() < changelog_width)
|
||||
m_update_message += " ";
|
||||
while (QLabel(m_update_message).sizeHint().width() < changelog_width)
|
||||
{
|
||||
update_message += " ";
|
||||
m_update_message += " ";
|
||||
}
|
||||
}
|
||||
|
||||
mb.setText(update_message);
|
||||
mb.setText(m_update_message);
|
||||
}
|
||||
|
||||
update_log.notice("Asking user for permission to update...");
|
||||
|
|
@ -400,8 +400,8 @@ void update_manager::update(bool auto_accept)
|
|||
|
||||
if (mb.checkBox()->isChecked())
|
||||
{
|
||||
update_log.notice("User requested to skip further automatic update notifications for version '%s'", m_update_info.new_version);
|
||||
m_gui_settings->SetValue(gui::ib_skip_version, m_update_info.new_version);
|
||||
update_log.notice("User requested to skip further automatic update notifications for version '%s'", m_new_version);
|
||||
m_gui_settings->SetValue(gui::ib_skip_version, QString::fromStdString(m_new_version));
|
||||
}
|
||||
|
||||
m_downloader->close_progress_dialog();
|
||||
|
|
@ -751,7 +751,7 @@ bool update_manager::handle_rpcs3(const QByteArray& data, bool auto_accept)
|
|||
if (fs::file update_file{fs::get_config_dir() + "update_history.log", fs::create + fs::write + fs::append})
|
||||
{
|
||||
const std::string update_time = QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss").toStdString();
|
||||
const std::string entry = fmt::format("%s: Updated from \"%s\" to \"%s\"", update_time, m_update_info.old_version, m_update_info.new_version);
|
||||
const std::string entry = fmt::format("%s: Updated from \"%s\" to \"%s\"", update_time, m_old_version, m_new_version);
|
||||
update_file.write(fmt::format("%s\n", entry));
|
||||
update_log.notice("Added entry '%s' to update_history.log", entry);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,28 +19,20 @@ private:
|
|||
|
||||
std::shared_ptr<gui_settings> m_gui_settings;
|
||||
|
||||
// This message is empty if there is no download available
|
||||
QString m_update_message;
|
||||
|
||||
struct changelog_data
|
||||
{
|
||||
QString version;
|
||||
QString title;
|
||||
};
|
||||
|
||||
struct update_info
|
||||
{
|
||||
bool update_found = false;
|
||||
bool hash_found = false;
|
||||
qint64 diff_msec = 0;
|
||||
QString cur_date;
|
||||
QString lts_date;
|
||||
QString old_version;
|
||||
QString new_version;
|
||||
std::vector<changelog_data> changelog;
|
||||
};
|
||||
|
||||
update_info m_update_info {};
|
||||
std::vector<changelog_data> m_changelog;
|
||||
|
||||
std::string m_request_url;
|
||||
std::string m_expected_hash;
|
||||
std::string m_old_version;
|
||||
std::string m_new_version;
|
||||
u64 m_expected_size = 0;
|
||||
|
||||
bool handle_json(bool automatic, bool check_only, bool auto_accept, const QByteArray& data);
|
||||
|
|
|
|||
Loading…
Reference in a new issue