Skip to content

Commit

Permalink
Fix sorting getting corrupted (#211)
Browse files Browse the repository at this point in the history
ocornut/imgui#4233
bug in imgui, sorts can return corrupted data when specs_dirty is false
fixed in imgui 1.84, pyimgui is imgui 1.82

here we were always checking sort specs as different tabs can have different table ids, but switching them dont count as specs_dirty
thus always checking the actual specs allowed to sort again when changing tabs

now instead we save the specs of all such tables when its specs_dirty is true
means no checking specs without specs_dirty, avoiding the imgui bug
but can still use correct sorting when changing tab as we save different sorts for different table ids

thanks FaceCrap for finding that imgui issue thread!
  • Loading branch information
Willy-JL authored Dec 23, 2024
1 parent 01e2dab commit 2bcfe9f
Showing 1 changed file with 16 additions and 13 deletions.
29 changes: 16 additions & 13 deletions modules/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ def __init__(self):
self.selected_games_count = 0
self.game_hitbox_click = False
self.hovered_game: Game = None
self.sorts: list[SortSpec] = []
self.filters: list[Filter] = []
self.poll_chars: list[int] = []
self.refresh_ratio_smooth = 0.0
Expand All @@ -341,6 +340,7 @@ def __init__(self):
self.prev_filters: list[Filter] = []
self.ghost_columns_enabled_count = 0
self.bg_mode_notifs_timer: float = None
self.sorts: dict[str, list[SortSpec]] = {}
self.show_games_ids: dict[Tab, list[int]] = {}

# Setup Qt objects
Expand Down Expand Up @@ -2901,19 +2901,22 @@ def draw_tabbar(self):
globals.settings.display_tab = new_tab
async_thread.run(db.update_settings("display_tab"))

def calculate_ids(self, sorts: imgui.core._ImGuiTableSortSpecs):
def calculate_ids(self, table_id: str, sorts: imgui.core._ImGuiTableSortSpecs):
manual_sort = cols.manual_sort.enabled
if manual_sort != self.prev_manual_sort:
self.prev_manual_sort = manual_sort
self.recalculate_ids = True
if self.prev_filters != self.filters:
self.prev_filters = self.filters.copy()
self.recalculate_ids = True
if sorts.specs_count > 0:
self.sorts = []
if sorts.specs_dirty:
new_sorts = []
for sort_spec in sorts.specs:
self.sorts.insert(0, SortSpec(index=sort_spec.column_index, reverse=bool(sort_spec.sort_direction - 1)))
if sorts.specs_dirty or self.recalculate_ids:
new_sorts.insert(0, SortSpec(index=sort_spec.column_index, reverse=bool(sort_spec.sort_direction - 1)))
self.sorts[table_id] = new_sorts
sorts.specs_dirty = False
self.recalculate_ids = True
if self.recalculate_ids:
self.recalculate_ids = False
# Pick base ID list
if manual_sort:
Expand Down Expand Up @@ -2991,7 +2994,7 @@ def key(id):
base_ids = list(base_ids)
# Sort globally by sortspecs
if not manual_sort:
for sort_spec in self.sorts:
for sort_spec in self.sorts[table_id]:
match sort_spec.index:
case cols.type.index:
key = lambda id: globals.games[id].type.name
Expand Down Expand Up @@ -3036,7 +3039,6 @@ def key(id):
for game in globals.games.values():
if game.selected and game.id not in tab_games_ids:
game.selected = False
sorts.specs_dirty = False
else:
tab_games_ids = self.show_games_ids[self.current_tab]

Expand Down Expand Up @@ -3106,7 +3108,6 @@ def sync_scroll(self):
else:
self.scroll_percent = imgui.get_scroll_y() / scroll_max_y

@property
def games_table_id(self):
tab_id = self.current_tab.id if self.current_tab else -1
return f"###game_list{tab_id if globals.settings.independent_tab_views else ''}"
Expand All @@ -3117,8 +3118,9 @@ def draw_games_list(self):
ghost_column_size = (imgui.style.frame_padding.x + imgui.style.cell_padding.x * 2)
offset = ghost_column_size * self.ghost_columns_enabled_count
imgui.set_cursor_pos_x(imgui.get_cursor_pos_x() - offset)
table_id = self.games_table_id()
if imgui.begin_table(
self.games_table_id,
table_id,
column=cols.count,
flags=self.game_list_table_flags,
outer_size_height=-imgui.get_frame_height_with_spacing() # Bottombar
Expand All @@ -3137,7 +3139,7 @@ def draw_games_list(self):
if column is cols.manual_sort:
can_sort = imgui.TABLE_COLUMN_NO_SORT * cols.manual_sort.enabled
imgui.table_setup_scroll_freeze(0, 1) # Sticky column headers
self.calculate_ids(imgui.table_get_sort_specs())
self.calculate_ids(table_id, imgui.table_get_sort_specs())

# Column headers
imgui.table_next_row(imgui.TABLE_ROW_HEADERS)
Expand Down Expand Up @@ -3274,8 +3276,9 @@ def draw_games_list(self):
def tick_list_columns(self):
# Hack: get sort and column specs for list mode in grid and kanban mode
pos = imgui.get_cursor_pos_y()
table_id = self.games_table_id()
if imgui.begin_table(
self.games_table_id,
table_id,
column=cols.count,
flags=self.game_list_table_flags,
outer_size_height=1
Expand All @@ -3288,7 +3291,7 @@ def tick_list_columns(self):
# Set sorting condition
if column is cols.manual_sort:
can_sort = imgui.TABLE_COLUMN_NO_SORT * cols.manual_sort.enabled
self.calculate_ids(imgui.table_get_sort_specs())
self.calculate_ids(table_id, imgui.table_get_sort_specs())
imgui.end_table()
imgui.set_cursor_pos_y(pos)

Expand Down

0 comments on commit 2bcfe9f

Please sign in to comment.