Add an entry on Log panel's contextual menu to show the main disk usa… (#17715)

Added the entry `Show Disk Usage` on `Log` panel's contextual menu to
show the main disk usage of the emulator.
It reports VFS disk usage (with the exception of useless usb
directories) and cache disk usage.
I avoided to automatically display the disk usage, e.g. when refreshing
the game list, just because the disk usage calculation can require some
time (so it will slow down the emulator). So I opted to provide the
functionality on demand.
This PR is propaedeutic to pr6008. A separated PR to complete pr6008 will
follow. It will allow multiple selection of games on game list and a
contextual menu to manage the removal of the selected games.
This commit is contained in:
Antonino Di Guardo 2025-11-26 12:05:10 +01:00 committed by GitHub
parent 914b52cf4a
commit 6ebdb0c0c1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 136 additions and 0 deletions

View file

@ -101,6 +101,48 @@ namespace rpcs3::utils
return worker(); return worker();
} }
std::vector<std::pair<std::string, u64>> get_vfs_disk_usage()
{
std::vector<std::pair<std::string, u64>> disk_usage;
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_hdd0_dir(), 1); data_size != umax)
{
disk_usage.push_back({"dev_hdd0", data_size});
}
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_hdd1_dir(), 1); data_size != umax)
{
disk_usage.push_back({"dev_hdd1", data_size});
}
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_flash_dir(), 1); data_size != umax)
{
disk_usage.push_back({"dev_flash", data_size});
}
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_flash2_dir(), 1); data_size != umax)
{
disk_usage.push_back({"dev_flash2", data_size});
}
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_flash3_dir(), 1); data_size != umax)
{
disk_usage.push_back({"dev_flash3", data_size});
}
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_bdvd_dir(), 1); data_size != umax)
{
disk_usage.push_back({"dev_bdvd", data_size});
}
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_games_dir(), 1); data_size != umax)
{
disk_usage.push_back({"games", data_size});
}
return disk_usage;
}
std::string get_emu_dir() std::string get_emu_dir()
{ {
const std::string& emu_dir_ = g_cfg_vfs.emulator_dir; const std::string& emu_dir_ = g_cfg_vfs.emulator_dir;
@ -122,6 +164,36 @@ namespace rpcs3::utils
return g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, get_emu_dir()); return g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, get_emu_dir());
} }
std::string get_flash_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.dev_flash, get_emu_dir());
}
std::string get_flash2_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.dev_flash2, get_emu_dir());
}
std::string get_flash3_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.dev_flash3, get_emu_dir());
}
std::string get_bdvd_dir()
{
return g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, get_emu_dir());
}
u64 get_cache_disk_usage()
{
if (const u64 data_size = fs::get_dir_size(rpcs3::utils::get_cache_dir(), 1); data_size != umax)
{
return data_size;
}
return 0;
}
std::string get_cache_dir() std::string get_cache_dir()
{ {
return fs::get_cache_dir() + "cache/"; return fs::get_cache_dir() + "cache/";

View file

@ -23,10 +23,19 @@ namespace rpcs3::utils
bool install_pkg(const std::string& path); bool install_pkg(const std::string& path);
// VFS directories and disk usage
std::vector<std::pair<std::string, u64>> get_vfs_disk_usage();
std::string get_emu_dir(); std::string get_emu_dir();
std::string get_games_dir(); std::string get_games_dir();
std::string get_hdd0_dir(); std::string get_hdd0_dir();
std::string get_hdd1_dir(); std::string get_hdd1_dir();
std::string get_flash_dir();
std::string get_flash2_dir();
std::string get_flash3_dir();
std::string get_bdvd_dir();
// Cache directories and disk usage
u64 get_cache_disk_usage();
std::string get_cache_dir(); std::string get_cache_dir();
std::string get_cache_dir(std::string_view module_path); std::string get_cache_dir(std::string_view module_path);

View file

@ -4,10 +4,14 @@
#include "hex_validator.h" #include "hex_validator.h"
#include "memory_viewer_panel.h" #include "memory_viewer_panel.h"
#include "Emu/System.h"
#include "Emu/system_utils.hpp"
#include "Utilities/lockless.h" #include "Utilities/lockless.h"
#include "util/asm.hpp" #include "util/asm.hpp"
#include <QtConcurrent>
#include <QMenu> #include <QMenu>
#include <QMessageBox>
#include <QActionGroup> #include <QActionGroup>
#include <QScrollBar> #include <QScrollBar>
#include <QVBoxLayout> #include <QVBoxLayout>
@ -17,6 +21,8 @@
#include <deque> #include <deque>
#include <mutex> #include <mutex>
LOG_CHANNEL(sys_log, "SYS");
extern fs::file g_tty; extern fs::file g_tty;
extern atomic_t<s64> g_tty_size; extern atomic_t<s64> g_tty_size;
extern std::array<std::deque<std::string>, 16> g_tty_input; extern std::array<std::deque<std::string>, 16> g_tty_input;
@ -165,6 +171,28 @@ log_frame::log_frame(std::shared_ptr<gui_settings> _gui_settings, QWidget* paren
connect(m_timer, &QTimer::timeout, this, &log_frame::UpdateUI); connect(m_timer, &QTimer::timeout, this, &log_frame::UpdateUI);
} }
void log_frame::show_disk_usage(const std::vector<std::pair<std::string, u64>>& vfs_disk_usage, u64 cache_disk_usage)
{
QString text;
u64 tot_data_size = 0;
for (const auto& [dev, data_size] : vfs_disk_usage)
{
text += tr("\n %0: %1").arg(QString::fromStdString(dev)).arg(gui::utils::format_byte_size(data_size));
tot_data_size += data_size;
}
if (!text.isEmpty())
{
text = tr("\n VFS disk usage: %0%1").arg(gui::utils::format_byte_size(tot_data_size)).arg(text);
}
text += tr("\n Cache disk usage: %0").arg(gui::utils::format_byte_size(cache_disk_usage));
sys_log.success("%s", text);
QMessageBox::information(this, tr("Disk usage"), text);
}
void log_frame::SetLogLevel(logs::level lev) const void log_frame::SetLogLevel(logs::level lev) const
{ {
switch (lev) switch (lev)
@ -245,6 +273,26 @@ void log_frame::CreateAndConnectActions()
m_tty->clear(); m_tty->clear();
}); });
m_show_disk_usage_act = new QAction(tr("Show Disk Usage"), this);
connect(m_show_disk_usage_act, &QAction::triggered, [this]()
{
if (m_disk_usage_future.isRunning())
{
return; // Still running the last request
}
m_disk_usage_future = QtConcurrent::run([this]()
{
const std::vector<std::pair<std::string, u64>> vfs_disk_usage = rpcs3::utils::get_vfs_disk_usage();
const u64 cache_disk_usage = rpcs3::utils::get_cache_disk_usage();
Emu.CallFromMainThread([this, vfs_disk_usage, cache_disk_usage]()
{
show_disk_usage(vfs_disk_usage, cache_disk_usage);
}, nullptr, false);
});
});
m_perform_goto_on_debugger = new QAction(tr("Go-To On The Debugger"), this); m_perform_goto_on_debugger = new QAction(tr("Go-To On The Debugger"), this);
connect(m_perform_goto_on_debugger, &QAction::triggered, [this]() connect(m_perform_goto_on_debugger, &QAction::triggered, [this]()
{ {
@ -369,6 +417,9 @@ void log_frame::CreateAndConnectActions()
{ {
QMenu* menu = m_log->createStandardContextMenu(); QMenu* menu = m_log->createStandardContextMenu();
menu->addAction(m_clear_act); menu->addAction(m_clear_act);
menu->addSeparator();
menu->addAction(m_show_disk_usage_act);
menu->addSeparator();
menu->addAction(m_perform_goto_on_debugger); menu->addAction(m_perform_goto_on_debugger);
menu->addAction(m_perform_goto_thread_on_debugger); menu->addAction(m_perform_goto_thread_on_debugger);
menu->addAction(m_perform_show_in_mem_viewer); menu->addAction(m_perform_show_in_mem_viewer);

View file

@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <QFuture>
#include <QTabWidget> #include <QTabWidget>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QActionGroup> #include <QActionGroup>
@ -38,6 +39,7 @@ protected:
private Q_SLOTS: private Q_SLOTS:
void UpdateUI(); void UpdateUI();
private: private:
void show_disk_usage(const std::vector<std::pair<std::string, u64>>& vfs_disk_usage, u64 cache_disk_usage);
void SetLogLevel(logs::level lev) const; void SetLogLevel(logs::level lev) const;
void SetTTYLogging(bool val) const; void SetTTYLogging(bool val) const;
@ -48,6 +50,7 @@ private:
std::unique_ptr<find_dialog> m_find_dialog; std::unique_ptr<find_dialog> m_find_dialog;
QTimer* m_timer = nullptr; QTimer* m_timer = nullptr;
QFuture<void> m_disk_usage_future;
std::vector<QColor> m_color; std::vector<QColor> m_color;
QColor m_color_stack; QColor m_color_stack;
@ -72,6 +75,7 @@ private:
QAction* m_clear_act = nullptr; QAction* m_clear_act = nullptr;
QAction* m_clear_tty_act = nullptr; QAction* m_clear_tty_act = nullptr;
QAction* m_show_disk_usage_act = nullptr;
QAction* m_perform_goto_on_debugger = nullptr; QAction* m_perform_goto_on_debugger = nullptr;
QAction* m_perform_goto_thread_on_debugger = nullptr; QAction* m_perform_goto_thread_on_debugger = nullptr;
QAction* m_perform_show_in_mem_viewer = nullptr; QAction* m_perform_show_in_mem_viewer = nullptr;