mirror of
https://github.com/aclist/dztui.git
synced 2026-11-01 15:42:51 +01:00
Compare commits
41
Commits
c97e34c336
...
7.0.0b21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28cd6b8c45 | ||
|
|
81e327fb35 | ||
|
|
37e247d1d9 | ||
|
|
286e3f2d80 | ||
|
|
2ef27a55d8 | ||
|
|
d0ac09ffe5 | ||
|
|
c0015c05ec | ||
|
|
682b5bb4c0 | ||
|
|
3551877192 | ||
|
|
b22aba8593 | ||
|
|
f85f1ef2a5 | ||
|
|
010d7984b6 | ||
|
|
70e1e9e740 | ||
|
|
734af7cf22 | ||
|
|
d8f4977ffe | ||
|
|
c9fd00f938 | ||
|
|
f4db1484d8 | ||
|
|
99ef9a31b9 | ||
|
|
4c392dc571 | ||
|
|
155ffea15d | ||
|
|
57d231331d | ||
|
|
d5fe3c35dc | ||
|
|
3cf547e903 | ||
|
|
bd0bfcb03d | ||
|
|
4f6c583294 | ||
|
|
5e5a6b4eaf | ||
|
|
ff59d6dc35 | ||
|
|
1c154a709d | ||
|
|
fb47564618 | ||
|
|
30e309442b | ||
|
|
3e4ed95908 | ||
|
|
93edbac5b0 | ||
|
|
c947bc2c9b | ||
|
|
06315972b1 | ||
|
|
4e36824ed7 | ||
|
|
0bb618b703 | ||
|
|
b8e11d5b59 | ||
|
|
db8b1acbc6 | ||
|
|
1e5d66c9be | ||
|
|
202620c062 | ||
|
|
673038a1ab |
No files matched your search
@@ -44,6 +44,7 @@
|
|||||||
- Play offline (load mods directly)
|
- Play offline (load mods directly)
|
||||||
- Generate Steam shortcuts and cover art
|
- Generate Steam shortcuts and cover art
|
||||||
- Warn user if background downloads are disabled
|
- Warn user if background downloads are disabled
|
||||||
|
- Dynamic copy button
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Conform to PEP 440 versioning for beta versions
|
- Conform to PEP 440 versioning for beta versions
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
- Propagate subscribed mods to Steam client
|
- Propagate subscribed mods to Steam client
|
||||||
|
|
||||||
### Dropped
|
### Dropped
|
||||||
|
- Battlemetrics API support
|
||||||
- Debug mode
|
- Debug mode
|
||||||
- Branch switching
|
- Branch switching
|
||||||
- Manual mod install mode (describe rationale)
|
- Manual mod install mode (describe rationale)
|
||||||
@@ -73,6 +75,7 @@
|
|||||||
- Center server title text on server dialogs
|
- Center server title text on server dialogs
|
||||||
- Rare segfaults when changing maps (threading)
|
- Rare segfaults when changing maps (threading)
|
||||||
- Moved dialogs out of threads
|
- Moved dialogs out of threads
|
||||||
|
- History table not being in lock-step with state file
|
||||||
|
|
||||||
### Unreleased
|
### Unreleased
|
||||||
- Load offline mods
|
- Load offline mods
|
||||||
|
|||||||
+5
-1
@@ -139,6 +139,9 @@ def get_remote_signatures(mods: list[str]) -> list[tuple[str, str, int, int]]:
|
|||||||
j = r.json()
|
j = r.json()
|
||||||
rows = j["response"]["publishedfiledetails"]
|
rows = j["response"]["publishedfiledetails"]
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
# NOTE: not a valid published file
|
||||||
|
if row["result"] == 9:
|
||||||
|
continue
|
||||||
title = str(row["title"])
|
title = str(row["title"])
|
||||||
_id = str(row["publishedfileid"])
|
_id = str(row["publishedfileid"])
|
||||||
time = int(row["time_updated"])
|
time = int(row["time_updated"])
|
||||||
@@ -205,9 +208,11 @@ def launch_offline(
|
|||||||
proc = subprocess.run([*client_args, *params])
|
proc = subprocess.run([*client_args, *params])
|
||||||
return proc.returncode
|
return proc.returncode
|
||||||
|
|
||||||
|
|
||||||
def find_loginusers(path: Path) -> Path:
|
def find_loginusers(path: Path) -> Path:
|
||||||
return path / "config" / "loginusers.vdf"
|
return path / "config" / "loginusers.vdf"
|
||||||
|
|
||||||
|
|
||||||
def find_user_id(path: Path) -> str | None:
|
def find_user_id(path: Path) -> str | None:
|
||||||
resolved_path = find_loginusers(path)
|
resolved_path = find_loginusers(path)
|
||||||
try:
|
try:
|
||||||
@@ -226,7 +231,6 @@ def find_user_id(path: Path) -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_user_id_32(path: Path) -> int:
|
def find_user_id_32(path: Path) -> int:
|
||||||
uid = find_user_id(path)
|
uid = find_user_id(path)
|
||||||
if uid is None:
|
if uid is None:
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ class Prerequisites:
|
|||||||
mods: list[list[str]]
|
mods: list[list[str]]
|
||||||
game_mode: bool
|
game_mode: bool
|
||||||
is_last_server: bool
|
is_last_server: bool
|
||||||
|
invalid_mods: list[tuple[str, str]]
|
||||||
allows_downloads: tuple[bool, str]
|
allows_downloads: tuple[bool, str]
|
||||||
|
|
||||||
|
|
||||||
@@ -191,6 +192,9 @@ class ConnectionManager:
|
|||||||
|
|
||||||
is_last = self.is_last_server()
|
is_last = self.is_last_server()
|
||||||
|
|
||||||
|
# TODO: strings
|
||||||
|
invalid_mods = [(mod[0], mod[1]) for mod in remote_mods if mod[2] == "Invalid mod"]
|
||||||
|
|
||||||
prereqs = Prerequisites(
|
prereqs = Prerequisites(
|
||||||
name=info.server_name,
|
name=info.server_name,
|
||||||
appid=info.game_id,
|
appid=info.game_id,
|
||||||
@@ -206,6 +210,7 @@ class ConnectionManager:
|
|||||||
mods=remote_mods,
|
mods=remote_mods,
|
||||||
game_mode=game_mode,
|
game_mode=game_mode,
|
||||||
is_last_server=is_last,
|
is_last_server=is_last,
|
||||||
|
invalid_mods=invalid_mods,
|
||||||
allows_downloads=allows_downloads,
|
allows_downloads=allows_downloads,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -261,6 +266,11 @@ class ConnectionManager:
|
|||||||
for mod in alpha_mods:
|
for mod in alpha_mods:
|
||||||
if any(mod[1] in tuple for tuple in missing_mods):
|
if any(mod[1] in tuple for tuple in missing_mods):
|
||||||
mod[2] = resync
|
mod[2] = resync
|
||||||
|
for mod in alpha_mods:
|
||||||
|
# NOTE: if the mod is neither synched or out of date, it is a malformed mod
|
||||||
|
if mod[2] == "":
|
||||||
|
# TODO: strings
|
||||||
|
mod[2] = "Invalid mod"
|
||||||
|
|
||||||
return alpha_mods, missing_mods
|
return alpha_mods, missing_mods
|
||||||
|
|
||||||
|
|||||||
@@ -85,8 +85,8 @@ class ProxyModelManager:
|
|||||||
if found is False:
|
if found is False:
|
||||||
self.control_model.append(history)
|
self.control_model.append(history)
|
||||||
|
|
||||||
# if len(self.control_model) == 11:
|
if len(self.control_model) == 11:
|
||||||
# del self.control_model[0]
|
del self.control_model[0]
|
||||||
|
|
||||||
self.filter(FilterMode.INITIAL, skip_cache=True)
|
self.filter(FilterMode.INITIAL, skip_cache=True)
|
||||||
|
|
||||||
|
|||||||
+20
-14
@@ -15,7 +15,7 @@ from dzgui.const.constants import (
|
|||||||
from dzgui.const.enum import FilterMode, Preferences, ServerTab
|
from dzgui.const.enum import FilterMode, Preferences, ServerTab
|
||||||
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
|
from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager
|
||||||
from dzgui.strings import dialogs
|
from dzgui.strings import dialogs
|
||||||
from dzgui.util.strings import api_warn_msg, dialog
|
from dzgui.util.strings import server_timeout, dialog
|
||||||
from dzgui.views.dialogs.generic import ExceptionDialog
|
from dzgui.views.dialogs.generic import ExceptionDialog
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
@@ -175,18 +175,25 @@ class ServerModelManager:
|
|||||||
# TODO: wrap except
|
# TODO: wrap except
|
||||||
if self.controller.get_exit_event().is_set():
|
if self.controller.get_exit_event().is_set():
|
||||||
return
|
return
|
||||||
res = future.result(timeout=API_TIMEOUT)
|
|
||||||
self.thread_man.increment_dialog()
|
self.thread_man.increment_dialog()
|
||||||
# NOTE: failing entries are culled
|
|
||||||
if res is None:
|
"""
|
||||||
# TODO: log which servers failed
|
Collects futures in linear order after completion
|
||||||
continue
|
for lock-step representation of the state file
|
||||||
servers.append(res)
|
"""
|
||||||
if len(servers) == 0:
|
for future in futures:
|
||||||
self.thread_man.set_cleanup_func(
|
res = future.result(timeout=API_TIMEOUT)
|
||||||
StoredFunc(self._cleanup_on_failure), destroy_first=True
|
# NOTE: failing entries are culled
|
||||||
)
|
if res is None:
|
||||||
return
|
# TODO: log which servers failed
|
||||||
|
# query_direct() currently does not return enough information
|
||||||
|
continue
|
||||||
|
servers.append(res)
|
||||||
|
if len(servers) == 0:
|
||||||
|
self.thread_man.set_cleanup_func(
|
||||||
|
StoredFunc(self._cleanup_on_failure), destroy_first=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
parsed = Servers.parse_json(servers)
|
parsed = Servers.parse_json(servers)
|
||||||
self._push_data(parsed)
|
self._push_data(parsed)
|
||||||
@@ -234,7 +241,6 @@ class ServerModelManager:
|
|||||||
|
|
||||||
self.first_iteration = False
|
self.first_iteration = False
|
||||||
self.emitter.emit("load_maps", store)
|
self.emitter.emit("load_maps", store)
|
||||||
# self.emitter.emit("servers_loaded_init")
|
|
||||||
|
|
||||||
# TODO: dataclass for record rows; check for other dict annotations
|
# TODO: dataclass for record rows; check for other dict annotations
|
||||||
def add_to_history(self, data: tuple[dict[str, Any], "Record"]) -> None:
|
def add_to_history(self, data: tuple[dict[str, Any], "Record"]) -> None:
|
||||||
@@ -413,7 +419,7 @@ class ServerModelManager:
|
|||||||
# TODO: distinguish signals, e.g. "servers_failed_to_load", "servers_loaded_empty"
|
# TODO: distinguish signals, e.g. "servers_failed_to_load", "servers_loaded_empty"
|
||||||
# customize statusbar and dialog accordingly
|
# customize statusbar and dialog accordingly
|
||||||
if show_dialog:
|
if show_dialog:
|
||||||
dialog = ExceptionDialog(self.controller, api_warn_msg)
|
dialog = ExceptionDialog(self.controller, server_timeout)
|
||||||
dialog.run()
|
dialog.run()
|
||||||
|
|
||||||
def _push_data(self, data: list[Any]) -> None:
|
def _push_data(self, data: list[Any]) -> None:
|
||||||
|
|||||||
@@ -100,10 +100,7 @@ steam_missing = "Local Steam installation is not set, possibly malformed config
|
|||||||
build_corrupted = (
|
build_corrupted = (
|
||||||
"Steam settings or DayZ installation may be corrupted. Try restarting Steam."
|
"Steam settings or DayZ installation may be corrupted. Try restarting Steam."
|
||||||
)
|
)
|
||||||
api_warn_msg = """No servers returned. Please wait and try again.
|
server_timeout = "Timed out when querying server(s). Check IP or try again later."
|
||||||
This usually indicates a transitory network timeout. If this issue persists, your API key or network may be malfunctioning.
|
|
||||||
"""
|
|
||||||
server_timeout = "Timed out when querying server, check IP or try again later."
|
|
||||||
server_error = (
|
server_error = (
|
||||||
"Error while contacting server, possibly timed out. Please wait and try again."
|
"Error while contacting server, possibly timed out. Please wait and try again."
|
||||||
)
|
)
|
||||||
@@ -308,7 +305,7 @@ class Options:
|
|||||||
force_eventbox: str
|
force_eventbox: str
|
||||||
self_update: str
|
self_update: str
|
||||||
no_self_update: str
|
no_self_update: str
|
||||||
api_keys: str
|
api_key: str
|
||||||
prefs: str
|
prefs: str
|
||||||
mods: str
|
mods: str
|
||||||
version: str
|
version: str
|
||||||
@@ -330,8 +327,8 @@ mod_panel = ModPanelStrings(
|
|||||||
unhighlight_stale_tooltip="Clears highlight from stale mods",
|
unhighlight_stale_tooltip="Clears highlight from stale mods",
|
||||||
highlight_stale="Highlight stale",
|
highlight_stale="Highlight stale",
|
||||||
highlight_stale_tooltip=(
|
highlight_stale_tooltip=(
|
||||||
"Shows locally-installed mods which are not used by any server "
|
"Shows locally-installed mods which are not \n"
|
||||||
"in your Saved Servers"
|
"used by any server in your Saved Servers"
|
||||||
),
|
),
|
||||||
unsub_selected="Unsubscribe selected",
|
unsub_selected="Unsubscribe selected",
|
||||||
unsub_selected_tooltip="Unsubscribes from selected mods",
|
unsub_selected_tooltip="Unsubscribes from selected mods",
|
||||||
@@ -405,7 +402,7 @@ options = Options(
|
|||||||
"In-app updates are disabled when DZGUI is "
|
"In-app updates are disabled when DZGUI is "
|
||||||
"installed globally (e.g., via package manager)."
|
"installed globally (e.g., via package manager)."
|
||||||
),
|
),
|
||||||
api_keys="API Keys",
|
api_key="API Key",
|
||||||
prefs="Preferences",
|
prefs="Preferences",
|
||||||
mods="Mods",
|
mods="Mods",
|
||||||
version="Version",
|
version="Version",
|
||||||
|
|||||||
+4
-1
@@ -54,7 +54,10 @@ class OuterWindow(Gtk.Window):
|
|||||||
MainController.register_widget("window", self)
|
MainController.register_widget("window", self)
|
||||||
|
|
||||||
# NOTE: steam deck taskbar may occlude elements
|
# NOTE: steam deck taskbar may occlude elements
|
||||||
if MainController.get_prefs().is_steam_deck is False:
|
is_deck = MainController.get_prefs().is_steam_deck
|
||||||
|
if is_deck:
|
||||||
|
self.maximize()
|
||||||
|
else:
|
||||||
self.set_titlebar(self.hb)
|
self.set_titlebar(self.hb)
|
||||||
|
|
||||||
self.connect("delete-event", self._on_delete_event)
|
self.connect("delete-event", self._on_delete_event)
|
||||||
|
|||||||
@@ -111,19 +111,22 @@ class WaitDialog(GenericDialog):
|
|||||||
|
|
||||||
self.connect("delete-event", lambda widget, event: True)
|
self.connect("delete-event", lambda widget, event: True)
|
||||||
content = self.get_content_area()
|
content = self.get_content_area()
|
||||||
spinner = Gtk.Spinner()
|
|
||||||
self.prog = Gtk.ProgressBar()
|
self.prog = Gtk.ProgressBar()
|
||||||
|
|
||||||
content.pack_end(self.cancel, NO_EXPAND, NO_FILL, 0)
|
spinner_box = Gtk.Box(
|
||||||
content.pack_end(spinner, NO_EXPAND, NO_FILL, 0)
|
orientation=Gtk.Orientation.HORIZONTAL, halign=Gtk.Align.CENTER
|
||||||
|
)
|
||||||
|
spinner = Gtk.Spinner()
|
||||||
|
spinner_box.add(spinner)
|
||||||
|
|
||||||
if self.jobs > 1:
|
if self.jobs > 1:
|
||||||
content.pack_end(self.prog, NO_EXPAND, NO_FILL, 0)
|
content.pack_start(self.prog, NO_EXPAND, NO_FILL, 0)
|
||||||
else:
|
else:
|
||||||
|
content.pack_start(spinner_box, NO_EXPAND, NO_FILL, 0)
|
||||||
spinner.start()
|
spinner.start()
|
||||||
|
|
||||||
if show_cancel is False:
|
if show_cancel is True:
|
||||||
self.connect("realize", lambda _: self.cancel.set_visible(False))
|
content.pack_start(self.cancel, NO_EXPAND, NO_FILL, 0)
|
||||||
|
|
||||||
def update_text(self, msg: str) -> None:
|
def update_text(self, msg: str) -> None:
|
||||||
self.format_secondary_text(msg)
|
self.format_secondary_text(msg)
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ class CursorMixin:
|
|||||||
end = len(model) - 1
|
end = len(model) - 1
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
cur_row = self.get_focused_row_index() # type: ignore
|
|
||||||
|
try:
|
||||||
|
cur_row = self.get_focused_row_index() # type: ignore
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
if position == CursorPosition.DOWN:
|
if position == CursorPosition.DOWN:
|
||||||
if cur_row == end:
|
if cur_row == end:
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ class Changelog(HelpMenuMixin, ScrollableMixin, Gtk.ScrolledWindow): # type: ig
|
|||||||
|
|
||||||
# TODO: should long text be wrapped?
|
# TODO: should long text be wrapped?
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5, margin_top=10)
|
self.box = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=5, margin_top=10
|
||||||
|
)
|
||||||
self.add(self.box)
|
self.add(self.box)
|
||||||
|
|
||||||
self.connect("key-press-event", self._on_keypress)
|
self.connect("key-press-event", self._on_keypress)
|
||||||
@@ -55,7 +57,6 @@ class Changelog(HelpMenuMixin, ScrollableMixin, Gtk.ScrolledWindow): # type: ig
|
|||||||
return version, date
|
return version, date
|
||||||
raise ValueError("Changelog parse error")
|
raise ValueError("Changelog parse error")
|
||||||
|
|
||||||
|
|
||||||
def _generate_nodes(self, releases: list[tuple[str, list[str]]]) -> None:
|
def _generate_nodes(self, releases: list[tuple[str, list[str]]]) -> None:
|
||||||
for header, changes in releases:
|
for header, changes in releases:
|
||||||
for ind in (0, -1):
|
for ind in (0, -1):
|
||||||
@@ -64,8 +65,12 @@ class Changelog(HelpMenuMixin, ScrollableMixin, Gtk.ScrolledWindow): # type: ig
|
|||||||
text = "\n".join(changes)
|
text = "\n".join(changes)
|
||||||
formatted = format_pango(text)
|
formatted = format_pango(text)
|
||||||
|
|
||||||
label = Gtk.Label(valign=Gtk.Align.START, margin=15, halign=Gtk.Align.START)
|
container = Gtk.Box(
|
||||||
|
valign=Gtk.Align.START, halign=Gtk.Align.START
|
||||||
|
)
|
||||||
|
label = Gtk.Label()
|
||||||
label.set_markup(formatted)
|
label.set_markup(formatted)
|
||||||
|
container.add(label)
|
||||||
|
|
||||||
version, date = self._parse_version(header)
|
version, date = self._parse_version(header)
|
||||||
button_text = f"{version} ({date})"
|
button_text = f"{version} ({date})"
|
||||||
@@ -73,9 +78,20 @@ class Changelog(HelpMenuMixin, ScrollableMixin, Gtk.ScrolledWindow): # type: ig
|
|||||||
|
|
||||||
expander = Gtk.Expander()
|
expander = Gtk.Expander()
|
||||||
expander.set_label_widget(button)
|
expander.set_label_widget(button)
|
||||||
expander.add(label)
|
expander.add(container)
|
||||||
|
expander.connect("activate", self._on_expand, container)
|
||||||
self.box.add(expander)
|
self.box.add(expander)
|
||||||
|
|
||||||
|
def _on_expand(self, expander: Gtk.Box, container: Gtk.Box) -> None:
|
||||||
|
"""
|
||||||
|
Wayland/some themes do not expect widgets to have a size allocation until expanded.
|
||||||
|
Trying to set margins a priori may cause negative allocation,
|
||||||
|
as the margins are subtracted from zero. In effect, the widget is not realized
|
||||||
|
until it is expanded for the first time.
|
||||||
|
"""
|
||||||
|
container.set_margin_start(15)
|
||||||
|
container.set_margin_top(15)
|
||||||
|
container.set_margin_bottom(15)
|
||||||
|
|
||||||
def _parse(self, changelog: str) -> list[tuple[str, list[str]]]:
|
def _parse(self, changelog: str) -> list[tuple[str, list[str]]]:
|
||||||
release = ""
|
release = ""
|
||||||
|
|||||||
@@ -103,4 +103,4 @@ class Keybindings(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
|
|||||||
return grid
|
return grid
|
||||||
|
|
||||||
def grab_content_area(self) -> None:
|
def grab_content_area(self) -> None:
|
||||||
self.box.grab_focus()
|
self.grab_focus()
|
||||||
@@ -521,3 +521,6 @@ class OfflineLoader(Gtk.Box):
|
|||||||
self.mission_frame.present_folder_changed(mission)
|
self.mission_frame.present_folder_changed(mission)
|
||||||
return
|
return
|
||||||
self.offline_man.launch(appid, mission, local_mods, custom_folder, custom_mods)
|
self.offline_man.launch(appid, mission, local_mods, custom_folder, custom_mods)
|
||||||
|
|
||||||
|
def grab_content_area(self) -> None:
|
||||||
|
self.local_frame.tree.grab_focus()
|
||||||
@@ -20,11 +20,13 @@ from dzgui.const.enum import Preferences, ServerTab
|
|||||||
from dzgui.strings import errors, options
|
from dzgui.strings import errors, options
|
||||||
from dzgui.util import strings, css, open_links
|
from dzgui.util import strings, css, open_links
|
||||||
|
|
||||||
|
from dzgui.views.components.box import VBox
|
||||||
from dzgui.views.components.labels import LeftLabel
|
from dzgui.views.components.labels import LeftLabel
|
||||||
from dzgui.views.components.buttons import WebButton
|
from dzgui.views.components.buttons import WebButton
|
||||||
from dzgui.views.components.frame import HeadingFrame
|
from dzgui.views.components.frame import HeadingFrame
|
||||||
from dzgui.views.components.misc import ClientCombo
|
from dzgui.views.components.misc import ClientCombo
|
||||||
from dzgui.views.dialogs.generic import ExceptionDialog
|
from dzgui.views.dialogs.generic import ExceptionDialog
|
||||||
|
from dzgui.views.mixins.scrollable_mixin import ScrollableMixin
|
||||||
|
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
@@ -44,10 +46,9 @@ class ShortHBox(Gtk.Box):
|
|||||||
self.pack_start(widget, NO_EXPAND, NO_FILL, NO_PADDING)
|
self.pack_start(widget, NO_EXPAND, NO_FILL, NO_PADDING)
|
||||||
|
|
||||||
|
|
||||||
class Options(Gtk.Box):
|
class Options(ScrollableMixin, Gtk.ScrolledWindow): # type: ignore
|
||||||
def __init__(self, controller: "Controller"):
|
def __init__(self, controller: "Controller"):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
orientation=Gtk.Orientation.VERTICAL,
|
|
||||||
margin_start=10,
|
margin_start=10,
|
||||||
margin_end=10,
|
margin_end=10,
|
||||||
)
|
)
|
||||||
@@ -60,11 +61,6 @@ class Options(Gtk.Box):
|
|||||||
self.DEFAULT_WIDTH = 1
|
self.DEFAULT_WIDTH = 1
|
||||||
self.DEFAULT_HEIGHT = 1
|
self.DEFAULT_HEIGHT = 1
|
||||||
|
|
||||||
label = Gtk.Label(label=strings.options.header)
|
|
||||||
label.set_halign(Gtk.Align.CENTER)
|
|
||||||
css.add_class(label, "page-heading")
|
|
||||||
self.add(label)
|
|
||||||
|
|
||||||
self.steam_entry: Gtk.Entry
|
self.steam_entry: Gtk.Entry
|
||||||
|
|
||||||
self.steam = WebButton(label=strings.options.steam_web)
|
self.steam = WebButton(label=strings.options.steam_web)
|
||||||
@@ -74,7 +70,7 @@ class Options(Gtk.Box):
|
|||||||
strings.options.enter_steam, Preferences.STEAM, True
|
strings.options.enter_steam, Preferences.STEAM, True
|
||||||
)
|
)
|
||||||
api_rows = [
|
api_rows = [
|
||||||
[LeftLabel(strings.options.steam_placeholder), self.steam_box],
|
[LeftLabel(strings.options.steam_placeholder), self.steam_box, self.steam],
|
||||||
]
|
]
|
||||||
|
|
||||||
self.player_box = self._make_submit_field(
|
self.player_box = self._make_submit_field(
|
||||||
@@ -136,17 +132,6 @@ class Options(Gtk.Box):
|
|||||||
api_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
api_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||||
api_grid = self._make_grid(api_rows)
|
api_grid = self._make_grid(api_rows)
|
||||||
api_box.add(api_grid)
|
api_box.add(api_grid)
|
||||||
api_links_box = Gtk.Box(
|
|
||||||
orientation=Gtk.Orientation.HORIZONTAL,
|
|
||||||
margin_start=5,
|
|
||||||
margin_end=5,
|
|
||||||
margin_top=5,
|
|
||||||
margin_bottom=10,
|
|
||||||
homogeneous=True,
|
|
||||||
spacing=10,
|
|
||||||
)
|
|
||||||
api_links_box.add(self.steam)
|
|
||||||
api_box.add(api_links_box)
|
|
||||||
|
|
||||||
prefs_grid = self._make_grid(pref_rows)
|
prefs_grid = self._make_grid(pref_rows)
|
||||||
version_grid = self._make_grid(version_rows)
|
version_grid = self._make_grid(version_rows)
|
||||||
@@ -167,7 +152,7 @@ class Options(Gtk.Box):
|
|||||||
grid.attach(developers, 1, 0, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
|
grid.attach(developers, 1, 0, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
|
||||||
|
|
||||||
for pair in [
|
for pair in [
|
||||||
(api_box, strings.options.api_keys),
|
(api_box, strings.options.api_key),
|
||||||
(prefs_grid, strings.options.prefs),
|
(prefs_grid, strings.options.prefs),
|
||||||
(version_grid, strings.options.version),
|
(version_grid, strings.options.version),
|
||||||
]:
|
]:
|
||||||
@@ -176,9 +161,16 @@ class Options(Gtk.Box):
|
|||||||
grid.attach(frame, col, row, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
|
grid.attach(frame, col, row, self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
self.scrollable = Gtk.ScrolledWindow(vexpand=True)
|
label = Gtk.Label(label=strings.options.header)
|
||||||
self.scrollable.add(grid)
|
label.set_halign(Gtk.Align.CENTER)
|
||||||
self.add(self.scrollable)
|
css.add_class(label, "page-heading")
|
||||||
|
|
||||||
|
box = VBox()
|
||||||
|
box.add(label)
|
||||||
|
box.add(grid)
|
||||||
|
self.add(box)
|
||||||
|
|
||||||
|
self.connect("key-press-event", self._on_keypress)
|
||||||
|
|
||||||
def get_client_name(self) -> str:
|
def get_client_name(self) -> str:
|
||||||
model = self.client_combo.get_model()
|
model = self.client_combo.get_model()
|
||||||
@@ -453,4 +445,4 @@ class Options(Gtk.Box):
|
|||||||
widget.set_visibility(state)
|
widget.set_visibility(state)
|
||||||
|
|
||||||
def grab_content_area(self) -> None:
|
def grab_content_area(self) -> None:
|
||||||
return
|
self.grab_focus()
|
||||||
@@ -239,6 +239,15 @@ class PreConnectionAssistant(Gtk.Box):
|
|||||||
)
|
)
|
||||||
|
|
||||||
"""Errors"""
|
"""Errors"""
|
||||||
|
if len(prereqs.invalid_mods) > 0:
|
||||||
|
pairs = [": ".join(sub) for sub in prereqs.invalid_mods]
|
||||||
|
lines = "\n".join(pairs)
|
||||||
|
msg = (
|
||||||
|
"Server has invalid mods that are not recognized by Steam.\n"
|
||||||
|
"Contact the server owner and include these mod IDs in your report:\n"
|
||||||
|
f"{lines}"
|
||||||
|
)
|
||||||
|
errors.append(msg)
|
||||||
if prereqs.binary_missing:
|
if prereqs.binary_missing:
|
||||||
errors.append(
|
errors.append(
|
||||||
f"Remote server is running the build '{prereqs.build}', but it is not installed.\n{resync_msg}"
|
f"Remote server is running the build '{prereqs.build}', but it is not installed.\n{resync_msg}"
|
||||||
@@ -275,10 +284,10 @@ class PreConnectionAssistant(Gtk.Box):
|
|||||||
allows_dl, running_app = prereqs.allows_downloads
|
allows_dl, running_app = prereqs.allows_downloads
|
||||||
if len(prereqs.mods) > 0 and allows_dl is False:
|
if len(prereqs.mods) > 0 and allows_dl is False:
|
||||||
msg = (
|
msg = (
|
||||||
f"The game '{running_app}' is currently running in Steam, but background downloads are not enabled.\n"
|
f"The app '{running_app}' is currently running in Steam, but background downloads are not enabled.\n"
|
||||||
"Either stop the game first, or update your global Steam settings or the game's local settings.\n"
|
"Either stop the game first, or update your global Steam settings or the game's local settings.\n"
|
||||||
"Otherwise, mods may be queued for download but never update."
|
"Otherwise, mods may be queued for download but never update."
|
||||||
)
|
)
|
||||||
warnings.append(msg)
|
warnings.append(msg)
|
||||||
|
|
||||||
self.add_warnings(warnings)
|
self.add_warnings(warnings)
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ description = "DayZ server browser and mod manager for Linux"
|
|||||||
authors = [
|
authors = [
|
||||||
{name = "aclist"}
|
{name = "aclist"}
|
||||||
]
|
]
|
||||||
version = "7.0.0b20"
|
version = "7.0.0b21"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
license-files = ["LICENSE"]
|
license-files = ["LICENSE"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
Reference in new issue
Block a user