kvui: allow sorting hints in the hint tab (#2684)

This commit is contained in:
Fabian Dill 2024-03-12 14:52:57 +01:00 committed by GitHub
parent 30ad2aa4a8
commit c795c72471
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 14 deletions

View File

@ -61,36 +61,42 @@
found_text: "Found?" found_text: "Found?"
TooltipLabel: TooltipLabel:
id: receiving id: receiving
sort_key: 'receiving'
text: root.receiving_text text: root.receiving_text
halign: 'center' halign: 'center'
valign: 'center' valign: 'center'
pos_hint: {"center_y": 0.5} pos_hint: {"center_y": 0.5}
TooltipLabel: TooltipLabel:
id: item id: item
sort_key: 'item'
text: root.item_text text: root.item_text
halign: 'center' halign: 'center'
valign: 'center' valign: 'center'
pos_hint: {"center_y": 0.5} pos_hint: {"center_y": 0.5}
TooltipLabel: TooltipLabel:
id: finding id: finding
sort_key: 'finding'
text: root.finding_text text: root.finding_text
halign: 'center' halign: 'center'
valign: 'center' valign: 'center'
pos_hint: {"center_y": 0.5} pos_hint: {"center_y": 0.5}
TooltipLabel: TooltipLabel:
id: location id: location
sort_key: 'location'
text: root.location_text text: root.location_text
halign: 'center' halign: 'center'
valign: 'center' valign: 'center'
pos_hint: {"center_y": 0.5} pos_hint: {"center_y": 0.5}
TooltipLabel: TooltipLabel:
id: entrance id: entrance
sort_key: 'entrance'
text: root.entrance_text text: root.entrance_text
halign: 'center' halign: 'center'
valign: 'center' valign: 'center'
pos_hint: {"center_y": 0.5} pos_hint: {"center_y": 0.5}
TooltipLabel: TooltipLabel:
id: found id: found
sort_key: 'found'
text: root.found_text text: root.found_text
halign: 'center' halign: 'center'
valign: 'center' valign: 'center'

57
kvui.py
View File

@ -2,6 +2,7 @@ import os
import logging import logging
import sys import sys
import typing import typing
import re
if sys.platform == "win32": if sys.platform == "win32":
import ctypes import ctypes
@ -72,6 +73,8 @@ if typing.TYPE_CHECKING:
else: else:
context_type = object context_type = object
remove_between_brackets = re.compile(r"\[.*?]")
# I was surprised to find this didn't already exist in kivy :( # I was surprised to find this didn't already exist in kivy :(
class HoverBehavior(object): class HoverBehavior(object):
@ -303,7 +306,6 @@ class HintLabel(RecycleDataViewBehavior, BoxLayout):
selected = BooleanProperty(False) selected = BooleanProperty(False)
striped = BooleanProperty(False) striped = BooleanProperty(False)
index = None index = None
no_select = []
def __init__(self): def __init__(self):
super(HintLabel, self).__init__() super(HintLabel, self).__init__()
@ -321,9 +323,7 @@ class HintLabel(RecycleDataViewBehavior, BoxLayout):
def refresh_view_attrs(self, rv, index, data): def refresh_view_attrs(self, rv, index, data):
self.index = index self.index = index
if "select" in data and not data["select"] and index not in self.no_select: self.striped = data.get("striped", False)
self.no_select.append(index)
self.striped = data["striped"]
self.receiving_text = data["receiving"]["text"] self.receiving_text = data["receiving"]["text"]
self.item_text = data["item"]["text"] self.item_text = data["item"]["text"]
self.finding_text = data["finding"]["text"] self.finding_text = data["finding"]["text"]
@ -337,24 +337,44 @@ class HintLabel(RecycleDataViewBehavior, BoxLayout):
""" Add selection on touch down """ """ Add selection on touch down """
if super(HintLabel, self).on_touch_down(touch): if super(HintLabel, self).on_touch_down(touch):
return True return True
if self.index not in self.no_select: if self.index: # skip header
if self.collide_point(*touch.pos): if self.collide_point(*touch.pos):
if self.selected: if self.selected:
self.parent.clear_selection() self.parent.clear_selection()
else: else:
text = "".join([self.receiving_text, "\'s ", self.item_text, " is at ", self.location_text, " in ", text = "".join((self.receiving_text, "\'s ", self.item_text, " is at ", self.location_text, " in ",
self.finding_text, "\'s World", (" at " + self.entrance_text) self.finding_text, "\'s World", (" at " + self.entrance_text)
if self.entrance_text != "Vanilla" if self.entrance_text != "Vanilla"
else "", ". (", self.found_text.lower(), ")"]) else "", ". (", self.found_text.lower(), ")"))
temp = MarkupLabel(text).markup temp = MarkupLabel(text).markup
text = "".join( text = "".join(
part for part in temp if not part.startswith(("[color", "[/color]", "[ref=", "[/ref]"))) part for part in temp if not part.startswith(("[color", "[/color]", "[ref=", "[/ref]")))
Clipboard.copy(escape_markup(text).replace("&", "&").replace("&bl;", "[").replace("&br;", "]")) Clipboard.copy(escape_markup(text).replace("&", "&").replace("&bl;", "[").replace("&br;", "]"))
return self.parent.select_with_touch(self.index, touch) return self.parent.select_with_touch(self.index, touch)
else:
parent = self.parent
parent.clear_selection()
parent: HintLog = parent.parent
# find correct column
for child in self.children:
if child.collide_point(*touch.pos):
key = child.sort_key
parent.hint_sorter = lambda element: remove_between_brackets.sub("", element[key]["text"]).lower()
if key == parent.sort_key:
# second click reverses order
parent.reversed = not parent.reversed
else:
parent.sort_key = key
parent.reversed = False
break
else:
logging.warning("Did not find clicked header for sorting.")
App.get_running_app().update_hints()
def apply_selection(self, rv, index, is_selected): def apply_selection(self, rv, index, is_selected):
""" Respond to the selection of items in the view. """ """ Respond to the selection of items in the view. """
if self.index not in self.no_select: if self.index:
self.selected = is_selected self.selected = is_selected
@ -646,20 +666,20 @@ class HintLog(RecycleView):
"entrance": {"text": "[u]Entrance[/u]"}, "entrance": {"text": "[u]Entrance[/u]"},
"found": {"text": "[u]Status[/u]"}, "found": {"text": "[u]Status[/u]"},
"striped": True, "striped": True,
"select": False,
} }
sort_key: str = ""
reversed: bool = False
def __init__(self, parser): def __init__(self, parser):
super(HintLog, self).__init__() super(HintLog, self).__init__()
self.data = [self.header] self.data = [self.header]
self.parser = parser self.parser = parser
def refresh_hints(self, hints): def refresh_hints(self, hints):
self.data = [self.header] data = []
striped = False
for hint in hints: for hint in hints:
self.data.append({ data.append({
"striped": striped,
"receiving": {"text": self.parser.handle_node({"type": "player_id", "text": hint["receiving_player"]})}, "receiving": {"text": self.parser.handle_node({"type": "player_id", "text": hint["receiving_player"]})},
"item": {"text": self.parser.handle_node( "item": {"text": self.parser.handle_node(
{"type": "item_id", "text": hint["item"], "flags": hint["item_flags"]})}, {"type": "item_id", "text": hint["item"], "flags": hint["item_flags"]})},
@ -672,7 +692,16 @@ class HintLog(RecycleView):
"text": self.parser.handle_node({"type": "color", "color": "green" if hint["found"] else "red", "text": self.parser.handle_node({"type": "color", "color": "green" if hint["found"] else "red",
"text": "Found" if hint["found"] else "Not Found"})}, "text": "Found" if hint["found"] else "Not Found"})},
}) })
striped = not striped
data.sort(key=self.hint_sorter, reverse=self.reversed)
for i in range(0, len(data), 2):
data[i]["striped"] = True
data.insert(0, self.header)
self.data = data
@staticmethod
def hint_sorter(element: dict) -> str:
return ""
class E(ExceptionHandler): class E(ExceptionHandler):