Version 3.2.0: fast lists with loading spinners, names from the game files, INT docs and screenshots, cleanup

This commit is contained in:
2026-10-10 14:58:17 +02:00
parent fbde809370
commit 1586abb8e9
40 changed files with 449 additions and 19279 deletions

View File

@@ -269,7 +269,9 @@ HEAD = 0x200 # prefetch head size of variation 1
def make_banks(cooked, speech_wems):
"""Loose bank + two packages (one bank in both) + a prefetch head of INT SPEECH_ENTRY variation 1."""
from ackit.bnk import fnv1
names = ["Init", "CHR_SynthFootsteps_Media", "CHR_SynthFoley", "GUI_Synth", "Speech_Synth"]
names = ["Init", "CHR_SynthFootsteps_Media", "CHR_SynthFoley", "GUI_Synth", "Speech_Synth",
# banks whose streamed media are the WAD entries (entry ID = FNV-1 of the bank name)
"CHR_RadioScanner", "Speech_TAPE_JOKER_1", "Music", "AMB_Steel_B3"]
with open(os.path.join(cooked, "CookedBanks.txt"), "w", newline="\r\n") as f:
f.write("\n".join(names) + "\n")
foot = {FOOT[0]: wem(0.4, 800), FOOT[1]: wem(0.3, 900)}

View File

@@ -66,6 +66,28 @@ def test_browse_search_filter(win):
assert w.proxy.rowCount() == w.model.rowCount()
def test_sort_order_survives_filter_changes(win):
"""Rows that a filter shows again go to their sorted place (not appended at the end)."""
from PySide6.QtCore import Qt
from app.models import C_NAME, SORT_ROLE
w, _, _ = win
def keys():
return [w.proxy.data(w.proxy.index(r, C_NAME), SORT_ROLE) for r in range(w.proxy.rowCount())]
w.table.sortByColumn(C_NAME, Qt.SortOrder.AscendingOrder)
assert keys() == sorted(keys())
w.cmb_group.setCurrentText("Music")
w.clear_filters()
type_search(w, "radio")
type_search(w, "")
assert w.proxy.rowCount() == w.model.rowCount() and keys() == sorted(keys())
w.table.sortByColumn(C_NAME, Qt.SortOrder.DescendingOrder)
w.cmb_group.setCurrentText("Speech")
w.clear_filters()
assert keys() == sorted(keys(), reverse=True)
def test_replace_apply_revert_byte_identical(win, tmp_path):
w, root, originals = win
before = files(root)
@@ -296,6 +318,39 @@ class HeldRunner:
self.real.start(*self.held.pop(0))
def test_selection_survives_sort_and_filter(win):
from PySide6.QtCore import Qt
from app.models import C_LEN
w, _, _ = win
assert w.select_name("Speech_Synth_Radio_02")
s = w.editor.sound
w.table.sortByColumn(C_LEN, Qt.SortOrder.DescendingOrder)
type_search(w, "radio")
cur = w.table.currentIndex()
assert cur.isValid() and w.proxy.sound_at(cur) is s and [x.key for x in w.selected_sounds()] == [s.key]
type_search(w, "music") # the row is filtered out: no current row
assert not w.table.currentIndex().isValid() and not w.selected_sounds()
def test_list_spinners_while_loading(win):
"""The sound list and the text lists show the loading overlay while they load (background jobs); a subtitle
asked for meanwhile is selected when the rows arrive."""
from ackit import subtitles
w, root, _ = win
held = w.runner = HeldRunner(w.runner)
w.load_game(root, "INT")
assert w.table_busy.busy and w.table_busy.timer.isActive()
held.release()
assert not w.table_busy.busy and w.model.rowCount() == len(w.ws.catalog.sounds)
w._text_loaded.clear()
sub = w.ws.texts.subtitles("INT")[0]
key = subtitles.key("INT", sub.speech, sub.line)
w.show_subtitle(key)
assert w.subs.busy.busy and w.subs.busy.timer.isActive()
held.release()
assert not w.subs.busy.busy and w.subs.current is not None and w.subs.current.key == key
def test_spinners_while_loading(win, tmp_path):
w, root, _ = win
held = w.runner = HeldRunner(w.runner)