mirror of
https://github.com/aclist/dztui.git
synced 2026-08-30 03:37:00 +02:00
Compare commits
No commits in common. "a8b7ea50083476faa0756f71b16ce154aa058a19" and "ad85bb73437d686fbdbbba424124c986fbabdae9" have entirely different histories.
a8b7ea5008
...
ad85bb7343
@ -53,13 +53,13 @@ def is_mission(path: Path) -> bool:
|
|||||||
file = path / "init.c"
|
file = path / "init.c"
|
||||||
return file.exists()
|
return file.exists()
|
||||||
|
|
||||||
def tokenize(mod: Path) -> dict[str, Any] | None:
|
def tokenize(mod: Path) -> dict[Any] | None:
|
||||||
file = mod.joinpath("meta.cpp")
|
file = mod.joinpath("meta.cpp")
|
||||||
delimiter=r"\s*=\s*"
|
delimiter=r"\s*=\s*"
|
||||||
modmeta = {}
|
modmeta = {}
|
||||||
try:
|
try:
|
||||||
with open(file, "r", encoding="utf-8") as f:
|
with open(file, "r", encoding="utf-8") as file:
|
||||||
for line in f:
|
for line in file:
|
||||||
line = line.strip().rstrip(";")
|
line = line.strip().rstrip(";")
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository.Gtk import ListStore # noqa E402
|
from gi.repository.Gtk import ListStore # noqa E402
|
||||||
from gi.repository import Gdk, GObject # noqa E402
|
from gi.repository import Gdk, GObject # noqa E402
|
||||||
@ -156,7 +155,7 @@ class Emitter(GObject.GObject):
|
|||||||
def lan_page_initialized(self) -> None:
|
def lan_page_initialized(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(object, str))
|
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(object, str, bool))
|
||||||
def custom_mods_loaded(self, store: "FastInsertListStore", folder: str) -> None:
|
def custom_mods_loaded(self, store: "FastInsertListStore", folder: str) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -30,8 +30,9 @@ class OfflineManager:
|
|||||||
self.local_mods: list[str] | None
|
self.local_mods: list[str] | None
|
||||||
self.custom_mods: list[str] | None
|
self.custom_mods: list[str] | None
|
||||||
|
|
||||||
|
|
||||||
def get_mission(self) -> None:
|
def get_mission(self) -> None:
|
||||||
folder = self.open_folderpicker(dialogs.mission_dialog)
|
folder = self.open_folderpicker()
|
||||||
if folder is None:
|
if folder is None:
|
||||||
return
|
return
|
||||||
is_valid = is_mission(folder)
|
is_valid = is_mission(folder)
|
||||||
@ -42,7 +43,7 @@ class OfflineManager:
|
|||||||
self.emitter.emit("custom_mission_loaded", str(folder), is_valid)
|
self.emitter.emit("custom_mission_loaded", str(folder), is_valid)
|
||||||
|
|
||||||
def get_custom_mods(self, local_mods: list[str]) -> None:
|
def get_custom_mods(self, local_mods: list[str]) -> None:
|
||||||
folder = self.open_folderpicker(dialogs.custom_mod_dialog)
|
folder = self.open_folderpicker()
|
||||||
if folder is None:
|
if folder is None:
|
||||||
return
|
return
|
||||||
self.parse_custom_mods(local_mods, folder)
|
self.parse_custom_mods(local_mods, folder)
|
||||||
@ -53,9 +54,7 @@ class OfflineManager:
|
|||||||
store = ModelFactory().make_mod_store()
|
store = ModelFactory().make_mod_store()
|
||||||
store.extend(mods)
|
store.extend(mods)
|
||||||
|
|
||||||
func = StoredFunc(
|
func = StoredFunc(lambda: self.emitter.emit("custom_mods_loaded", store, folder))
|
||||||
lambda: self.emitter.emit("custom_mods_loaded", store, folder)
|
|
||||||
)
|
|
||||||
self.thread_man.set_cleanup_func(func)
|
self.thread_man.set_cleanup_func(func)
|
||||||
|
|
||||||
def setup(
|
def setup(
|
||||||
@ -92,8 +91,8 @@ class OfflineManager:
|
|||||||
|
|
||||||
launch_offline(client, self.appid, name, combined_mods, self.mission_folder)
|
launch_offline(client, self.appid, name, combined_mods, self.mission_folder)
|
||||||
|
|
||||||
def open_folderpicker(self, title: str) -> Union["Path", None]:
|
def open_folderpicker(self) -> Union["Path", None]:
|
||||||
picker = FolderPicker(self.controller.get_window(), title)
|
picker = FolderPicker(self.controller.get_window())
|
||||||
folder = picker.pick_folder()
|
folder = picker.pick_folder()
|
||||||
picker.destroy()
|
picker.destroy()
|
||||||
return folder
|
return folder
|
||||||
|
|||||||
@ -16,6 +16,3 @@ checking_api = "Checking API key"
|
|||||||
running = "Running"
|
running = "Running"
|
||||||
failed = "FAILED"
|
failed = "FAILED"
|
||||||
ok = "OK"
|
ok = "OK"
|
||||||
|
|
||||||
mission_dialog = "Set a mission folder location"
|
|
||||||
custom_mod_dialog = "Set location to a custom mods folder"
|
|
||||||
|
|||||||
@ -31,61 +31,40 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
class Icon(Gtk.Image):
|
class Icon(Gtk.Image):
|
||||||
def __init__(self, name: str, margin_start: int = 0, margin_end: int = 0) -> None:
|
def __init__(self, name: str, l_margin: int = 0) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
icon_name=name,
|
icon_name=name,
|
||||||
icon_size=Gtk.IconSize.BUTTON,
|
icon_size=Gtk.IconSize.BUTTON,
|
||||||
margin_start=margin_start,
|
margin_start=l_margin,
|
||||||
margin_end=margin_end,
|
|
||||||
ypad=2,
|
ypad=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class LargeIcon(Gtk.Image):
|
class LargeIcon(Gtk.Image):
|
||||||
def __init__(self, name: str, margin_start: int = 5, margin_end: int = 0) -> None:
|
def __init__(self, name: str, l_margin: int = 5) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
icon_name=name,
|
icon_name=name, icon_size=Gtk.IconSize.LARGE_TOOLBAR, margin_start=l_margin
|
||||||
icon_size=Gtk.IconSize.LARGE_TOOLBAR,
|
|
||||||
margin_start=margin_start,
|
|
||||||
margin_end=margin_end,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class IconButton(Gtk.Button):
|
class IconButton(Gtk.Button):
|
||||||
def __init__(
|
def __init__(self, icon: str, margin: int = 0) -> None:
|
||||||
self,
|
|
||||||
icon: str,
|
|
||||||
position: Gtk.PositionType = Gtk.PositionType.RIGHT,
|
|
||||||
margin_start: int = 0,
|
|
||||||
margin_end: int = 0,
|
|
||||||
) -> None:
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.icon = Icon(icon, margin_start=margin_start, margin_end=margin_end)
|
self.icon = Icon(icon, l_margin=margin)
|
||||||
self.set_image(self.icon)
|
self.set_image(self.icon)
|
||||||
self.set_image_position(position)
|
self.set_image_position(Gtk.PositionType.RIGHT)
|
||||||
# self.set_image_position(Gtk.PositionType.RIGHT)
|
|
||||||
self.set_focus_on_click(False)
|
self.set_focus_on_click(False)
|
||||||
|
|
||||||
|
|
||||||
class IconTextButton(IconButton):
|
class IconTextButton(IconButton):
|
||||||
def __init__(
|
def __init__(self, icon: str, label: str) -> None:
|
||||||
self, icon: str, label: str, position: Gtk.PositionType = Gtk.PositionType.RIGHT
|
super().__init__(icon, margin=5)
|
||||||
) -> None:
|
|
||||||
match position:
|
|
||||||
case Gtk.PositionType.RIGHT:
|
|
||||||
super().__init__(icon, position, margin_start=5)
|
|
||||||
case Gtk.PositionType.LEFT:
|
|
||||||
super().__init__(icon, position, margin_end=5)
|
|
||||||
case _:
|
|
||||||
raise ValueError("Unsupported position type")
|
|
||||||
self.set_label(label)
|
self.set_label(label)
|
||||||
|
|
||||||
|
|
||||||
class LargeIconTextButton(IconButton):
|
class LargeIconTextButton(IconButton):
|
||||||
def __init__(
|
def __init__(self, icon: str, label: str) -> None:
|
||||||
self, icon: str, label: str, position: Gtk.PositionType = Gtk.PositionType.RIGHT
|
super().__init__(icon)
|
||||||
) -> None:
|
|
||||||
super().__init__(icon, position)
|
|
||||||
self.set_label(label)
|
self.set_label(label)
|
||||||
self.set_image(LargeIcon(icon))
|
self.set_image(LargeIcon(icon))
|
||||||
|
|
||||||
|
|||||||
@ -36,9 +36,9 @@ class FilePicker(Gtk.FileChooserDialog):
|
|||||||
|
|
||||||
|
|
||||||
class FolderPicker(Gtk.FileChooserDialog):
|
class FolderPicker(Gtk.FileChooserDialog):
|
||||||
def __init__(self, parent: Gtk.Window, title: str) -> None:
|
def __init__(self, parent: Gtk.Window) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
title=title,
|
title=picker.title,
|
||||||
action=Gtk.FileChooserAction.SELECT_FOLDER,
|
action=Gtk.FileChooserAction.SELECT_FOLDER,
|
||||||
parent=parent,
|
parent=parent,
|
||||||
resizable=True,
|
resizable=True,
|
||||||
|
|||||||
@ -66,13 +66,11 @@ class FolderHBox(HBox):
|
|||||||
self.set_margin_bottom(5)
|
self.set_margin_bottom(5)
|
||||||
|
|
||||||
# TODO: alternate class for left-aligned icons
|
# TODO: alternate class for left-aligned icons
|
||||||
self.button = IconTextButton(FOLDER, btn_label, Gtk.PositionType.LEFT)
|
self.button = IconTextButton(FOLDER, btn_label)
|
||||||
self.button.set_halign(Gtk.Align.START)
|
self.button.set_halign(Gtk.Align.START)
|
||||||
self.button.set_image_position(Gtk.PositionType.LEFT)
|
self.button.set_image_position(Gtk.PositionType.LEFT)
|
||||||
|
|
||||||
self.scrolled_label = Gtk.ScrolledWindow(
|
self.scrolled_label = Gtk.ScrolledWindow(propagate_natural_width=True, halign=Gtk.Align.START)
|
||||||
propagate_natural_width=True, halign=Gtk.Align.START
|
|
||||||
)
|
|
||||||
self.label = Gtk.Label()
|
self.label = Gtk.Label()
|
||||||
self.scrolled_label.add(self.label)
|
self.scrolled_label.add(self.label)
|
||||||
self.extend([self.button, self.scrolled_label])
|
self.extend([self.button, self.scrolled_label])
|
||||||
@ -90,9 +88,7 @@ class FolderHBox(HBox):
|
|||||||
|
|
||||||
|
|
||||||
class ModFrame(HeadingFrame):
|
class ModFrame(HeadingFrame):
|
||||||
def __init__(
|
def __init__(self, parent: OfflineLoader, controller: "Controller", label: str) -> None:
|
||||||
self, parent: OfflineLoader, controller: "Controller", label: str
|
|
||||||
) -> None:
|
|
||||||
super().__init__(heading=label)
|
super().__init__(heading=label)
|
||||||
|
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
@ -122,12 +118,7 @@ class ModFrame(HeadingFrame):
|
|||||||
|
|
||||||
# TODO: inherit icons from warnings area in preconnect dialog
|
# TODO: inherit icons from warnings area in preconnect dialog
|
||||||
# TODO: strings
|
# TODO: strings
|
||||||
self.error_label = Gtk.Label(
|
self.error_label = Gtk.Label(label="No mods found", halign=Gtk.Align.START, margin_start=10, margin_bottom=5)
|
||||||
label="No mods found",
|
|
||||||
halign=Gtk.Align.START,
|
|
||||||
margin_start=10,
|
|
||||||
margin_bottom=5,
|
|
||||||
)
|
|
||||||
self.vbox.pack_end(self.error_label, expand=True, fill=True, padding=3)
|
self.vbox.pack_end(self.error_label, expand=True, fill=True, padding=3)
|
||||||
|
|
||||||
def set_error(self, msg: str) -> None:
|
def set_error(self, msg: str) -> None:
|
||||||
@ -208,7 +199,7 @@ class CustomModFrame(ModFrame):
|
|||||||
self.custom_hbox.hide_label()
|
self.custom_hbox.hide_label()
|
||||||
self.tree_vbox.hide()
|
self.tree_vbox.hide()
|
||||||
|
|
||||||
def present_tree(self, store: "FastInsertListStore", folder: str) -> None:
|
def present_tree(self, folder: str, store: "FastInsertListStore") -> None:
|
||||||
self.custom_hbox.set_label(folder)
|
self.custom_hbox.set_label(folder)
|
||||||
self.tree.set_model(store)
|
self.tree.set_model(store)
|
||||||
self.tree_vbox.show()
|
self.tree_vbox.show()
|
||||||
@ -223,13 +214,12 @@ class CustomModFrame(ModFrame):
|
|||||||
if len(store) == 0:
|
if len(store) == 0:
|
||||||
self.hide_tree()
|
self.hide_tree()
|
||||||
else:
|
else:
|
||||||
self.present_tree(store, folder)
|
self.present_tree()
|
||||||
|
|
||||||
def _on_custom_button_clicked(self, button: Gtk.Button) -> None:
|
def _on_custom_button_clicked(self, button: Gtk.Button) -> None:
|
||||||
local_mods = self.get_mods()
|
local_mods = self.get_mods()
|
||||||
self.parent.offline_man.get_custom_mods(local_mods)
|
self.parent.offline_man.get_custom_mods(local_mods)
|
||||||
|
|
||||||
|
|
||||||
class MissionFrame(HeadingFrame):
|
class MissionFrame(HeadingFrame):
|
||||||
def __init__(self, parent: OfflineLoader, controller: "Controller") -> None:
|
def __init__(self, parent: OfflineLoader, controller: "Controller") -> None:
|
||||||
super().__init__(heading=offline.mission_frame)
|
super().__init__(heading=offline.mission_frame)
|
||||||
@ -242,18 +232,14 @@ class MissionFrame(HeadingFrame):
|
|||||||
self.mission_button = self.mission_hbox.get_button()
|
self.mission_button = self.mission_hbox.get_button()
|
||||||
self.mission_button.connect("clicked", self._on_mission_button_clicked)
|
self.mission_button.connect("clicked", self._on_mission_button_clicked)
|
||||||
|
|
||||||
self.warning = Gtk.Label(
|
self.warning = Gtk.Label(halign=Gtk.Align.START, margin_start=10, margin_bottom=5)
|
||||||
halign=Gtk.Align.START, margin_start=10, margin_bottom=5
|
|
||||||
)
|
|
||||||
self.vbox = VBox()
|
self.vbox = VBox()
|
||||||
self.vbox.extend([self.mission_hbox, self.warning])
|
self.vbox.extend([self.mission_hbox, self.warning])
|
||||||
self.frame.add(self.vbox)
|
self.frame.add(self.vbox)
|
||||||
|
|
||||||
self.emitter.connect("custom_mission_loaded", self._on_mission_loaded)
|
self.emitter.connect("custom_mission_loaded", self._on_mission_loaded)
|
||||||
|
|
||||||
def _on_mission_loaded(
|
def _on_mission_loaded(self, emitter: "Emitter", folder: str, is_valid: bool) -> None:
|
||||||
self, emitter: "Emitter", folder: str, is_valid: bool
|
|
||||||
) -> None:
|
|
||||||
self.mission_hbox.set_label(folder)
|
self.mission_hbox.set_label(folder)
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
self.warning.show()
|
self.warning.show()
|
||||||
|
|||||||
@ -60,27 +60,6 @@ class ModTreeView(ModsMixin, ContextMixin, TreeView): # type: ignore
|
|||||||
self.connect("button-press-event", self.present_menu)
|
self.connect("button-press-event", self.present_menu)
|
||||||
self.connect("key-press-event", self.present_menu)
|
self.connect("key-press-event", self.present_menu)
|
||||||
|
|
||||||
self.connect("button-press-event", self.on_row_click)
|
|
||||||
|
|
||||||
def on_row_click(self, widget: Gtk.TreeView, event: Gdk.EventButton) -> bool:
|
|
||||||
if event.state is Gdk.ModifierType.CONTROL_MASK and event.button == 1:
|
|
||||||
path_info = widget.get_path_at_pos(int(event.x), int(event.y))
|
|
||||||
if path_info is None:
|
|
||||||
return False
|
|
||||||
path, column, cellx, celly = path_info
|
|
||||||
model = self.get_model()
|
|
||||||
if model is None:
|
|
||||||
return False
|
|
||||||
if path is None:
|
|
||||||
return False
|
|
||||||
_iter = model.get_iter(path)
|
|
||||||
if self.get_selection().iter_is_selected(_iter):
|
|
||||||
self.get_selection().unselect_iter(_iter)
|
|
||||||
else:
|
|
||||||
self.get_selection().select_iter(_iter)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_mod_man(self) -> ModManager:
|
def get_mod_man(self) -> ModManager:
|
||||||
return self.mod_man
|
return self.mod_man
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user