mirror of
https://github.com/aclist/dztui.git
synced 2026-10-30 06:32:53 +01:00
feat: server threading WIP
This commit is contained in:
1 parent
2788abb755
commit
fdd6cefe48
11 files changed
+140
-155
No files matched your search
+1
-1
@@ -53,7 +53,7 @@ def concat_mods(mods: list[str]) -> str:
|
|||||||
|
|
||||||
# TEST: set config to name=user, use official server and no mods,
|
# TEST: set config to name=user, use official server and no mods,
|
||||||
# ensure that formatted string is identical to fixture
|
# ensure that formatted string is identical to fixture
|
||||||
def connect(addr: str, appid: int, name: str, mods: list):
|
def connect(addr: str, appid: int, name: str, mods: list) -> None:
|
||||||
# TODO: get name from configs
|
# TODO: get name from configs
|
||||||
# TODO: concat_mods(mods):
|
# TODO: concat_mods(mods):
|
||||||
# @<mod>;@<mod>;
|
# @<mod>;@<mod>;
|
||||||
|
|||||||
+101
-68
@@ -5,7 +5,7 @@ import textwrap
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, TYPE_CHECKING
|
from typing import Any, Callable, Literal, TYPE_CHECKING
|
||||||
|
|
||||||
import dzgui.api.pefile as PeFile
|
import dzgui.api.pefile as PeFile
|
||||||
import dzgui.util._json as JSON # noqa
|
import dzgui.util._json as JSON # noqa
|
||||||
@@ -246,6 +246,7 @@ class Controller:
|
|||||||
self.mediator.statusbar.set_text(text)
|
self.mediator.statusbar.set_text(text)
|
||||||
|
|
||||||
def set_statusbar_placeholder(self, text: str) -> None:
|
def set_statusbar_placeholder(self, text: str) -> None:
|
||||||
|
# TODO: use statusbar stacks instead
|
||||||
self.statusbar_placeholder = text
|
self.statusbar_placeholder = text
|
||||||
|
|
||||||
def set_statusbar_dist(self, haversine: "Haversine") -> None:
|
def set_statusbar_dist(self, haversine: "Haversine") -> None:
|
||||||
@@ -263,6 +264,7 @@ class Controller:
|
|||||||
dist = str(separated) + " km"
|
dist = str(separated) + " km"
|
||||||
text = self.statusbar_placeholder
|
text = self.statusbar_placeholder
|
||||||
self.set_statusbar(f"{text} | Distance: {dist}")
|
self.set_statusbar(f"{text} | Distance: {dist}")
|
||||||
|
self.mediator.statusbar.spinner.stop()
|
||||||
|
|
||||||
def delete_multiple_mods(self) -> None:
|
def delete_multiple_mods(self) -> None:
|
||||||
sel = self.mediator.modtreeview.get_selection()
|
sel = self.mediator.modtreeview.get_selection()
|
||||||
@@ -275,6 +277,7 @@ class Controller:
|
|||||||
self.update_mod_statusbar()
|
self.update_mod_statusbar()
|
||||||
|
|
||||||
def load_mods(self) -> None:
|
def load_mods(self) -> None:
|
||||||
|
# TODO: threading
|
||||||
model = self.model_manager.get_mod_store()
|
model = self.model_manager.get_mod_store()
|
||||||
model.clear()
|
model.clear()
|
||||||
path = self.query_config(Preferences.DEFAULT)
|
path = self.query_config(Preferences.DEFAULT)
|
||||||
@@ -310,10 +313,6 @@ class Controller:
|
|||||||
self.mediator.grid.notebook.settings.populate_settings()
|
self.mediator.grid.notebook.settings.populate_settings()
|
||||||
return
|
return
|
||||||
|
|
||||||
# NOTE: disabled for now
|
|
||||||
#def present_toast(self, text: str) -> None:
|
|
||||||
# self.mediator.window.toast.set_text_and_fade(text)
|
|
||||||
|
|
||||||
def open_keybindings(self) -> None:
|
def open_keybindings(self) -> None:
|
||||||
notebook = self.mediator.grid.notebook
|
notebook = self.mediator.grid.notebook
|
||||||
notebook.toggle_keybindings()
|
notebook.toggle_keybindings()
|
||||||
@@ -322,23 +321,6 @@ class Controller:
|
|||||||
notebook = self.mediator.grid.notebook
|
notebook = self.mediator.grid.notebook
|
||||||
notebook.focus_current()
|
notebook.focus_current()
|
||||||
|
|
||||||
# TODO: deprecated
|
|
||||||
def spawn_dialog(self, msg: str, mode: Popup) -> bool:
|
|
||||||
"""
|
|
||||||
Spawns a GenericDialog transient to the OuterWindow
|
|
||||||
"""
|
|
||||||
msg = textwrap.dedent(msg)
|
|
||||||
dialog = GenericDialog(self, msg, mode)
|
|
||||||
response = dialog.run()
|
|
||||||
dialog.destroy()
|
|
||||||
|
|
||||||
match response:
|
|
||||||
case Gtk.ResponseType.OK:
|
|
||||||
return False
|
|
||||||
case Gtk.ResponseType.CANCEL | Gtk.ResponseType.DELETE_EVENT:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def set_statusbar_by_row(self, row: "RowType") -> None:
|
def set_statusbar_by_row(self, row: "RowType") -> None:
|
||||||
self.mediator.statusbar.refresh(row)
|
self.mediator.statusbar.refresh(row)
|
||||||
|
|
||||||
@@ -366,7 +348,11 @@ class Controller:
|
|||||||
self.save_res_and_quit()
|
self.save_res_and_quit()
|
||||||
return
|
return
|
||||||
case ButtonType.OPTIONS:
|
case ButtonType.OPTIONS:
|
||||||
|
try:
|
||||||
|
# TODO: where to put config file check
|
||||||
self.mediator.grid.notebook.settings.populate_settings()
|
self.mediator.grid.notebook.settings.populate_settings()
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
case ButtonType.MODS:
|
case ButtonType.MODS:
|
||||||
self.load_mods()
|
self.load_mods()
|
||||||
case ButtonType.HELP:
|
case ButtonType.HELP:
|
||||||
@@ -374,11 +360,10 @@ class Controller:
|
|||||||
pass
|
pass
|
||||||
case ButtonType.SERVERS:
|
case ButtonType.SERVERS:
|
||||||
self.mediator.notebook.set_page_by_enum(button.opens)
|
self.mediator.notebook.set_page_by_enum(button.opens)
|
||||||
# TODO: use cache
|
|
||||||
self.update_server_status()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self.mediator.notebook.set_page_by_enum(button.opens)
|
self.mediator.notebook.set_page_by_enum(button.opens)
|
||||||
|
# TODO: set crumbs by signal
|
||||||
self.set_crumbs(button.get_label())
|
self.set_crumbs(button.get_label())
|
||||||
|
|
||||||
def open_user_workshop(self, uid: str) -> None:
|
def open_user_workshop(self, uid: str) -> None:
|
||||||
@@ -445,7 +430,9 @@ class Controller:
|
|||||||
def update_mod_statusbar(self) -> None:
|
def update_mod_statusbar(self) -> None:
|
||||||
total_mods, total_size = self.calc_mod_size()
|
total_mods, total_size = self.calc_mod_size()
|
||||||
msg = format_mods(total_size, total_mods)
|
msg = format_mods(total_size, total_mods)
|
||||||
|
# TODO: combine
|
||||||
self.mediator.statusbar.set_text(msg)
|
self.mediator.statusbar.set_text(msg)
|
||||||
|
self.mediator.statusbar.spinner.stop()
|
||||||
|
|
||||||
def calc_mod_size(self) -> tuple[int, int]:
|
def calc_mod_size(self) -> tuple[int, int]:
|
||||||
model = self.model_manager.get_mod_store()
|
model = self.model_manager.get_mod_store()
|
||||||
@@ -508,13 +495,16 @@ class Controller:
|
|||||||
log = self.prefs.paths.debug
|
log = self.prefs.paths.debug
|
||||||
store = self.model_manager.get_log_store()
|
store = self.model_manager.get_log_store()
|
||||||
store.clear()
|
store.clear()
|
||||||
|
# NOTE: this model is reloaded each time as log changes
|
||||||
# TODO: pop dialog if log is missing
|
try:
|
||||||
with open(log, "r") as f:
|
with open(log, "r") as f:
|
||||||
lines = [line.split(strings.delimiter) for line in f.read().splitlines()]
|
lines = [line.split(strings.delimiter) for line in f.read().splitlines()]
|
||||||
for record in lines:
|
for record in lines:
|
||||||
clean = redact_log(record)
|
clean = redact_log(record)
|
||||||
store.append(clean)
|
store.append(clean)
|
||||||
|
except Exception as e:
|
||||||
|
dialog = ExceptionDialog(self, str(e))
|
||||||
|
dialog.run()
|
||||||
self.open_page(NotebookPage.LOG)
|
self.open_page(NotebookPage.LOG)
|
||||||
|
|
||||||
def select_colorized(self) -> None:
|
def select_colorized(self) -> None:
|
||||||
@@ -552,20 +542,51 @@ class Controller:
|
|||||||
import time
|
import time
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
# TODO: use model managers, etc.
|
# TODO: use model managers, etc.
|
||||||
self.data = (["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False])
|
self.data = (
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
["BAR", "a", "a", "a", 1, 1, 1, "185.207.214.16:2302", 0, 0, "a", False],
|
||||||
|
)
|
||||||
# TODO: refer to prior implementation--should need to load data into model while in thread
|
# TODO: refer to prior implementation--should need to load data into model while in thread
|
||||||
self.get_func_data()
|
self.get_func_data()
|
||||||
self.destroy_on_idle()
|
self.destroy_on_idle()
|
||||||
|
|
||||||
def get_func_data(self) -> tuple:
|
def get_func_data(self) -> tuple:
|
||||||
|
def test():
|
||||||
|
# NOTE: do not insert model until main thread is idle
|
||||||
|
# TODO: grab from model manager and insert entire model
|
||||||
|
# TODO: do not start refresh button count until load finished
|
||||||
|
for row in data:
|
||||||
|
model.append(row)
|
||||||
|
treeview.set_loaded(True)
|
||||||
|
self.update_server_status()
|
||||||
|
treeview.grab_focus()
|
||||||
# TODO: use model manager
|
# TODO: use model manager
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
model = treeview.get_model()
|
model = treeview.get_model()
|
||||||
data = self.data
|
data = self.data
|
||||||
model.append(data)
|
GLib.idle_add(test)
|
||||||
treeview.set_loaded(True)
|
|
||||||
self.update_server_status()
|
|
||||||
treeview.grab_focus()
|
|
||||||
|
|
||||||
def highlight_stale(self) -> None:
|
def highlight_stale(self) -> None:
|
||||||
self.call_on_thread(self.colorize_mods)
|
self.call_on_thread(self.colorize_mods)
|
||||||
@@ -577,14 +598,11 @@ class Controller:
|
|||||||
thread = threading.Thread(target=func, args=args)
|
thread = threading.Thread(target=func, args=args)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def destroy_on_idle(self) -> None:
|
def get_callback(self) -> Callable | None:
|
||||||
self.wait_dialog.destroy()
|
return self.callback["func"]
|
||||||
# TODO: improve upon this
|
|
||||||
func = self.callback["func"]
|
def get_callback_args(self) -> Any:
|
||||||
if func is not None:
|
return self.callback["args"]
|
||||||
args = self.callback["args"]
|
|
||||||
GLib.idle_add(func, *args)
|
|
||||||
self.set_callback(None, None)
|
|
||||||
|
|
||||||
def set_callback(self, callback: Callable | None, *args) -> None:
|
def set_callback(self, callback: Callable | None, *args) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -593,6 +611,14 @@ class Controller:
|
|||||||
"""
|
"""
|
||||||
self.callback = { "func": callback, "args": args }
|
self.callback = { "func": callback, "args": args }
|
||||||
|
|
||||||
|
def destroy_on_idle(self) -> None:
|
||||||
|
self.wait_dialog.destroy()
|
||||||
|
func = self.get_callback()
|
||||||
|
if func is not None:
|
||||||
|
args = self.get_callback_args()
|
||||||
|
GLib.idle_add(func, *args)
|
||||||
|
self.set_callback(None, None)
|
||||||
|
|
||||||
def dump_diagnostics(self) -> None:
|
def dump_diagnostics(self) -> None:
|
||||||
picker = FilePicker(self.mediator.window)
|
picker = FilePicker(self.mediator.window)
|
||||||
file = picker.pick_file()
|
file = picker.pick_file()
|
||||||
@@ -600,7 +626,8 @@ class Controller:
|
|||||||
try:
|
try:
|
||||||
write_diagnostic(self.prefs.paths.config, file)
|
write_diagnostic(self.prefs.paths.config, file)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.spawn_dialog(str(e), Popup.NOTIFY)
|
dialog = ExceptionDialog(self, str(e))
|
||||||
|
dialog.run()
|
||||||
|
|
||||||
def test_api_response(self, text: str, key: Preferences) -> None:
|
def test_api_response(self, text: str, key: Preferences) -> None:
|
||||||
if key is Preferences.STEAM:
|
if key is Preferences.STEAM:
|
||||||
@@ -614,7 +641,8 @@ class Controller:
|
|||||||
self.destroy_on_idle()
|
self.destroy_on_idle()
|
||||||
else:
|
else:
|
||||||
self.destroy_on_idle()
|
self.destroy_on_idle()
|
||||||
self.spawn_dialog(strings.api_error, Popup.NOTIFY)
|
dialog = ExceptionDialog(self, strings.api_error)
|
||||||
|
dialog.run()
|
||||||
|
|
||||||
|
|
||||||
def update_api_key(self, text: str, key: Preferences) -> None:
|
def update_api_key(self, text: str, key: Preferences) -> None:
|
||||||
@@ -645,13 +673,6 @@ class Controller:
|
|||||||
logger.info(f"Using default window size {w},{h}")
|
logger.info(f"Using default window size {w},{h}")
|
||||||
window.set_default_size(w, h)
|
window.set_default_size(w, h)
|
||||||
|
|
||||||
def update_server_status(self) -> None:
|
|
||||||
treeview = self.mediator.notebook.servers.get_active_treeview()
|
|
||||||
model = treeview.get_model()
|
|
||||||
status = format_player_count(model)
|
|
||||||
self.set_statusbar_placeholder(status)
|
|
||||||
self.set_statusbar(status + "| Calculating...")
|
|
||||||
|
|
||||||
def propagate_column_width(self, col: Gtk.TreeViewColumn) -> None:
|
def propagate_column_width(self, col: Gtk.TreeViewColumn) -> None:
|
||||||
GLib.idle_add(self.mediator.servers.update_tab_widths, col)
|
GLib.idle_add(self.mediator.servers.update_tab_widths, col)
|
||||||
|
|
||||||
@@ -662,25 +683,31 @@ class Controller:
|
|||||||
return self.crumbs_cache
|
return self.crumbs_cache
|
||||||
|
|
||||||
def refresh_tree(self) -> None:
|
def refresh_tree(self) -> None:
|
||||||
treeview = self.mediator.notebook.servers.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
treeview.set_loaded(False)
|
treeview.set_loaded(False)
|
||||||
self.populate_model()
|
self.populate_model()
|
||||||
|
|
||||||
|
def update_server_status(self) -> None:
|
||||||
|
# TODO: emit signal on statusbar only if page changed
|
||||||
|
treeview = self.get_active_treeview()
|
||||||
|
model = treeview.get_model()
|
||||||
|
status = format_player_count(model)
|
||||||
|
self.set_statusbar_placeholder(status)
|
||||||
|
self.set_statusbar(status)
|
||||||
|
self.mediator.statusbar.spinner.start()
|
||||||
|
|
||||||
def populate_model(self) -> None:
|
def populate_model(self) -> None:
|
||||||
print("POPULATING MODEL")
|
|
||||||
# TODO: always use same server model, store in servertreeview class
|
# TODO: always use same server model, store in servertreeview class
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
if treeview.get_loaded() is False:
|
if treeview.get_loaded() is False:
|
||||||
new_model = self.model_manager.new_model()
|
new_model = self.model_manager.new_model()
|
||||||
# NOTE: set_query_func()
|
# NOTE: set_query_func()
|
||||||
func = treeview.get_query_func()
|
func = treeview.get_query_func()
|
||||||
print(func)
|
|
||||||
if func is not None:
|
if func is not None:
|
||||||
model = treeview.get_model()
|
model = treeview.get_model()
|
||||||
print(model)
|
|
||||||
# TODO: this may lag?
|
# TODO: this may lag?
|
||||||
model.clear()
|
model.clear()
|
||||||
self.set_callback(None, None)#self.get_func_data)
|
self.set_callback(None, None)
|
||||||
self.call_on_thread(func)
|
self.call_on_thread(func)
|
||||||
|
|
||||||
def focus_button_box(self) -> None:
|
def focus_button_box(self) -> None:
|
||||||
@@ -688,7 +715,7 @@ class Controller:
|
|||||||
|
|
||||||
def present_servers(self) -> None:
|
def present_servers(self) -> None:
|
||||||
# TODO: abstract
|
# TODO: abstract
|
||||||
self.grab_active_treeview()
|
# TODO: signal for crumbs
|
||||||
self.update_server_status()
|
self.update_server_status()
|
||||||
crumbs = self.mediator.servers.get_cached_label()
|
crumbs = self.mediator.servers.get_cached_label()
|
||||||
self.set_crumbs(crumbs)
|
self.set_crumbs(crumbs)
|
||||||
@@ -696,21 +723,26 @@ class Controller:
|
|||||||
#tree = self.get_active_treeview()
|
#tree = self.get_active_treeview()
|
||||||
#tree.emit("on_distcalc_started")
|
#tree.emit("on_distcalc_started")
|
||||||
|
|
||||||
def toggle_check(self, event: Gdk.EventKey) -> None:
|
def toggle_check(self, event: Gdk.EventKey) -> None | Literal[False]:
|
||||||
keyname = Gdk.keyval_name(event.keyval)
|
mappings = {
|
||||||
if keyname.isnumeric() and int(keyname) > 0:
|
Gdk.KEY_1: 0,
|
||||||
digit = int(keyname) - 1
|
Gdk.KEY_2: 1,
|
||||||
self.mediator.grid.right_panel.filters_vbox.toggle_check(digit)
|
Gdk.KEY_3: 2,
|
||||||
else:
|
Gdk.KEY_4: 3,
|
||||||
match event.keyval:
|
Gdk.KEY_5: 4,
|
||||||
case Gdk.KEY_0:
|
Gdk.KEY_6: 5,
|
||||||
self.mediator.grid.right_panel.filters_vbox.toggle_check(9)
|
Gdk.KEY_7: 6,
|
||||||
case Gdk.KEY_minus:
|
Gdk.KEY_8: 7,
|
||||||
self.mediator.grid.right_panel.filters_vbox.toggle_check(10)
|
Gdk.KEY_9: 8,
|
||||||
case Gdk.KEY_backslash:
|
Gdk.KEY_0: 9,
|
||||||
self.mediator.grid.right_panel.filters_vbox.toggle_check(11)
|
Gdk.KEY_minus: 10,
|
||||||
case _:
|
Gdk.KEY_backslash: 11,
|
||||||
|
}
|
||||||
|
if event.keyval not in mappings:
|
||||||
return False
|
return False
|
||||||
|
index = mappings[event.keyval]
|
||||||
|
# TODO: register filter panel widget
|
||||||
|
self.mediator.grid.right_panel.filters_vbox.toggle_check(index)
|
||||||
|
|
||||||
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
|
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
|
||||||
fav = str(self.query_config(Preferences.FAV_LBL))
|
fav = str(self.query_config(Preferences.FAV_LBL))
|
||||||
@@ -723,5 +755,6 @@ class Controller:
|
|||||||
def get_dist_cache(self) -> dict[str, "Haversine"]:
|
def get_dist_cache(self) -> dict[str, "Haversine"]:
|
||||||
return self.dist_cache
|
return self.dist_cache
|
||||||
|
|
||||||
|
# TODO: deprecated in favor of map/unmap
|
||||||
def toggle_lan_panel(self, state: bool) -> None:
|
def toggle_lan_panel(self, state: bool) -> None:
|
||||||
self.mediator.grid.conpan.set_visible(state)
|
self.mediator.grid.conpan.set_visible(state)
|
||||||
@@ -74,6 +74,7 @@ def get_coords(ips: "Path", ip: str) -> Coords:
|
|||||||
if split[2] == upper_digits[2]:
|
if split[2] == upper_digits[2]:
|
||||||
if split[3] > upper_digits[3]:
|
if split[3] > upper_digits[3]:
|
||||||
continue
|
continue
|
||||||
|
# TODO: handle last digit equals
|
||||||
|
|
||||||
if split[2] <= upper_digits[2]:
|
if split[2] <= upper_digits[2]:
|
||||||
return Coords(float(fields[-2]), float(fields[-1]))
|
return Coords(float(fields[-2]), float(fields[-1]))
|
||||||
|
|||||||
+5
-68
@@ -1,26 +1,16 @@
|
|||||||
import json
|
|
||||||
import locale
|
|
||||||
import logging
|
import logging
|
||||||
import multiprocessing
|
#import multiprocessing
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
#import threading
|
||||||
import textwrap
|
|
||||||
import threading
|
|
||||||
import typing # noqa
|
import typing # noqa
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
#from concurrent.futures import wait
|
#from concurrent.futures import wait
|
||||||
#from concurrent.futures import ThreadPoolExecutor
|
#from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from enum import Enum
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import TYPE_CHECKING, Literal
|
from typing import TYPE_CHECKING, Literal
|
||||||
|
|
||||||
from dzgui.const.enum import NotebookPage, VAdjustment
|
from dzgui.const.enum import NotebookPage
|
||||||
from dzgui.const.constants import NO_EXPAND, NO_FILL, NO_PADDING
|
|
||||||
from dzgui.const.constants import APP_NAME, APP_NAME_LOWER
|
from dzgui.const.constants import APP_NAME, APP_NAME_LOWER
|
||||||
from dzgui.controllers.mc import Controller
|
from dzgui.controllers.mc import Controller
|
||||||
from dzgui.util import css, strings
|
from dzgui.util import css, strings
|
||||||
@@ -40,21 +30,9 @@ from dzgui.views.pages.servers import ServerNotebook
|
|||||||
from dzgui.views.pages.thanks import Thanks
|
from dzgui.views.pages.thanks import Thanks
|
||||||
|
|
||||||
from dzgui.views.components.statusbar import Statusbar
|
from dzgui.views.components.statusbar import Statusbar
|
||||||
from dzgui.views.components.mod_panel import ModSelectionPanel
|
|
||||||
from dzgui.views.components.right_panel import RightPanel
|
from dzgui.views.components.right_panel import RightPanel
|
||||||
from dzgui.views.components.toast import Toast
|
|
||||||
from dzgui.views.dialogs.generic import GenericDialog
|
|
||||||
from dzgui.views.mixins.scrollable_mixin import ScrollableMixin
|
from dzgui.views.mixins.scrollable_mixin import ScrollableMixin
|
||||||
|
|
||||||
# TREES
|
|
||||||
from dzgui.views.trees.tree_menu import MenuTreeView
|
|
||||||
from dzgui.views.trees.tree_log import LogTreeView
|
|
||||||
from dzgui.views.trees.tree_mods import ModTreeView
|
|
||||||
from dzgui.views.trees.tree_servers import ServerTreeView
|
|
||||||
|
|
||||||
# TODO: not going to be in base anymore
|
|
||||||
import dzgui.util._json as JSON # noqa
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from dzgui.config.userprefs import UserPrefs
|
from dzgui.config.userprefs import UserPrefs
|
||||||
|
|
||||||
@@ -160,41 +138,6 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# #return
|
# #return
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def process_user_input(enum: RowType) -> None:
|
|
||||||
# prompt = enum.dict["prompt"]
|
|
||||||
# link_label = enum.dict["link_label"]
|
|
||||||
# cmd_string = enum.dict["label"]
|
|
||||||
#
|
|
||||||
# if enum == RowType.CONN_BY_ID:
|
|
||||||
# key = MainController.query_config(Preferences.BM)
|
|
||||||
# if len(key) == 0:
|
|
||||||
# spawn_dialog(
|
|
||||||
# "No Battlemetrics API key is set; see Options", Popup.NOTIFY
|
|
||||||
# )
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# user_entry = EntryDialog(prompt, Popup.ENTRY, link_label, button_type=enum)
|
|
||||||
# response = user_entry.get_input()
|
|
||||||
#
|
|
||||||
# if response is None:
|
|
||||||
# logger.info("User aborted entry dialog")
|
|
||||||
# return
|
|
||||||
# logger.info(f"User entered: '{response}'")
|
|
||||||
#
|
|
||||||
# if enum == RowType.CONN_BY_IP:
|
|
||||||
# connect_by_ip(enum, response)
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# if enum == RowType.CONN_BY_ID:
|
|
||||||
# connect_by_id(enum, response, key)
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# show_wait_dialog = True
|
|
||||||
# wait_msg = "Working"
|
|
||||||
# call_on_thread(
|
|
||||||
# show_wait_dialog, cmd_string, wait_msg, response, choice=enum
|
|
||||||
# )
|
|
||||||
# return
|
|
||||||
|
|
||||||
class OuterWindow(Gtk.Window):
|
class OuterWindow(Gtk.Window):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -216,6 +159,7 @@ class OuterWindow(Gtk.Window):
|
|||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
css.load_css()
|
css.load_css()
|
||||||
|
|
||||||
# TODO: first run
|
# TODO: first run
|
||||||
MainController.open_page(NotebookPage.SERVERS)
|
MainController.open_page(NotebookPage.SERVERS)
|
||||||
MainController.mediator.grid.conpan.lan.set_visible(False)
|
MainController.mediator.grid.conpan.lan.set_visible(False)
|
||||||
@@ -344,7 +288,7 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore
|
|||||||
try:
|
try:
|
||||||
w.focus_first_row()
|
w.focus_first_row()
|
||||||
w.grab_focus()
|
w.grab_focus()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
w.grab_focus()
|
w.grab_focus()
|
||||||
|
|
||||||
def get_page(self) -> Gtk.Widget | None:
|
def get_page(self) -> Gtk.Widget | None:
|
||||||
@@ -370,12 +314,6 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore
|
|||||||
status = enum.dict["statusbar"]
|
status = enum.dict["statusbar"]
|
||||||
MainController.set_crumbs(crumbs)
|
MainController.set_crumbs(crumbs)
|
||||||
|
|
||||||
#is_mods = True if enum is NotebookPage.MODS else False
|
|
||||||
#is_servers = True if enum is NotebookPage.SERVERS else False
|
|
||||||
# TODO: use signals internal to servers.py
|
|
||||||
#MainController.toggle_mod_panel(is_mods)
|
|
||||||
#MainController.toggle_server_panels(is_servers)
|
|
||||||
|
|
||||||
if status is False:
|
if status is False:
|
||||||
MainController.set_statusbar("")
|
MainController.set_statusbar("")
|
||||||
if enum is NotebookPage.SERVERS:
|
if enum is NotebookPage.SERVERS:
|
||||||
@@ -409,7 +347,6 @@ class Grid(Gtk.Grid):
|
|||||||
|
|
||||||
self.attach(self.notebook, 0, 0, MAX_COLS, SINGLE_ROW)
|
self.attach(self.notebook, 0, 0, MAX_COLS, SINGLE_ROW)
|
||||||
|
|
||||||
|
|
||||||
els = (
|
els = (
|
||||||
(self.crumb_box, self.notebook, Gtk.PositionType.TOP, MAX_COLS, SINGLE_ROW),
|
(self.crumb_box, self.notebook, Gtk.PositionType.TOP, MAX_COLS, SINGLE_ROW),
|
||||||
(self.conpan, self.notebook, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW),
|
(self.conpan, self.notebook, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW),
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ class ContextualButton(Gtk.Button):
|
|||||||
def __init__(self, label, opens, tooltip, context):
|
def __init__(self, label, opens, tooltip, context):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
label=label,
|
label=label,
|
||||||
tooltip_text=tooltip
|
tooltip_text=tooltip,
|
||||||
|
focus_on_click=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from dzgui.api.servers import validate_ip
|
|
||||||
from dzgui.util.css import add_class, remove_class
|
|
||||||
from dzgui.util.strings import connect_panel, fav_panel, lan_panel
|
from dzgui.util.strings import connect_panel, fav_panel, lan_panel
|
||||||
from dzgui.views.components.buttons import AddButton, ClipboardButton, SteamConnectButton
|
from dzgui.views.components.buttons import AddButton, ClipboardButton, SteamConnectButton
|
||||||
from dzgui.views.components.entry import IpEntry, PortEntry
|
from dzgui.views.components.entry import IpEntry, PortEntry
|
||||||
@@ -63,7 +61,8 @@ class FavPanel(Gtk.Frame):
|
|||||||
user_fav, self.fav_ip = self.controller.get_favorite()
|
user_fav, self.fav_ip = self.controller.get_favorite()
|
||||||
server_name = f"{user_fav} ({self.fav_ip})" if user_fav is not None else connect_panel.no_fav
|
server_name = f"{user_fav} ({self.fav_ip})" if user_fav is not None else connect_panel.no_fav
|
||||||
self.fav_label = Gtk.Label(label=server_name, track_visited_links=False, halign=Gtk.Align.START, hexpand=True)
|
self.fav_label = Gtk.Label(label=server_name, track_visited_links=False, halign=Gtk.Align.START, hexpand=True)
|
||||||
scrollable_label = Gtk.ScrolledWindow()
|
# NOTE: disable vscrollbar to prevent layout jumping behavior
|
||||||
|
scrollable_label = Gtk.ScrolledWindow(vscrollbar_policy=Gtk.PolicyType.NEVER)
|
||||||
scrollable_label.add(self.fav_label)
|
scrollable_label.add(self.fav_label)
|
||||||
|
|
||||||
self.fav_button = SteamConnectButton()
|
self.fav_button = SteamConnectButton()
|
||||||
|
|||||||
@@ -10,32 +10,40 @@ from gi.repository import Gtk # noqa E402
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from dzgui.controllers.mc import Controller
|
from dzgui.controllers.mc import Controller
|
||||||
|
|
||||||
class Statusbar(Gtk.Statusbar):
|
class Statusbar(Gtk.Grid):
|
||||||
def __init__(self, controller: "Controller") -> None:
|
def __init__(self, controller: "Controller") -> None:
|
||||||
super().__init__()
|
super().__init__(orientation=Gtk.Orientation.HORIZONTAL)
|
||||||
|
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.controller.register_widget("statusbar", self)
|
self.controller.register_widget("statusbar", self)
|
||||||
|
|
||||||
help_text = strings.statusbar_helptext
|
help_text = strings.statusbar_helptext
|
||||||
self.set_text(help_text)
|
|
||||||
|
self.statusbar = Gtk.Statusbar()
|
||||||
|
|
||||||
|
self.spinner = Gtk.Spinner()
|
||||||
|
self.spinner.start()
|
||||||
|
|
||||||
version = self.controller.get_prefs().version
|
version = self.controller.get_prefs().version
|
||||||
self.status_right_label = Gtk.Label(label=version)
|
self.status_right_label = Gtk.Label(label=version, hexpand=True, halign=Gtk.Align.END)
|
||||||
self.add(self.status_right_label)
|
|
||||||
|
|
||||||
|
self.attach(self.statusbar, 0, 0, 3, 1)
|
||||||
|
self.attach_next_to(self.spinner, self.statusbar, Gtk.PositionType.RIGHT, 3, 1)
|
||||||
|
self.attach_next_to(self.status_right_label, self.spinner, Gtk.PositionType.RIGHT, 3, 1)
|
||||||
|
|
||||||
|
self.set_text(help_text)
|
||||||
self.players = ""
|
self.players = ""
|
||||||
|
|
||||||
def get_text(self) -> str:
|
def get_text(self) -> str:
|
||||||
area = self.get_message_area()
|
area = self.statusbar.get_message_area()
|
||||||
label = area.get_children()[0]
|
label = area.get_children()[0]
|
||||||
return label.get_text()
|
return label.get_text()
|
||||||
|
|
||||||
def set_text(self, string: str) -> None:
|
def set_text(self, string: str) -> None:
|
||||||
if string is None:
|
if string is None:
|
||||||
return
|
return
|
||||||
meta = self.get_context_id("Statusbar")
|
meta = self.statusbar.get_context_id("Statusbar")
|
||||||
self.push(meta, string)
|
self.statusbar.push(meta, string)
|
||||||
|
|
||||||
def refresh(self, row: "RowType") -> None:
|
def refresh(self, row: "RowType") -> None:
|
||||||
if row is None:
|
if row is None:
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ from dzgui.util import strings, css, open_links
|
|||||||
from dzgui.views.components.label import LeftLabel
|
from dzgui.views.components.label import LeftLabel
|
||||||
from dzgui.views.components.eventbox import InfoEventBox
|
from dzgui.views.components.eventbox import InfoEventBox
|
||||||
from dzgui.views.components.buttons import WebButton
|
from dzgui.views.components.buttons import WebButton
|
||||||
|
from dzgui.views.dialogs.generic import ExceptionDialog
|
||||||
from dzgui.views.dialogs.link_dialog import WorkshopLinkDialog
|
from dzgui.views.dialogs.link_dialog import WorkshopLinkDialog
|
||||||
|
|
||||||
from dzgui.const.enum import Preferences, Popup
|
from dzgui.const.enum import Preferences
|
||||||
from dzgui.const.endpoints import STEAM_API_SETUP, BM_API_SETUP
|
from dzgui.const.endpoints import STEAM_API_SETUP, BM_API_SETUP
|
||||||
from dzgui.const.constants import (
|
from dzgui.const.constants import (
|
||||||
APPID_DAYZ,
|
APPID_DAYZ,
|
||||||
@@ -427,7 +428,10 @@ class Options(Gtk.Box):
|
|||||||
prefs = self.controller.get_prefs()
|
prefs = self.controller.get_prefs()
|
||||||
if prefs.paths.config.is_file() is False:
|
if prefs.paths.config.is_file() is False:
|
||||||
# NOTE: in case file got deleted locally
|
# NOTE: in case file got deleted locally
|
||||||
self.controller.spawn_dialog(strings.config_not_found, Popup.QUIT)
|
dialog = ExceptionDialog(self.controller, strings.config_not_found)
|
||||||
|
dialog.run()
|
||||||
|
raise Exception
|
||||||
|
# FIXME: return to main menu
|
||||||
return
|
return
|
||||||
|
|
||||||
config = query.get_config(prefs.paths.config)
|
config = query.get_config(prefs.paths.config)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class ServerNotebook(Gtk.ScrolledWindow):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
# TODO: set model on init of servertreeview
|
# TODO: set model only on init of servertreeview
|
||||||
# TODO: set model manager for each tab on init
|
# TODO: set model manager for each tab on init
|
||||||
# TODO: add set_ and get_model_manager() methods
|
# TODO: add set_ and get_model_manager() methods
|
||||||
tree.set_model(store)
|
tree.set_model(store)
|
||||||
|
|||||||
@@ -88,8 +88,10 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
|
|||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
if is_navkey(event.keyval):
|
if is_navkey(event.keyval):
|
||||||
# TODO: investigate this
|
# FIXME: will fail on mod list
|
||||||
tv = self.controller.get_active_treeview()
|
tv = self.controller.get_active_treeview()
|
||||||
|
if len(tv.get_model()) < 1:
|
||||||
|
return
|
||||||
if self.sel_blocked is False:
|
if self.sel_blocked is False:
|
||||||
self.controller.suppress_signal(
|
self.controller.suppress_signal(
|
||||||
tv,
|
tv,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
@@ -145,7 +146,6 @@ class ServerTreeView(TreeView):
|
|||||||
self.controller.mediator.grid.conpan.lan.set_visible(True)
|
self.controller.mediator.grid.conpan.lan.set_visible(True)
|
||||||
|
|
||||||
def _on_unmap(self, a) -> None:
|
def _on_unmap(self, a) -> None:
|
||||||
# TODO: could be done just when changing pages?
|
|
||||||
if self.get_enum() is ServerTab.LAN:
|
if self.get_enum() is ServerTab.LAN:
|
||||||
self.controller.mediator.grid.conpan.lan.set_visible(False)
|
self.controller.mediator.grid.conpan.lan.set_visible(False)
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ class ServerTreeView(TreeView):
|
|||||||
if self.current_proc and self.current_proc.is_alive():
|
if self.current_proc and self.current_proc.is_alive():
|
||||||
self.current_proc.terminate()
|
self.current_proc.terminate()
|
||||||
|
|
||||||
def _on_distcalc_started(self, treeview):
|
def _on_distcalc_started(self, treeview: Self):
|
||||||
record = self.get_record()
|
record = self.get_record()
|
||||||
if record is None:
|
if record is None:
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in new issue
Block a user