Skip to content

Commit 7b991de

Browse files
committed
Qt: Bump currently-visible covers to front on scale change
Fixes flicker when very quickly changing scales from small to large.
1 parent 78db5ad commit 7b991de

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

src/duckstation-qt/gamelistwidget.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,32 @@ void GameListModel::refreshCovers()
323323
emit dataChanged(index(0, Column_Cover), index(rowCount() - 1, Column_Cover), {Qt::DecorationRole});
324324
}
325325

326-
void GameListModel::updateCacheSize(int num_rows, int num_columns)
326+
void GameListModel::updateCacheSize(int num_rows, int num_columns, QSortFilterProxyModel* const sort_model,
327+
int top_left_row)
327328
{
328329
// Add additional buffer zone to the rows, since Qt will grab them early when scrolling.
329330
const int num_items = (num_rows + MIN_COVER_CACHE_ROW_BUFFER) * num_columns;
330331

331332
// This is a bit conversative, since it doesn't consider padding, but better to be over than under.
332-
m_cover_pixmap_cache.SetMaxCapacity(static_cast<int>(std::max(num_items, MIN_COVER_CACHE_SIZE)));
333+
const int cache_size = std::max(num_items, MIN_COVER_CACHE_SIZE);
334+
if (static_cast<u32>(cache_size) < m_cover_pixmap_cache.GetSize())
335+
{
336+
// If we're removing items, make sure we try to keep those currently in view in the cache.
337+
// Otherwise we'll have flicker of the loading pixmap as they get evicted and reloaded.
338+
const auto lock = GameList::GetLock();
339+
for (int row = 0; row < cache_size; row++)
340+
{
341+
const QModelIndex real_index = sort_model->mapToSource(sort_model->index(top_left_row + row, Column_Cover));
342+
if (!real_index.isValid())
343+
continue;
344+
345+
const GameList::Entry* ge = GameList::GetEntryByIndex(static_cast<u32>(real_index.row()));
346+
if (ge)
347+
m_cover_pixmap_cache.Lookup(ge->path);
348+
}
349+
}
350+
351+
m_cover_pixmap_cache.SetMaxCapacity(static_cast<u32>(cache_size));
333352
}
334353

335354
void GameListModel::setDevicePixelRatio(qreal dpr)
@@ -2345,7 +2364,7 @@ void GameListListView::clearAnimatedGameIconDelegate()
23452364
}
23462365

23472366
GameListGridView::GameListGridView(GameListModel* model, GameListSortModel* sort_model, QWidget* parent)
2348-
: QListView(parent), m_model(model)
2367+
: QListView(parent), m_model(model), m_sort_model(sort_model)
23492368
{
23502369
setModel(sort_model);
23512370
setModelColumn(GameListModel::Column_Cover);
@@ -2415,7 +2434,8 @@ void GameListGridView::updateLayout()
24152434

24162435
setGridSize(QSize(item_width, item_height));
24172436

2418-
m_model->updateCacheSize(num_rows, num_columns);
2437+
const int top_left_row = (verticalScrollBar()->value() / item_height) * num_columns;
2438+
m_model->updateCacheSize(num_rows, num_columns, m_sort_model, top_left_row);
24192439

24202440
m_horizontal_offset = margin;
24212441
m_vertical_offset = item_spacing;

src/duckstation-qt/gamelistwidget.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class GameListModel final : public QAbstractTableModel
111111
int getCoverArtSize() const;
112112
int getCoverArtSpacing() const;
113113
void refreshCovers();
114-
void updateCacheSize(int num_rows, int num_columns);
114+
void updateCacheSize(int num_rows, int num_columns, QSortFilterProxyModel* const sort_model, int top_left_row);
115115

116116
qreal getDevicePixelRatio() const { return m_device_pixel_ratio; }
117117
void setDevicePixelRatio(qreal dpr);
@@ -237,6 +237,7 @@ class GameListGridView final : public QListView
237237

238238
private:
239239
GameListModel* m_model = nullptr;
240+
GameListSortModel* m_sort_model = nullptr;
240241
int m_horizontal_offset = 0;
241242
int m_vertical_offset = 0;
242243
};

0 commit comments

Comments
 (0)