mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
Qt: lazy load game list icons and dir size
This commit is contained in:
parent
e9df63119b
commit
b401ad85d1
10 changed files with 418 additions and 89 deletions
|
@ -671,6 +671,7 @@
|
|||
<ClCompile Include="rpcs3qt\localized.cpp" />
|
||||
<ClCompile Include="rpcs3qt\log_viewer.cpp" />
|
||||
<ClCompile Include="rpcs3qt\microphone_creator.cpp" />
|
||||
<ClCompile Include="rpcs3qt\movie_item.cpp" />
|
||||
<ClCompile Include="rpcs3qt\osk_dialog_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\pad_led_settings_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\pad_motion_settings_dialog.cpp" />
|
||||
|
@ -696,6 +697,7 @@
|
|||
<ClCompile Include="rpcs3qt\shortcut_utils.cpp" />
|
||||
<ClCompile Include="rpcs3qt\skylander_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\system_cmd_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\table_item_delegate.cpp" />
|
||||
<ClCompile Include="rpcs3qt\tooltips.cpp" />
|
||||
<ClCompile Include="rpcs3qt\update_manager.cpp" />
|
||||
<ClCompile Include="rpcs3qt\qt_camera_video_surface.cpp" />
|
||||
|
|
|
@ -936,6 +936,12 @@
|
|||
<ClCompile Include="QTGeneratedFiles\Release\moc_system_cmd_dialog.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\table_item_delegate.cpp">
|
||||
<Filter>Gui\custom items</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\movie_item.cpp">
|
||||
<Filter>Gui\custom items</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||
|
|
|
@ -43,6 +43,7 @@ set(SRC_FILES
|
|||
memory_string_searcher.cpp
|
||||
memory_viewer_panel.cpp
|
||||
microphone_creator.cpp
|
||||
movie_item.cpp
|
||||
msg_dialog_frame.cpp
|
||||
osk_dialog_frame.cpp
|
||||
pad_led_settings_dialog.cpp
|
||||
|
@ -81,6 +82,7 @@ set(SRC_FILES
|
|||
skylander_dialog.cpp
|
||||
syntax_highlighter.cpp
|
||||
system_cmd_dialog.cpp
|
||||
table_item_delegate.cpp
|
||||
tooltips.cpp
|
||||
trophy_manager_dialog.cpp
|
||||
trophy_notification_frame.cpp
|
||||
|
|
|
@ -81,7 +81,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
|||
|
||||
m_game_list = new game_list();
|
||||
m_game_list->setShowGrid(false);
|
||||
m_game_list->setItemDelegate(new table_item_delegate(this, true));
|
||||
m_game_list->setItemDelegate(new table_item_delegate(m_game_list, true));
|
||||
m_game_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
m_game_list->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_game_list->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
@ -140,8 +140,8 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
|||
connect(&m_refresh_watcher, &QFutureWatcher<void>::finished, this, &game_list_frame::OnRefreshFinished);
|
||||
connect(&m_refresh_watcher, &QFutureWatcher<void>::canceled, this, [this]()
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_size_watcher, true, m_size_watcher_cancel);
|
||||
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||
WaitAndAbortSizeCalcThreads();
|
||||
WaitAndAbortRepaintThreads();
|
||||
|
||||
m_path_entries.clear();
|
||||
m_path_list.clear();
|
||||
|
@ -158,6 +158,21 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
|||
item->call_icon_func();
|
||||
}
|
||||
});
|
||||
connect(this, &game_list_frame::IconReady, this, [this](movie_item* item)
|
||||
{
|
||||
if (!m_is_list_layout || !item) return;
|
||||
item->call_icon_func();
|
||||
});
|
||||
connect(this, &game_list_frame::SizeOnDiskReady, this, [this](const game_info& game)
|
||||
{
|
||||
if (!m_is_list_layout || !game || !game->item) return;
|
||||
if (QTableWidgetItem* size_item = m_game_list->item(game->item->row(), gui::column_dir_size))
|
||||
{
|
||||
const u64& game_size = game->info.size_on_disk;
|
||||
size_item->setText(game_size != umax ? gui::utils::format_byte_size(game_size) : tr("Unknown"));
|
||||
size_item->setData(Qt::UserRole, QVariant::fromValue<qulonglong>(game_size));
|
||||
}
|
||||
});
|
||||
connect(&m_size_watcher, &QFutureWatcher<void>::canceled, this, [this]()
|
||||
{
|
||||
if (m_size_watcher_cancel)
|
||||
|
@ -267,8 +282,8 @@ void game_list_frame::LoadSettings()
|
|||
|
||||
game_list_frame::~game_list_frame()
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_size_watcher, true);
|
||||
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||
WaitAndAbortSizeCalcThreads();
|
||||
WaitAndAbortRepaintThreads();
|
||||
gui::utils::stop_future_watcher(m_refresh_watcher, true);
|
||||
|
||||
SaveSettings();
|
||||
|
@ -440,9 +455,9 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
|
|||
{
|
||||
if (from_drive)
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_size_watcher, true, m_size_watcher_cancel);
|
||||
WaitAndAbortSizeCalcThreads();
|
||||
}
|
||||
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||
WaitAndAbortRepaintThreads();
|
||||
gui::utils::stop_future_watcher(m_refresh_watcher, from_drive);
|
||||
|
||||
if (from_drive)
|
||||
|
@ -781,8 +796,8 @@ void game_list_frame::Refresh(const bool from_drive, const bool scroll_after)
|
|||
|
||||
void game_list_frame::OnRefreshFinished()
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_size_watcher, true, m_size_watcher_cancel);
|
||||
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||
WaitAndAbortSizeCalcThreads();
|
||||
WaitAndAbortRepaintThreads();
|
||||
|
||||
for (auto&& g : m_games.pop_all())
|
||||
{
|
||||
|
@ -856,6 +871,38 @@ void game_list_frame::OnRefreshFinished()
|
|||
|
||||
m_size_watcher_cancel = std::make_shared<atomic_t<bool>>(false);
|
||||
|
||||
if (m_is_list_layout)
|
||||
{
|
||||
for (auto& game : m_game_data)
|
||||
{
|
||||
if (movie_item* item = game->item)
|
||||
{
|
||||
item->set_size_calc_func([this, game, cancel = item->size_on_disk_loading_aborted(), dev_flash = g_cfg_vfs.get_dev_flash()]()
|
||||
{
|
||||
if (game && game->info.size_on_disk == umax && (!cancel || !cancel->load()))
|
||||
{
|
||||
if (game->info.path.starts_with(dev_flash))
|
||||
{
|
||||
// Do not report size of apps inside /dev_flash (it does not make sense to do so)
|
||||
game->info.size_on_disk = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
game->info.size_on_disk = fs::get_dir_size(game->info.path, 1, cancel.get());
|
||||
}
|
||||
|
||||
if (!cancel || !cancel->load())
|
||||
{
|
||||
Q_EMIT SizeOnDiskReady(game);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_size_watcher.setFuture(QtConcurrent::map(m_game_data, [this, cancel = m_size_watcher_cancel, dev_flash = g_cfg_vfs.get_dev_flash()](const game_info& game) -> void
|
||||
{
|
||||
if (game)
|
||||
|
@ -2393,7 +2440,7 @@ void game_list_frame::ResizeIcons(const int& slider_pos)
|
|||
|
||||
void game_list_frame::RepaintIcons(const bool& from_settings)
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||
WaitAndAbortRepaintThreads();
|
||||
|
||||
if (from_settings)
|
||||
{
|
||||
|
@ -2415,8 +2462,52 @@ void game_list_frame::RepaintIcons(const bool& from_settings)
|
|||
for (auto& game : m_game_data)
|
||||
{
|
||||
game->pxmap = placeholder;
|
||||
|
||||
if (movie_item* item = game->item)
|
||||
{
|
||||
item->set_icon_load_func([this, game, cancel = item->icon_loading_aborted()]()
|
||||
{
|
||||
if (cancel && cancel->load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static std::unordered_set<std::string> warn_once_list;
|
||||
static shared_mutex s_mtx;
|
||||
|
||||
if (game->icon.isNull() && (game->info.icon_path.empty() || !game->icon.load(qstr(game->info.icon_path))))
|
||||
{
|
||||
if (game_list_log.warning)
|
||||
{
|
||||
bool logged = false;
|
||||
{
|
||||
std::lock_guard lock(s_mtx);
|
||||
logged = !warn_once_list.emplace(game->info.icon_path).second;
|
||||
}
|
||||
|
||||
if (!logged)
|
||||
{
|
||||
game_list_log.warning("Could not load image from path %s", sstr(QDir(qstr(game->info.icon_path)).absolutePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!game->item || (cancel && cancel->load()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QColor color = getGridCompatibilityColor(game->compat.color);
|
||||
{
|
||||
std::lock_guard lock(game->item->pixmap_mutex);
|
||||
game->pxmap = PaintedPixmap(game->icon, game->hasCustomConfig, game->hasCustomPadConfig, color);
|
||||
}
|
||||
|
||||
if (!cancel || !cancel->load())
|
||||
{
|
||||
Q_EMIT IconReady(game->item);
|
||||
}
|
||||
});
|
||||
item->call_icon_func();
|
||||
}
|
||||
}
|
||||
|
@ -2430,6 +2521,8 @@ void game_list_frame::RepaintIcons(const bool& from_settings)
|
|||
|
||||
// Shorten the last section to remove horizontal scrollbar if possible
|
||||
m_game_list->resizeColumnToContents(gui::column_count - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const std::function func = [this](const game_info& game) -> movie_item*
|
||||
|
@ -2606,12 +2699,14 @@ void game_list_frame::PopulateGameList()
|
|||
{
|
||||
ensure(icon_item && game);
|
||||
|
||||
if (QMovie* movie = icon_item->movie(); movie && icon_item->get_active())
|
||||
if (std::shared_ptr<QMovie> movie = icon_item->movie(); movie && icon_item->get_active())
|
||||
{
|
||||
icon_item->setData(Qt::DecorationRole, movie->currentPixmap().scaled(m_icon_size, Qt::KeepAspectRatio));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard lock(icon_item->pixmap_mutex);
|
||||
|
||||
icon_item->setData(Qt::DecorationRole, game->pxmap);
|
||||
|
||||
if (!game->has_hover_gif)
|
||||
|
@ -2986,3 +3081,29 @@ std::string game_list_frame::GetGameVersion(const game_info& game)
|
|||
|
||||
return game->info.app_ver;
|
||||
}
|
||||
|
||||
void game_list_frame::WaitAndAbortRepaintThreads()
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_repaint_watcher, true);
|
||||
|
||||
for (const game_info& game : m_game_data)
|
||||
{
|
||||
if (game && game->item)
|
||||
{
|
||||
game->item->wait_for_icon_loading(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_frame::WaitAndAbortSizeCalcThreads()
|
||||
{
|
||||
gui::utils::stop_future_watcher(m_size_watcher, true, m_size_watcher_cancel);
|
||||
|
||||
for (const game_info& game : m_game_data)
|
||||
{
|
||||
if (game && game->item)
|
||||
{
|
||||
game->item->wait_for_size_on_disk_loading(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,8 @@ Q_SIGNALS:
|
|||
void RequestBoot(const game_info& game, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "", const std::string& savestate = "");
|
||||
void RequestIconSizeChange(const int& val);
|
||||
void NotifyEmuSettingsChange();
|
||||
void IconReady(movie_item* item);
|
||||
void SizeOnDiskReady(const game_info& game);
|
||||
protected:
|
||||
/** Override inherited method from Qt to allow signalling when close happened.*/
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
@ -127,6 +129,9 @@ private:
|
|||
game_info GetGameInfoByMode(const QTableWidgetItem* item) const;
|
||||
static game_info GetGameInfoFromItem(const QTableWidgetItem* item);
|
||||
|
||||
void WaitAndAbortRepaintThreads();
|
||||
void WaitAndAbortSizeCalcThreads();
|
||||
|
||||
// Which widget we are displaying depends on if we are in grid or list mode.
|
||||
QMainWindow* m_game_dock = nullptr;
|
||||
QStackedWidget* m_central_widget = nullptr;
|
||||
|
|
|
@ -81,7 +81,7 @@ movie_item* game_list_grid::addItem(const game_info& app, const QString& name, c
|
|||
exp_size_f = m_icon_size + m_icon_size * m_margin_factor * 2;
|
||||
}
|
||||
|
||||
QMovie* movie = item->movie();
|
||||
std::shared_ptr<QMovie> movie = item->movie();
|
||||
const bool draw_movie_frame = movie && movie->isValid() && item->get_active();
|
||||
const QSize exp_size = (exp_size_f * device_pixel_ratio).toSize();
|
||||
|
||||
|
|
148
rpcs3/rpcs3qt/movie_item.cpp
Normal file
148
rpcs3/rpcs3qt/movie_item.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "stdafx.h"
|
||||
#include "movie_item.h"
|
||||
|
||||
movie_item::movie_item() : QTableWidgetItem()
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item::movie_item(const QString& text, int type) : QTableWidgetItem(text, type)
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item::movie_item(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type)
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item::~movie_item()
|
||||
{
|
||||
if (m_movie)
|
||||
{
|
||||
m_movie->stop();
|
||||
}
|
||||
|
||||
wait_for_icon_loading(true);
|
||||
wait_for_size_on_disk_loading(true);
|
||||
}
|
||||
|
||||
void movie_item::init_pointers()
|
||||
{
|
||||
m_icon_loading_aborted.reset(new atomic_t<bool>(false));
|
||||
m_size_on_disk_loading_aborted.reset(new atomic_t<bool>(false));
|
||||
}
|
||||
|
||||
void movie_item::set_active(bool active)
|
||||
{
|
||||
if (!std::exchange(m_active, active) && active && m_movie)
|
||||
{
|
||||
m_movie->jumpToFrame(1);
|
||||
m_movie->start();
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item::init_movie(const QString& path)
|
||||
{
|
||||
if (path.isEmpty() || !m_icon_callback) return;
|
||||
|
||||
m_movie.reset(new QMovie(path));
|
||||
|
||||
if (!m_movie->isValid())
|
||||
{
|
||||
m_movie.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(m_movie.get(), &QMovie::frameChanged, m_movie.get(), m_icon_callback);
|
||||
}
|
||||
|
||||
void movie_item::call_icon_func() const
|
||||
{
|
||||
if (m_icon_callback)
|
||||
{
|
||||
m_icon_callback(0);
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item::set_icon_func(const icon_callback_t& func)
|
||||
{
|
||||
m_icon_callback = func;
|
||||
call_icon_func();
|
||||
}
|
||||
|
||||
void movie_item::call_icon_load_func()
|
||||
{
|
||||
wait_for_icon_loading(true);
|
||||
|
||||
if (!m_icon_load_callback || m_icon_loading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*m_icon_loading_aborted = false;
|
||||
m_icon_loading = true;
|
||||
m_icon_load_thread.reset(QThread::create([this]()
|
||||
{
|
||||
if (m_icon_load_callback)
|
||||
{
|
||||
m_icon_load_callback();
|
||||
}
|
||||
}));
|
||||
m_icon_load_thread->start();
|
||||
}
|
||||
|
||||
void movie_item::set_icon_load_func(const icon_load_callback_t& func)
|
||||
{
|
||||
wait_for_icon_loading(true);
|
||||
|
||||
m_icon_loading = false;
|
||||
m_icon_load_callback = func;
|
||||
}
|
||||
|
||||
void movie_item::call_size_calc_func()
|
||||
{
|
||||
wait_for_size_on_disk_loading(true);
|
||||
|
||||
if (!m_size_calc_callback || m_size_on_disk_loading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*m_size_on_disk_loading_aborted = false;
|
||||
m_size_on_disk_loading = true;
|
||||
m_size_calc_thread.reset(QThread::create([this]()
|
||||
{
|
||||
if (m_size_calc_callback)
|
||||
{
|
||||
m_size_calc_callback();
|
||||
}
|
||||
}));
|
||||
m_size_calc_thread->start();
|
||||
}
|
||||
|
||||
void movie_item::set_size_calc_func(const size_calc_callback_t& func)
|
||||
{
|
||||
m_size_on_disk_loading = false;
|
||||
m_size_calc_callback = func;
|
||||
}
|
||||
|
||||
void movie_item::wait_for_icon_loading(bool abort)
|
||||
{
|
||||
if (m_icon_load_thread)
|
||||
{
|
||||
*m_icon_loading_aborted = abort;
|
||||
m_icon_load_thread->wait();
|
||||
m_icon_load_thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item::wait_for_size_on_disk_loading(bool abort)
|
||||
{
|
||||
if (m_size_calc_thread)
|
||||
{
|
||||
*m_size_on_disk_loading_aborted = abort;
|
||||
m_size_calc_thread->wait();
|
||||
m_size_calc_thread.reset();
|
||||
}
|
||||
}
|
|
@ -1,87 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/atomic.hpp"
|
||||
|
||||
#include <QTableWidgetItem>
|
||||
#include <QMovie>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
using icon_callback_t = std::function<void(int)>;
|
||||
using icon_load_callback_t = std::function<void()>;
|
||||
using size_calc_callback_t = std::function<void()>;
|
||||
|
||||
class movie_item : public QTableWidgetItem
|
||||
{
|
||||
public:
|
||||
movie_item() : QTableWidgetItem()
|
||||
{
|
||||
}
|
||||
movie_item(const QString& text, int type = Type) : QTableWidgetItem(text, type)
|
||||
{
|
||||
}
|
||||
movie_item(const QIcon& icon, const QString& text, int type = Type) : QTableWidgetItem(icon, text, type)
|
||||
{
|
||||
}
|
||||
movie_item();
|
||||
movie_item(const QString& text, int type = Type);
|
||||
movie_item(const QIcon& icon, const QString& text, int type = Type);
|
||||
~movie_item();
|
||||
|
||||
~movie_item()
|
||||
{
|
||||
if (m_movie)
|
||||
{
|
||||
m_movie->stop();
|
||||
delete m_movie;
|
||||
}
|
||||
}
|
||||
void init_pointers();
|
||||
|
||||
void set_active(bool active)
|
||||
{
|
||||
if (!std::exchange(m_active, active) && active && m_movie)
|
||||
{
|
||||
m_movie->jumpToFrame(1);
|
||||
m_movie->start();
|
||||
}
|
||||
}
|
||||
void set_active(bool active);
|
||||
|
||||
[[nodiscard]] bool get_active() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
[[nodiscard]] QMovie* movie() const
|
||||
[[nodiscard]] std::shared_ptr<QMovie> movie() const
|
||||
{
|
||||
return m_movie;
|
||||
}
|
||||
|
||||
void init_movie(const QString& path)
|
||||
void init_movie(const QString& path);
|
||||
|
||||
void call_icon_func() const;
|
||||
void set_icon_func(const icon_callback_t& func);
|
||||
|
||||
void call_icon_load_func();
|
||||
void set_icon_load_func(const icon_load_callback_t& func);
|
||||
|
||||
void call_size_calc_func();
|
||||
void set_size_calc_func(const size_calc_callback_t& func);
|
||||
|
||||
void wait_for_icon_loading(bool abort);
|
||||
void wait_for_size_on_disk_loading(bool abort);
|
||||
|
||||
bool icon_loading() const
|
||||
{
|
||||
if (path.isEmpty() || !m_icon_callback) return;
|
||||
|
||||
if (QMovie* movie = new QMovie(path); movie->isValid())
|
||||
{
|
||||
m_movie = movie;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete movie;
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(m_movie, &QMovie::frameChanged, m_movie, m_icon_callback);
|
||||
return m_icon_loading;
|
||||
}
|
||||
|
||||
void call_icon_func() const
|
||||
bool size_on_disk_loading() const
|
||||
{
|
||||
if (m_icon_callback)
|
||||
{
|
||||
m_icon_callback(0);
|
||||
}
|
||||
return m_size_on_disk_loading;
|
||||
}
|
||||
|
||||
void set_icon_func(const icon_callback_t& func)
|
||||
std::shared_ptr<atomic_t<bool>> icon_loading_aborted() const
|
||||
{
|
||||
m_icon_callback = func;
|
||||
call_icon_func();
|
||||
return m_icon_loading_aborted;
|
||||
}
|
||||
|
||||
std::shared_ptr<atomic_t<bool>> size_on_disk_loading_aborted() const
|
||||
{
|
||||
return m_size_on_disk_loading_aborted;
|
||||
}
|
||||
|
||||
std::mutex pixmap_mutex;
|
||||
|
||||
private:
|
||||
QMovie* m_movie = nullptr;
|
||||
std::shared_ptr<QMovie> m_movie;
|
||||
std::unique_ptr<QThread> m_icon_load_thread;
|
||||
std::unique_ptr<QThread> m_size_calc_thread;
|
||||
bool m_active = false;
|
||||
atomic_t<bool> m_size_on_disk_loading = false;
|
||||
atomic_t<bool> m_icon_loading = false;
|
||||
size_calc_callback_t m_size_calc_callback = nullptr;
|
||||
icon_load_callback_t m_icon_load_callback = nullptr;
|
||||
icon_callback_t m_icon_callback = nullptr;
|
||||
|
||||
std::shared_ptr<atomic_t<bool>> m_icon_loading_aborted;
|
||||
std::shared_ptr<atomic_t<bool>> m_size_on_disk_loading_aborted;
|
||||
};
|
||||
|
|
68
rpcs3/rpcs3qt/table_item_delegate.cpp
Normal file
68
rpcs3/rpcs3qt/table_item_delegate.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "table_item_delegate.h"
|
||||
|
||||
#include <QTableWidget>
|
||||
#include "movie_item.h"
|
||||
#include "gui_settings.h"
|
||||
|
||||
table_item_delegate::table_item_delegate(QObject* parent, bool has_icons)
|
||||
: QStyledItemDelegate(parent), m_has_icons(has_icons)
|
||||
{
|
||||
}
|
||||
|
||||
void table_item_delegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
|
||||
{
|
||||
// Remove the focus frame around selected items
|
||||
option->state &= ~QStyle::State_HasFocus;
|
||||
|
||||
if (m_has_icons && index.column() == 0)
|
||||
{
|
||||
// Don't highlight icons
|
||||
option->state &= ~QStyle::State_Selected;
|
||||
|
||||
// Center icons
|
||||
option->decorationAlignment = Qt::AlignCenter;
|
||||
option->decorationPosition = QStyleOptionViewItem::Top;
|
||||
}
|
||||
|
||||
QStyledItemDelegate::initStyleOption(option, index);
|
||||
}
|
||||
|
||||
void table_item_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() == gui::game_list_columns::column_icon && option.state & QStyle::State_Selected)
|
||||
{
|
||||
// Add background highlight color to icons
|
||||
painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
// Find out if the icon or size items are visible
|
||||
if (index.column() == gui::game_list_columns::column_dir_size || (m_has_icons && index.column() == gui::game_list_columns::column_icon))
|
||||
{
|
||||
if (const QTableWidget* table = static_cast<const QTableWidget*>(parent()))
|
||||
{
|
||||
if (const QTableWidgetItem* current_item = table->item(index.row(), index.column());
|
||||
current_item && table->visibleRegion().intersects(table->visualItemRect(current_item)))
|
||||
{
|
||||
if (movie_item* item = static_cast<movie_item*>(table->item(index.row(), gui::game_list_columns::column_icon)))
|
||||
{
|
||||
if (index.column() == gui::game_list_columns::column_dir_size)
|
||||
{
|
||||
if (!item->size_on_disk_loading())
|
||||
{
|
||||
item->call_size_calc_func();
|
||||
}
|
||||
}
|
||||
else if (m_has_icons && index.column() == gui::game_list_columns::column_icon)
|
||||
{
|
||||
if (!item->icon_loading())
|
||||
{
|
||||
item->call_icon_load_func();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,34 +10,9 @@ private:
|
|||
bool m_has_icons;
|
||||
|
||||
public:
|
||||
explicit table_item_delegate(QObject *parent = nullptr, bool has_icons = false) : QStyledItemDelegate(parent), m_has_icons(has_icons) {}
|
||||
explicit table_item_delegate(QObject *parent = nullptr, bool has_icons = false);
|
||||
|
||||
void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override
|
||||
{
|
||||
// Remove the focus frame around selected items
|
||||
option->state &= ~QStyle::State_HasFocus;
|
||||
void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override;
|
||||
|
||||
if (m_has_icons && index.column() == 0)
|
||||
{
|
||||
// Don't highlight icons
|
||||
option->state &= ~QStyle::State_Selected;
|
||||
|
||||
// Center icons
|
||||
option->decorationAlignment = Qt::AlignCenter;
|
||||
option->decorationPosition = QStyleOptionViewItem::Top;
|
||||
}
|
||||
|
||||
QStyledItemDelegate::initStyleOption(option, index);
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
if (index.column() == 0 && option.state & QStyle::State_Selected)
|
||||
{
|
||||
// Add background highlight color to icons
|
||||
painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue