Qt: Use header resize mode for game list column widths

Simpler code, no need for workarounds in showEvent() either.
pull/3499/head
Stenzek 3 months ago
parent 76fdbb0b38
commit 73f326cd75
No known key found for this signature in database

@ -859,6 +859,11 @@ std::unique_lock<std::recursive_mutex> GameList::GetLock()
return std::unique_lock(s_mutex); return std::unique_lock(s_mutex);
} }
std::span<const GameList::Entry> GameList::GetEntries()
{
return s_entries;
}
const GameList::Entry* GameList::GetEntryByIndex(u32 index) const GameList::Entry* GameList::GetEntryByIndex(u32 index)
{ {
return (index < s_entries.size()) ? &s_entries[index] : nullptr; return (index < s_entries.size()) ? &s_entries[index] : nullptr;

@ -93,6 +93,7 @@ bool PopulateEntryFromPath(const std::string& path, Entry* entry);
// Game list access. It's the caller's responsibility to hold the lock while manipulating the entry in any way. // Game list access. It's the caller's responsibility to hold the lock while manipulating the entry in any way.
std::unique_lock<std::recursive_mutex> GetLock(); std::unique_lock<std::recursive_mutex> GetLock();
std::span<const Entry> GetEntries();
const Entry* GetEntryByIndex(u32 index); const Entry* GetEntryByIndex(u32 index);
const Entry* GetEntryForPath(std::string_view path); const Entry* GetEntryForPath(std::string_view path);
const Entry* GetEntryBySerial(std::string_view serial); const Entry* GetEntryBySerial(std::string_view serial);

@ -1423,6 +1423,10 @@ void GameListWidget::onRefreshComplete()
m_ui.stack->setCurrentIndex(2); m_ui.stack->setCurrentIndex(2);
setFocusProxy(nullptr); setFocusProxy(nullptr);
} }
else
{
m_list_view->updateDynamicColumnWidths();
}
} }
void GameListWidget::onSelectionModelCurrentChanged(const QModelIndex& current, const QModelIndex& previous) void GameListWidget::onSelectionModelCurrentChanged(const QModelIndex& current, const QModelIndex& previous)
@ -1572,7 +1576,6 @@ void GameListWidget::updateView(bool grid_view)
{ {
m_ui.stack->setCurrentIndex(0); m_ui.stack->setCurrentIndex(0);
setFocusProxy(m_list_view); setFocusProxy(m_list_view);
resizeListViewColumnsToFit();
} }
} }
@ -1595,11 +1598,6 @@ void GameListWidget::resizeEvent(QResizeEvent* event)
updateBackground(false); updateBackground(false);
} }
void GameListWidget::resizeListViewColumnsToFit()
{
m_list_view->resizeColumnsToFit();
}
const GameList::Entry* GameListWidget::getSelectedEntry() const const GameList::Entry* GameListWidget::getSelectedEntry() const
{ {
if (isShowingGameList()) if (isShowingGameList())
@ -1647,6 +1645,11 @@ GameListListView::GameListListView(GameListModel* model, GameListSortModel* sort
QHeaderView* const horizontal_header = horizontalHeader(); QHeaderView* const horizontal_header = horizontalHeader();
horizontal_header->setHighlightSections(false); horizontal_header->setHighlightSections(false);
horizontal_header->setContextMenuPolicy(Qt::CustomContextMenu); horizontal_header->setContextMenuPolicy(Qt::CustomContextMenu);
setFixedColumnWidths();
updateDynamicColumnWidths();
horizontal_header->setSectionResizeMode(GameListModel::Column_Title, QHeaderView::ResizeMode::Stretch);
horizontal_header->setSectionResizeMode(GameListModel::Column_FileTitle, QHeaderView::ResizeMode::Stretch);
verticalHeader()->hide(); verticalHeader()->hide();
@ -1669,32 +1672,76 @@ GameListListView::GameListListView(GameListModel* model, GameListSortModel* sort
GameListListView::~GameListListView() = default; GameListListView::~GameListListView() = default;
void GameListListView::resizeEvent(QResizeEvent* e) void GameListListView::setFixedColumnWidth(int column, int width)
{ {
QTableView::resizeEvent(e); horizontalHeader()->setSectionResizeMode(column, QHeaderView::Fixed);
resizeColumnsToFit(); setColumnWidth(column, width);
} }
void GameListListView::resizeColumnsToFit() void GameListListView::setFixedColumnWidth(const QFontMetrics& fm, int column, int str_width, int padding)
{ {
QtUtils::ResizeColumnsForTableView(this, { const int width = std::max(fm.boundingRect(m_model->getColumnDisplayName(column)).width(), str_width) + (padding * 2);
45, // type setFixedColumnWidth(column, width);
95, // serial }
-1, // title
-1, // file title void GameListListView::updateDynamicColumnWidths()
200, // developer {
200, // publisher s64 max_file_size = 0;
200, // genre u64 max_disk_file_size = 0;
50, // year
100, // players {
85, // time played const auto lock = GameList::GetLock();
85, // last played for (const GameList::Entry& entry : GameList::GetEntries())
80, // file size {
80, // size max_file_size = std::max(max_file_size, entry.file_size);
55, // region max_disk_file_size = std::max(max_disk_file_size, entry.uncompressed_size);
100, // achievements }
100 // compatibility }
});
const QFontMetrics fm(font());
const auto width_for = [&fm](const QString& text) { return fm.boundingRect(text).width(); };
setFixedColumnWidth(fm, GameListModel::Column_FileSize,
width_for(QStringLiteral("%1 MB").arg(static_cast<double>(max_file_size) / 1048576.0, 0, 'f', 2)),
10);
setFixedColumnWidth(
fm, GameListModel::Column_UncompressedSize,
width_for(QStringLiteral("%1 MB").arg(static_cast<double>(max_disk_file_size) / 1048576.0, 0, 'f', 2)), 10);
}
void GameListListView::setFixedColumnWidths()
{
const QFontMetrics fm(font());
const auto width_for = [&fm](const QString& text) { return fm.boundingRect(text).width(); };
setFixedColumnWidth(fm, GameListModel::Column_Serial, width_for(QStringLiteral("SWWW-00000")), 4);
setFixedColumnWidth(fm, GameListModel::Column_Year, width_for(QStringLiteral("1999")), 4);
setFixedColumnWidth(fm, GameListModel::Column_Players, width_for(QStringLiteral("1 - 2")), 4);
// Played time is a little trickier, since some locales might have longer words for "hours" and "minutes".
setFixedColumnWidth(fm, GameListModel::Column_TimePlayed,
std::max(width_for(qApp->translate("GameList", "%n seconds", "", 59)),
std::max(width_for(qApp->translate("GameList", "%n minutes", "", 59)),
width_for(qApp->translate("GameList", "%n hours", "", 1000)))),
10);
// And this is a monstrosity.
setFixedColumnWidth(
fm, GameListModel::Column_LastPlayed,
std::max(width_for(qApp->translate("GameList", "Today")),
std::max(width_for(qApp->translate("GameList", "Yesterday")),
std::max(width_for(qApp->translate("GameList", "Never")),
width_for(QtHost::FormatNumber(Host::NumberFormatType::ShortDate,
static_cast<s64>(QDateTime::currentSecsSinceEpoch())))))),
10);
setFixedColumnWidth(GameListModel::Column_Icon, 45);
setFixedColumnWidth(GameListModel::Column_Region, 55);
setFixedColumnWidth(GameListModel::Column_Achievements, 100);
setFixedColumnWidth(GameListModel::Column_Compatibility, 100);
setColumnWidth(GameListModel::Column_Developer, 200);
setColumnWidth(GameListModel::Column_Publisher, 200);
setColumnWidth(GameListModel::Column_Genre, 200);
} }
static TinyString getColumnVisibilitySettingsKeyName(int column) static TinyString getColumnVisibilitySettingsKeyName(int column)
@ -1771,7 +1818,6 @@ void GameListListView::setAndSaveColumnHidden(int column, bool hidden)
setColumnHidden(column, hidden); setColumnHidden(column, hidden);
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), !hidden); Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), !hidden);
Host::CommitBaseSettingChanges(); Host::CommitBaseSettingChanges();
resizeColumnsToFit();
} }
void GameListListView::onHeaderSortIndicatorChanged(int, Qt::SortOrder) void GameListListView::onHeaderSortIndicatorChanged(int, Qt::SortOrder)
@ -1791,10 +1837,7 @@ void GameListListView::onHeaderContextMenuRequested(const QPoint& point)
QAction* action = menu.addAction(m_model->getColumnDisplayName(column)); QAction* action = menu.addAction(m_model->getColumnDisplayName(column));
action->setCheckable(true); action->setCheckable(true);
action->setChecked(!isColumnHidden(column)); action->setChecked(!isColumnHidden(column));
connect(action, &QAction::triggered, [this, column](bool enabled) { connect(action, &QAction::triggered, [this, column](bool enabled) { setAndSaveColumnHidden(column, !enabled); });
setAndSaveColumnHidden(column, !enabled);
resizeColumnsToFit();
});
} }
menu.exec(mapToGlobal(point)); menu.exec(mapToGlobal(point));

@ -161,15 +161,16 @@ public:
void setAndSaveColumnHidden(int column, bool hidden); void setAndSaveColumnHidden(int column, bool hidden);
void resizeColumnsToFit(); void updateDynamicColumnWidths();
protected:
void resizeEvent(QResizeEvent* e) override;
private: private:
void onHeaderSortIndicatorChanged(int, Qt::SortOrder); void onHeaderSortIndicatorChanged(int, Qt::SortOrder);
void onHeaderContextMenuRequested(const QPoint& point); void onHeaderContextMenuRequested(const QPoint& point);
void setFixedColumnWidth(int column, int width);
void setFixedColumnWidth(const QFontMetrics& fm, int column, int str_width, int padding);
void setFixedColumnWidths();
void loadColumnVisibilitySettings(); void loadColumnVisibilitySettings();
void loadColumnSortSettings(); void loadColumnSortSettings();
void saveColumnSortSettings(); void saveColumnSortSettings();
@ -222,7 +223,6 @@ public:
void initialize(QAction* actionGameList, QAction* actionGameGrid, QAction* actionMergeDiscSets, void initialize(QAction* actionGameList, QAction* actionGameGrid, QAction* actionMergeDiscSets,
QAction* actionListShowIcons, QAction* actionGridShowTitles); QAction* actionListShowIcons, QAction* actionGridShowTitles);
void resizeListViewColumnsToFit();
void refresh(bool invalidate_cache); void refresh(bool invalidate_cache);
void cancelRefresh(); void cancelRefresh();

@ -2681,17 +2681,6 @@ void MainWindow::openInputProfileEditor(const std::string_view name)
m_input_profile_editor_window->switchProfile(name); m_input_profile_editor_window->switchProfile(name);
} }
void MainWindow::showEvent(QShowEvent* event)
{
QMainWindow::showEvent(event);
// This is a bit silly, but for some reason resizing *before* the window is shown
// gives the incorrect sizes for columns, if you set the style before setting up
// the rest of the window... so, instead, let's just force it to be resized on show.
if (isShowingGameList())
m_game_list_widget->resizeListViewColumnsToFit();
}
void MainWindow::closeEvent(QCloseEvent* event) void MainWindow::closeEvent(QCloseEvent* event)
{ {
// If there's no VM, we can just exit as normal. // If there's no VM, we can just exit as normal.

@ -227,7 +227,6 @@ private Q_SLOTS:
void openCPUDebugger(); void openCPUDebugger();
protected: protected:
void showEvent(QShowEvent* event) override;
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;
void changeEvent(QEvent* event) override; void changeEvent(QEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;

Loading…
Cancel
Save