Initial commit
This commit is contained in:
163
app/dialogs.py
Normal file
163
app/dialogs.py
Normal file
@@ -0,0 +1,163 @@
|
||||
"""Settings, mod export and mod import dialogs."""
|
||||
import os
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (QCheckBox, QComboBox, QDialog, QDialogButtonBox, QFileDialog, QFormLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QListWidget, QListWidgetItem, QPlainTextEdit, QPushButton, QSlider,
|
||||
QTreeWidget, QTreeWidgetItem, QVBoxLayout)
|
||||
|
||||
from ackit.game import find_installs, is_game_dir
|
||||
from .audioio import output_devices
|
||||
|
||||
|
||||
def pick_game_dir(parent, start=""):
|
||||
"""Folder chooser that explains what to pick (also Proton/Linux paths)."""
|
||||
d = QFileDialog.getExistingDirectory(
|
||||
parent, "Select the Batman: Arkham City folder (contains BmGame and Binaries)", start or os.path.expanduser("~"))
|
||||
return d or None
|
||||
|
||||
|
||||
class SettingsDialog(QDialog):
|
||||
def __init__(self, settings, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Settings")
|
||||
self.settings = dict(settings)
|
||||
f = QFormLayout(self)
|
||||
self.game = QLineEdit(settings.get("game_dir") or "")
|
||||
b = QPushButton("Browse…")
|
||||
b.clicked.connect(self._browse_game)
|
||||
row = QHBoxLayout()
|
||||
row.addWidget(self.game, 1)
|
||||
row.addWidget(b)
|
||||
found = find_installs()
|
||||
hint = QLabel("Found via Steam: " + ("; ".join(found) if found else "none (Linux/Proton: "
|
||||
"~/.steam/steam/steamapps/common/Batman Arkham City GOTY)"))
|
||||
hint.setWordWrap(True)
|
||||
f.addRow("Game folder", row)
|
||||
f.addRow("", hint)
|
||||
self.store = QLineEdit(settings.get("store_root") or "")
|
||||
self.store.setPlaceholderText("default: in your user data folder")
|
||||
b2 = QPushButton("Browse…")
|
||||
b2.clicked.connect(lambda: self._browse(self.store))
|
||||
row2 = QHBoxLayout()
|
||||
row2.addWidget(self.store, 1)
|
||||
row2.addWidget(b2)
|
||||
f.addRow("Originals store", row2)
|
||||
self.full = QCheckBox("Keep one full copy of each audio archive before its first change (safest)")
|
||||
self.full.setChecked(settings.get("full_backup", True))
|
||||
f.addRow("", self.full)
|
||||
self.out = QComboBox()
|
||||
self.out.addItem("Default output")
|
||||
for d in output_devices():
|
||||
self.out.addItem(d.description())
|
||||
if settings.get("output_device"):
|
||||
i = self.out.findText(settings["output_device"])
|
||||
if i >= 0:
|
||||
self.out.setCurrentIndex(i)
|
||||
f.addRow("Playback device", self.out)
|
||||
# appearance
|
||||
self.bg_on = QCheckBox("Show the Arkham City wallpaper behind the filters")
|
||||
self.bg_on.setChecked(settings.get("background_enabled", True))
|
||||
f.addRow("Background", self.bg_on)
|
||||
self.opacity = QSlider(Qt.Orientation.Horizontal)
|
||||
self.opacity.setRange(0, 100)
|
||||
self.opacity.setValue(int(round(float(settings.get("background_opacity", 0.1)) * 100)))
|
||||
f.addRow("Background strength", self.opacity)
|
||||
self.bg_on.toggled.connect(self.opacity.setEnabled)
|
||||
self.opacity.setEnabled(self.bg_on.isChecked())
|
||||
bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
||||
bb.accepted.connect(self.accept)
|
||||
bb.rejected.connect(self.reject)
|
||||
f.addRow(bb)
|
||||
self.resize(640, 0)
|
||||
|
||||
def _browse_game(self):
|
||||
d = pick_game_dir(self, self.game.text())
|
||||
if d:
|
||||
self.game.setText(d)
|
||||
|
||||
def _browse(self, edit):
|
||||
d = QFileDialog.getExistingDirectory(self, "Choose folder", edit.text())
|
||||
if d:
|
||||
edit.setText(d)
|
||||
|
||||
def values(self):
|
||||
s = dict(self.settings)
|
||||
gd = self.game.text().strip()
|
||||
s["game_dir"] = gd if is_game_dir(gd) else s.get("game_dir")
|
||||
s["store_root"] = self.store.text().strip() or None
|
||||
s["full_backup"] = self.full.isChecked()
|
||||
s["output_device"] = self.out.currentText() if self.out.currentIndex() > 0 else None
|
||||
s["background_enabled"] = self.bg_on.isChecked()
|
||||
s["background_opacity"] = self.opacity.value() / 100.0
|
||||
return s
|
||||
|
||||
|
||||
class ExportModDialog(QDialog):
|
||||
"""Pick which modified sounds go into a .acmod package."""
|
||||
|
||||
def __init__(self, items, parent=None):
|
||||
"""items: [(key, name)]"""
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Export mod package")
|
||||
lay = QVBoxLayout(self)
|
||||
f = QFormLayout()
|
||||
self.title = QLineEdit()
|
||||
self.author = QLineEdit()
|
||||
self.desc = QPlainTextEdit()
|
||||
self.desc.setMaximumHeight(70)
|
||||
f.addRow("Title", self.title)
|
||||
f.addRow("Author", self.author)
|
||||
f.addRow("Description", self.desc)
|
||||
lay.addLayout(f)
|
||||
lay.addWidget(QLabel("Sounds to include:"))
|
||||
self.list = QListWidget()
|
||||
for key, name in items:
|
||||
it = QListWidgetItem(name)
|
||||
it.setData(Qt.ItemDataRole.UserRole, key)
|
||||
it.setFlags(it.flags() | Qt.ItemFlag.ItemIsUserCheckable)
|
||||
it.setCheckState(Qt.CheckState.Checked)
|
||||
self.list.addItem(it)
|
||||
lay.addWidget(self.list)
|
||||
bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Save | QDialogButtonBox.StandardButton.Cancel)
|
||||
bb.accepted.connect(self.accept)
|
||||
bb.rejected.connect(self.reject)
|
||||
lay.addWidget(bb)
|
||||
self.resize(520, 480)
|
||||
|
||||
def selected_keys(self):
|
||||
return [self.list.item(i).data(Qt.ItemDataRole.UserRole) for i in range(self.list.count())
|
||||
if self.list.item(i).checkState() == Qt.CheckState.Checked]
|
||||
|
||||
|
||||
class ImportModDialog(QDialog):
|
||||
"""Shows how each item of a package matches this game before installing."""
|
||||
|
||||
def __init__(self, manifest, items, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Import mod package")
|
||||
lay = QVBoxLayout(self)
|
||||
head = "<b>%s</b>" % (manifest.get("name") or "Mod package")
|
||||
if manifest.get("author"):
|
||||
head += " by %s" % manifest["author"]
|
||||
lab = QLabel(head + ("<br>" + manifest["description"] if manifest.get("description") else ""))
|
||||
lab.setWordWrap(True)
|
||||
lay.addWidget(lab)
|
||||
self.tree = QTreeWidget()
|
||||
self.tree.setHeaderLabels(["Sound", "Match", "Note"])
|
||||
n_ok = 0
|
||||
for im in items:
|
||||
note = {"exact": "same sound", "by name": "matched by name (other language) - will be re-encoded",
|
||||
"missing": im.note}[im.how]
|
||||
QTreeWidgetItem(self.tree, [im.item.get("name") or im.item["target"], im.how, note])
|
||||
n_ok += im.how != "missing"
|
||||
self.tree.resizeColumnToContents(0)
|
||||
lay.addWidget(self.tree)
|
||||
lay.addWidget(QLabel("%d of %d sounds will be installed." % (n_ok, len(items))))
|
||||
bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
||||
bb.button(QDialogButtonBox.StandardButton.Ok).setText("Install")
|
||||
bb.button(QDialogButtonBox.StandardButton.Ok).setEnabled(n_ok > 0)
|
||||
bb.accepted.connect(self.accept)
|
||||
bb.rejected.connect(self.reject)
|
||||
lay.addWidget(bb)
|
||||
self.resize(720, 420)
|
||||
Reference in New Issue
Block a user