kvui: allow sorting hints in the hint tab (#2684)
This commit is contained in:
		
							parent
							
								
									30ad2aa4a8
								
							
						
					
					
						commit
						c795c72471
					
				| 
						 | 
					@ -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
								
								
								
								
							
							
						
						
									
										57
									
								
								kvui.py
								
								
								
								
							| 
						 | 
					@ -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):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue