implemented sort_tracks_by option

This commit is contained in:
Faraphel 2022-08-07 18:19:25 +02:00
parent cc41a22a82
commit 3f58094d59
3 changed files with 99 additions and 24 deletions

View file

@ -35,4 +35,4 @@ class AbstractPreviewWindow(tkinter.Toplevel, ABC):
raise InvalidPreviewWindowName(name) raise InvalidPreviewWindowName(name)
from source.gui.preview import track_formatting, track_selecting from source.gui.preview import track_formatting, track_selecting, track_sorting

View file

@ -0,0 +1,65 @@
import tkinter
from tkinter import ttk
from source.mkw.MKWColor import MKWColor
from source.gui.preview import AbstractPreviewWindow
from source.gui import better_gui_error
ModConfig: any
class Window(AbstractPreviewWindow):
name = "track_sorting"
def __init__(self, mod_config: "ModConfig", template_variable: tkinter.StringVar = None):
super().__init__(mod_config, template_variable)
self.grid_rowconfigure(2, weight=1)
self.grid_columnconfigure(1, weight=1)
self.grab_set()
if template_variable is None: template_variable = tkinter.StringVar()
self.mod_config = mod_config
self.entry_template_input = ttk.Entry(self, width=100, textvariable=template_variable)
self.entry_template_input.grid(row=1, column=1, columnspan=2, sticky="NEWS")
self.entry_template_input.bind("<Return>", self.preview)
self.text_track_format = tkinter.Text(
self, background="black", foreground=MKWColor("off").color_code, state=tkinter.DISABLED
)
self.text_track_format.grid(row=2, column=1, sticky="NEWS")
self.scrollbar_track_preview = ttk.Scrollbar(self, command=self.text_track_format.yview)
self.scrollbar_track_preview.grid(row=2, column=2, sticky="NEWS")
self.text_track_format.configure(yscrollcommand=self.scrollbar_track_preview.set)
self.text_track_format.tag_configure("error", background="red", foreground="white")
self.preview()
@better_gui_error
def preview(self, event: tkinter.Event = None):
"""
Preview all the tracks name with the track format
:return:
"""
self.text_track_format.configure(state=tkinter.NORMAL)
self.text_track_format.delete(1.0, tkinter.END)
template = self.entry_template_input.get()
# insert all the tracks representation
for track in self.mod_config.get_all_tracks(
ignore_filter=True,
sorting_template=template if template else None
):
try:
self.text_track_format.insert(tkinter.END, f"{track}\n")
except Exception as exc:
formatted_exc = str(exc).replace('\n', ' ')
self.text_track_format.insert(tkinter.END, f"< Error: {formatted_exc} >\n")
self.text_track_format.tag_add("error", "end-1c-1l", "end-1c")
self.text_track_format.configure(state=tkinter.DISABLED)

View file

@ -1,6 +1,6 @@
import shutil import shutil
from pathlib import Path from pathlib import Path
from typing import Generator, Callable from typing import Generator, Callable, Iterator
from PIL import Image from PIL import Image
@ -18,10 +18,8 @@ from source.wt.szs import SZSPath
CT_ICON_SIZE: int = 128 CT_ICON_SIZE: int = 128
Thread: any Thread: any
global_settings = { global_settings = {
"force_random_new": { "force_random_new": {
"text": { "text": {
@ -44,12 +42,8 @@ global_settings = {
"en": "Sort tracks by", "en": "Sort tracks by",
"fr": "Trier les courses par" "fr": "Trier les courses par"
}, },
"type": "choices", "type": "string",
"choices": [ "preview": "track_sorting"
"test1",
"test2",
"test3"
]
} }
} }
@ -166,12 +160,12 @@ class ModConfig:
:return: the modconfig environment :return: the modconfig environment
""" """
return { return {
"mod_config": self, "mod_config": self,
"bmg_color_raw": bmg_color_raw, "bmg_color_raw": bmg_color_raw,
"bmg_color_text": bmg_color_text "bmg_color_text": bmg_color_text
} | ( } | (
base_env if base_env is not None else {} base_env if base_env is not None else {}
) )
def safe_eval(self, *args, env: dict[str, any] = None, **kwargs) -> any: def safe_eval(self, *args, env: dict[str, any] = None, **kwargs) -> any:
""" """
@ -202,7 +196,9 @@ class ModConfig:
for track in self.get_tracks(*args, **kwargs): for track in self.get_tracks(*args, **kwargs):
yield from track.get_tracks() yield from track.get_tracks()
def get_tracks(self, ignore_filter: bool = False) -> Generator["Track | TrackGroup", None, None]: def get_tracks(self, ignore_filter: bool = False,
sorting_template: str = None,
ignore_sorting: bool = False) -> Generator["Track | TrackGroup", None, None]:
""" """
Get all the tracks or tracks groups elements Get all the tracks or tracks groups elements
:ignore_filter: should the tracks filter be ignored :ignore_filter: should the tracks filter be ignored
@ -210,17 +206,31 @@ class ModConfig:
""" """
filter_template: str | None = self.global_settings["include_track_if"].value if not ignore_filter else None filter_template: str | None = self.global_settings["include_track_if"].value if not ignore_filter else None
settings_sort: str | None = self.global_settings["sort_tracks_by"].value
# filter_template_func is the function checking if the track should be included. If no parameter is set, # filter_template_func is the function checking if the track should be included. If no parameter is set,
# then always return True # then always return True
filter_template_func: Callable = self.safe_eval( filter_template_func: Callable = self.safe_eval(
filter_template, return_lambda=True, lambda_args=["track"] filter_template if filter_template is not None else "True",
) if filter_template is not None else ( return_lambda=True,
lambda track: True lambda_args=["track"]
) )
# if a sorting function is set, use it. If no function is set, but sorting is not disabled, use settings.
iterator: Iterator = filter(lambda track: filter_template_func(track=track) is True, self._tracks)
if not ignore_sorting and (sorting_template is not None or settings_sort is not None):
# get the sorting_template_func. If not defined, use the settings one.
sorting_template_func: Callable = self.safe_eval(
template=sorting_template if sorting_template is not None else settings_sort,
return_lambda=True,
lambda_args=["track"]
)
# wrap the iterator inside a sort function
iterator = sorted(iterator, key=sorting_template_func)
# Go though all the tracks and filter them if enabled # Go though all the tracks and filter them if enabled
for track in filter(lambda track: filter_template_func(track=track) is True, self._tracks): for track in iterator:
yield track yield track
def get_ordered_cups(self) -> Generator["Cup", None, None]: def get_ordered_cups(self) -> Generator["Cup", None, None]:
@ -245,7 +255,7 @@ class ModConfig:
# if there is still tracks in the buffer, create a cup with them and fill with default> # if there is still tracks in the buffer, create a cup with them and fill with default>
if len(track_buffer) > 0: if len(track_buffer) > 0:
track_buffer.extend([self.default_track] * (4 - len(track_buffer))) track_buffer.extend([self.default_track] * (4 - len(track_buffer)))
yield Cup(tracks=track_buffer, cup_name=f"{current_tag_name}/{current_tag_count+1}") yield Cup(tracks=track_buffer, cup_name=f"{current_tag_name}/{current_tag_count + 1}")
def get_unordered_cups(self) -> Generator["Cup", None, None]: def get_unordered_cups(self) -> Generator["Cup", None, None]:
""" """
@ -255,8 +265,8 @@ class ModConfig:
# for track that have don't have a tag in self.tags_cups # for track that have don't have a tag in self.tags_cups
track_buffer: "Track | TrackGroup" = [] track_buffer: "Track | TrackGroup" = []
for track in filter( for track in filter(
lambda track: not any(item in getattr(track, "tags", []) for item in self.tags_cups), lambda track: not any(item in getattr(track, "tags", []) for item in self.tags_cups),
self.get_tracks() self.get_tracks()
): ):
track_buffer.append(track) track_buffer.append(track)