3838
3939LOG_CHANNEL (GameList);
4040
41- static constexpr float MIN_SCALE = 0 .1f ;
42- static constexpr float MAX_SCALE = 2 .0f ;
41+ static constexpr float MIN_ICON_SCALE = 1 .0f ;
42+ static constexpr float MAX_ICON_SCALE = 5 .0f ;
43+ static constexpr float MIN_COVER_SCALE = 0 .1f ;
44+ static constexpr float MAX_COVER_SCALE = 2 .0f ;
4345
4446static const char * SUPPORTED_FORMATS_STRING =
4547 QT_TRANSLATE_NOOP (GameListWidget, " .cue (Cue Sheets)\n "
@@ -57,6 +59,8 @@ static constexpr int COVER_ART_SIZE = 512;
5759static constexpr int COVER_ART_SPACING = 32 ;
5860static constexpr int MIN_COVER_CACHE_SIZE = 256 ;
5961static constexpr int MIN_COVER_CACHE_ROW_BUFFER = 4 ;
62+ static constexpr int MEMORY_CARD_ICON_SIZE = 16 ;
63+ static constexpr int MEMORY_CARD_ICON_PADDING = 12 ;
6064
6165static void resizeAndPadImage (QImage* image, int expected_width, int expected_height, bool fill_with_top_left)
6266{
@@ -127,6 +131,7 @@ GameListModel::GameListModel(QObject* parent)
127131 : QAbstractTableModel(parent), m_memcard_pixmap_cache(MIN_COVER_CACHE_SIZE)
128132{
129133 m_cover_scale = Host::GetBaseFloatSettingValue (" UI" , " GameListCoverArtScale" , 0 .45f );
134+ m_icon_scale = Host::GetBaseFloatSettingValue (" UI" , " GameListIconScale" , 1 .00f );
130135 m_show_localized_titles = GameList::ShouldShowLocalizedTitles ();
131136 m_show_titles_for_covers = Host::GetBaseBoolSettingValue (" UI" , " GameListShowCoverTitles" , true );
132137 m_show_game_icons = Host::GetBaseBoolSettingValue (" UI" , " GameListShowGameIcons" , true );
@@ -174,6 +179,26 @@ void GameListModel::refreshIcons()
174179 emit dataChanged (index (0 , Column_Icon), index (rowCount () - 1 , Column_Icon), {Qt::DecorationRole});
175180}
176181
182+ void GameListModel::setIconScale (float scale)
183+ {
184+ if (m_icon_scale == scale)
185+ return ;
186+
187+ m_icon_scale = scale;
188+
189+ Host::SetBaseFloatSettingValue (" UI" , " GameListIconScale" , scale);
190+ Host::CommitBaseSettingChanges ();
191+ updateIconScale ();
192+ }
193+
194+ void GameListModel::updateIconScale ()
195+ {
196+ m_memcard_pixmap_cache.Clear ();
197+
198+ emit iconScaleChanged (m_icon_scale);
199+ refresh ();
200+ }
201+
177202void GameListModel::setCoverScale (float scale)
178203{
179204 if (m_cover_scale == scale)
@@ -393,7 +418,7 @@ const QPixmap& GameListModel::getIconPixmapForEntry(const GameList::Entry* ge) c
393418 QPixmap pm;
394419 if (!path.empty () && pm.load (QString::fromStdString (path)))
395420 {
396- fixIconPixmapSize (pm);
421+ const_cast <GameListModel*>( this )-> fixIconPixmapSize (pm);
397422 return *m_memcard_pixmap_cache.Insert (ge->serial , std::move (pm));
398423 }
399424
@@ -467,16 +492,16 @@ void GameListModel::fixIconPixmapSize(QPixmap& pm)
467492 const int width = static_cast <int >(static_cast <float >(pm.width ()) * dpr);
468493 const int height = static_cast <int >(static_cast <float >(pm.height ()) * dpr);
469494 const int max_dim = std::max (width, height);
470- if (max_dim == 16 )
471- return ;
472495
473496 const float wanted_dpr = qApp->devicePixelRatio ();
474497 pm.setDevicePixelRatio (wanted_dpr);
475498
476- const float scale = static_cast <float >(max_dim) / 16 . 0f / wanted_dpr;
499+ const float scale = static_cast <float >(max_dim) / MEMORY_CARD_ICON_SIZE / wanted_dpr / m_icon_scale ;
477500 const int new_width = static_cast <int >(static_cast <float >(width) / scale);
478501 const int new_height = static_cast <int >(static_cast <float >(height) / scale);
479- pm = pm.scaled (new_width, new_height);
502+
503+ if (width != new_width || height != new_height)
504+ QtUtils::scaleMemoryCardIconWithSharpBilinear (pm, std::max (new_width, new_height));
480505}
481506
482507int GameListModel::getCoverArtSize () const
@@ -1248,6 +1273,7 @@ void GameListWidget::initialize(QAction* actionGameList, QAction* actionGameGrid
12481273{
12491274 m_model = new GameListModel (this );
12501275 connect (m_model, &GameListModel::coverScaleChanged, this , &GameListWidget::onCoverScaleChanged);
1276+ connect (m_model, &GameListModel::iconScaleChanged, this , &GameListWidget::onIconScaleChanged);
12511277
12521278 m_sort_model = new GameListSortModel (m_model);
12531279 m_sort_model->setSourceModel (m_model);
@@ -1284,6 +1310,7 @@ void GameListWidget::initialize(QAction* actionGameList, QAction* actionGameGrid
12841310 m_ui.showLocalizedTitles ->setDefaultAction (actionShowLocalizedTitles);
12851311
12861312 connect (m_ui.gridScale , &QSlider::valueChanged, m_grid_view, &GameListGridView::setZoomPct);
1313+ connect (m_ui.listScale , &QSlider::valueChanged, m_list_view, &GameListListView::setZoomPct);
12871314 connect (m_ui.filterType , &QComboBox::currentIndexChanged, this , [this ](int index) {
12881315 m_sort_model->setFilterType ((index == 0 ) ? GameList::EntryType::MaxCount :
12891316 static_cast <GameList::EntryType>(index - 1 ));
@@ -1318,6 +1345,7 @@ void GameListWidget::initialize(QAction* actionGameList, QAction* actionGameGrid
13181345 actionListShowIcons->setChecked (m_model->getShowGameIcons ());
13191346 actionGridShowTitles->setChecked (m_model->getShowCoverTitles ());
13201347 onCoverScaleChanged (m_model->getCoverScale ());
1348+ onIconScaleChanged (m_model->getIconScale ());
13211349
13221350 updateView (grid_view);
13231351 updateToolbar (grid_view);
@@ -1623,6 +1651,7 @@ void GameListWidget::updateToolbar(bool grid_view)
16231651 m_ui.showGameIcons ->setVisible (!grid_view);
16241652 m_ui.showGridTitles ->setVisible (grid_view);
16251653 m_ui.gridScale ->setVisible (grid_view);
1654+ m_ui.listScale ->setVisible (!grid_view);
16261655}
16271656
16281657void GameListWidget::onCoverScaleChanged (float scale)
@@ -1631,6 +1660,12 @@ void GameListWidget::onCoverScaleChanged(float scale)
16311660 m_ui.gridScale ->setValue (static_cast <int >(scale * 100 .0f ));
16321661}
16331662
1663+ void GameListWidget::onIconScaleChanged (float scale)
1664+ {
1665+ QSignalBlocker sb (m_ui.listScale );
1666+ m_ui.listScale ->setValue (static_cast <int >(scale * 4 .0f ));
1667+ }
1668+
16341669void GameListWidget::resizeEvent (QResizeEvent* event)
16351670{
16361671 QWidget::resizeEvent (event);
@@ -1688,8 +1723,12 @@ GameListListView::GameListListView(GameListModel* model, GameListSortModel* sort
16881723
16891724 horizontal_header->setSectionResizeMode (GameListModel::Column_Title, QHeaderView::Stretch);
16901725 horizontal_header->setSectionResizeMode (GameListModel::Column_FileTitle, QHeaderView::Stretch);
1726+ horizontal_header->setSectionResizeMode (GameListModel::Column_Icon, QHeaderView::ResizeToContents);
16911727
1692- verticalHeader ()->hide ();
1728+ QHeaderView* const vertical_header = verticalHeader ();
1729+ vertical_header->hide ();
1730+ vertical_header->setDefaultSectionSize (MEMORY_CARD_ICON_SIZE + MEMORY_CARD_ICON_PADDING +
1731+ style ()->pixelMetric (QStyle::PM_FocusFrameVMargin, nullptr , this ));
16931732
16941733 setVerticalScrollBarPolicy (Qt::ScrollBarAsNeeded);
16951734 setVerticalScrollMode (QAbstractItemView::ScrollMode::ScrollPerPixel);
@@ -1706,10 +1745,30 @@ GameListListView::GameListListView(GameListModel* model, GameListSortModel* sort
17061745 connect (horizontal_header, &QHeaderView::sortIndicatorChanged, this , &GameListListView::onHeaderSortIndicatorChanged);
17071746 connect (horizontal_header, &QHeaderView::customContextMenuRequested, this ,
17081747 &GameListListView::onHeaderContextMenuRequested);
1748+ connect (m_model, &GameListModel::iconScaleChanged, this , &GameListListView::onIconScaleChanged);
17091749}
17101750
17111751GameListListView::~GameListListView () = default ;
17121752
1753+ void GameListListView::wheelEvent (QWheelEvent* e)
1754+ {
1755+ if (e->modifiers () & Qt::ControlModifier)
1756+ {
1757+ int dy = e->angleDelta ().y ();
1758+ if (dy != 0 )
1759+ {
1760+ if (dy < 0 )
1761+ zoomOut ();
1762+ else
1763+ zoomIn ();
1764+
1765+ return ;
1766+ }
1767+ }
1768+
1769+ QTableView::wheelEvent (e);
1770+ }
1771+
17131772void GameListListView::setFixedColumnWidth (int column, int width)
17141773{
17151774 horizontalHeader ()->setSectionResizeMode (column, QHeaderView::Fixed);
@@ -1865,6 +1924,44 @@ void GameListListView::onHeaderContextMenuRequested(const QPoint& point)
18651924 menu.exec (mapToGlobal (point));
18661925}
18671926
1927+ void GameListListView::onIconScaleChanged (float scale)
1928+ {
1929+ updateLayout ();
1930+ }
1931+
1932+ void GameListListView::adjustZoom (float delta)
1933+ {
1934+ const float new_scale = std::clamp (m_model->getIconScale () + delta, MIN_ICON_SCALE, MAX_ICON_SCALE);
1935+ m_model->setIconScale (new_scale);
1936+ }
1937+
1938+ void GameListListView::zoomIn ()
1939+ {
1940+ adjustZoom (0 .25f );
1941+ }
1942+
1943+ void GameListListView::zoomOut ()
1944+ {
1945+ adjustZoom (-0 .25f );
1946+ }
1947+
1948+ void GameListListView::setZoomPct (int int_scale)
1949+ {
1950+ const float new_scale = std::clamp (static_cast <float >(int_scale) / 4 .0f , MIN_ICON_SCALE, MAX_ICON_SCALE);
1951+ m_model->setIconScale (new_scale);
1952+ }
1953+
1954+ void GameListListView::updateLayout ()
1955+ {
1956+ const float row_count = m_model->rowCount ();
1957+ const float icon_scale = m_model->getIconScale ();
1958+ const int height =
1959+ icon_scale * MEMORY_CARD_ICON_SIZE + 12 + style ()->pixelMetric (QStyle::PM_FocusFrameVMargin, nullptr , this );
1960+
1961+ for (int i = 0 ; i < row_count; i++)
1962+ setRowHeight (i, height);
1963+ }
1964+
18681965GameListGridView::GameListGridView (GameListModel* model, GameListSortModel* sort_model, QWidget* parent)
18691966 : QListView(parent), m_model(model)
18701967{
@@ -1922,7 +2019,7 @@ void GameListGridView::onCoverScaleChanged(float scale)
19222019
19232020void GameListGridView::adjustZoom (float delta)
19242021{
1925- const float new_scale = std::clamp (m_model->getCoverScale () + delta, MIN_SCALE, MAX_SCALE );
2022+ const float new_scale = std::clamp (m_model->getCoverScale () + delta, MIN_COVER_SCALE, MAX_COVER_SCALE );
19262023 m_model->setCoverScale (new_scale);
19272024}
19282025
@@ -1938,7 +2035,7 @@ void GameListGridView::zoomOut()
19382035
19392036void GameListGridView::setZoomPct (int int_scale)
19402037{
1941- const float new_scale = std::clamp (static_cast <float >(int_scale) / 100 .0f , MIN_SCALE, MAX_SCALE );
2038+ const float new_scale = std::clamp (static_cast <float >(int_scale) / 100 .0f , MIN_COVER_SCALE, MAX_COVER_SCALE );
19422039 m_model->setCoverScale (new_scale);
19432040}
19442041
0 commit comments