fix: clean up signal emission

This commit is contained in:
aclist committed 2026-02-11 20:44:07 +09:00
1 parent 4946705a8b
commit 25f19cfd10
15 files changed
+116 -72

No files matched your search

+4 -1
View File
@@ -2,7 +2,9 @@ from dataclasses import dataclass
from dzgui.config.xdg import Xdg from dzgui.config.xdg import Xdg
from dzgui.util.ip import Coords from dzgui.util.ip import Coords
@dataclass(slots=True, frozen=True)
# NOTE: mutable dataclass, 'use_miles' key changes on demand
@dataclass(slots=True)
class UserPrefs: class UserPrefs:
is_steam_deck: bool is_steam_deck: bool
is_game_mode: bool is_game_mode: bool
@@ -11,3 +13,4 @@ class UserPrefs:
version: str version: str
allow_updates: bool allow_updates: bool
paths: Xdg paths: Xdg
use_miles: bool
+1
View File
@@ -34,6 +34,7 @@ CLIPBOARD = "edit-copy-symbolic"
LIST_ADD = "list-add-symbolic" LIST_ADD = "list-add-symbolic"
STEAM_ICON = "steam_tray_mono" STEAM_ICON = "steam_tray_mono"
VIEW_CONCEAL = "view-conceal-symbolic" VIEW_CONCEAL = "view-conceal-symbolic"
SEARCH_ICON = "system-search-symbolic"
VIEW_REVEAL = "view-reveal-symbolic" VIEW_REVEAL = "view-reveal-symbolic"
INPUT_KEYBOARD = "input-keyboard-symbolic" INPUT_KEYBOARD = "input-keyboard-symbolic"
HELP_BUBBLE = "help-about-symbolic" HELP_BUBBLE = "help-about-symbolic"
+9
View File
@@ -15,6 +15,7 @@ class Emitter(GObject.GObject):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
# TODO: rename request verbs
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=()) @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=())
def request_keyword_focus(self) -> None: def request_keyword_focus(self) -> None:
"""User invoked Ctrl-f keybinding from ServerTreeView""" """User invoked Ctrl-f keybinding from ServerTreeView"""
@@ -57,6 +58,14 @@ class Emitter(GObject.GObject):
def distcalc_started(self) -> None: def distcalc_started(self) -> None:
pass pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
def mod_page_toggled(self, state: bool) -> None:
pass
@GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(bool,))
def lan_tab_toggled(self, state: bool) -> None:
pass
@GObject.Signal( @GObject.Signal(
flags=GObject.SignalFlags.RUN_LAST, flags=GObject.SignalFlags.RUN_LAST,
arg_types=( arg_types=(
+8 -12
View File
@@ -104,7 +104,7 @@ class Controller(GObject.GObject):
def call_on_thread(func: Callable) -> Callable: def call_on_thread(func: Callable) -> Callable:
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
self = args[0] self = args[0]
self.wait_dialog = WaitDialog(self, strings.dialog.fetching) self.wait_dialog = WaitDialog(self, strings.dialog.filtering)
self.wait_dialog.show_all() self.wait_dialog.show_all()
thread = threading.Thread(target=func, args=args) thread = threading.Thread(target=func, args=args)
thread.start() thread.start()
@@ -253,7 +253,6 @@ class Controller(GObject.GObject):
def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None: def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None:
context = self.get_active_context() context = self.get_active_context()
print(context)
page = self.mediator.notebook.get_page_by_enum() page = self.mediator.notebook.get_page_by_enum()
""" """
NOTE: prevents race condition when server tab changed, NOTE: prevents race condition when server tab changed,
@@ -261,7 +260,6 @@ class Controller(GObject.GObject):
""" """
if page != NotebookPage.SERVERS: if page != NotebookPage.SERVERS:
self.emitter.emit("distcalc_ended" , None, context) self.emitter.emit("distcalc_ended" , None, context)
#self.mediator.statusbar.spinner.stop()
return return
if enum != context: if enum != context:
self.emitter.emit("distcalc_ended" , None, context) self.emitter.emit("distcalc_ended" , None, context)
@@ -272,8 +270,7 @@ class Controller(GObject.GObject):
if haversine is None: if haversine is None:
dist = "Unknown" dist = "Unknown"
else: else:
# FIXME: always opens file; cache distance pref at boot and when it changes if self.prefs.use_miles:
if self.query_config(Preferences.DIST) is True:
raw = round(haversine.as_miles()) raw = round(haversine.as_miles())
separated = number(raw) separated = number(raw)
dist = str(separated) + " mi" dist = str(separated) + " mi"
@@ -310,6 +307,9 @@ class Controller(GObject.GObject):
config = self.prefs.paths.config config = self.prefs.paths.config
try: try:
update.toggle_config(config, context) update.toggle_config(config, context)
# NOTE: 'use_miles' key is updated dynamically for statusbar unit
if context == Preferences.DIST:
self.prefs.use_miles = not self.prefs.use_miles
except Exception as e: except Exception as e:
logger.critical(e) logger.critical(e)
trace = traceback.format_exc() trace = traceback.format_exc()
@@ -337,9 +337,6 @@ class Controller(GObject.GObject):
notebook = self.mediator.grid.notebook notebook = self.mediator.grid.notebook
notebook.focus_current() notebook.focus_current()
def toggle_mod_panel(self, state: bool) -> None:
self.mediator.grid.right_panel.sel_panel.set_visible(state)
def show_developers_page(self) -> None: def show_developers_page(self) -> None:
self.open_page(NotebookPage.DEVELOPERS) self.open_page(NotebookPage.DEVELOPERS)
@@ -631,11 +628,10 @@ class Controller(GObject.GObject):
treeview.grab_focus() treeview.grab_focus()
self.destroy_on_idle() self.destroy_on_idle()
if self.success is False: if self.success is False:
# TODO: different dialogs for server tab contexts, e.g. lan timeout
# TODO: if history/favorites is empty, don't even trigger a call to dump data
dialog = ExceptionDialog(self, "API TIMEOUT") dialog = ExceptionDialog(self, "API TIMEOUT")
dialog.run() dialog.run()
#if treeview.get_filter_man().get_model() is None:
# TODO: different dialogs for server tab contexts, e.g. lan timeout
# TODO: if history/favorites is empty, don't even trigger a call
def push_data(self, data: tuple, mode: Optional[FilterMode], success: bool) -> None: def push_data(self, data: tuple, mode: Optional[FilterMode], success: bool) -> None:
@@ -772,7 +768,7 @@ class Controller(GObject.GObject):
# FIXME: optional label/map/keyword parameter # FIXME: optional label/map/keyword parameter
def refilter_model(self, mode: FilterMode, label: Optional[str] = None) -> None: def refilter_model(self, mode: FilterMode, label: Optional[str] = None) -> None:
tv = self.get_active_treeview() tv = self.get_active_treeview()
if tv.get_model() is None: if tv.filter_man.get_control() is None:
return return
tv.set_model(None) tv.set_model(None)
# TODO: deprecated in this context? # TODO: deprecated in this context?
+4
View File
@@ -7,7 +7,9 @@ import warnings
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from dzgui.api.mods import remove_stale_signatures from dzgui.api.mods import remove_stale_signatures
from dzgui.const.enum import Preferences
from dzgui.config.ipdb import get_ipdb from dzgui.config.ipdb import get_ipdb
from dzgui.config.query import lookup
from dzgui.config.userprefs import UserPrefs from dzgui.config.userprefs import UserPrefs
from dzgui.config.xdg import get_xdg_paths, parse_filepaths from dzgui.config.xdg import get_xdg_paths, parse_filepaths
from dzgui.const.update import ALLOW_UPDATES from dzgui.const.update import ALLOW_UPDATES
@@ -126,6 +128,7 @@ def main() -> None:
# TODO: handle IP DB failure and use coords fallback # TODO: handle IP DB failure and use coords fallback
get_ipdb(XDG.ips) get_ipdb(XDG.ips)
local_coords = get_local_coords(XDG.ips) local_coords = get_local_coords(XDG.ips)
use_miles = lookup(XDG.config, Preferences.DIST)
prefs = UserPrefs( prefs = UserPrefs(
_is_steam_deck, _is_steam_deck,
@@ -135,6 +138,7 @@ def main() -> None:
version, version,
allow, allow,
XDG, XDG,
use_miles,
) )
print("All OK. Loading UI...") print("All OK. Loading UI...")
App(prefs) App(prefs)
+44 -11
View File
@@ -1,20 +1,26 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
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
from dzgui.views.components.labels import BoldLabel from dzgui.views.components.labels import BoldLabel
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk # noqa E402 from gi.repository import Gtk, Gdk # noqa E402
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller, Emitter
COLS = 1 COLS = 1
ROWS = 1 ROWS = 1
class LanPanel(Gtk.Frame): class LanPanel(Gtk.Frame):
def __init__(self, controller: "Controller") -> None: def __init__(self, controller: "Controller") -> None:
super().__init__(margin_top=10, margin_bottom=5) super().__init__(margin_top=10, margin_bottom=5)
@@ -27,20 +33,26 @@ class LanPanel(Gtk.Frame):
self.set_label_widget(label) self.set_label_widget(label)
radio1 = Gtk.RadioButton.new_with_label(None, lan_panel.default_button) radio1 = Gtk.RadioButton.new_with_label(None, lan_panel.default_button)
radio2 = Gtk.RadioButton.new_with_label_from_widget(radio1, lan_panel.custom_button) radio2 = Gtk.RadioButton.new_with_label_from_widget(
radio1, lan_panel.custom_button
)
self.entry = PortEntry(controller) self.entry = PortEntry(controller)
self.scan = Gtk.Button(label=lan_panel.scan_button) self.scan = Gtk.Button(label=lan_panel.scan_button)
self.entry.connect("string_validated", self._on_port_validated) self.entry.connect("string_validated", self._on_port_validated)
self.emitter.connect("request_lan_entry_focus", lambda _: self.entry.grab_focus()) self.emitter.connect(
"request_lan_entry_focus", lambda _: self.entry.grab_focus()
)
radio1.connect("toggled", self._on_radio_toggled) radio1.connect("toggled", self._on_radio_toggled)
self.grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5) self.grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5)
self.grid.attach(radio1, 0, 0, COLS, ROWS) self.grid.attach(radio1, 0, 0, COLS, ROWS)
self.grid.attach_next_to(radio2, radio1, Gtk.PositionType.RIGHT, COLS, ROWS) self.grid.attach_next_to(radio2, radio1, Gtk.PositionType.RIGHT, COLS, ROWS)
self.grid.attach_next_to(self.entry, radio2, Gtk.PositionType.RIGHT, COLS, ROWS) self.grid.attach_next_to(self.entry, radio2, Gtk.PositionType.RIGHT, COLS, ROWS)
self.grid.attach_next_to(self.scan, self.entry, Gtk.PositionType.RIGHT, COLS, ROWS) self.grid.attach_next_to(
self.scan, self.entry, Gtk.PositionType.RIGHT, COLS, ROWS
)
self.add(self.grid) self.add(self.grid)
@@ -52,6 +64,7 @@ class LanPanel(Gtk.Frame):
def _on_port_validated(self, entry: Gtk.Entry, state: bool) -> None: def _on_port_validated(self, entry: Gtk.Entry, state: bool) -> None:
self.scan.set_sensitive(state) self.scan.set_sensitive(state)
class FavPanel(Gtk.Frame): class FavPanel(Gtk.Frame):
def __init__(self, controller: "Controller") -> None: def __init__(self, controller: "Controller") -> None:
super().__init__(margin_top=10, margin_bottom=5) super().__init__(margin_top=10, margin_bottom=5)
@@ -63,8 +76,17 @@ class FavPanel(Gtk.Frame):
# TODO: improve upon this, cache fav ip when changed globally # TODO: improve upon this, cache fav ip when changed globally
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 = (
self.fav_label = Gtk.Label(label=server_name, track_visited_links=False, halign=Gtk.Align.START, hexpand=True) 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,
)
# NOTE: disable vscrollbar to prevent layout jumping behavior # NOTE: disable vscrollbar to prevent layout jumping behavior
scrollable_label = Gtk.ScrolledWindow(vscrollbar_policy=Gtk.PolicyType.NEVER) scrollable_label = Gtk.ScrolledWindow(vscrollbar_policy=Gtk.PolicyType.NEVER)
scrollable_label.add(self.fav_label) scrollable_label.add(self.fav_label)
@@ -108,12 +130,18 @@ class AddPanel(Gtk.Frame):
self.entry = IpEntry(controller) self.entry = IpEntry(controller)
self.entry.connect("string_validated", self._on_ip_validated) self.entry.connect("string_validated", self._on_ip_validated)
self.emitter.connect("request_ip_entry_focus", lambda _: self.entry.grab_focus()) self.emitter.connect(
"request_ip_entry_focus", lambda _: self.entry.grab_focus()
)
self.grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5) self.grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5)
self.grid.attach(self.entry, 0, 0, COLS, ROWS) self.grid.attach(self.entry, 0, 0, COLS, ROWS)
self.grid.attach_next_to(self.add_server, self.entry, Gtk.PositionType.RIGHT, COLS, ROWS) self.grid.attach_next_to(
self.grid.attach_next_to(self.conn_server, self.add_server, Gtk.PositionType.RIGHT, COLS, ROWS) self.add_server, self.entry, Gtk.PositionType.RIGHT, COLS, ROWS
)
self.grid.attach_next_to(
self.conn_server, self.add_server, Gtk.PositionType.RIGHT, COLS, ROWS
)
self.add(self.grid) self.add(self.grid)
@@ -127,6 +155,8 @@ class ConnectPanel(Gtk.Box):
super().__init__(orientation=Gtk.Orientation.VERTICAL) super().__init__(orientation=Gtk.Orientation.VERTICAL)
self.controller = controller self.controller = controller
emitter = self.controller.get_emitter()
emitter.connect("lan_tab_toggled", self._on_lan_tab_toggled)
self.lan = LanPanel(controller) self.lan = LanPanel(controller)
self.fav = FavPanel(controller) self.fav = FavPanel(controller)
@@ -134,3 +164,6 @@ class ConnectPanel(Gtk.Box):
for el in self.lan, self.fav, self.add_panel: for el in self.lan, self.fav, self.add_panel:
self.add(el) self.add(el)
def _on_lan_tab_toggled(self, emitter: "Emitter", state: bool) -> None:
self.lan.set_visible(state)
+13 -9
View File
@@ -2,7 +2,7 @@ import logging
from typing import Literal, TYPE_CHECKING from typing import Literal, TYPE_CHECKING
from dzgui.const.enum import FilterMode from dzgui.const.enum import FilterMode
from dzgui.const.constants import NO_EXPAND, NO_FILL, NO_PADDING from dzgui.const.constants import NO_EXPAND, NO_FILL, NO_PADDING, SEARCH_ICON
from dzgui.util import strings from dzgui.util import strings
from dzgui.util.margins import set_surrounding_margins from dzgui.util.margins import set_surrounding_margins
from dzgui.views.components.labels import BoldLabel from dzgui.views.components.labels import BoldLabel
@@ -42,7 +42,7 @@ class FilterPanel(Gtk.Box):
self.controller.register_widget("filters", self) self.controller.register_widget("filters", self)
self.emitter = self.controller.get_emitter() self.emitter = self.controller.get_emitter()
map_store = self.controller.get_map_store() self.map_store = self.controller.get_map_store()
self.checks = [] self.checks = []
self.maps_hr = [] self.maps_hr = []
@@ -86,8 +86,13 @@ class FilterPanel(Gtk.Box):
self.keyword_entry = Gtk.Entry() self.keyword_entry = Gtk.Entry()
# TODO :strings # TODO :strings
self.keyword_entry.set_placeholder_text("Filter by keyword") self.keyword_entry.set_placeholder_text("Filter by keyword")
self.keyword_entry.connect("activate", self._on_keyword_enter) self.keyword_entry.connect("activate", self._on_keyword_activated)
self.keyword_entry.connect("key-press-event", self._on_keyword_keypress) self.keyword_entry.connect("key-press-event", self._on_keyword_keypress)
self.keyword_entry.set_icon_from_icon_name(
Gtk.EntryIconPosition.SECONDARY, SEARCH_ICON
)
self.keyword_entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, False)
# entry.connect("icon-release", self._on_icon_release)
self.emitter.connect( self.emitter.connect(
"request_keyword_focus", lambda _: self.keyword_entry.grab_focus() "request_keyword_focus", lambda _: self.keyword_entry.grab_focus()
@@ -103,7 +108,7 @@ class FilterPanel(Gtk.Box):
completion.connect("match_selected", self._on_completer_match) completion.connect("match_selected", self._on_completer_match)
renderer_text = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END) renderer_text = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END)
self.maps_combo = Gtk.ComboBox.new_with_model_and_entry(map_store) self.maps_combo = Gtk.ComboBox.new_with_model_and_entry(self.map_store)
self.maps_combo.set_entry_text_column(0) self.maps_combo.set_entry_text_column(0)
self.maps_entry = self.maps_combo.get_child() self.maps_entry = self.maps_combo.get_child()
@@ -166,7 +171,7 @@ class FilterPanel(Gtk.Box):
If entry is exact match for value in liststore, If entry is exact match for value in liststore,
trigger map change function trigger map change function
""" """
for i in enumerate(map_store): # type: ignore for i in enumerate(self.map_store): # type: ignore
if text == i[1][0]: if text == i[1][0]:
self.maps_combo.set_active(i[0]) self.maps_combo.set_active(i[0])
self._on_map_changed(self.maps_combo) self._on_map_changed(self.maps_combo)
@@ -174,7 +179,7 @@ class FilterPanel(Gtk.Box):
GLib.idle_add(self.restore_focus_to_treeview) GLib.idle_add(self.restore_focus_to_treeview)
""" """
This is a workaround for widget.grab_remove() This is a workaround for widget.grab_remove()
Sets cursor position to SOL when unfocusing Sets cursor position to start of line when unfocusing
""" """
text = self.maps_entry.get_text() text = self.maps_entry.get_text()
self.maps_entry.set_position(len(text)) self.maps_entry.set_position(len(text))
@@ -192,9 +197,8 @@ class FilterPanel(Gtk.Box):
def _on_map_completion(self, entry, editable): def _on_map_completion(self, entry, editable):
text = entry.get_text() text = entry.get_text()
completion = entry.get_completion() completion = entry.get_completion()
map_store = self.controller.get_map_store()
if len(text) >= completion.get_minimum_key_length(): if len(text) >= completion.get_minimum_key_length():
completion.set_model(map_store) completion.set_model(self.map_store)
def restore_focus_to_treeview(self) -> Literal[False]: def restore_focus_to_treeview(self) -> Literal[False]:
view = self.controller.get_active_treeview() view = self.controller.get_active_treeview()
@@ -232,7 +236,7 @@ class FilterPanel(Gtk.Box):
def get_keyword_filter(self) -> str: def get_keyword_filter(self) -> str:
return self.keyword_filter return self.keyword_filter
def _on_keyword_enter(self, entry: Gtk.Entry) -> None: def _on_keyword_activated(self, entry: Gtk.Entry) -> None:
# TODO: # TODO:
self.controller.mediator.window.set_keep_below(False) self.controller.mediator.window.set_keep_below(False)
keyword = entry.get_text().lower() keyword = entry.get_text().lower()
+6 -1
View File
@@ -11,7 +11,7 @@ gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa E402 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, Emitter
class EnumeratedModButton(Gtk.Button): class EnumeratedModButton(Gtk.Button):
@@ -28,6 +28,8 @@ class ModSelectionPanel(Gtk.Box):
super().__init__(spacing=6, orientation=Gtk.Orientation.VERTICAL, margin_top=15) super().__init__(spacing=6, orientation=Gtk.Orientation.VERTICAL, margin_top=15)
self.controller = controller self.controller = controller
emitter = controller.get_emitter()
emitter.connect("mod_page_toggled", self._on_mod_page_toggled)
header = BoldLabel(mod_panel.header) header = BoldLabel(mod_panel.header)
@@ -58,6 +60,9 @@ class ModSelectionPanel(Gtk.Box):
for el in header, self.main_panel, self.stale_panel: for el in header, self.main_panel, self.stale_panel:
self.pack_start(el, NO_EXPAND, FILL, NO_PADDING) self.pack_start(el, NO_EXPAND, FILL, NO_PADDING)
def _on_mod_page_toggled(self, emitter: "Emitter", state: bool) -> None:
self.set_visible(state)
def after_colorize(self) -> None: def after_colorize(self) -> None:
self.controller.unselect_all_mods() self.controller.unselect_all_mods()
self.swap_sensitive(True) self.swap_sensitive(True)
+1
View File
@@ -29,6 +29,7 @@ class RightPanel(Gtk.Box):
self.button_vbox = ButtonBox(controller) self.button_vbox = ButtonBox(controller)
self.filters_vbox = FilterPanel(controller) self.filters_vbox = FilterPanel(controller)
self.sel_panel = ModSelectionPanel(controller) self.sel_panel = ModSelectionPanel(controller)
emitter.connect("servers_loaded", self.toggle_refresh_button) emitter.connect("servers_loaded", self.toggle_refresh_button)
+2 -16
View File
@@ -49,25 +49,10 @@ class Statusbar(Gtk.Grid):
"switch-page", self._on_notebook_page_changed "switch-page", self._on_notebook_page_changed
) )
# TODO:
self.emitter.connect("distcalc_started", self._on_distcalc_started) self.emitter.connect("distcalc_started", self._on_distcalc_started)
self.emitter.connect("distcalc_ended", self._on_distcalc_ended) self.emitter.connect("distcalc_ended", self._on_distcalc_ended)
self.emitter.connect("servers_loaded", self._on_servers_loaded) self.emitter.connect("servers_loaded", self._on_servers_loaded)
# self.connect("distcalc_ended", self._on_distcalc_ended)
# @GObject.Signal(
# flags=GObject.SignalFlags.RUN_LAST,
# arg_types=(
# object,
# object,
# ),
# )
# def distcalc_ended(
# self, dist: Union[str, None], context: Union["ServerTab", NotebookPage]
# ) -> None:
# pass
def _on_notebook_page_changed( def _on_notebook_page_changed(
self, notebook: "Notebook", child: Gtk.Widget, index: int self, notebook: "Notebook", child: Gtk.Widget, index: int
) -> None: ) -> None:
@@ -95,7 +80,8 @@ 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) context = self.controller.get_active_context()
self.emitter.emit("servers_loaded", context)
return return
case NotebookPage.KEYS: case NotebookPage.KEYS:
bar = question_to_return bar = question_to_return
+1 -1
View File
@@ -5,6 +5,7 @@ from dzgui.const.enum import NotebookPage
from dzgui.util.css import add_class from dzgui.util.css import add_class
from dzgui.util.strings import developers from dzgui.util.strings import developers
from dzgui.views.components.labels import BoldLabel from dzgui.views.components.labels import BoldLabel
from dzgui.views.trees.tree_base import TreeView
import gi # noqa E402 import gi # noqa E402
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "3.0")
@@ -61,7 +62,6 @@ class Developers(Gtk.ScrolledWindow):
self.controller.open_page(NotebookPage.OPTIONS) self.controller.open_page(NotebookPage.OPTIONS)
def _make_tree(self, prefs: Union["Xdg", "UserPrefs"]) -> Gtk.TreeView: def _make_tree(self, prefs: Union["Xdg", "UserPrefs"]) -> Gtk.TreeView:
from dzgui.views.trees.tree_base import TreeView
view = TreeView(self.controller) view = TreeView(self.controller)
renderer = Gtk.CellRendererText() renderer = Gtk.CellRendererText()
for i, col in enumerate(developers.columns): for i, col in enumerate(developers.columns):
+3 -3
View File
@@ -15,6 +15,7 @@ class Mods(Gtk.ScrolledWindow):
super().__init__() super().__init__()
self.controller = controller self.controller = controller
self.emitter = controller.get_emitter()
self.tree = ModTreeView(controller) self.tree = ModTreeView(controller)
self.add(self.tree) self.add(self.tree)
@@ -23,12 +24,11 @@ class Mods(Gtk.ScrolledWindow):
self.connect("map", self._on_map) self.connect("map", self._on_map)
self.connect("unmap", self._on_unmap) self.connect("unmap", self._on_unmap)
# TODO: use emitter
def _on_unmap(self, widget: Self) -> None: def _on_unmap(self, widget: Self) -> None:
self.controller.toggle_mod_panel(False) self.emitter.emit("mod_page_toggled", False)
def _on_map(self, widget: Self) -> None: def _on_map(self, widget: Self) -> None:
self.controller.toggle_mod_panel(True) self.emitter.emit("mod_page_toggled", True)
def grab_content_area(self) -> None: def grab_content_area(self) -> None:
self.tree.grab_focus() self.tree.grab_focus()
+4 -2
View File
@@ -59,8 +59,10 @@ class ServerNotebook(Gtk.ScrolledWindow):
def _on_map(self, widget: Self) -> None: def _on_map(self, widget: Self) -> None:
self.emitter.emit("server_page_toggled", True) self.emitter.emit("server_page_toggled", True)
print("page changed, starting queue checker") # FIXME: only applies to server notebook, not atomic page
self.get_active_treeview().start_timeout() # this can be delegated to the map/unmap signal of the ServerTreeView itself
# print("page changed, starting queue checker")
# self.get_active_treeview().start_timeout()
def _on_unmap(self, widget: Self) -> None: def _on_unmap(self, widget: Self) -> None:
self.emitter.emit("server_page_toggled", False) self.emitter.emit("server_page_toggled", False)
-1
View File
@@ -125,7 +125,6 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
self._on_tree_selection_changed(selection) self._on_tree_selection_changed(selection)
def _on_tree_selection_changed(self, selection: Gtk.TreeSelection) -> None: def _on_tree_selection_changed(self, selection: Gtk.TreeSelection) -> None:
print("selection changed")
self.emit("generic_treesel_changed", selection) self.emit("generic_treesel_changed", selection)
def toggle_selection(self, state: bool) -> None: def toggle_selection(self, state: bool) -> None:
+16 -15
View File
@@ -1,7 +1,7 @@
import logging import logging
import multiprocessing import multiprocessing
import threading import threading
from typing import Any from typing import Any, Optional
from warnings import deprecated from warnings import deprecated
from dzgui.views.mixins.context_mixin import ContextMixin from dzgui.views.mixins.context_mixin import ContextMixin
@@ -50,7 +50,8 @@ class ServerTreeView(ContextMixin, TreeView):
self.set_fixed_height_mode(True) self.set_fixed_height_mode(True)
self.set_headers_visible(True) self.set_headers_visible(True)
self.queue_id: int = 0 self.queue_id: int
self.handler_id: int
self.current_proc = None self.current_proc = None
self.queue = multiprocessing.Queue() self.queue = multiprocessing.Queue()
@@ -108,10 +109,6 @@ 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)
# TODO: simplify this
self.emitter.connect("statusbar_loaded", self.start_distcalc)
# self.emitter.connect("distcalc_started", self._on_distcalc_started)
def _get_ping( def _get_ping(
self, self,
column: Gtk.TreeViewColumn, column: Gtk.TreeViewColumn,
@@ -146,8 +143,6 @@ class ServerTreeView(ContextMixin, TreeView):
pass pass
def start_timeout(self) -> None: def start_timeout(self) -> None:
if self.queue_id:
GLib.Source.remove(self.queue_id)
self.queue_id = GLib.timeout_add(QUEUE_CHECK_DELAY, self._check_result_queue) self.queue_id = GLib.timeout_add(QUEUE_CHECK_DELAY, self._check_result_queue)
def get_filter_man(self) -> FilteredModelManager: def get_filter_man(self) -> FilteredModelManager:
@@ -180,12 +175,19 @@ class ServerTreeView(ContextMixin, TreeView):
def _on_map(self, a) -> None: def _on_map(self, a) -> None:
if self.get_enum() is ServerTab.LAN: if self.get_enum() is ServerTab.LAN:
# TODO: use emitter here self.emitter.emit("lan_tab_toggled", True)
self.controller.mediator.grid.conpan.lan.set_visible(True)
# FIXME: only if the tab is active
self.handler_id = self.emitter.connect("statusbar_loaded", self.start_distcalc)
self.start_timeout()
self.start_distcalc()
def _on_unmap(self, a) -> None: def _on_unmap(self, a) -> None:
# NOTE: remove queue checker for this tab
GLib.Source.remove(self.queue_id)
self.emitter.disconnect(self.handler_id)
if self.get_enum() is ServerTab.LAN: if self.get_enum() is ServerTab.LAN:
self.controller.mediator.grid.conpan.lan.set_visible(False) self.emitter.emit("lan_tab_toggled", False)
def set_query_func(self, func: Callable) -> None: def set_query_func(self, func: Callable) -> None:
self.query_func = func self.query_func = func
@@ -206,8 +208,6 @@ 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()
from typing import Optional
def start_distcalc(self, emitter: Optional["Emitter"] = None): def start_distcalc(self, emitter: Optional["Emitter"] = None):
self.terminate_process() self.terminate_process()
self.emitter.emit("distcalc_started") self.emitter.emit("distcalc_started")
@@ -230,7 +230,6 @@ class ServerTreeView(ContextMixin, TreeView):
self.current_proc.start() self.current_proc.start()
def _check_result_queue(self) -> Literal[True]: def _check_result_queue(self) -> Literal[True]:
# TODO: delegate to controller
latest_result = None latest_result = None
while not self.queue.empty(): while not self.queue.empty():
latest_result = self.queue.get() latest_result = self.queue.get()
@@ -242,6 +241,7 @@ class ServerTreeView(ContextMixin, TreeView):
haversine = latest_result[1] haversine = latest_result[1]
if addr not in cache: if addr not in cache:
cache[addr] = haversine cache[addr] = haversine
# TODO: should be emitting a statusbar signal here instead?
self.controller.set_statusbar_dist(haversine, self.get_enum()) self.controller.set_statusbar_dist(haversine, self.get_enum())
return True return True
@@ -251,6 +251,7 @@ class ServerTreeView(ContextMixin, TreeView):
if event.state is Gdk.ModifierType.CONTROL_MASK: if event.state is Gdk.ModifierType.CONTROL_MASK:
match event.keyval: match event.keyval:
case Gdk.KEY_r: case Gdk.KEY_r:
# TODO: unimplemented
self.refresh_player_count() self.refresh_player_count()
case Gdk.KEY_f: case Gdk.KEY_f:
self.emitter.emit("request_keyword_focus") self.emitter.emit("request_keyword_focus")
@@ -260,7 +261,7 @@ class ServerTreeView(ContextMixin, TreeView):
self.emitter.emit("request_ip_entry_focus") self.emitter.emit("request_ip_entry_focus")
case Gdk.KEY_p: case Gdk.KEY_p:
if self.enum is ServerTab.LAN: if self.enum is ServerTab.LAN:
self.emitter.emit("request_lan_entry_focus", self.enum) self.emitter.emit("request_lan_entry_focus")
case Gdk.KEY_c: case Gdk.KEY_c:
record = self.get_record() record = self.get_record()
self.controller.copy_ip(record) self.controller.copy_ip(record)