Replace TableProxyModel with TableDelegate.

This commit is contained in:
spxtr 2016-02-17 21:12:24 -08:00
parent cafc879b7c
commit dfb0db9d31
7 changed files with 126 additions and 102 deletions

View File

@ -18,7 +18,7 @@ set(SRCS
GameList/GameListModel.cpp GameList/GameListModel.cpp
GameList/GameTracker.cpp GameList/GameTracker.cpp
GameList/ListProxyModel.cpp GameList/ListProxyModel.cpp
GameList/TableProxyModel.cpp GameList/TableDelegate.cpp
) )
list(APPEND LIBS core uicommon) list(APPEND LIBS core uicommon)

View File

@ -7,16 +7,18 @@
#include "DolphinQt2/Settings.h" #include "DolphinQt2/Settings.h"
#include "DolphinQt2/GameList/GameList.h" #include "DolphinQt2/GameList/GameList.h"
#include "DolphinQt2/GameList/ListProxyModel.h" #include "DolphinQt2/GameList/ListProxyModel.h"
#include "DolphinQt2/GameList/TableProxyModel.h" #include "DolphinQt2/GameList/TableDelegate.h"
GameList::GameList(QWidget* parent): QStackedWidget(parent) GameList::GameList(QWidget* parent): QStackedWidget(parent)
{ {
m_model = new GameListModel(this); m_model = new GameListModel(this);
m_table_proxy = new TableProxyModel(this); m_table_proxy = new QSortFilterProxyModel(this);
m_table_proxy->setSourceModel(m_model); m_table_proxy->setSourceModel(m_model);
m_list_proxy = new ListProxyModel(this); m_list_proxy = new ListProxyModel(this);
m_list_proxy->setSourceModel(m_model); m_list_proxy->setSourceModel(m_model);
m_delegate = new TableDelegate(this);
MakeTableView(); MakeTableView();
MakeListView(); MakeListView();
MakeEmptyView(); MakeEmptyView();
@ -39,6 +41,7 @@ void GameList::MakeTableView()
{ {
m_table = new QTableView(this); m_table = new QTableView(this);
m_table->setModel(m_table_proxy); m_table->setModel(m_table_proxy);
m_table->setItemDelegate(m_delegate);
m_table->setSelectionMode(QAbstractItemView::SingleSelection); m_table->setSelectionMode(QAbstractItemView::SingleSelection);
m_table->setSelectionBehavior(QAbstractItemView::SelectRows); m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
m_table->setAlternatingRowColors(true); m_table->setAlternatingRowColors(true);
@ -58,15 +61,15 @@ void GameList::MakeTableView()
m_table->setColumnHidden(GameListModel::COL_RATING, false); m_table->setColumnHidden(GameListModel::COL_RATING, false);
QHeaderView* hor_header = m_table->horizontalHeader(); QHeaderView* hor_header = m_table->horizontalHeader();
hor_header->setSectionResizeMode(GameListModel::COL_PLATFORM, QHeaderView::Fixed); hor_header->setSectionResizeMode(GameListModel::COL_PLATFORM, QHeaderView::ResizeToContents);
hor_header->setSectionResizeMode(GameListModel::COL_COUNTRY, QHeaderView::Fixed); hor_header->setSectionResizeMode(GameListModel::COL_COUNTRY, QHeaderView::ResizeToContents);
hor_header->setSectionResizeMode(GameListModel::COL_ID, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_ID, QHeaderView::ResizeToContents);
hor_header->setSectionResizeMode(GameListModel::COL_BANNER, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_BANNER, QHeaderView::ResizeToContents);
hor_header->setSectionResizeMode(GameListModel::COL_TITLE, QHeaderView::Stretch); hor_header->setSectionResizeMode(GameListModel::COL_TITLE, QHeaderView::Stretch);
hor_header->setSectionResizeMode(GameListModel::COL_MAKER, QHeaderView::Stretch); hor_header->setSectionResizeMode(GameListModel::COL_MAKER, QHeaderView::Stretch);
hor_header->setSectionResizeMode(GameListModel::COL_SIZE, QHeaderView::ResizeToContents); hor_header->setSectionResizeMode(GameListModel::COL_SIZE, QHeaderView::ResizeToContents);
hor_header->setSectionResizeMode(GameListModel::COL_DESCRIPTION, QHeaderView::Stretch); 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(); QHeaderView* ver_header = m_table->verticalHeader();
ver_header->setSectionResizeMode(QHeaderView::ResizeToContents); ver_header->setSectionResizeMode(QHeaderView::ResizeToContents);

View File

@ -13,6 +13,8 @@
#include "DolphinQt2/GameList/GameFile.h" #include "DolphinQt2/GameList/GameFile.h"
#include "DolphinQt2/GameList/GameListModel.h" #include "DolphinQt2/GameList/GameListModel.h"
class TableDelegate;
class GameList final : public QStackedWidget class GameList final : public QStackedWidget
{ {
Q_OBJECT Q_OBJECT
@ -41,6 +43,7 @@ private:
void ConsiderViewChange(); void ConsiderViewChange();
GameListModel* m_model; GameListModel* m_model;
TableDelegate* m_delegate;
QSortFilterProxyModel* m_table_proxy; QSortFilterProxyModel* m_table_proxy;
QSortFilterProxyModel* m_list_proxy; QSortFilterProxyModel* m_list_proxy;

View File

@ -0,0 +1,94 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <QPainter>
#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<QPixmap>().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);
}

View File

@ -0,0 +1,20 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <QStyledItemDelegate>
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;
};

View File

@ -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<QPixmap>().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();
}

View File

@ -1,19 +0,0 @@
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <QSortFilterProxyModel>
// 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;
};