diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index d66dece122..d7990b904a 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -18,7 +18,7 @@ set(SRCS GameList/GameListModel.cpp GameList/GameTracker.cpp GameList/ListProxyModel.cpp - GameList/TableProxyModel.cpp + GameList/TableDelegate.cpp ) list(APPEND LIBS core uicommon) diff --git a/Source/Core/DolphinQt2/GameList/GameList.cpp b/Source/Core/DolphinQt2/GameList/GameList.cpp index 0f2fb89487..5927be5a4d 100644 --- a/Source/Core/DolphinQt2/GameList/GameList.cpp +++ b/Source/Core/DolphinQt2/GameList/GameList.cpp @@ -10,16 +10,18 @@ #include "DolphinQt2/Settings.h" #include "DolphinQt2/GameList/GameList.h" #include "DolphinQt2/GameList/ListProxyModel.h" -#include "DolphinQt2/GameList/TableProxyModel.h" +#include "DolphinQt2/GameList/TableDelegate.h" GameList::GameList(QWidget* parent): QStackedWidget(parent) { m_model = new GameListModel(this); - m_table_proxy = new TableProxyModel(this); + m_table_proxy = new QSortFilterProxyModel(this); m_table_proxy->setSourceModel(m_model); m_list_proxy = new ListProxyModel(this); m_list_proxy->setSourceModel(m_model); + m_delegate = new TableDelegate(this); + MakeTableView(); MakeListView(); MakeEmptyView(); @@ -42,6 +44,7 @@ void GameList::MakeTableView() { m_table = new QTableView(this); m_table->setModel(m_table_proxy); + m_table->setItemDelegate(m_delegate); m_table->setSelectionMode(QAbstractItemView::SingleSelection); m_table->setSelectionBehavior(QAbstractItemView::SelectRows); m_table->setAlternatingRowColors(true); @@ -63,15 +66,15 @@ void GameList::MakeTableView() m_table->setColumnHidden(GameListModel::COL_RATING, false); QHeaderView* hor_header = m_table->horizontalHeader(); - hor_header->setSectionResizeMode(GameListModel::COL_PLATFORM, QHeaderView::Fixed); - hor_header->setSectionResizeMode(GameListModel::COL_COUNTRY, QHeaderView::Fixed); + hor_header->setSectionResizeMode(GameListModel::COL_PLATFORM, QHeaderView::ResizeToContents); + hor_header->setSectionResizeMode(GameListModel::COL_COUNTRY, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_ID, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_BANNER, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_TITLE, QHeaderView::Stretch); hor_header->setSectionResizeMode(GameListModel::COL_MAKER, QHeaderView::Stretch); hor_header->setSectionResizeMode(GameListModel::COL_SIZE, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_DESCRIPTION, QHeaderView::Stretch); - hor_header->setSectionResizeMode(GameListModel::COL_RATING, QHeaderView::Fixed); + hor_header->setSectionResizeMode(GameListModel::COL_RATING, QHeaderView::ResizeToContents); QHeaderView* ver_header = m_table->verticalHeader(); ver_header->setSectionResizeMode(QHeaderView::ResizeToContents); diff --git a/Source/Core/DolphinQt2/GameList/GameList.h b/Source/Core/DolphinQt2/GameList/GameList.h index 32c8c2292d..7508cdb641 100644 --- a/Source/Core/DolphinQt2/GameList/GameList.h +++ b/Source/Core/DolphinQt2/GameList/GameList.h @@ -13,6 +13,8 @@ #include "DolphinQt2/GameList/GameFile.h" #include "DolphinQt2/GameList/GameListModel.h" +class TableDelegate; + class GameList final : public QStackedWidget { Q_OBJECT @@ -45,6 +47,7 @@ private: void ConsiderViewChange(); GameListModel* m_model; + TableDelegate* m_delegate; QSortFilterProxyModel* m_table_proxy; QSortFilterProxyModel* m_list_proxy; diff --git a/Source/Core/DolphinQt2/GameList/TableDelegate.cpp b/Source/Core/DolphinQt2/GameList/TableDelegate.cpp new file mode 100644 index 0000000000..26951cbf67 --- /dev/null +++ b/Source/Core/DolphinQt2/GameList/TableDelegate.cpp @@ -0,0 +1,94 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include "DolphinQt2/Resources.h" +#include "DolphinQt2/GameList/GameListModel.h" +#include "DolphinQt2/GameList/TableDelegate.h" + +static QSize NORMAL_BANNER_SIZE(96, 32); + +// Convert an integer size to a friendly string representation. +static QString FormatSize(qint64 size) +{ + QStringList units{ + QStringLiteral("KB"), + QStringLiteral("MB"), + QStringLiteral("GB"), + QStringLiteral("TB") + }; + QStringListIterator i(units); + QString unit = QStringLiteral("B"); + double num = (double) size; + while (num > 1024.0 && i.hasNext()) + { + unit = i.next(); + num /= 1024.0; + } + return QStringLiteral("%1 %2").arg(QString::number(num, 'f', 1)).arg(unit); +} + +TableDelegate::TableDelegate(QWidget* parent) : QStyledItemDelegate(parent) +{ +} + +void TableDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + QVariant data = index.data(Qt::DisplayRole); + switch (index.column()) + { + case GameListModel::COL_PLATFORM: + DrawPixmap(painter, option.rect, Resources::GetPlatform(data.toInt())); + break; + case GameListModel::COL_COUNTRY: + DrawPixmap(painter, option.rect, Resources::GetCountry(data.toInt())); + break; + case GameListModel::COL_RATING: + DrawPixmap(painter, option.rect, Resources::GetRating(data.toInt())); + break; + case GameListModel::COL_BANNER: + DrawPixmap(painter, option.rect, data.value().scaled( + NORMAL_BANNER_SIZE, + Qt::KeepAspectRatio, + Qt::SmoothTransformation)); + break; + case GameListModel::COL_SIZE: + painter->drawText(option.rect, Qt::AlignCenter, FormatSize(data.toULongLong())); + break; + // Fall through. + case GameListModel::COL_ID: + case GameListModel::COL_TITLE: + case GameListModel::COL_DESCRIPTION: + case GameListModel::COL_MAKER: + painter->drawText(option.rect, Qt::AlignVCenter, data.toString()); + break; + default: break; + } +} + +QSize TableDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + switch (index.column()) + { + case GameListModel::COL_PLATFORM: + return Resources::GetPlatform(0).size(); + case GameListModel::COL_COUNTRY: + return Resources::GetCountry(0).size(); + case GameListModel::COL_RATING: + return Resources::GetRating(0).size(); + case GameListModel::COL_BANNER: + return NORMAL_BANNER_SIZE; + default: return QSize(0, 0); + } +} + +void TableDelegate::DrawPixmap(QPainter* painter, const QRect& rect, const QPixmap& pixmap) const +{ + // We don't want to stretch the pixmap out, so center it in the rect. + painter->drawPixmap( + rect.left() + (rect.width() - pixmap.width()) / 2, + rect.top() + (rect.height() - pixmap.height()) / 2, + pixmap); +} diff --git a/Source/Core/DolphinQt2/GameList/TableDelegate.h b/Source/Core/DolphinQt2/GameList/TableDelegate.h new file mode 100644 index 0000000000..bf40438371 --- /dev/null +++ b/Source/Core/DolphinQt2/GameList/TableDelegate.h @@ -0,0 +1,20 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class TableDelegate final : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit TableDelegate(QWidget* parent = nullptr); + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; + +private: + void DrawPixmap(QPainter* painter, const QRect& rect, const QPixmap& pixmap) const; +}; diff --git a/Source/Core/DolphinQt2/GameList/TableProxyModel.cpp b/Source/Core/DolphinQt2/GameList/TableProxyModel.cpp deleted file mode 100644 index df5766efe3..0000000000 --- a/Source/Core/DolphinQt2/GameList/TableProxyModel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "DolphinQt2/Resources.h" -#include "DolphinQt2/GameList/GameListModel.h" -#include "DolphinQt2/GameList/TableProxyModel.h" - -static constexpr QSize NORMAL_BANNER_SIZE(96, 32); - -// Convert an integer size to a friendly string representation. -static QString FormatSize(qint64 size) -{ - QStringList units{ - QStringLiteral("KB"), - QStringLiteral("MB"), - QStringLiteral("GB"), - QStringLiteral("TB") - }; - QStringListIterator i(units); - QString unit = QStringLiteral("B"); - double num = (double) size; - while (num > 1024.0 && i.hasNext()) - { - unit = i.next(); - num /= 1024.0; - } - return QStringLiteral("%1 %2").arg(QString::number(num, 'f', 1)).arg(unit); -} - -TableProxyModel::TableProxyModel(QObject* parent) - : QSortFilterProxyModel(parent) -{ - setSortCaseSensitivity(Qt::CaseInsensitive); -} - -QVariant TableProxyModel::data(const QModelIndex& i, int role) const -{ - QModelIndex source_index = mapToSource(i); - QVariant source_data = sourceModel()->data(source_index, Qt::DisplayRole); - if (role == Qt::DisplayRole) - { - switch (i.column()) - { - // Sort by the integer but display the formatted string. - case GameListModel::COL_SIZE: - return FormatSize(source_data.toULongLong()); - // These fall through to the underlying model. - case GameListModel::COL_ID: - case GameListModel::COL_TITLE: - case GameListModel::COL_DESCRIPTION: - case GameListModel::COL_MAKER: - return source_data; - } - } - else if (role == Qt::DecorationRole) - { - switch (i.column()) - { - // Show icons in the decoration roles. This lets us sort by the - // underlying ints, but display just the icons without doing any - // fixed-width hacks. - case GameListModel::COL_PLATFORM: - return Resources::GetPlatform(source_data.toInt()); - case GameListModel::COL_BANNER: - return source_data.value().scaled( - NORMAL_BANNER_SIZE, - Qt::KeepAspectRatio, - Qt::SmoothTransformation); - case GameListModel::COL_COUNTRY: - return Resources::GetCountry(source_data.toInt()); - case GameListModel::COL_RATING: - return Resources::GetRating(source_data.toInt()); - } - } - return QVariant(); -} diff --git a/Source/Core/DolphinQt2/GameList/TableProxyModel.h b/Source/Core/DolphinQt2/GameList/TableProxyModel.h deleted file mode 100644 index 3e178b4f11..0000000000 --- a/Source/Core/DolphinQt2/GameList/TableProxyModel.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include - -// This subclass of QSortFilterProxyModel transforms the raw GameFile data -// into presentable icons, and allows for sorting and filtering. -// For instance, the GameListModel exposes country as an integer, so this -// class converts that into a flag, while still allowing sorting on the -// underlying integer. -class TableProxyModel final : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - explicit TableProxyModel(QObject* parent = nullptr); - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; -};