Version 3.4.0: Edit tab (edit list, large subtitle, replacements with effects and presets), Sounds tab only browses, ackit fx (pedalboard + own reverb) and replace --fx, first Linux build, catalog without a mod package

This commit is contained in:
2026-10-28 13:54:12 +01:00
parent a706dae419
commit 6de470174e
36 changed files with 2872 additions and 278 deletions

View File

@@ -6,8 +6,8 @@ length), menu texts into the localization files. Revert per text or all; changed
"""
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt, QTimer, Signal
from PySide6.QtWidgets import (QAbstractItemView, QCheckBox, QComboBox, QDialog, QDialogButtonBox, QFormLayout,
QHBoxLayout, QHeaderView, QLabel, QLineEdit, QPushButton, QSplitter, QTableView,
QVBoxLayout, QWidget)
QHBoxLayout, QHeaderView, QLabel, QLineEdit, QPlainTextEdit, QPushButton, QSplitter,
QTableView, QVBoxLayout, QWidget)
from ackit import subtitles
from ackit.texts import CHANGED, FOREIGN, LOST, MODIFIED, ORIGINAL, TextConflictError
@@ -240,6 +240,102 @@ class SubtitleBox(QWidget):
self.win.runner.start(lambda job: fn(job, False), done, failed)
class SubtitleEdit(QPlainTextEdit):
"""A subtitle line as a large wrapping text box (one line of text in the game: Enter is ignored and pasted
line breaks become spaces). Has the QLineEdit calls SubtitleBox uses: text(), textChanged."""
def __init__(self, text, parent=None):
super().__init__(parent)
f = self.font()
f.setPointSizeF(f.pointSizeF() * 1.3)
self.setFont(f)
self.setPlainText(text)
self.setTabChangesFocus(True)
self.setFixedHeight(self.fontMetrics().lineSpacing() * 2 + 14) # 2 lines at the Edit tab's width
def text(self):
return self.toPlainText()
def setText(self, text):
self.setPlainText(text)
def keyPressEvent(self, e):
if e.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
e.ignore()
return
super().keyPressEvent(e)
def insertFromMimeData(self, source):
self.insertPlainText(" ".join(source.text().split()))
class SubtitlePanel(SubtitleBox):
"""The subtitle of the sound in the Edit tab: large text, the game's original under it (and the
English line when editing another language), room counter, Apply / Revert / Show in list."""
def __init__(self, win, parent=None):
super().__init__(win, parent)
self.lines = QVBoxLayout()
self.lines.setContentsMargins(0, 0, 0, 0)
self.lines.setSpacing(4)
outer = self.layout()
outer.insertLayout(0, self.lines)
outer.setSpacing(4)
row = outer.itemAt(outer.count() - 1).layout() # one row: room counter | Apply | Revert | Show in list
for w in (self.lbl, self.b_open):
outer.removeWidget(w)
row.insertWidget(0, self.lbl, 3)
row.addWidget(self.b_open, 1)
self._parts = []
self._english = {}
def _english_text(self, ln):
if ln.lang == "INT":
return None
if not self._english:
try:
self._english = {(x.speech, x.line): x.text for x in self.win.ws.texts.subtitles("INT")}
except Exception: # noqa: BLE001 - only a reference text
self._english = {None: None}
return self._english.get((ln.speech, ln.line))
def set_sound(self, s):
for w in self._parts:
self.lines.removeWidget(w)
w.deleteLater()
self._parts, self.edits, self.keys = [], [], []
ws = self.win.ws
lines = ws.texts.for_sound(s, self.win.language) if ws and s else []
if not lines:
self.lbl.setText("No subtitle for this sound." if s else "")
for b in (self.b_apply, self.b_revert, self.b_open):
b.setEnabled(False)
return
tx = ws.texts
for i, ln in enumerate(lines):
k = subtitles.key(ln.lang, ln.speech, ln.line)
e = SubtitleEdit(tx.records().get(k, {}).get("applied") or ln.text)
e.setToolTip("Room: %d characters" % ln.room)
e.textChanged.connect(self._check)
self.lines.addWidget(e)
part = " (part %d of %d)" % (i + 1, len(lines)) if len(lines) > 1 else ""
ref = "Original%s: %s" % (part, ln.text)
en = self._english_text(ln)
if en and en != ln.text:
ref += "\nEnglish: " + en
r = QLabel(ref)
r.setObjectName("Muted")
r.setWordWrap(True)
r.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
self.lines.addWidget(r)
self._parts += [e, r]
self.edits.append(e)
self.keys.append(k)
self.b_open.setEnabled(True)
self.b_revert.setEnabled(any(k in tx.records() for k in self.keys))
self._check()
class TextPanel(QWidget):
"""kind 'subs' (subtitles) or 'menu' (menu text)."""
changed = Signal()