fix: signal emission

This commit is contained in:
aclist committed 2026-02-07 18:49:06 +09:00
1 parent 045f242e09
commit 6fc348ea34
8 files changed
+89 -56

No files matched your search

+8
View File
@@ -48,10 +48,18 @@ class Emitter(GObject.GObject):
"""Triggered on map/unmap signal from NotebookPage.SERVERS. Shows/hides grid panels.""" """Triggered on map/unmap signal from NotebookPage.SERVERS. Shows/hides grid panels."""
pass pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=())
def statusbar_loaded(self) -> None:
pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=()) @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=())
def distcalc_started(self) -> None: def distcalc_started(self) -> None:
pass pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(object,))
def servers_loaded(self, tag: "ServerTab") -> None:
pass
@GObject.Signal( @GObject.Signal(
flags=GObject.SignalFlags.RUN_LAST, flags=GObject.SignalFlags.RUN_LAST,
arg_types=( arg_types=(
+38 -32
View File
@@ -2,6 +2,7 @@ import logging
import shutil import shutil
import threading import threading
import traceback import traceback
from typing import Optional
from warnings import deprecated from warnings import deprecated
from concurrent.futures import wait from concurrent.futures import wait
@@ -189,8 +190,6 @@ class Controller(GObject.GObject):
widget.handler_block_by_func(func) widget.handler_block_by_func(func)
else: else:
widget.handler_unblock_by_func(func) widget.handler_unblock_by_func(func)
# TODO: deprecated?
# self.mediator.menu.sel_blocked = state
def toggle_debug_mode(self) -> None: def toggle_debug_mode(self) -> None:
self.toggle_config(Preferences.DEBUG) self.toggle_config(Preferences.DEBUG)
@@ -377,8 +376,11 @@ class Controller(GObject.GObject):
for future in futures: for future in futures:
res = future.result() res = future.result()
if res.status != 200 or not res.parsed: if res.status != 200 or not res.parsed:
# NOTE: this is happening in a thread, need to exit first
# TODO: set internal state and pass failure flag
# TODO: pop warning dialog # TODO: pop warning dialog
self.push_data(None, FilterMode.INITIAL) print("failed to parse/timeout error")
self.push_data(None, success=False)
return return
j = res.json j = res.json
serv += j["response"]["servers"] serv += j["response"]["servers"]
@@ -391,7 +393,7 @@ class Controller(GObject.GObject):
# TODO: ping column pass # TODO: ping column pass
parsed = Servers.parse_json(serv) parsed = Servers.parse_json(serv)
self.mediator.filters.set_unique_maps(parsed) self.mediator.filters.set_unique_maps(parsed)
self.push_data(parsed, FilterMode.INITIAL) self.push_data(parsed, FilterMode.INITIAL, success=True)
#def set_unique_maps(self, records: list) -> None: #def set_unique_maps(self, records: list) -> None:
# if len(records) < 1: # if len(records) < 1:
@@ -615,10 +617,10 @@ class Controller(GObject.GObject):
import time import time
time.sleep(1) time.sleep(1)
data = ( 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", 1, 1, "a", False],
["BAR", "a", "a", "a", 1, 1, 1, "172.111.51.156:2302", 0, 0, "a", False], ["BAR", "a", "a", "a", 1, 1, 1, "172.111.51.156:2302", 1, 1, "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", 1, 1, "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", 1, 1, "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],
@@ -627,39 +629,47 @@ class Controller(GObject.GObject):
["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],
) )
self.push_data(data) self.push_data(data, FilterMode.INITIAL, success=True)
def cleanup(self) -> None: def cleanup(self) -> None:
# TODO: if success failed, throw popup
treeview = self.get_active_treeview() treeview = self.get_active_treeview()
context = self.get_active_context() context = self.get_active_context()
# TODO: rename signal # TODO: rename signal
self.mediator.statusbar.emit("server_page_changed", context) self.emitter.emit("servers_loaded", context)
# TODO: may be superfluous
treeview.grab_focus() treeview.grab_focus()
self.destroy_on_idle() self.destroy_on_idle()
if len(treeview.filter_man.get_model()) == 0: if treeview.get_filter_man().get_model() is None:
# FIXME: this may not indicate failure, just empty results
# TODO: different dialogs for server tab contexts # TODO: different dialogs for server tab contexts
# TODO: if history/favorites is empty, don't even trigger a call # TODO: if history/favorites is empty, don't even trigger a call
# TODO: add proper string for this dialog # TODO: add proper string for this dialog
dialog = ExceptionDialog(self, "API TIMEOUT") # TODO: this is a placeholder string
dialog.run() # TODO: only pop this is success was failure
if self.success is False:
dialog = ExceptionDialog(self, "API TIMEOUT")
dialog.run()
def push_data(self, data: tuple, mode: FilterMode) -> None: def push_data(self, data: tuple, mode: Optional[FilterMode], success: bool) -> None:
treeview = self.get_active_treeview() treeview = self.get_active_treeview()
# context = self.get_active_context() # context = self.get_active_context()
manager = treeview.get_filter_man() manager = treeview.get_filter_man()
# TODO:
self.success = success
if data is None: if success:
insert = None if data is None:
else: insert = None
# TODO: consolidate into filter manager else:
if mode == FilterMode.INITIAL: # TODO: consolidate into filter manager
manager.set_control(data) if mode == FilterMode.INITIAL:
# TODO: init maps here manager.set_control(data)
manager.filter(mode) # TODO: init maps here
insert = manager.get_model() manager.filter(mode)
treeview.set_model(insert) # FIXME: inserting none may cause problems if this was a simple refresh action
insert = manager.get_model()
treeview.set_model(insert)
treeview.set_loaded(True) treeview.set_loaded(True)
GLib.idle_add(self.cleanup) GLib.idle_add(self.cleanup)
@@ -775,7 +785,7 @@ class Controller(GObject.GObject):
def refilter_model(self, mode: FilterMode, label: str) -> None: def refilter_model(self, mode: FilterMode, label: str) -> None:
tv = self.get_active_treeview() tv = self.get_active_treeview()
# TODO: shouldn't empty model be None? # TODO: shouldn't empty model be None?
if len(tv.get_model()) == 0: if tv.get_model() is None:
return return
tv.set_model(None) tv.set_model(None)
self.set_callback(None, None) self.set_callback(None, None)
@@ -784,12 +794,12 @@ class Controller(GObject.GObject):
def populate_model(self) -> None: def populate_model(self) -> None:
treeview = self.get_active_treeview() treeview = self.get_active_treeview()
if treeview.is_loaded() is True: if treeview.is_loaded() is True:
self.mediator.statusbar.emit("server_page_changed", treeview.get_enum()) self.emitter.emit("servers_loaded", treeview.get_enum())
return return
func = treeview.get_query_func() func = treeview.get_query_func()
if func is None: if func is None:
self.mediator.statusbar.emit("server_page_changed", treeview.get_enum()) self.emitter.emit("servers_loaded", treeview.get_enum())
return return
# TODO: on legacy version, model clearing happens in thread # TODO: on legacy version, model clearing happens in thread
treeview.set_model(None) treeview.set_model(None)
@@ -812,10 +822,6 @@ class Controller(GObject.GObject):
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:
self.mediator.grid.conpan.set_visible(state)
# TODO: use model manager, map and keyword caches # TODO: use model manager, map and keyword caches
# TODO: model cache that hooks checkbox signal # TODO: model cache that hooks checkbox signal
def get_filters(self) -> list: def get_filters(self) -> list:
+1
View File
@@ -12,6 +12,7 @@ import dzgui.api.pefile as PeFile
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def is_dayz_installed(config: Path) -> None: def is_dayz_installed(config: Path) -> None:
try: try:
path = lookup(config, Preferences.DEFAULT) path = lookup(config, Preferences.DEFAULT)
+1 -1
View File
@@ -32,7 +32,7 @@ from dzgui.util.symlink import rebuild_symlinks
from dzgui.util.strings import init, flags from dzgui.util.strings import init, flags
from dzgui.views.base import App from dzgui.views.base import App
from dzgui.views.dialogs.early_alert import EarlyAlertDialog from dzgui.views.dialogs.early_alert import EarlyAlertDialog, EarlyIgnoreDialog
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
parser = argparse.ArgumentParser(description=flags.description) parser = argparse.ArgumentParser(description=flags.description)
+5 -12
View File
@@ -49,15 +49,10 @@ class Statusbar(Gtk.Grid):
) )
# TODO: # TODO:
self.emitter.connect("distcalc_started", lambda _: self.spinner.start()) self.emitter.connect("distcalc_started", lambda _: self.spinner.start())
self.emitter.connect("servers_loaded", self._on_servers_loaded)
self.connect("distcalc_ended", self._on_distcalc_ended) self.connect("distcalc_ended", self._on_distcalc_ended)
self.connect("server_page_changed", self._on_server_page_changed)
# TODO: move to emitter
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(object,))
def server_page_changed(self, tab: ServerTab) -> None:
pass
@GObject.Signal( @GObject.Signal(
flags=GObject.SignalFlags.RUN_LAST, flags=GObject.SignalFlags.RUN_LAST,
arg_types=( arg_types=(
@@ -97,7 +92,7 @@ class Statusbar(Gtk.Grid):
case NotebookPage.HELP: case NotebookPage.HELP:
bar = self.controller.get_help_row() bar = self.controller.get_help_row()
case NotebookPage.SERVERS: case NotebookPage.SERVERS:
self.emit("server_page_changed", ServerTab.BROWSER) # self.emit("server_page_changed", ServerTab.BROWSER)
return return
case NotebookPage.KEYS: case NotebookPage.KEYS:
bar = question_to_return bar = question_to_return
@@ -128,14 +123,12 @@ class Statusbar(Gtk.Grid):
def append_distance(self, dist: str) -> str: def append_distance(self, dist: str) -> str:
return f"{self.playercount} | Distance: {dist}" return f"{self.playercount} | Distance: {dist}"
def _on_server_page_changed(self, statusbar: Self, context: "ServerTab") -> None: def _on_servers_loaded(self, statusbar: Self, context: "ServerTab") -> None:
count = self.controller.get_player_count() count = self.controller.get_player_count()
self.playercount = count self.playercount = count
self.set_by_context(context, count) self.set_by_context(context, count)
tree = self.controller.get_active_treeview() self.emitter.emit("statusbar_loaded")
# TODO: emit page change signal on emitter, treeview catches signal and calls distcalc directly
tree.emit("distcalc_started")
def pop(self, context: Union["ServerTab", "NotebookPage"]) -> None: def pop(self, context: Union["ServerTab", "NotebookPage"]) -> None:
cid = self.statusbar.get_context_id(str(context)) cid = self.statusbar.get_context_id(str(context))
+16 -2
View File
@@ -27,10 +27,24 @@ class EarlyAlertDialog(Gtk.MessageDialog):
self.set_default_size(250, 100) self.set_default_size(250, 100)
self.connect("response", self._on_response) abort = self.get_widget_for_response(Gtk.ResponseType.OK)
abort.set_label("Exit")
self.connect("response", self._on_response)
self.run() self.run()
self.destroy() self.destroy()
def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None: def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None:
sys.exit(1) match response:
case Gtk.ResponseType.OK:
sys.exit(1)
case Gtk.ResponseType.CANCEL:
return
class EarlyIgnoreDialog(EarlyAlertDialog):
def __init__(self, string: str) -> None:
super().__init__(string=string)
# TODO: reverse order
self.add_button("Ignore", Gtk.ResponseType.CANCEL)
+15 -1
View File
@@ -62,6 +62,7 @@ class GenericDialog(Gtk.MessageDialog):
def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None: def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None:
self.destroy() self.destroy()
return response
class ConfirmationDialog(GenericDialog): class ConfirmationDialog(GenericDialog):
@@ -74,6 +75,19 @@ class ConfirmationDialog(GenericDialog):
secondary=secondary, secondary=secondary,
) )
class IgnoreDialog(GenericDialog):
def __init__(self, controller: "Controller", secondary: str):
super().__init__(
controller=controller,
text=strings.confirm,
mtype=Gtk.MessageType.QUESTION,
buttons=Gtk.ButtonsType.OK_CANCEL,
secondary=secondary,
)
cancel = self.get_widget_for_response(Gtk.ResponseType.CANCEL)
cancel.set_label("Ignore")
class NotifyDialog(GenericDialog): class NotifyDialog(GenericDialog):
def __init__(self, controller: "Controller", secondary: str): def __init__(self, controller: "Controller", secondary: str):
@@ -81,7 +95,7 @@ class NotifyDialog(GenericDialog):
controller=controller, controller=controller,
text=strings.notice, text=strings.notice,
mtype=Gtk.MessageType.INFO, mtype=Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK, buttons=Gtk.ButtonsType.OK_CANCEL,
secondary=secondary, secondary=secondary,
) )
+5 -8
View File
@@ -24,6 +24,7 @@ logger = logging.getLogger(__name__)
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
from dzgui.controllers.emitter import Emitter
class ServerTreeView(ContextMixin, TreeView): class ServerTreeView(ContextMixin, TreeView):
@@ -93,7 +94,6 @@ class ServerTreeView(ContextMixin, TreeView):
column.connect("notify::fixed-width", self._on_col_width_changed) column.connect("notify::fixed-width", self._on_col_width_changed)
self.append_column(column) self.append_column(column)
self.connect("distcalc_started", self._on_distcalc_started)
self.connect("key-press-event", self._on_server_keypress) self.connect("key-press-event", self._on_server_keypress)
self.connect("generic_row_activated", self._parent_row_activated) self.connect("generic_row_activated", self._parent_row_activated)
self.connect("generic_treesel_changed", self._parent_selection_changed) self.connect("generic_treesel_changed", self._parent_selection_changed)
@@ -103,12 +103,10 @@ class ServerTreeView(ContextMixin, TreeView):
self.connect("key-press-event", self.present_menu) self.connect("key-press-event", self.present_menu)
self.connect("button-press-event", self.present_menu) self.connect("button-press-event", self.present_menu)
self.emitter.connect("statusbar_loaded", self._on_distcalc_started)
self.emitter.connect("distcalc_started", self._on_distcalc_started)
GLib.timeout_add(QUEUE_CHECK_DELAY, self._check_result_queue) GLib.timeout_add(QUEUE_CHECK_DELAY, self._check_result_queue)
@GObject.Signal(flags=GObject.SignalFlags.RUN_FIRST, arg_types=())
def distcalc_started(self) -> None:
pass
def get_filter_man(self) -> FilteredModelManager: def get_filter_man(self) -> FilteredModelManager:
return self.filter_man return self.filter_man
@@ -165,12 +163,11 @@ class ServerTreeView(ContextMixin, 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: Self): def _on_distcalc_started(self, emitter: "Emitter"):
record = self.get_record() record = self.get_record()
if record is None: if record is None:
return return
self.emitter.emit("distcalc_started")
cache = self.controller.get_dist_cache() cache = self.controller.get_dist_cache()
if record.ip in cache: if record.ip in cache:
@@ -259,7 +256,7 @@ class ServerTreeView(ContextMixin, TreeView):
def _parent_selection_changed(self, base_class: TreeView, sel: Gtk.TreeSelection): def _parent_selection_changed(self, base_class: TreeView, sel: Gtk.TreeSelection):
self.terminate_process() self.terminate_process()
self.emit("distcalc_started") self.emitter.emit("distcalc_started")
def get_record_string(self) -> str: def get_record_string(self) -> str:
addr = self.get_value_at_index(7) addr = self.get_value_at_index(7)