Skip to content

GameList: Allow sorting by more columns #1571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 86 additions & 13 deletions src/gui/components/wxGameList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,25 +434,97 @@ static inline int order_to_int(const std::weak_ordering &wo)
return 0;
}

int wxGameList::SortComparator(uint64 titleId1, uint64 titleId2, SortData* sortData)
static bool operator<(const iosu::pdm::GameListStat& a, const iosu::pdm::GameListStat& b)
{
const auto isFavoriteA = GetConfig().IsGameListFavorite(titleId1);
const auto isFavoriteB = GetConfig().IsGameListFavorite(titleId2);
const auto& name1 = GetNameByTitleId(titleId1);
const auto& name2 = GetNameByTitleId(titleId2);
const auto& lastA = a.last_played;
const auto& lastB = b.last_played;

if(sortData->dir > 0)
return order_to_int(std::tie(isFavoriteB, name1) <=> std::tie(isFavoriteA, name2));
if(lastA.year < lastB.year)
return true;
if(lastA.year > lastB.year)
return false;

// same year
if(lastA.month < lastB.month)
return true;
if(lastA.month > lastB.month)
return false;

// same year and month
return lastA.day < lastB.day;
}

static bool operator==(const iosu::pdm::GameListStat& a, const iosu::pdm::GameListStat& b)
{
const auto& lastA = a.last_played;
const auto& lastB = b.last_played;

return lastA.year == lastB.year &&
lastA.month == lastB.month &&
lastA.day == lastB.day;
}

static std::weak_ordering operator<=>(const iosu::pdm::GameListStat& a, const iosu::pdm::GameListStat& b)
{
if (a == b)
return std::weak_ordering::equivalent;
if (a < b)
return std::weak_ordering::less;
else
return order_to_int(std::tie(isFavoriteB, name2) <=> std::tie(isFavoriteA, name1));
return std::weak_ordering::greater;
}

std::weak_ordering wxGameList::SortComparator(uint64 titleId1, uint64 titleId2, SortData* sortData)
{
auto titleLastPlayed = [](uint64_t id)
{
iosu::pdm::GameListStat playTimeStat{};
iosu::pdm::GetStatForGamelist(id, playTimeStat);
return playTimeStat;
};

auto titlePlayMinutes = [](uint64_t id)
{
iosu::pdm::GameListStat playTimeStat;
if (!iosu::pdm::GetStatForGamelist(id, playTimeStat))
return 0u;
return playTimeStat.numMinutesPlayed;
};

auto titleRegion = [](uint64_t id)
{
return CafeTitleList::GetGameInfo(id).GetRegion();
};

switch(sortData->column)
{
default:
case ColumnName:
{
const auto isFavoriteA = GetConfig().IsGameListFavorite(titleId1);
const auto isFavoriteB = GetConfig().IsGameListFavorite(titleId2);
const auto nameA = GetNameByTitleId(titleId1);
const auto nameB = GetNameByTitleId(titleId2);
return std::tie(isFavoriteB, nameA) <=> std::tie(isFavoriteA, nameB);
}
case ColumnGameStarted:
return titleLastPlayed(titleId1) <=> titleLastPlayed(titleId2);
case ColumnGameTime:
return titlePlayMinutes(titleId1) <=> titlePlayMinutes(titleId2);
case ColumnRegion:
return titleRegion(titleId1) <=> titleRegion(titleId2);
case ColumnTitleID:
return titleId1 <=> titleId2;
}
// unreachable
cemu_assert_debug(false);
return std::weak_ordering::less;
}

int wxGameList::SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
{
const auto sort_data = (SortData*)sortData;
const int dir = sort_data->dir;

return sort_data->thisptr->SortComparator((uint64)item1, (uint64)item2, sort_data);
return sort_data->dir * order_to_int(sort_data->thisptr->SortComparator((uint64)item1, (uint64)item2, sort_data));
}

void wxGameList::SortEntries(int column)
Expand All @@ -479,8 +551,9 @@ void wxGameList::SortEntries(int column)
case ColumnGameTime:
case ColumnGameStarted:
case ColumnRegion:
case ColumnTitleID:
{
SortData data{ this, column, s_direction };
SortData data{ this, ItemColumns{column}, s_direction };
SortItems(SortFunction, (wxIntPtr)&data);
break;
}
Expand Down Expand Up @@ -1004,7 +1077,7 @@ void wxGameList::OnClose(wxCloseEvent& event)

int wxGameList::FindInsertPosition(TitleId titleId)
{
SortData data{ this, s_last_column, s_direction };
SortData data{ this, ItemColumns{s_last_column}, s_direction };
const auto itemCount = GetItemCount();
if (itemCount == 0)
return 0;
Expand Down
6 changes: 3 additions & 3 deletions src/gui/components/wxGameList.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class wxGameList : public wxListCtrl
inline static const wxColour kSecondColor{ 0xFDF9F2 };
void UpdateItemColors(sint32 startIndex = 0);

enum ItemColumns
enum ItemColumns : int
{
ColumnHiddenName = 0,
ColumnIcon,
Expand All @@ -91,12 +91,12 @@ class wxGameList : public wxListCtrl
struct SortData
{
wxGameList* thisptr;
int column;
ItemColumns column;
int dir;
};

int FindInsertPosition(TitleId titleId);
int SortComparator(uint64 titleId1, uint64 titleId2, SortData* sortData);
std::weak_ordering SortComparator(uint64 titleId1, uint64 titleId2, SortData* sortData);
static int SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData);

wxTimer* m_tooltip_timer;
Expand Down
Loading