From f54da22f6f4146ffb8b2bbe93559e5b789cbba7c Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 17 Dec 2022 10:12:27 +0200 Subject: [PATCH] UI: Report Game Size On Disk, Make Game Removal An Informed Decision --- rpcs3/Emu/GameInfo.h | 1 + rpcs3/rpcs3qt/game_list_frame.cpp | 26 +++++++++++++++++++++----- rpcs3/rpcs3qt/gui_settings.cpp | 13 ++++++------- rpcs3/rpcs3qt/gui_settings.h | 3 +++ rpcs3/rpcs3qt/main_window.cpp | 9 ++++----- rpcs3/rpcs3qt/qt_utils.cpp | 16 ++++++++++++++++ rpcs3/rpcs3qt/qt_utils.h | 3 +++ 7 files changed, 54 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/GameInfo.h b/rpcs3/Emu/GameInfo.h index efd2819799..99f46ea041 100644 --- a/rpcs3/Emu/GameInfo.h +++ b/rpcs3/Emu/GameInfo.h @@ -20,6 +20,7 @@ struct GameInfo u32 parental_lvl = 0; u32 sound_format = 0; u32 resolution = 0; + usz size_on_disk = umax; GameInfo() { diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index 5ab5e16b61..c89fd12be8 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -133,6 +133,7 @@ game_list_frame::game_list_frame(std::shared_ptr gui_settings, std add_column(gui::column_last_play, tr("Last Played"), tr("Show Last Played")); add_column(gui::column_playtime, tr("Time Played"), tr("Show Time Played")); add_column(gui::column_compat, tr("Compatibility"), tr("Show Compatibility")); + add_column(gui::column_dir_size, tr("Space On Disk"), tr("Show Space On Disk")); // Events connect(&m_refresh_watcher, &QFutureWatcher::finished, this, &game_list_frame::OnRefreshFinished); @@ -608,6 +609,7 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after) game.sound_format = psf::get_integer(psf, "SOUND_FORMAT", 0); game.bootable = psf::get_integer(psf, "BOOTABLE", 0); game.attr = psf::get_integer(psf, "ATTRIBUTE", 0); + game.size_on_disk = fs::get_dir_size(dir); if (m_show_custom_icons) { @@ -1421,12 +1423,23 @@ void game_list_frame::ShowContextMenu(const QPoint &pos) return; } - QMessageBox* mb = new QMessageBox(QMessageBox::Question, tr("Confirm %1 Removal").arg(gameinfo->localized_category), tr("Permanently remove %0 from drive?\nPath: %1").arg(name).arg(qstr(current_game.path)), QMessageBox::Yes | QMessageBox::No, this); - mb->setCheckBox(new QCheckBox(tr("Remove caches and custom configs"))); - mb->deleteLater(); - if (mb->exec() == QMessageBox::Yes) + QString size_information; + + if (current_game.size_on_disk != umax) { - const bool remove_caches = mb->checkBox()->isChecked(); + fs::device_stat stat{}; + if (fs::statfs(current_game.path, stat)) + { + size_information = tr("Game Directory Size: %0\nCurrent Free Disk Space: %1\n\n").arg(gui::utils::format_byte_size(current_game.size_on_disk)).arg(gui::utils::format_byte_size(stat.avail_free)); + } + } + + QMessageBox mb(QMessageBox::Question, tr("Confirm %1 Removal").arg(gameinfo->localized_category), tr("Permanently remove %0 from drive?\n%1Path: %2").arg(name).arg(size_information).arg(qstr(current_game.path)), QMessageBox::Yes | QMessageBox::No, this); + mb.setCheckBox(new QCheckBox(tr("Remove caches and custom configs"))); + + if (mb.exec() == QMessageBox::Yes) + { + const bool remove_caches = mb.checkBox()->isChecked(); if (fs::remove_all(current_game.path)) { if (remove_caches) @@ -2579,6 +2592,8 @@ void game_list_frame::PopulateGameList() } } + const usz game_size = game->info.size_on_disk; + m_game_list->setItem(row, gui::column_icon, icon_item); m_game_list->setItem(row, gui::column_name, title_item); m_game_list->setItem(row, gui::column_serial, serial_item); @@ -2593,6 +2608,7 @@ void game_list_frame::PopulateGameList() m_game_list->setItem(row, gui::column_last_play, new custom_table_widget_item(locale.toString(last_played, last_played >= QDateTime::currentDateTime().addDays(-7) ? gui::persistent::last_played_date_with_time_of_day_format : gui::persistent::last_played_date_format_new), Qt::UserRole, last_played)); m_game_list->setItem(row, gui::column_playtime, new custom_table_widget_item(elapsed_ms == 0 ? tr("Never played") : localized.GetVerboseTimeByMs(elapsed_ms), Qt::UserRole, elapsed_ms)); m_game_list->setItem(row, gui::column_compat, compat_item); + m_game_list->setItem(row, gui::column_dir_size, new custom_table_widget_item(game_size != umax ? gui::utils::format_byte_size(game_size) : tr("Unknown"), Qt::UserRole, QVariant::fromValue(game_size))); if (selected_item == game->info.path + game->info.icon_path) { diff --git a/rpcs3/rpcs3qt/gui_settings.cpp b/rpcs3/rpcs3qt/gui_settings.cpp index 1e1823e736..07fb3380b5 100644 --- a/rpcs3/rpcs3qt/gui_settings.cpp +++ b/rpcs3/rpcs3qt/gui_settings.cpp @@ -117,23 +117,22 @@ void gui_settings::ShowBox(QMessageBox::Icon icon, const QString& title, const Q const QFlags buttons = icon != QMessageBox::Information ? QMessageBox::Yes | QMessageBox::No : QMessageBox::Ok; - QMessageBox* mb = new QMessageBox(icon, title, text, buttons, parent, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | (always_on_top ? Qt::WindowStaysOnTopHint : Qt::Widget)); - mb->deleteLater(); - mb->setTextFormat(Qt::RichText); + QMessageBox mb(icon, title, text, buttons, parent, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | (always_on_top ? Qt::WindowStaysOnTopHint : Qt::Widget)); + mb.setTextFormat(Qt::RichText); if (has_gui_setting && icon != QMessageBox::Critical) { - mb->setCheckBox(new QCheckBox(tr("Don't show again"))); + mb.setCheckBox(new QCheckBox(tr("Don't show again"))); } - connect(mb, &QMessageBox::finished, [&](int res) + connect(&mb, &QMessageBox::finished, [&](int res) { if (result) { *result = res; } - const auto checkBox = mb->checkBox(); + const auto checkBox = mb.checkBox(); if (checkBox && checkBox->isChecked()) { @@ -142,7 +141,7 @@ void gui_settings::ShowBox(QMessageBox::Icon icon, const QString& title, const Q } }); - mb->exec(); + mb.exec(); } void gui_settings::ShowConfirmationBox(const QString& title, const QString& text, const gui_save& entry, int* result = nullptr, QWidget* parent = nullptr) diff --git a/rpcs3/rpcs3qt/gui_settings.h b/rpcs3/rpcs3qt/gui_settings.h index ea397370d9..e1983c4250 100644 --- a/rpcs3/rpcs3qt/gui_settings.h +++ b/rpcs3/rpcs3qt/gui_settings.h @@ -33,6 +33,7 @@ namespace gui column_last_play, column_playtime, column_compat, + column_dir_size, column_count }; @@ -69,6 +70,8 @@ namespace gui return "column_playtime"; case column_compat: return "column_compat"; + case column_dir_size: + return "column_dir_size"; case column_count: return ""; } diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index a593c01398..2b9d10e90d 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -294,13 +294,12 @@ bool main_window::OnMissingFw() const QString message = tr("Commercial games require the firmware (PS3UPDAT.PUP file) to be installed." "\n
For information about how to obtain the required firmware read the quickstart guide."); - QMessageBox* mb = new QMessageBox(QMessageBox::Question, title, message, QMessageBox::Ok | QMessageBox::Cancel, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); - mb->deleteLater(); - mb->setTextFormat(Qt::RichText); + QMessageBox mb(QMessageBox::Question, title, message, QMessageBox::Ok | QMessageBox::Cancel, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); + mb.setTextFormat(Qt::RichText); - mb->button(QMessageBox::Ok)->setText(tr("Locate PS3UPDAT.PUP")); + mb.button(QMessageBox::Ok)->setText(tr("Locate PS3UPDAT.PUP")); - if (mb->exec() == QMessageBox::Ok) + if (mb.exec() == QMessageBox::Ok) { InstallPup(); return true; diff --git a/rpcs3/rpcs3qt/qt_utils.cpp b/rpcs3/rpcs3qt/qt_utils.cpp index 37c162c597..556b94a5da 100644 --- a/rpcs3/rpcs3qt/qt_utils.cpp +++ b/rpcs3/rpcs3qt/qt_utils.cpp @@ -589,5 +589,21 @@ namespace gui } } } + + QString format_byte_size(usz size) + { + usz byte_unit = 0; + usz divisor = 1; + + static const QString s_units[]{"B", "KB", "MB", "GB", "TB", "PB"}; + + while (byte_unit < std::size(s_units) - 1 && size / divisor >= 1024) + { + byte_unit++; + divisor *= 1024; + } + + return QStringLiteral("%0 %1").arg(QString::number((size + 0.) / divisor, 'f', 2)).arg(s_units[byte_unit]); + } } // utils } // gui diff --git a/rpcs3/rpcs3qt/qt_utils.h b/rpcs3/rpcs3qt/qt_utils.h index edae53c0e6..f682eca607 100644 --- a/rpcs3/rpcs3qt/qt_utils.h +++ b/rpcs3/rpcs3qt/qt_utils.h @@ -124,5 +124,8 @@ namespace gui // Sort a QTreeWidget (currently only column 0) void sort_tree(QTreeWidget* tree, Qt::SortOrder sort_order, bool recursive); + + // Convert an arbitrary count of bytes to a readable format using global units (KB, MB...) + QString format_byte_size(usz size); } // utils } // gui