fix: handle null results

This commit is contained in:
aclist committed 2026-01-24 17:19:12 +09:00
1 parent ab9c97234e
commit e8e78ee6a1
5 files changed
+52 -60

No files matched your search

+35 -47
View File
@@ -12,7 +12,7 @@ from typing import Any, Callable, Literal, TYPE_CHECKING
import dzgui.api.pefile as PeFile import dzgui.api.pefile as PeFile
import dzgui.api.servers as Servers import dzgui.api.servers as Servers
import dzgui.util._json as JSON # noqa import dzgui.util._json as JSON # noqa
from dzgui.views.dialogs.generic import ExceptionDialog from dzgui.views.dialogs.generic import ExceptionDialog, WaitDialog
from dzgui.api.probe import test_steam_api, test_bm_api from dzgui.api.probe import test_steam_api, test_bm_api
from dzgui.api.mods import ( from dzgui.api.mods import (
@@ -182,6 +182,10 @@ class Controller(GObject.GObject):
def toggle_debug_mode(self) -> None: def toggle_debug_mode(self) -> None:
self.toggle_config(Preferences.DEBUG) self.toggle_config(Preferences.DEBUG)
def get_active_context(self) -> NotebookPage:
tv = self.get_active_treeview()
return tv.get_enum()
def get_active_treeview(self) -> "ServerTreeView": def get_active_treeview(self) -> "ServerTreeView":
return self.mediator.notebook.servers.get_active_treeview() return self.mediator.notebook.servers.get_active_treeview()
@@ -236,11 +240,10 @@ class Controller(GObject.GObject):
return msg_id return msg_id
def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None: def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None:
tv = self.get_active_treeview() context = self.get_active_context()
context = tv.get_enum()
page = self.mediator.notebook.get_page_by_enum() page = self.mediator.notebook.get_page_by_enum()
""" """
NOTE: prevents race condition when notebook page changed, NOTE: prevents race condition when server tab changed,
but allows caching the distance in the background but allows caching the distance in the background
""" """
if page != NotebookPage.SERVERS: if page != NotebookPage.SERVERS:
@@ -289,8 +292,6 @@ class Controller(GObject.GObject):
mod.append(None) mod.append(None)
model.append(mod) model.append(mod)
# self.update_mod_statusbar()
def toggle_config(self, context: Preferences) -> None: def toggle_config(self, context: Preferences) -> None:
config = self.prefs.paths.config config = self.prefs.paths.config
try: try:
@@ -356,7 +357,7 @@ class Controller(GObject.GObject):
self.mediator.notebook.set_page_by_enum(button.opens) self.mediator.notebook.set_page_by_enum(button.opens)
def _dump_api(self): def dump_api(self):
key = self.query_config(Preferences.STEAM) key = self.query_config(Preferences.STEAM)
job = Servers.query_api job = Servers.query_api
params = Servers.params params = Servers.params
@@ -370,10 +371,7 @@ 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:
# ModelManager.set_store(None) self.push_data(None)
# ModelManager.set_success(False)
# GLib.idle_add(self._filter_cleanup)
print("status error")
return return
j = res.json j = res.json
serv += j["response"]["servers"] serv += j["response"]["servers"]
@@ -383,14 +381,9 @@ class Controller(GObject.GObject):
j = res.json j = res.json
serv += j["response"]["servers"] serv += j["response"]["servers"]
# TODO: ping column pass
parsed = Servers.parse_json(serv) parsed = Servers.parse_json(serv)
self.data = parsed self.push_data(parsed)
self.get_func_data()
self.destroy_on_idle()
# try:
# except Exception as e:
# print(e)
# return parsed
def get_help_row(self) -> str: def get_help_row(self) -> str:
tv = self.mediator.menu tv = self.mediator.menu
@@ -574,18 +567,16 @@ class Controller(GObject.GObject):
import time import time
time.sleep(1) time.sleep(1)
self.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", 0, 0, "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", 0, 0, "a", False],
) )
# TODO: refer to prior implementation--should need to load data into model while in thread self.push_data(data)
self.get_func_data()
self.destroy_on_idle()
def dump_test_2(self) -> None: def dump_test_2(self) -> None:
import time import time
time.sleep(1) time.sleep(1)
self.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", 0, 0, "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", 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],
@@ -598,37 +589,34 @@ 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],
) )
# TODO: refer to prior implementation--should need to load data into model while in thread self.push_data(data)
self.get_func_data()
self.destroy_on_idle()
def get_func_data(self) -> None: def push_data(self, data: tuple) -> None:
def test(): def cleanup():
# NOTE: do not insert model until main thread is idle # TODO: rename signal
# TODO: grab from model manager and insert entire model
# TODO: do not start refresh button count until load finished
# TODO: append rows into filtered model
# when complete, destroy dialog and set model
for row in data:
manager.append_row(row)
treeview.set_model(manager.get_model())
treeview.set_loaded(True)
self.mediator.statusbar.emit("server_page_changed", context) self.mediator.statusbar.emit("server_page_changed", context)
# TODO: may be superfluous
treeview.grab_focus() treeview.grab_focus()
self.destroy_on_idle()
treeview = self.get_active_treeview() treeview = self.get_active_treeview()
context = treeview.get_enum() context = self.get_active_context()
manager = treeview.get_filter_man() if data is None:
data = self.data insert = None
GLib.idle_add(test) else:
manager = treeview.get_filter_man()
for row in data:
manager.append_row(row)
insert = manager.get_model()
treeview.set_model(insert)
treeview.set_loaded(True)
GLib.idle_add(cleanup)
def highlight_stale(self) -> None: def highlight_stale(self) -> None:
self.call_on_thread(self.colorize_mods) self.call_on_thread(self.colorize_mods)
def call_on_thread(self, func: Callable, *args) -> None: def call_on_thread(self, func: Callable, *args) -> None:
from dzgui.views.dialogs.generic import WaitDialog
self.wait_dialog = WaitDialog(self, strings.dialog.fetching) self.wait_dialog = WaitDialog(self, strings.dialog.fetching)
self.wait_dialog.show_all() self.wait_dialog.show_all()
thread = threading.Thread(target=func, args=args) thread = threading.Thread(target=func, args=args)
@@ -650,6 +638,8 @@ class Controller(GObject.GObject):
def destroy_on_idle(self) -> None: def destroy_on_idle(self) -> None:
self.wait_dialog.destroy() self.wait_dialog.destroy()
func = self.get_callback() func = self.get_callback()
self.mediator.window.set_sensitive(True)
# TODO: spawn error dialog if API crawl failed
if func is not None: if func is not None:
args = self.get_callback_args() args = self.get_callback_args()
GLib.idle_add(func, *args) GLib.idle_add(func, *args)
@@ -735,14 +725,12 @@ class Controller(GObject.GObject):
if func is None: if func is None:
self.mediator.statusbar.emit("server_page_changed", treeview.get_enum()) self.mediator.statusbar.emit("server_page_changed", treeview.get_enum())
return return
manager = treeview.get_filter_man()
# TODO: this may lag?
treeview.set_model(None) treeview.set_model(None)
manager = treeview.get_filter_man()
manager.clear_model() manager.clear_model()
self.set_callback(None, None) 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:
self.mediator.right_panel.focus_button_box() self.mediator.right_panel.focus_button_box()
@@ -791,5 +779,5 @@ class Controller(GObject.GObject):
def get_map(self) -> str: def get_map(self) -> str:
self.mediator.filters.get_selected_map() self.mediator.filters.get_selected_map()
def get_prio_map(self) -> str: def get_prior_map(self) -> str:
self.mediator.filters.get_prior_map() self.mediator.filters.get_prior_map()
+2 -2
View File
@@ -53,9 +53,9 @@ class FilteredModelManager:
self.success = True self.success = True
def append_row(self, row: list) -> None: def append_row(self, row: list) -> None:
self.real_model.append(row) # self.real_model.append(row)
# NOTE: append null rows to thin client # NOTE: append null rows to thin client
self.model.append() self.model.append(row)
def clear_model(self) -> None: def clear_model(self) -> None:
self.model.clear() self.model.clear()
+2 -2
View File
@@ -34,9 +34,8 @@ class ServerNotebook(Gtk.ScrolledWindow):
) )
self.lan = ServerTreeView(controller, ServerTab.LAN, ContextMenuGroup.SCAN_LAN) self.lan = ServerTreeView(controller, ServerTab.LAN, ContextMenuGroup.SCAN_LAN)
# self.browser.set_query_func(self.controller.dump_test_2)
self.lan.set_query_func(self.controller.dump_test_2) self.lan.set_query_func(self.controller.dump_test_2)
self.browser.set_query_func(self.controller._dump_api) self.browser.set_query_func(self.controller.dump_api)
tabs = [ tabs = [
(self.browser, server_labels.browser), (self.browser, server_labels.browser),
@@ -92,6 +91,7 @@ class ServerNotebook(Gtk.ScrolledWindow):
# TODO: strings # TODO: strings
text = label.strip("*") text = label.strip("*")
self.notebook.set_tab_label_text(child, text) self.notebook.set_tab_label_text(child, text)
# NOTE: spawns a thread
self.controller.populate_model() self.controller.populate_model()
def get_active_treeview(self) -> ServerTreeView: def get_active_treeview(self) -> ServerTreeView:
+2
View File
@@ -104,6 +104,8 @@ class TreeView(CursorMixin, Gtk.TreeView): # type: ignore
# self.get_selection().select_iter(it) # self.get_selection().select_iter(it)
# return True # return True
if self.get_model() is None:
return
if len(self.get_model()) < 2: if len(self.get_model()) < 2:
return return
+11 -9
View File
@@ -1,6 +1,7 @@
import logging import logging
import multiprocessing import multiprocessing
from typing import Any, Self from typing import Any, Self
from warnings import deprecated
from dzgui.const.enum import ContextMenu, ContextMenuGroup, FilterMode, ServerTab from dzgui.const.enum import ContextMenu, ContextMenuGroup, FilterMode, ServerTab
from dzgui.api.servers import Record from dzgui.api.servers import Record
@@ -24,8 +25,6 @@ logger = logging.getLogger(__name__)
if TYPE_CHECKING: if TYPE_CHECKING:
from dzgui.controllers.mc import Controller from dzgui.controllers.mc import Controller
# TODO: restore missing methods
class EnumeratedMenuItem(Gtk.MenuItem): class EnumeratedMenuItem(Gtk.MenuItem):
def __init__(self, enum: ContextMenu): def __init__(self, enum: ContextMenu):
@@ -76,7 +75,6 @@ class ServerTreeView(TreeView):
renderer = Gtk.CellRendererText() renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(column_title, renderer, text=i) column = Gtk.TreeViewColumn(column_title, renderer, text=i)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
column.set_cell_data_func(renderer, self._lazy_load, func_data=i)
column.set_resizable(True) column.set_resizable(True)
column.set_sort_column_id(i) column.set_sort_column_id(i)
@@ -336,8 +334,6 @@ class ServerTreeView(TreeView):
print(self.get_value_at_index(0)) print(self.get_value_at_index(0))
def _parent_selection_changed(self, base_class: TreeView, sel: Gtk.TreeSelection): def _parent_selection_changed(self, base_class: TreeView, sel: Gtk.TreeSelection):
# TODO: lazy load
# https://stackoverflow.com/questions/3164262/lazy-loaded-list-view-in-gtk
self.terminate_process() self.terminate_process()
self.emit("distcalc_started") self.emit("distcalc_started")
@@ -351,7 +347,6 @@ class ServerTreeView(TreeView):
select = self.get_selection() select = self.get_selection()
sels = select.get_selected_rows() sels = select.get_selected_rows()
(model, pathlist) = sels (model, pathlist) = sels
# TODO: clean up per lazy load logic
if len(pathlist) < 1: if len(pathlist) < 1:
return None return None
path = pathlist[0] path = pathlist[0]
@@ -372,6 +367,7 @@ class ServerTreeView(TreeView):
def set_loaded(self, status: bool) -> None: def set_loaded(self, status: bool) -> None:
self.loaded = status self.loaded = status
@deprecated("Currently unused")
def _lazy_load( def _lazy_load(
self, self,
column: Gtk.TreeViewColumn, column: Gtk.TreeViewColumn,
@@ -380,11 +376,17 @@ class ServerTreeView(TreeView):
it: Gtk.TreeIter, it: Gtk.TreeIter,
col_index: int, col_index: int,
) -> Any: ) -> Any:
# TODO: initially load empty rows """
# TODO: if cell is in visible range Lazy load contents from model manager into visible CellRenderers on demand
N.B., all row data will be stringified
cf. Gtk.TreeViewColumn.set_cell_data_func()
"""
path = model.get_path(it) path = model.get_path(it)
row_index = path.get_indices()[0] row_index = path.get_indices()[0]
start, end = self.get_visible_range() try:
start, end = self.get_visible_range()
except Exception:
return
if row_index >= start[0] <= end[0]: if row_index >= start[0] <= end[0]:
real_model = self.filter_man.get_real_model() real_model = self.filter_man.get_real_model()
value = real_model[row_index][col_index] value = real_model[row_index][col_index]