mirror of
https://github.com/aclist/dztui.git
synced 2026-08-29 03:06:56 +02:00
fix: update active maps combo on tab change
This commit is contained in:
parent
4d0bb2f4f8
commit
c3e2f6e4b4
@ -361,14 +361,14 @@ def details(ip: str, qport: int) -> Details:
|
|||||||
return Details(rows, description, True)
|
return Details(rows, description, True)
|
||||||
|
|
||||||
|
|
||||||
def ping(iteration: int, row: list) -> Ping:
|
def ping(iteration: int, addr: list, qport: int, ping: int) -> Ping:
|
||||||
addr = row[7]
|
# addr = row[7]
|
||||||
qport = row[8]
|
# qport = row[8]
|
||||||
|
|
||||||
res = None
|
res = None
|
||||||
|
|
||||||
if row[9] != 9999:
|
if ping != 9999:
|
||||||
return Ping(addr, iteration, row[9])
|
return Ping(addr, iteration, ping)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ip = addr.split(":")[0]
|
ip = addr.split(":")[0]
|
||||||
|
|||||||
@ -115,9 +115,12 @@ class Controller(GObject.GObject):
|
|||||||
self.emitter = Emitter()
|
self.emitter = Emitter()
|
||||||
self.emitter.connect("map_selection_changed", self._on_map_selection_changed)
|
self.emitter.connect("map_selection_changed", self._on_map_selection_changed)
|
||||||
self.emitter.connect("check_toggled", self._on_check_toggled)
|
self.emitter.connect("check_toggled", self._on_check_toggled)
|
||||||
|
self.emitter.connect("servers_loaded", self._on_servers_loaded)
|
||||||
|
self.emitter.connect("servers_loaded_init", self._on_servers_loaded_init)
|
||||||
|
|
||||||
# NOTE: suppress requests until entire UI is loaded
|
# NOTE: suppress requests until entire UI is loaded
|
||||||
self.loaded = False
|
self.loaded = False
|
||||||
|
self.pending_jobs = 1
|
||||||
|
|
||||||
def get_emitter(self) -> Emitter:
|
def get_emitter(self) -> Emitter:
|
||||||
return self.emitter
|
return self.emitter
|
||||||
@ -131,7 +134,7 @@ class Controller(GObject.GObject):
|
|||||||
GLib.idle_add(self._destroy_on_idle)
|
GLib.idle_add(self._destroy_on_idle)
|
||||||
|
|
||||||
self = args[0]
|
self = args[0]
|
||||||
self.wait_dialog = WaitDialog(self, dialog_str, True)
|
self.wait_dialog = WaitDialog(self, dialog_str, jobs=self.pending_jobs)
|
||||||
self.wait_dialog.show_all()
|
self.wait_dialog.show_all()
|
||||||
thread = threading.Thread(target=callback)
|
thread = threading.Thread(target=callback)
|
||||||
thread.start()
|
thread.start()
|
||||||
@ -388,48 +391,29 @@ class Controller(GObject.GObject):
|
|||||||
params = Servers.params
|
params = Servers.params
|
||||||
serv = []
|
serv = []
|
||||||
i = 0
|
i = 0
|
||||||
total = 10
|
|
||||||
with ThreadPoolExecutor() as executor:
|
with ThreadPoolExecutor() as executor:
|
||||||
futures = [executor.submit(job, key, APPID_DAYZ, param) for param in params]
|
futures = [executor.submit(job, key, APPID_DAYZ, param) for param in params]
|
||||||
# wait(futures)
|
|
||||||
for future in as_completed(futures):
|
for future in as_completed(futures):
|
||||||
try:
|
try:
|
||||||
i += 1
|
i += 1
|
||||||
GLib.idle_add(lambda: self.wait_dialog.prog.set_fraction(i / total))
|
GLib.idle_add(lambda: self.wait_dialog.increment())
|
||||||
res = future.result(timeout=3)
|
res = future.result(timeout=3)
|
||||||
if res.status != 200 or not res.parsed:
|
if res.status != 200 or not res.parsed:
|
||||||
# TODO: pop warning dialog, create enum around various failure states
|
|
||||||
# set failure type here
|
|
||||||
self.cleanup_func = CleanupFunc(self.cleanup_on_failure)
|
self.cleanup_func = CleanupFunc(self.cleanup_on_failure)
|
||||||
return
|
return
|
||||||
j = res.json
|
j = res.json
|
||||||
serv += j["response"]["servers"]
|
serv += j["response"]["servers"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# TODO: save exception text
|
logger.critical(e)
|
||||||
print(e)
|
|
||||||
self.cleanup_func = CleanupFunc(self.cleanup_on_failure)
|
self.cleanup_func = CleanupFunc(self.cleanup_on_failure)
|
||||||
|
|
||||||
"""
|
# NOTE: This step is allowed to fail, since this metadata is incidental
|
||||||
TODO: e.g. class method like 'total'
|
|
||||||
total of 10 params for this call
|
|
||||||
@call_on_thread(msg, jobs=10)
|
|
||||||
if total > 1, pop progress bar
|
|
||||||
GLib.idle_add(lambda: self.wait_dialog.format_secondary_text("Pass 2"))
|
|
||||||
GLib.idle_add(lambda: self.wait_dialog.prog.set_fraction(0.5))
|
|
||||||
subclass or wrap add fraction and increment, then calculate off of total
|
|
||||||
This next step is allowed to fail, since this metadata is incidental
|
|
||||||
"""
|
|
||||||
res = Servers.query_api(key, APPID_DAYZ_EXP, "")
|
res = Servers.query_api(key, APPID_DAYZ_EXP, "")
|
||||||
if res.status == 200 and res.parsed is True:
|
if res.status == 200 and res.parsed is True:
|
||||||
j = res.json
|
j = res.json
|
||||||
serv += j["response"]["servers"]
|
serv += j["response"]["servers"]
|
||||||
|
|
||||||
GLib.idle_add(
|
GLib.idle_add(lambda: self.wait_dialog.increment("Unpacking servers"))
|
||||||
lambda: self.wait_dialog.format_secondary_text("Unpacking servers")
|
|
||||||
)
|
|
||||||
GLib.idle_add(lambda: self.wait_dialog.prog.set_fraction(10 / total))
|
|
||||||
|
|
||||||
# TODO: additional ping column pass, collated
|
|
||||||
parsed = Servers.parse_json(serv)
|
parsed = Servers.parse_json(serv)
|
||||||
self.push_data_success(parsed, FilterMode.INITIAL)
|
self.push_data_success(parsed, FilterMode.INITIAL)
|
||||||
|
|
||||||
@ -466,7 +450,6 @@ class Controller(GObject.GObject):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def copy_name(self, path: Gtk.TreePath) -> None:
|
def copy_name(self, path: Gtk.TreePath) -> None:
|
||||||
# TODO: column values are deterministic, perhaps use a col name to index map
|
|
||||||
name = self.get_col_value_by_path_index(path, 0)
|
name = self.get_col_value_by_path_index(path, 0)
|
||||||
if name is None:
|
if name is None:
|
||||||
return
|
return
|
||||||
@ -659,13 +642,13 @@ class Controller(GObject.GObject):
|
|||||||
sel.select_path(path)
|
sel.select_path(path)
|
||||||
|
|
||||||
# TODO: make as method of tree?
|
# TODO: make as method of tree?
|
||||||
# FIXME: move cursor when finished
|
|
||||||
def uncolorize_mods(self) -> None:
|
def uncolorize_mods(self) -> None:
|
||||||
model = self.get_mod_store()
|
model = self.get_mod_store()
|
||||||
for mod in model:
|
for mod in model:
|
||||||
it = mod.iter
|
it = mod.iter
|
||||||
path = model.get_path(it)
|
path = model.get_path(it)
|
||||||
model[path][4] = None
|
model[path][4] = None
|
||||||
|
self.mediator.modtreeview.set_cursor(0)
|
||||||
|
|
||||||
def dump_test_2(self) -> None:
|
def dump_test_2(self) -> None:
|
||||||
import time
|
import time
|
||||||
@ -833,8 +816,10 @@ class Controller(GObject.GObject):
|
|||||||
return self.get_active_treeview().get_map_man()
|
return self.get_active_treeview().get_map_man()
|
||||||
|
|
||||||
def cleanup_on_success(self) -> None:
|
def cleanup_on_success(self) -> None:
|
||||||
|
self.pending_jobs = 1
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
treeview.set_loaded(True)
|
treeview.set_loaded(True)
|
||||||
|
|
||||||
treeview.set_model(self.to_insert)
|
treeview.set_model(self.to_insert)
|
||||||
map_man = treeview.get_map_man()
|
map_man = treeview.get_map_man()
|
||||||
|
|
||||||
@ -842,6 +827,7 @@ class Controller(GObject.GObject):
|
|||||||
# model insertion after thread closes
|
# model insertion after thread closes
|
||||||
# cf. servers_loaded signal
|
# cf. servers_loaded signal
|
||||||
|
|
||||||
|
# TODO: servers_loaded vs servers_reloaded
|
||||||
context = self.get_active_context()
|
context = self.get_active_context()
|
||||||
self.emitter.emit("servers_loaded", context)
|
self.emitter.emit("servers_loaded", context)
|
||||||
|
|
||||||
@ -856,27 +842,29 @@ class Controller(GObject.GObject):
|
|||||||
|
|
||||||
def cleanup_on_failure(self) -> None:
|
def cleanup_on_failure(self) -> None:
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
treeview.set_model(None)
|
|
||||||
treeview.set_loaded(True)
|
treeview.set_loaded(True)
|
||||||
map_man = treeview.get_map_man()
|
map_man = treeview.get_map_man()
|
||||||
# TODO: what if refresh action occurred, and the old model is still valid?
|
|
||||||
# TODO: disable map, keyword, and filter widgets if model is None
|
# TODO: disable map, keyword, and filter widgets if model is None
|
||||||
# -> signal driven (servers_empty)
|
# -> signal driven (servers_empty)
|
||||||
map_man.set_unique_maps(None)
|
# TODO: what if refresh action occurred and failed, and the old model is still valid?
|
||||||
|
# skip the step below if refresh action failed
|
||||||
|
# do not wipe control model in this case
|
||||||
|
# e.g. if treeview.is_refresh():
|
||||||
|
# revert old model
|
||||||
|
# wipe refresh state to False
|
||||||
|
|
||||||
context = self.get_active_context()
|
treeview.set_model(None)
|
||||||
# TODO: distinguish signals, e.g. "servers_failed_to_load"
|
|
||||||
self.emitter.emit("servers_loaded", context)
|
|
||||||
treeview.grab_focus()
|
treeview.grab_focus()
|
||||||
dialog = ExceptionDialog(self, "API TIMEOUT")
|
|
||||||
dialog.run()
|
|
||||||
|
|
||||||
# def push_data_failure(self) -> None:
|
map_man.set_unique_maps(None)
|
||||||
# #treeview = self.get_active_treeview()
|
context = self.get_active_context()
|
||||||
# #treeview.set_loaded(True)
|
|
||||||
# # TODO: wipe control model on failure or keep old results?
|
# TODO: distinguish signals, e.g. "servers_failed_to_load"
|
||||||
# # manager = treeview.get_filter_man()
|
# may trigger different behavior
|
||||||
# self.cleanup_func = CleanupFunc(self.cleanup_on_failure)
|
self.emitter.emit("servers_loaded", context)
|
||||||
|
dialog = ExceptionDialog(self, strings.api_warn_msg)
|
||||||
|
dialog.run()
|
||||||
|
|
||||||
def push_data_success(self, data: tuple, mode: Optional[FilterMode]) -> None:
|
def push_data_success(self, data: tuple, mode: Optional[FilterMode]) -> None:
|
||||||
# FIXME: set outside of thread
|
# FIXME: set outside of thread
|
||||||
@ -901,6 +889,7 @@ class Controller(GObject.GObject):
|
|||||||
self.cleanup_func = CleanupFunc(self.cleanup_on_success)
|
self.cleanup_func = CleanupFunc(self.cleanup_on_success)
|
||||||
|
|
||||||
def highlight_stale_cleanup(self, stale_mods: list) -> None:
|
def highlight_stale_cleanup(self, stale_mods: list) -> None:
|
||||||
|
"""Manipulates attached ListStore in the main event loop"""
|
||||||
model = self.get_mod_store()
|
model = self.get_mod_store()
|
||||||
for mod in model:
|
for mod in model:
|
||||||
it = mod.iter
|
it = mod.iter
|
||||||
@ -911,6 +900,7 @@ class Controller(GObject.GObject):
|
|||||||
|
|
||||||
@call_on_thread(strings.dialog.working)
|
@call_on_thread(strings.dialog.working)
|
||||||
def highlight_stale(self) -> None:
|
def highlight_stale(self) -> None:
|
||||||
|
# TODO: set progress bar for number of mods
|
||||||
stale = find_stale_mods(self.prefs.paths.config)
|
stale = find_stale_mods(self.prefs.paths.config)
|
||||||
self.cleanup_func = CleanupFunc(self.highlight_stale_cleanup, stale)
|
self.cleanup_func = CleanupFunc(self.highlight_stale_cleanup, stale)
|
||||||
|
|
||||||
@ -995,6 +985,7 @@ class Controller(GObject.GObject):
|
|||||||
|
|
||||||
@call_on_thread(strings.dialog.fetching)
|
@call_on_thread(strings.dialog.fetching)
|
||||||
def run_query_func(self, func: Callable) -> None:
|
def run_query_func(self, func: Callable) -> None:
|
||||||
|
# TODO: use CleanupFunc -> StoredFunc
|
||||||
func()
|
func()
|
||||||
|
|
||||||
@call_on_thread(strings.dialog.filtering)
|
@call_on_thread(strings.dialog.filtering)
|
||||||
@ -1010,6 +1001,7 @@ class Controller(GObject.GObject):
|
|||||||
# TODO: call filter_man methods directly
|
# TODO: call filter_man methods directly
|
||||||
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()
|
||||||
|
#tv.freeze_child_notify()
|
||||||
filter_man = tv.get_filter_man()
|
filter_man = tv.get_filter_man()
|
||||||
if filter_man.get_control() is None:
|
if filter_man.get_control() is None:
|
||||||
return
|
return
|
||||||
@ -1022,7 +1014,7 @@ class Controller(GObject.GObject):
|
|||||||
self.emitter.emit("servers_loaded", treeview.get_enum())
|
self.emitter.emit("servers_loaded", treeview.get_enum())
|
||||||
return
|
return
|
||||||
|
|
||||||
func = treeview.get_query_func()
|
func, jobs = treeview.get_query_func()
|
||||||
if func is None:
|
if func is None:
|
||||||
self.emitter.emit("servers_loaded", treeview.get_enum())
|
self.emitter.emit("servers_loaded", treeview.get_enum())
|
||||||
treeview.set_model(None)
|
treeview.set_model(None)
|
||||||
@ -1031,8 +1023,10 @@ class Controller(GObject.GObject):
|
|||||||
# TODO: clear ephemeral model if necessary
|
# TODO: clear ephemeral model if necessary
|
||||||
# manager = treeview.get_filter_man()
|
# manager = treeview.get_filter_man()
|
||||||
# manager.clear_model()
|
# manager.clear_model()
|
||||||
|
#treeview.fancy_col.set_cell_data_func(treeview.fancy_rend, None)
|
||||||
|
|
||||||
self.first_iteration = True
|
self.first_iteration = True
|
||||||
|
self.pending_jobs = jobs
|
||||||
self.run_query_func(func)
|
self.run_query_func(func)
|
||||||
|
|
||||||
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
|
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
|
||||||
@ -1080,6 +1074,27 @@ class Controller(GObject.GObject):
|
|||||||
map_man = self.get_map_man()
|
map_man = self.get_map_man()
|
||||||
return map_man.get_prior_map()
|
return map_man.get_prior_map()
|
||||||
|
|
||||||
|
def get_active_map(self) -> None:
|
||||||
|
return self.get_map_man().get_active_map()
|
||||||
|
|
||||||
|
def set_active_map(self, ind: int) -> None:
|
||||||
|
self.get_map_man().set_active_map(ind)
|
||||||
|
|
||||||
|
def _on_servers_loaded_init(self, emitter: "Emitter") -> None:
|
||||||
|
# FIXME: wipe maps store when changing tabs if model is none
|
||||||
|
tv = self.get_active_treeview()
|
||||||
|
if tv.loaded is False:
|
||||||
|
return
|
||||||
|
store = self.get_map_store()
|
||||||
|
self.emitter.emit("load_maps", store)
|
||||||
|
|
||||||
|
def _on_servers_loaded(self, emitter: "Emitter", tab: "ServerTab") -> None:
|
||||||
|
# NOTE: workaround for GTK bug where fullscreen causes headers to vanish when model is None
|
||||||
|
state = self.has_server_model()
|
||||||
|
tv = self.get_active_treeview()
|
||||||
|
tv.set_headers_visible(state)
|
||||||
|
tv.set_headers_clickable(state)
|
||||||
|
|
||||||
def _on_check_toggled(self, emitter: Emitter, label: str, state: bool) -> None:
|
def _on_check_toggled(self, emitter: Emitter, label: str, state: bool) -> None:
|
||||||
map_man = self.get_map_man()
|
map_man = self.get_map_man()
|
||||||
map_man.set_filter(label, state)
|
map_man.set_filter(label, state)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
|
import datetime
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING
|
from typing import Optional, TYPE_CHECKING
|
||||||
from warnings import deprecated
|
from warnings import deprecated
|
||||||
|
|
||||||
from dzgui.const.enum import FilterMode
|
from dzgui.const.enum import FilterMode
|
||||||
@ -114,16 +115,18 @@ class FilteredModelManager:
|
|||||||
case FilterMode.TOGGLE_ON:
|
case FilterMode.TOGGLE_ON:
|
||||||
rows = self.filter_toggle_on(filters, *args)
|
rows = self.filter_toggle_on(filters, *args)
|
||||||
|
|
||||||
if mode is not FilterMode.INITIAL:
|
# if mode is not FilterMode.INITIAL:
|
||||||
for row in rows:
|
# for row in rows:
|
||||||
if row[7] in self.ping_cache:
|
# if row[7] in self.ping_cache:
|
||||||
row[9] = self.ping_cache[row[7]]
|
# row[9] = self.ping_cache[row[7]]
|
||||||
|
|
||||||
clone = self.new_model_from_class(ServerColumns)
|
clone = self.new_model_from_class(ServerColumns)
|
||||||
if len(rows) > 0:
|
if len(rows) > 0:
|
||||||
|
# TODO: considering exposing an option to not sort rows
|
||||||
rows = self.sort_rows(rows)
|
rows = self.sort_rows(rows)
|
||||||
for row in rows:
|
for row in rows:
|
||||||
clone.append(row)
|
clone.append(row)
|
||||||
|
|
||||||
# else:
|
# else:
|
||||||
# print("nothing to filter, sending none")
|
# print("nothing to filter, sending none")
|
||||||
# clone = None
|
# clone = None
|
||||||
@ -256,7 +259,7 @@ class FilteredModelManager:
|
|||||||
def convert_model_to_list(self, model: ListStore) -> list:
|
def convert_model_to_list(self, model: ListStore) -> list:
|
||||||
return [[el for el in row] for row in model]
|
return [[el for el in row] for row in model]
|
||||||
|
|
||||||
def set_filtered(self, rows: list | None) -> None:
|
def set_filtered(self, rows: Optional[list]) -> None:
|
||||||
if rows is None:
|
if rows is None:
|
||||||
rows = []
|
rows = []
|
||||||
self.filtered = rows
|
self.filtered = rows
|
||||||
|
|||||||
@ -31,12 +31,19 @@ class MapManager:
|
|||||||
strings.filter_unofficial: True,
|
strings.filter_unofficial: True,
|
||||||
strings.filter_modded: True,
|
strings.filter_modded: True,
|
||||||
}
|
}
|
||||||
|
self.active_map = 0
|
||||||
self.filters: list
|
self.filters: list
|
||||||
self.enabled_filters = dict(self.default_filters)
|
self.enabled_filters = dict(self.default_filters)
|
||||||
|
|
||||||
def reinit_filters(self) -> None:
|
def reinit_filters(self) -> None:
|
||||||
self.enabled_filters = dict(self.default_filters)
|
self.enabled_filters = dict(self.default_filters)
|
||||||
|
|
||||||
|
def get_active_map(self) -> int:
|
||||||
|
return self.active_map
|
||||||
|
|
||||||
|
def set_active_map(self, ind: int) -> None:
|
||||||
|
self.active_map = ind
|
||||||
|
|
||||||
def get_default_filters(self) -> dict:
|
def get_default_filters(self) -> dict:
|
||||||
"""Deep copy of defaults"""
|
"""Deep copy of defaults"""
|
||||||
return dict(self.default_filters)
|
return dict(self.default_filters)
|
||||||
|
|||||||
@ -99,10 +99,8 @@ steam_missing = "Local Steam installation is not set, possibly malformed config
|
|||||||
build_corrupted = (
|
build_corrupted = (
|
||||||
"Steam settings or DayZ installation may be corrupted. Try restarting Steam."
|
"Steam settings or DayZ installation may be corrupted. Try restarting Steam."
|
||||||
)
|
)
|
||||||
api_warn_msg = """No servers returned. Possible causes:
|
api_warn_msg = """No servers returned. Please wait and try again.
|
||||||
no servers in favorites/history, local network issue, or API key on cooldown.
|
If this issue persists, your API key may be defunct or your network is blocking requests.
|
||||||
Return to the main menu, wait 30s, and try again.
|
|
||||||
If this issue persists, your API key may be defunct.
|
|
||||||
"""
|
"""
|
||||||
server_timeout = "Timed out when querying server, check IP or try again later"
|
server_timeout = "Timed out when querying server, check IP or try again later"
|
||||||
server_error = (
|
server_error = (
|
||||||
@ -167,7 +165,7 @@ ping_tooltip = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# statusbar_helptext = "Select a row to see its detailed description"
|
# statusbar_helptext = "Select a row to see its detailed description"
|
||||||
#statusbar_helptext = "No server metadata to list."
|
# statusbar_helptext = "No server metadata to list."
|
||||||
|
|
||||||
# use e.g. filters.1pp
|
# use e.g. filters.1pp
|
||||||
filter_1pp = "1PP"
|
filter_1pp = "1PP"
|
||||||
|
|||||||
@ -153,7 +153,6 @@ class FilterPanel(Gtk.Box):
|
|||||||
"request_maps_focus", lambda _: self.maps_entry.grab_focus()
|
"request_maps_focus", lambda _: self.maps_entry.grab_focus()
|
||||||
)
|
)
|
||||||
self.emitter.connect("check_button_pressed", self.toggle_check_by_key)
|
self.emitter.connect("check_button_pressed", self.toggle_check_by_key)
|
||||||
# self.emitter.connect("servers_loaded", self._on_servers_loaded)
|
|
||||||
self.emitter.connect("load_maps", self._on_maps_loaded)
|
self.emitter.connect("load_maps", self._on_maps_loaded)
|
||||||
|
|
||||||
# TODO: break into MapsCombo class
|
# TODO: break into MapsCombo class
|
||||||
@ -177,6 +176,9 @@ class FilterPanel(Gtk.Box):
|
|||||||
self.maps_combo.connect("changed", self._on_map_changed)
|
self.maps_combo.connect("changed", self._on_map_changed)
|
||||||
self.maps_combo.connect("key-press-event", self._on_combo_keypress)
|
self.maps_combo.connect("key-press-event", self._on_combo_keypress)
|
||||||
|
|
||||||
|
# FIXME: should be a property of treeview's meta manager
|
||||||
|
self.active_map = 0
|
||||||
|
|
||||||
for el in (
|
for el in (
|
||||||
self.filters_label,
|
self.filters_label,
|
||||||
self.keyword_entry,
|
self.keyword_entry,
|
||||||
@ -194,10 +196,12 @@ class FilterPanel(Gtk.Box):
|
|||||||
if text == row[0]:
|
if text == row[0]:
|
||||||
self.maps_combo.set_active(i)
|
self.maps_combo.set_active(i)
|
||||||
self._on_map_changed(self.maps_combo)
|
self._on_map_changed(self.maps_combo)
|
||||||
|
self.controller.set_active_map(i)
|
||||||
|
|
||||||
def _on_maps_loaded(self, emitter: "Emitter", store: Gtk.ListStore) -> None:
|
def _on_maps_loaded(self, emitter: "Emitter", store: Gtk.ListStore) -> None:
|
||||||
self.maps_combo.set_model(store)
|
self.maps_combo.set_model(store)
|
||||||
self.maps_combo.set_active(0)
|
ind = self.controller.get_active_map()
|
||||||
|
self.maps_combo.set_active(ind)
|
||||||
self.button_grid.reload_filters()
|
self.button_grid.reload_filters()
|
||||||
|
|
||||||
# TODO: move into metamanager
|
# TODO: move into metamanager
|
||||||
@ -259,6 +263,8 @@ class FilterPanel(Gtk.Box):
|
|||||||
store = self.controller.get_map_store()
|
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(store)
|
completion.set_model(store)
|
||||||
|
ind = self.get_active_combo()
|
||||||
|
self.controller.set_active_map(ind)
|
||||||
|
|
||||||
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()
|
||||||
|
|||||||
@ -44,9 +44,10 @@ class RightPanel(Gtk.Box):
|
|||||||
state = self.controller.has_server_model()
|
state = self.controller.has_server_model()
|
||||||
for widget in (self.refresh_button, self.filters_vbox):
|
for widget in (self.refresh_button, self.filters_vbox):
|
||||||
widget.set_sensitive(state)
|
widget.set_sensitive(state)
|
||||||
|
|
||||||
# FIXME: may wish to reload these in place to show new data
|
# FIXME: may wish to reload these in place to show new data
|
||||||
if context in (ServerTab.RECENT, ServerTab.SAVED):
|
# if context in (ServerTab.RECENT, ServerTab.SAVED):
|
||||||
self.refresh_button.set_sensitive(False)
|
# self.refresh_button.set_sensitive(False)
|
||||||
|
|
||||||
# TODO: reference for ping pass
|
# TODO: reference for ping pass
|
||||||
# def _on_ping_clicked(self, button: Gtk.Button) -> None:
|
# def _on_ping_clicked(self, button: Gtk.Button) -> None:
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
import gi
|
|
||||||
|
|
||||||
gi.require_version("Gtk", "3.0")
|
|
||||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
|
||||||
|
|
||||||
from dzgui.const.constants import NO_EXPAND, NO_FILL, NO_PADDING
|
|
||||||
from dzgui.const.enum import Popup
|
|
||||||
|
|
||||||
|
|
||||||
class EntryDialog(GenericDialog):
|
|
||||||
def __init__(self, text: str, mode: Popup, link: str, button_type=None):
|
|
||||||
super().__init__(text, mode)
|
|
||||||
|
|
||||||
"""
|
|
||||||
Wraps Gtk.Entry in a dialog and provides basic response handling.
|
|
||||||
Returns user input as a string or None.
|
|
||||||
The Entry widget itself can be manipulated via the get_entry() method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.dialog = GenericDialog(text, mode)
|
|
||||||
self.dialogBox = self.dialog.get_content_area()
|
|
||||||
self.dialog.set_default_response(Gtk.ResponseType.OK)
|
|
||||||
self.dialog.set_size_request(500, 0)
|
|
||||||
|
|
||||||
self.user_entry = Gtk.Entry()
|
|
||||||
set_surrounding_margins(self.user_entry, 20)
|
|
||||||
self.user_entry.set_margin_top(0)
|
|
||||||
self.user_entry.set_size_request(250, 0)
|
|
||||||
self.user_entry.set_activates_default(True)
|
|
||||||
self.dialogBox.pack_start(self.user_entry, NO_EXPAND, NO_FILL, NO_PADDING)
|
|
||||||
|
|
||||||
if link:
|
|
||||||
button = Gtk.Button(label=link)
|
|
||||||
button.set_margin_start(60)
|
|
||||||
button.set_margin_end(60)
|
|
||||||
button.connect("clicked", self._on_button_clicked, button_type)
|
|
||||||
self.dialogBox.pack_end(button, NO_EXPAND, NO_FILL, NO_PADDING)
|
|
||||||
|
|
||||||
self.ok = self.dialog.action_area.get_children()[1]
|
|
||||||
self.ok.set_sensitive(False)
|
|
||||||
self.user_entry.connect("insert-text", self._on_text_typed)
|
|
||||||
self.user_entry.get_property("buffer").connect(
|
|
||||||
"deleted-text", self._on_text_deleted
|
|
||||||
)
|
|
||||||
|
|
||||||
def _is_valid_text(self, text: str) -> bool:
|
|
||||||
if text.isspace():
|
|
||||||
return False
|
|
||||||
if len(text) == 0:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _on_text_deleted(
|
|
||||||
self, buffer: Gtk.EntryBuffer, position: int, chars: int
|
|
||||||
) -> None:
|
|
||||||
text = buffer.get_text()
|
|
||||||
state = self._is_valid_text(text)
|
|
||||||
self.ok.set_sensitive(state)
|
|
||||||
|
|
||||||
def _on_text_typed(
|
|
||||||
self, entry: Gtk.Entry, text: str, length: int, pos: int
|
|
||||||
) -> None:
|
|
||||||
state = self._is_valid_text(text)
|
|
||||||
self.ok.set_sensitive(state)
|
|
||||||
|
|
||||||
def _on_button_clicked(self, button: Gtk.Button, enum: RowType) -> None:
|
|
||||||
result = open_links.open_link_by_rowtype(enum)
|
|
||||||
if result is False:
|
|
||||||
AppNav.window.spawn_dialog(strings.something_wrong, Popup.NOTIFY)
|
|
||||||
|
|
||||||
def get_entry(self) -> Gtk.Entry:
|
|
||||||
return self.user_entry
|
|
||||||
|
|
||||||
def get_input(self) -> str | None:
|
|
||||||
self.dialog.show_all()
|
|
||||||
|
|
||||||
response = self.dialog.run()
|
|
||||||
text = self.user_entry.get_text()
|
|
||||||
self.dialog.destroy()
|
|
||||||
if (response == Gtk.ResponseType.OK) and (text != ""):
|
|
||||||
return text
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
@ -101,9 +101,7 @@ class NotifyDialog(GenericDialog):
|
|||||||
|
|
||||||
|
|
||||||
class WaitDialog(GenericDialog):
|
class WaitDialog(GenericDialog):
|
||||||
def __init__(
|
def __init__(self, controller: "Controller", secondary: str, jobs: int = 1):
|
||||||
self, controller: "Controller", secondary: str, show_progress: bool = False
|
|
||||||
):
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
controller=controller,
|
controller=controller,
|
||||||
text=strings.wait,
|
text=strings.wait,
|
||||||
@ -112,16 +110,26 @@ class WaitDialog(GenericDialog):
|
|||||||
secondary=secondary,
|
secondary=secondary,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.jobs = jobs
|
||||||
|
self.cur_job = 1
|
||||||
|
|
||||||
self.connect("delete-event", self._on_dialog_delete)
|
self.connect("delete-event", self._on_dialog_delete)
|
||||||
content = self.get_content_area()
|
content = self.get_content_area()
|
||||||
spinner = Gtk.Spinner()
|
spinner = Gtk.Spinner()
|
||||||
self.prog = Gtk.ProgressBar()
|
self.prog = Gtk.ProgressBar()
|
||||||
content.pack_end(spinner, NO_EXPAND, NO_FILL, 0)
|
content.pack_end(spinner, NO_EXPAND, NO_FILL, 0)
|
||||||
if show_progress:
|
if self.jobs > 1:
|
||||||
content.pack_end(self.prog, NO_EXPAND, NO_FILL, 0)
|
content.pack_end(self.prog, NO_EXPAND, NO_FILL, 0)
|
||||||
else:
|
else:
|
||||||
spinner.start()
|
spinner.start()
|
||||||
|
|
||||||
|
def increment(self, msg: str = "") -> None:
|
||||||
|
if msg != "":
|
||||||
|
self.format_secondary_text(msg)
|
||||||
|
fraction = self.cur_job / self.jobs
|
||||||
|
self.prog.set_fraction(fraction)
|
||||||
|
self.cur_job += 1
|
||||||
|
|
||||||
def _on_dialog_delete(
|
def _on_dialog_delete(
|
||||||
self, response_id: Gtk.ResponseType, event: Gdk.Event
|
self, response_id: Gtk.ResponseType, event: Gdk.Event
|
||||||
) -> Literal[True]:
|
) -> Literal[True]:
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
import textwrap
|
import textwrap
|
||||||
from typing import Self, TYPE_CHECKING
|
from typing import Self, TYPE_CHECKING
|
||||||
|
|
||||||
from dzgui.const.enum import Popup, Preferences
|
|
||||||
from dzgui.const.constants import NO_EXPAND, NO_FILL
|
from dzgui.const.constants import NO_EXPAND, NO_FILL
|
||||||
from dzgui.util.open_links import open_user_workshop
|
|
||||||
from dzgui.util.strings import notice
|
from dzgui.util.strings import notice
|
||||||
from dzgui.views.dialogs.generic import GenericDialog
|
from dzgui.views.dialogs.generic import GenericDialog
|
||||||
from dzgui.views.components.buttons import SteamTextButton, WebButton
|
from dzgui.views.components.buttons import SteamTextButton
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402
|
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402
|
||||||
|
|
||||||
@ -18,9 +17,17 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
class WorkshopLinkDialog(GenericDialog):
|
class WorkshopLinkDialog(GenericDialog):
|
||||||
def __init__(self, controller: "Controller", text: str, button_label: str, uid: str):
|
def __init__(
|
||||||
|
self, controller: "Controller", text: str, button_label: str, uid: str
|
||||||
|
):
|
||||||
text = textwrap.dedent(text).replace("\n", " ")
|
text = textwrap.dedent(text).replace("\n", " ")
|
||||||
super().__init__(controller, text=notice, mtype=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.OK, secondary=text)
|
super().__init__(
|
||||||
|
controller,
|
||||||
|
text=notice,
|
||||||
|
mtype=Gtk.MessageType.INFO,
|
||||||
|
buttons=Gtk.ButtonsType.OK,
|
||||||
|
secondary=text,
|
||||||
|
)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.dialogBox = self.get_content_area()
|
self.dialogBox = self.get_content_area()
|
||||||
self.set_default_response(Gtk.ResponseType.OK)
|
self.set_default_response(Gtk.ResponseType.OK)
|
||||||
@ -43,12 +50,10 @@ class WorkshopLinkDialog(GenericDialog):
|
|||||||
def _on_button_clicked(self, button: Gtk.Button, uid: str) -> None:
|
def _on_button_clicked(self, button: Gtk.Button, uid: str) -> None:
|
||||||
# TODO: currently checks user id on instantiation
|
# TODO: currently checks user id on instantiation
|
||||||
self.controller.open_user_workshop(uid)
|
self.controller.open_user_workshop(uid)
|
||||||
#client = self.controller.query_config(Preferences.CLIENT)
|
# client = self.controller.query_config(Preferences.CLIENT)
|
||||||
#open_user_workshop(uid, client)
|
# open_user_workshop(uid, client)
|
||||||
|
|
||||||
def _on_dialog_response(
|
def _on_dialog_response(self, dialog: Self, resp: Gtk.ResponseType) -> None:
|
||||||
self, dialog: Self, resp: Gtk.ResponseType
|
|
||||||
) -> None:
|
|
||||||
match resp:
|
match resp:
|
||||||
case Gtk.ResponseType.DELETE_EVENT:
|
case Gtk.ResponseType.DELETE_EVENT:
|
||||||
return
|
return
|
||||||
|
|||||||
@ -20,27 +20,21 @@ class ContextMixin(TreeView):
|
|||||||
) -> None:
|
) -> None:
|
||||||
# FIXME: double click causes issue
|
# FIXME: double click causes issue
|
||||||
# split into present by click and present by key
|
# split into present by click and present by key
|
||||||
|
|
||||||
if self.is_selection_empty():
|
if self.is_selection_empty():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if event.type is Gdk.EventType.BUTTON_PRESS:
|
match event.type:
|
||||||
if event.button != 3:
|
case Gdk.EventType.BUTTON_PRESS:
|
||||||
return False
|
if event.button != 3:
|
||||||
try:
|
return False
|
||||||
pathinfo = self.get_path_at_pos(int(event.x), int(event.y))
|
self._process_button_event(event)
|
||||||
if pathinfo is None:
|
case Gdk.EventType.KEY_PRESS:
|
||||||
return True
|
if event.state is not Gdk.ModifierType.CONTROL_MASK:
|
||||||
(path, col, cellx, celly) = pathinfo
|
return False
|
||||||
if path is None:
|
if event.keyval is not Gdk.KEY_l:
|
||||||
return True
|
return False
|
||||||
self.set_cursor(path, col, False)
|
case _:
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if event.type is Gdk.EventType.KEY_PRESS:
|
|
||||||
if event.state is not Gdk.ModifierType.CONTROL_MASK:
|
|
||||||
return False
|
|
||||||
if event.keyval is not Gdk.KEY_l:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
group = self.menu
|
group = self.menu
|
||||||
@ -64,6 +58,18 @@ class ContextMixin(TreeView):
|
|||||||
|
|
||||||
self.context_menu.select_first(False)
|
self.context_menu.select_first(False)
|
||||||
|
|
||||||
|
def _process_button_event(self, event: Gdk.EventButton) -> None:
|
||||||
|
try:
|
||||||
|
pathinfo = self.get_path_at_pos(int(event.x), int(event.y))
|
||||||
|
if pathinfo is None:
|
||||||
|
return True
|
||||||
|
(path, col, cellx, celly) = pathinfo
|
||||||
|
if path is None:
|
||||||
|
return True
|
||||||
|
self.set_cursor(path, col, False)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def _on_menu_click(self, widget: Gtk.MenuItem, enum: ContextMenu) -> None:
|
def _on_menu_click(self, widget: Gtk.MenuItem, enum: ContextMenu) -> None:
|
||||||
"""
|
"""
|
||||||
Local mods page allows multi selection, so ensure that only focused row
|
Local mods page allows multi selection, so ensure that only focused row
|
||||||
|
|||||||
@ -37,8 +37,9 @@ class ServerNotebook(Gtk.ScrolledWindow):
|
|||||||
self.lan = ServerTreeView(controller, ServerTab.LAN, ContextMenuGroup.SCAN_LAN)
|
self.lan = ServerTreeView(controller, ServerTab.LAN, ContextMenuGroup.SCAN_LAN)
|
||||||
|
|
||||||
self.recent.set_query_func(self.controller.dump_test_2)
|
self.recent.set_query_func(self.controller.dump_test_2)
|
||||||
|
# TODO: number of servers will not be known a priori until reading file during query phase
|
||||||
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, jobs=11)
|
||||||
|
|
||||||
tabs = [
|
tabs = [
|
||||||
(self.browser, server_labels.browser),
|
(self.browser, server_labels.browser),
|
||||||
|
|||||||
@ -7,12 +7,14 @@ from warnings import deprecated
|
|||||||
from dzgui.views.mixins.context_mixin import ContextMixin
|
from dzgui.views.mixins.context_mixin import ContextMixin
|
||||||
from dzgui.const.enum import ContextMenuGroup, ServerTab
|
from dzgui.const.enum import ContextMenuGroup, ServerTab
|
||||||
from dzgui.api.servers import Record
|
from dzgui.api.servers import Record
|
||||||
|
from dzgui.api.servers import ping as Ping
|
||||||
from dzgui.model.map_model import MapManager
|
from dzgui.model.map_model import MapManager
|
||||||
from dzgui.model.filtered_model import FilteredModelManager
|
from dzgui.model.filtered_model import FilteredModelManager
|
||||||
from dzgui.util.dist import CalcDist
|
from dzgui.util.dist import CalcDist
|
||||||
from dzgui.util import strings
|
from dzgui.util import strings
|
||||||
from typing import Callable, Literal, TYPE_CHECKING
|
from typing import Callable, Literal, TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
from dzgui.views.trees.tree_base import TreeView
|
from dzgui.views.trees.tree_base import TreeView
|
||||||
import dzgui.util._json as JSON # noqa
|
import dzgui.util._json as JSON # noqa
|
||||||
|
|
||||||
@ -56,6 +58,9 @@ class ServerTreeView(ContextMixin, TreeView):
|
|||||||
|
|
||||||
self.queue_id: int
|
self.queue_id: int
|
||||||
self.handler_id: int
|
self.handler_id: int
|
||||||
|
self.query_func_jobs = 1
|
||||||
|
|
||||||
|
self.seen_cache = []
|
||||||
|
|
||||||
self.current_proc = None
|
self.current_proc = None
|
||||||
self.queue = multiprocessing.Queue()
|
self.queue = multiprocessing.Queue()
|
||||||
@ -95,17 +100,21 @@ class ServerTreeView(ContextMixin, TreeView):
|
|||||||
else:
|
else:
|
||||||
w = width_map[column_title]
|
w = width_map[column_title]
|
||||||
column.set_fixed_width(w)
|
column.set_fixed_width(w)
|
||||||
#if column_title == "Name":
|
#if column_title == "Ping":
|
||||||
|
#self.fancy_col = column
|
||||||
|
#self.fancy_rend = renderer
|
||||||
|
#column.set_cell_data_func(renderer, self._get_ping)
|
||||||
|
# if column_title == "Name":
|
||||||
# column.set_fixed_width(800)
|
# column.set_fixed_width(800)
|
||||||
#if column_title == "Map":
|
# if column_title == "Map":
|
||||||
# column.set_fixed_width(300)
|
# column.set_fixed_width(300)
|
||||||
|
|
||||||
# TODO: standardize widths based on column title and longest content
|
# TODO: standardize widths based on column title and longest content
|
||||||
#if column_title == "Name":
|
# if column_title == "Name":
|
||||||
# column.set_fixed_width(500)
|
# column.set_fixed_width(500)
|
||||||
#if column_title == "Map":
|
# if column_title == "Map":
|
||||||
# column.set_fixed_width(200)
|
# column.set_fixed_width(200)
|
||||||
#if column_title == "IP":
|
# if column_title == "IP":
|
||||||
# column.set_fixed_width(240)
|
# column.set_fixed_width(240)
|
||||||
|
|
||||||
column.connect("notify::fixed-width", self._on_col_width_changed)
|
column.connect("notify::fixed-width", self._on_col_width_changed)
|
||||||
@ -119,55 +128,47 @@ class ServerTreeView(ContextMixin, TreeView):
|
|||||||
self.connect("map", self._on_map)
|
self.connect("map", self._on_map)
|
||||||
self.connect("unmap", self._on_unmap)
|
self.connect("unmap", self._on_unmap)
|
||||||
|
|
||||||
self.emitter.connect("servers_loaded_init", self._on_servers_loaded_init)
|
def _get_ping(
|
||||||
self.emitter.connect("servers_loaded", self._on_servers_loaded)
|
self,
|
||||||
|
column: Gtk.TreeViewColumn,
|
||||||
|
cell: Gtk.CellRendererText,
|
||||||
|
model: Gtk.TreeModel,
|
||||||
|
it: Gtk.TreeIter,
|
||||||
|
data: Any,
|
||||||
|
):
|
||||||
|
def ping_server(model, _iter, ip: str, qport: int, ping: int):
|
||||||
|
#res = Ping(0, model[_iter])
|
||||||
|
res = Ping(0, ip, qport, ping)
|
||||||
|
ping = res.ping
|
||||||
|
print(res)
|
||||||
|
GLib.idle_add(lambda: model.set(_iter, ping_column, ping))
|
||||||
|
|
||||||
def _on_servers_loaded(self, emitter: "Emitter", tab: "ServerTab") -> None:
|
addr_column = 7
|
||||||
# FIXME: gets called on every tab, should be localized only to that context
|
qport_column = 8
|
||||||
# hook signal from main controller
|
ping_column = 9
|
||||||
state = self.controller.has_server_model()
|
# TODO: unpack model before entering thread
|
||||||
# NOTE: workaround for GTK bug where fullscreen causes headers to vanish when model is None
|
# test 40k servers with unpacked model
|
||||||
self.set_headers_visible(state)
|
addr = model.get_value(it, addr_column).split(":")[0]
|
||||||
self.set_headers_clickable(state)
|
qport = model.get_value(it, qport_column)
|
||||||
|
ping = model.get_value(it, ping_column)
|
||||||
|
ip = f"{addr}:{qport}"
|
||||||
|
|
||||||
def _on_servers_loaded_init(self, emitter: "Emitter") -> None:
|
if ip in self.seen_cache:
|
||||||
if self.loaded is False:
|
|
||||||
return
|
return
|
||||||
store = self.map_man.get_map_store()
|
self.seen_cache.append(ip)
|
||||||
self.emitter.emit("load_maps", store)
|
|
||||||
|
|
||||||
#def _get_ping(
|
thread = threading.Thread(
|
||||||
# self,
|
daemon=True,
|
||||||
# column: Gtk.TreeViewColumn,
|
target=ping_server,
|
||||||
# cell: Gtk.CellRendererText,
|
args=(
|
||||||
# model: Gtk.TreeModel,
|
model,
|
||||||
# it: Gtk.TreeIter,
|
it,
|
||||||
# data: Any,
|
ip,
|
||||||
#):
|
qport,
|
||||||
# def ping(model, it, ip: str):
|
ping
|
||||||
# # TODO: use a2s to ping server
|
),
|
||||||
# # a2s.info -> "ping" key
|
)
|
||||||
# # Servers.ping() -> this accepts a whole row
|
thread.start()
|
||||||
# # try, if failure just abort
|
|
||||||
# self.res = ip.replace(":", "%")
|
|
||||||
# num = 11111
|
|
||||||
# GLib.idle_add(lambda: model.set(it, 9, num))
|
|
||||||
|
|
||||||
# addr = model.get_value(it, 7).split(":")[0]
|
|
||||||
# qport = model.get_value(it, 8)
|
|
||||||
# ip = f"{addr}:{qport}"
|
|
||||||
|
|
||||||
# thread = threading.Thread(
|
|
||||||
# daemon=True,
|
|
||||||
# target=ping,
|
|
||||||
# args=(
|
|
||||||
# model,
|
|
||||||
# it,
|
|
||||||
# ip,
|
|
||||||
# ),
|
|
||||||
# )
|
|
||||||
# thread.start()
|
|
||||||
# pass
|
|
||||||
|
|
||||||
def start_timeout(self) -> None:
|
def start_timeout(self) -> None:
|
||||||
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)
|
||||||
@ -178,7 +179,7 @@ class ServerTreeView(ContextMixin, TreeView):
|
|||||||
def get_filter_man(self) -> FilteredModelManager:
|
def get_filter_man(self) -> FilteredModelManager:
|
||||||
return self.filter_man
|
return self.filter_man
|
||||||
|
|
||||||
#def shrink_to_fit(self) -> None:
|
# def shrink_to_fit(self) -> None:
|
||||||
# cols = self.get_columns()
|
# cols = self.get_columns()
|
||||||
# # TODO: run on only one treeview and propagate results
|
# # TODO: run on only one treeview and propagate results
|
||||||
# # TODO: does not shrink name, map, ip fields to fit
|
# # TODO: does not shrink name, map, ip fields to fit
|
||||||
@ -208,8 +209,8 @@ class ServerTreeView(ContextMixin, TreeView):
|
|||||||
if self.get_enum() is ServerTab.LAN:
|
if self.get_enum() is ServerTab.LAN:
|
||||||
self.emitter.emit("lan_tab_toggled", True)
|
self.emitter.emit("lan_tab_toggled", True)
|
||||||
|
|
||||||
# FIXME: only if the tab is active
|
|
||||||
store = self.map_man.get_map_store()
|
store = self.map_man.get_map_store()
|
||||||
|
# FIXME: if model is none, wipe maps
|
||||||
self.emitter.emit("load_maps", store)
|
self.emitter.emit("load_maps", store)
|
||||||
self.handler_id = self.emitter.connect("statusbar_loaded", self.start_distcalc)
|
self.handler_id = self.emitter.connect("statusbar_loaded", self.start_distcalc)
|
||||||
self.start_timeout()
|
self.start_timeout()
|
||||||
@ -222,11 +223,12 @@ class ServerTreeView(ContextMixin, TreeView):
|
|||||||
if self.get_enum() is ServerTab.LAN:
|
if self.get_enum() is ServerTab.LAN:
|
||||||
self.emitter.emit("lan_tab_toggled", False)
|
self.emitter.emit("lan_tab_toggled", False)
|
||||||
|
|
||||||
def set_query_func(self, func: Callable) -> None:
|
def set_query_func(self, func: Callable, jobs: int = 1) -> None:
|
||||||
self.query_func = func
|
self.query_func = func
|
||||||
|
self.query_func_jobs = jobs
|
||||||
|
|
||||||
def get_query_func(self) -> Callable | None:
|
def get_query_func(self) -> Callable | None:
|
||||||
return self.query_func
|
return self.query_func, self.query_func_jobs
|
||||||
|
|
||||||
def _on_col_width_changed(
|
def _on_col_width_changed(
|
||||||
self, col: Gtk.TreeViewColumn, width: GObject.ParamSpecInt
|
self, col: Gtk.TreeViewColumn, width: GObject.ParamSpecInt
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user