mirror of
https://github.com/aclist/dztui.git
synced 2026-10-30 14:42:54 +01:00
fix: statusbar race condition WIP
This commit is contained in:
1 parent
2f9000ee80
commit
9cc1ece0d7
9 files changed
+163
-119
No files matched your search
+52
-44
@@ -1,7 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import shutil
|
import shutil
|
||||||
import threading
|
import threading
|
||||||
import textwrap
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -17,23 +16,16 @@ from dzgui.api.mods import (
|
|||||||
get_local_mod_path,
|
get_local_mod_path,
|
||||||
find_stale_mods,
|
find_stale_mods,
|
||||||
_hash,
|
_hash,
|
||||||
remove_stale_signatures
|
remove_stale_signatures,
|
||||||
)
|
|
||||||
from dzgui.const.enum import (
|
|
||||||
Preferences,
|
|
||||||
Popup,
|
|
||||||
NotebookPage,
|
|
||||||
ButtonType,
|
|
||||||
ContextMenu,
|
|
||||||
RowType
|
|
||||||
)
|
)
|
||||||
|
from dzgui.const.enum import Preferences, NotebookPage, ButtonType, ContextMenu, RowType
|
||||||
|
|
||||||
from dzgui.const.constants import (
|
from dzgui.const.constants import (
|
||||||
APPID_DAYZ,
|
APPID_DAYZ,
|
||||||
APPID_DAYZ_EXP,
|
APPID_DAYZ_EXP,
|
||||||
HEX_RED,
|
HEX_RED,
|
||||||
WINDOW_DEFAULT_X,
|
WINDOW_DEFAULT_X,
|
||||||
WINDOW_DEFAULT_Y
|
WINDOW_DEFAULT_Y,
|
||||||
)
|
)
|
||||||
|
|
||||||
from dzgui.config import update
|
from dzgui.config import update
|
||||||
@@ -45,19 +37,20 @@ from dzgui.util.diag import write_diagnostic
|
|||||||
from dzgui.util._json import read_json, write_json
|
from dzgui.util._json import read_json, write_json
|
||||||
from dzgui.util.localize import number
|
from dzgui.util.localize import number
|
||||||
from dzgui.util.open_links import open_workshop_page, open_user_workshop
|
from dzgui.util.open_links import open_workshop_page, open_user_workshop
|
||||||
from dzgui.util.format import format_mods, format_player_count, pluralize
|
from dzgui.util.format import format_mods, format_player_count
|
||||||
from dzgui.util.redact import redact_log
|
from dzgui.util.redact import redact_log
|
||||||
|
|
||||||
from dzgui.views.dialogs.filepicker import FilePicker
|
from dzgui.views.dialogs.filepicker import FilePicker
|
||||||
from dzgui.views.dialogs.generic import GenericDialog
|
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402
|
from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from dzgui.const.enum import ServerTab
|
||||||
from dzgui.util.dist import Haversine
|
from dzgui.util.dist import Haversine
|
||||||
from dzgui.views.base import Notebook, Grid, OuterWindow
|
from dzgui.views.base import Notebook, Grid, OuterWindow
|
||||||
from dzgui.views.components.buttonbox import ContextualButton
|
from dzgui.views.components.buttonbox import ContextualButton
|
||||||
@@ -65,12 +58,12 @@ if TYPE_CHECKING:
|
|||||||
from dzgui.views.components.right_panel import RightPanel
|
from dzgui.views.components.right_panel import RightPanel
|
||||||
from dzgui.views.components.statusbar import Statusbar
|
from dzgui.views.components.statusbar import Statusbar
|
||||||
from dzgui.views.pages.servers import ServerNotebook
|
from dzgui.views.pages.servers import ServerNotebook
|
||||||
from dzgui.views.trees.tree_base import TreeView
|
|
||||||
from dzgui.views.trees.tree_log import LogTreeView
|
from dzgui.views.trees.tree_log import LogTreeView
|
||||||
from dzgui.views.trees.tree_menu import MenuTreeView
|
from dzgui.views.trees.tree_menu import MenuTreeView
|
||||||
from dzgui.views.trees.tree_mods import ModTreeView
|
from dzgui.views.trees.tree_mods import ModTreeView
|
||||||
from dzgui.views.trees.tree_servers import ServerTreeView
|
from dzgui.views.trees.tree_servers import ServerTreeView
|
||||||
|
|
||||||
|
|
||||||
class AppNavigation:
|
class AppNavigation:
|
||||||
window: "OuterWindow"
|
window: "OuterWindow"
|
||||||
grid: "Grid"
|
grid: "Grid"
|
||||||
@@ -80,16 +73,16 @@ class AppNavigation:
|
|||||||
modtreeview: "ModTreeView"
|
modtreeview: "ModTreeView"
|
||||||
menu: "MenuTreeView"
|
menu: "MenuTreeView"
|
||||||
servers: "ServerNotebook"
|
servers: "ServerNotebook"
|
||||||
browser: "ServerTreeView"
|
|
||||||
saved: "ServerTreeView"
|
saved: "ServerTreeView"
|
||||||
recent: "ServerTreeView"
|
recent: "ServerTreeView"
|
||||||
lan: "ServerTreeView"
|
lan: "ServerTreeView"
|
||||||
logtreeview: "LogTreeView"
|
logtreeview: "LogTreeView"
|
||||||
filters: "FilterPanel"
|
filters: "FilterPanel"
|
||||||
|
|
||||||
|
|
||||||
class Controller:
|
class Controller:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.dist_cache: dict[str, "Haversine"] = {}
|
self.dist_cache: dict[str, "Haversine", "ServerTab"] = {}
|
||||||
self.crumbs_cache = ""
|
self.crumbs_cache = ""
|
||||||
self.mediator = AppNavigation()
|
self.mediator = AppNavigation()
|
||||||
self.prefs: UserPrefs
|
self.prefs: UserPrefs
|
||||||
@@ -128,7 +121,8 @@ class Controller:
|
|||||||
|
|
||||||
def terminate_process(self) -> None:
|
def terminate_process(self) -> None:
|
||||||
# TODO: only used by server table multiprocessing queue
|
# TODO: only used by server table multiprocessing queue
|
||||||
self.mediator.notebook.servers.browser.terminate_process()
|
tv = self.get_active_treeview()
|
||||||
|
tv.terminate_process()
|
||||||
|
|
||||||
def get_prefs(self) -> UserPrefs:
|
def get_prefs(self) -> UserPrefs:
|
||||||
return self.prefs
|
return self.prefs
|
||||||
@@ -165,7 +159,9 @@ class Controller:
|
|||||||
"_on_tree_selection_changed",
|
"_on_tree_selection_changed",
|
||||||
state,
|
state,
|
||||||
)
|
)
|
||||||
self.suppress_signal(self.mediator.menu, self.mediator.menu, "_on_keypress", state)
|
self.suppress_signal(
|
||||||
|
self.mediator.menu, self.mediator.menu, "_on_keypress", state
|
||||||
|
)
|
||||||
for check in self.mediator.filters.checks:
|
for check in self.mediator.filters.checks:
|
||||||
self.suppress_signal(
|
self.suppress_signal(
|
||||||
self.mediator.filters,
|
self.mediator.filters,
|
||||||
@@ -184,7 +180,7 @@ class Controller:
|
|||||||
else:
|
else:
|
||||||
widget.handler_unblock_by_func(func)
|
widget.handler_unblock_by_func(func)
|
||||||
# TODO: deprecated?
|
# TODO: deprecated?
|
||||||
#self.mediator.menu.sel_blocked = state
|
# 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)
|
||||||
@@ -234,14 +230,22 @@ class Controller:
|
|||||||
def get_statusbar(self) -> str:
|
def get_statusbar(self) -> str:
|
||||||
return self.mediator.statusbar.get_text()
|
return self.mediator.statusbar.get_text()
|
||||||
|
|
||||||
def set_statusbar(self, text: str) -> None:
|
def remove_statusbar(self, context: str) -> None:
|
||||||
self.mediator.statusbar.set_text(text)
|
c = self.mediator.statusbar.statusbar.get_context_id(context)
|
||||||
|
self.mediator.statusbar.statusbar.remove_all(c)
|
||||||
|
|
||||||
|
def set_statusbar(self, text: str, context: str) -> None:
|
||||||
|
self.mediator.statusbar.set_text(text, context)
|
||||||
|
|
||||||
def set_statusbar_placeholder(self, text: str) -> None:
|
def set_statusbar_placeholder(self, text: str) -> None:
|
||||||
# TODO: use statusbar stacks instead
|
# TODO: use statusbar stacks instead
|
||||||
self.statusbar_placeholder = text
|
self.statusbar_placeholder = text
|
||||||
|
|
||||||
def set_statusbar_dist(self, haversine: "Haversine") -> None:
|
def set_statusbar_dist(self, haversine: "Haversine", enum: "ServerTab") -> None:
|
||||||
|
tv = self.get_active_treeview()
|
||||||
|
if tv.get_enum() != enum:
|
||||||
|
self.mediator.statusbar.spinner.stop()
|
||||||
|
return
|
||||||
dist: str
|
dist: str
|
||||||
if haversine is None:
|
if haversine is None:
|
||||||
dist = "Unknown"
|
dist = "Unknown"
|
||||||
@@ -255,7 +259,8 @@ class Controller:
|
|||||||
separated = number(raw)
|
separated = number(raw)
|
||||||
dist = str(separated) + " km"
|
dist = str(separated) + " km"
|
||||||
text = self.statusbar_placeholder
|
text = self.statusbar_placeholder
|
||||||
self.set_statusbar(f"{text} | Distance: {dist}")
|
# TODO: abstract
|
||||||
|
self.set_statusbar(f"{text} | Distance: {dist}", "Servers")
|
||||||
self.mediator.statusbar.spinner.stop()
|
self.mediator.statusbar.spinner.stop()
|
||||||
|
|
||||||
def delete_multiple_mods(self) -> None:
|
def delete_multiple_mods(self) -> None:
|
||||||
@@ -328,7 +333,7 @@ class Controller:
|
|||||||
def show_developers_page(self) -> None:
|
def show_developers_page(self) -> None:
|
||||||
self.open_page(NotebookPage.DEVELOPERS)
|
self.open_page(NotebookPage.DEVELOPERS)
|
||||||
# TODO: put cursor on first row
|
# TODO: put cursor on first row
|
||||||
#self.mediator.developers.focus_first_row()
|
# self.mediator.developers.focus_first_row()
|
||||||
|
|
||||||
def open_page(self, page: NotebookPage) -> None:
|
def open_page(self, page: NotebookPage) -> None:
|
||||||
self.mediator.grid.notebook.set_page_by_enum(page)
|
self.mediator.grid.notebook.set_page_by_enum(page)
|
||||||
@@ -386,7 +391,9 @@ class Controller:
|
|||||||
open_workshop_page(mod, cmd)
|
open_workshop_page(mod, cmd)
|
||||||
|
|
||||||
# TODO: put in model manager (dedicated manager for mod store)
|
# TODO: put in model manager (dedicated manager for mod store)
|
||||||
def get_mod_from_tree_path(self, tree_path: Gtk.TreePath) -> tuple[str, Gtk.TreeIter]:
|
def get_mod_from_tree_path(
|
||||||
|
self, tree_path: Gtk.TreePath
|
||||||
|
) -> tuple[str, Gtk.TreeIter]:
|
||||||
model = self.model_man.get_mod_store()
|
model = self.model_man.get_mod_store()
|
||||||
tree_iter = model.get_iter(tree_path)
|
tree_iter = model.get_iter(tree_path)
|
||||||
mod = model.get(tree_iter, 2)[0]
|
mod = model.get(tree_iter, 2)[0]
|
||||||
@@ -419,15 +426,13 @@ class Controller:
|
|||||||
model = self.model_man.get_mod_store()
|
model = self.model_man.get_mod_store()
|
||||||
model.remove(it)
|
model.remove(it)
|
||||||
|
|
||||||
|
|
||||||
def update_mod_statusbar(self) -> None:
|
def update_mod_statusbar(self) -> None:
|
||||||
total_mods, total_size = self.calc_mod_size()
|
total_mods, total_size = self.calc_mod_size()
|
||||||
msg = format_mods(total_size, total_mods)
|
msg = format_mods(total_size, total_mods)
|
||||||
# TODO: combine
|
# TODO: combine
|
||||||
meta = self.mediator.statusbar.statusbar.get_context_id("Mods")
|
# meta = self.mediator.statusbar.statusbar.get_context_id("Mods")
|
||||||
self.mediator.statusbar.statusbar.push(meta, msg)
|
# self.mediator.statusbar.statusbar.push(meta, msg)
|
||||||
#meta = self.mediator.statusbar.set_text(msg)
|
self.mediator.statusbar.set_text(msg, "Mods")
|
||||||
|
|
||||||
|
|
||||||
def calc_mod_size(self) -> tuple[int, int]:
|
def calc_mod_size(self) -> tuple[int, int]:
|
||||||
model = self.model_man.get_mod_store()
|
model = self.model_man.get_mod_store()
|
||||||
@@ -437,7 +442,6 @@ class Controller:
|
|||||||
total_size += mod[3]
|
total_size += mod[3]
|
||||||
return total_mods, total_size
|
return total_mods, total_size
|
||||||
|
|
||||||
|
|
||||||
def menu_action(self, action: ContextMenu, path: Gtk.TreePath) -> None:
|
def menu_action(self, action: ContextMenu, path: Gtk.TreePath) -> None:
|
||||||
match action:
|
match action:
|
||||||
# NOTE: manipulates server stores
|
# NOTE: manipulates server stores
|
||||||
@@ -470,14 +474,12 @@ class Controller:
|
|||||||
# Gtk.TreeModel, row-inserted/row-deleted
|
# Gtk.TreeModel, row-inserted/row-deleted
|
||||||
self.update_mod_statusbar()
|
self.update_mod_statusbar()
|
||||||
remove_stale_signatures(
|
remove_stale_signatures(
|
||||||
self.prefs.paths.config,
|
self.prefs.paths.config, self.prefs.paths.version
|
||||||
self.prefs.paths.version
|
|
||||||
)
|
)
|
||||||
|
|
||||||
case ContextMenu.OPEN_WORKSHOP:
|
case ContextMenu.OPEN_WORKSHOP:
|
||||||
self.open_mod_page(path)
|
self.open_mod_page(path)
|
||||||
|
|
||||||
|
|
||||||
def toggle_mod_selection(self, state: bool) -> None:
|
def toggle_mod_selection(self, state: bool) -> None:
|
||||||
sel = self.mediator.modtreeview.get_selection()
|
sel = self.mediator.modtreeview.get_selection()
|
||||||
if state:
|
if state:
|
||||||
@@ -493,7 +495,9 @@ class Controller:
|
|||||||
# NOTE: this model is reloaded each time as log changes
|
# NOTE: this model is reloaded each time as log changes
|
||||||
try:
|
try:
|
||||||
with open(log, "r") as f:
|
with open(log, "r") as f:
|
||||||
lines = [line.split(strings.delimiter) for line in f.read().splitlines()]
|
lines = [
|
||||||
|
line.split(strings.delimiter) for line in f.read().splitlines()
|
||||||
|
]
|
||||||
for record in lines:
|
for record in lines:
|
||||||
clean = redact_log(record)
|
clean = redact_log(record)
|
||||||
store.append(clean)
|
store.append(clean)
|
||||||
@@ -535,6 +539,7 @@ class Controller:
|
|||||||
|
|
||||||
def dump_test_1(self) -> None:
|
def dump_test_1(self) -> None:
|
||||||
import time
|
import time
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
# TODO: use model managers, etc.
|
# TODO: use model managers, etc.
|
||||||
self.data = (
|
self.data = (
|
||||||
@@ -561,6 +566,7 @@ class Controller:
|
|||||||
|
|
||||||
def dump_test_2(self) -> None:
|
def dump_test_2(self) -> None:
|
||||||
import time
|
import time
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
# TODO: use model managers, etc.
|
# TODO: use model managers, etc.
|
||||||
self.data = (
|
self.data = (
|
||||||
@@ -570,7 +576,7 @@ class Controller:
|
|||||||
self.get_func_data()
|
self.get_func_data()
|
||||||
self.destroy_on_idle()
|
self.destroy_on_idle()
|
||||||
|
|
||||||
def get_func_data(self):
|
def get_func_data(self) -> None:
|
||||||
def test():
|
def test():
|
||||||
# NOTE: do not insert model until main thread is idle
|
# NOTE: do not insert model until main thread is idle
|
||||||
# TODO: grab from model manager and insert entire model
|
# TODO: grab from model manager and insert entire model
|
||||||
@@ -580,6 +586,7 @@ class Controller:
|
|||||||
treeview.set_loaded(True)
|
treeview.set_loaded(True)
|
||||||
self.update_server_status()
|
self.update_server_status()
|
||||||
treeview.grab_focus()
|
treeview.grab_focus()
|
||||||
|
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
|
|
||||||
manager = treeview.get_filter_man()
|
manager = treeview.get_filter_man()
|
||||||
@@ -591,6 +598,7 @@ class Controller:
|
|||||||
|
|
||||||
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
|
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)
|
||||||
@@ -607,7 +615,7 @@ class Controller:
|
|||||||
Lets calling widgets register a callback function
|
Lets calling widgets register a callback function
|
||||||
when spawning a threaded process
|
when spawning a threaded process
|
||||||
"""
|
"""
|
||||||
self.callback = { "func": callback, "args": args }
|
self.callback = {"func": callback, "args": args}
|
||||||
|
|
||||||
def destroy_on_idle(self) -> None:
|
def destroy_on_idle(self) -> None:
|
||||||
self.wait_dialog.destroy()
|
self.wait_dialog.destroy()
|
||||||
@@ -642,7 +650,6 @@ class Controller:
|
|||||||
dialog = ExceptionDialog(self, strings.api_error)
|
dialog = ExceptionDialog(self, strings.api_error)
|
||||||
dialog.run()
|
dialog.run()
|
||||||
|
|
||||||
|
|
||||||
def update_api_key(self, text: str, key: Preferences) -> None:
|
def update_api_key(self, text: str, key: Preferences) -> None:
|
||||||
self.call_on_thread(self.test_api_response, text, key)
|
self.call_on_thread(self.test_api_response, text, key)
|
||||||
|
|
||||||
@@ -688,13 +695,15 @@ class Controller:
|
|||||||
def update_server_status(self) -> None:
|
def update_server_status(self) -> None:
|
||||||
# TODO: emit signal on statusbar only if page changed
|
# TODO: emit signal on statusbar only if page changed
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
|
context = str(treeview.enum)
|
||||||
model = treeview.get_model()
|
model = treeview.get_model()
|
||||||
status = format_player_count(model)
|
status = format_player_count(model)
|
||||||
self.set_statusbar_placeholder(status)
|
self.set_statusbar_placeholder(status)
|
||||||
self.set_statusbar(status)
|
|
||||||
|
self.set_statusbar(status, context)
|
||||||
|
if len(model) >= 1:
|
||||||
self.mediator.statusbar.spinner.start()
|
self.mediator.statusbar.spinner.start()
|
||||||
if len(model) < 1:
|
# self.mediator.statusbar.spinner.stop()
|
||||||
self.mediator.statusbar.spinner.stop()
|
|
||||||
|
|
||||||
def populate_model(self) -> None:
|
def populate_model(self) -> None:
|
||||||
treeview = self.get_active_treeview()
|
treeview = self.get_active_treeview()
|
||||||
@@ -718,8 +727,8 @@ class Controller:
|
|||||||
crumbs = self.mediator.servers.get_cached_label()
|
crumbs = self.mediator.servers.get_cached_label()
|
||||||
self.set_crumbs(crumbs)
|
self.set_crumbs(crumbs)
|
||||||
# TODO: could emit this when treeview gains keyboard focus
|
# TODO: could emit this when treeview gains keyboard focus
|
||||||
#tree = self.get_active_treeview()
|
# tree = self.get_active_treeview()
|
||||||
#tree.emit("on_distcalc_started")
|
# tree.emit("on_distcalc_started")
|
||||||
|
|
||||||
def toggle_check(self, event: Gdk.EventKey) -> None | Literal[False]:
|
def toggle_check(self, event: Gdk.EventKey) -> None | Literal[False]:
|
||||||
mappings = {
|
mappings = {
|
||||||
@@ -739,7 +748,6 @@ class Controller:
|
|||||||
if event.keyval not in mappings:
|
if event.keyval not in mappings:
|
||||||
return False
|
return False
|
||||||
index = mappings[event.keyval]
|
index = mappings[event.keyval]
|
||||||
# TODO: register filter panel widget
|
|
||||||
self.mediator.filters.toggle_check(index)
|
self.mediator.filters.toggle_check(index)
|
||||||
|
|
||||||
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
|
def get_favorite(self) -> tuple[str, str] | tuple[None, None]:
|
||||||
|
|||||||
+7
-2
@@ -44,10 +44,12 @@ args = parser.parse_args()
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
# TODO: profile load time
|
# TODO: profile load time
|
||||||
def make_parents(path: "Path") -> None:
|
def make_parents(path: "Path") -> None:
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def uninstall() -> None:
|
def uninstall() -> None:
|
||||||
# TODO: uninstall data files (-u)
|
# TODO: uninstall data files (-u)
|
||||||
# -u removes state, log, freedesktop
|
# -u removes state, log, freedesktop
|
||||||
@@ -56,6 +58,7 @@ def uninstall() -> None:
|
|||||||
# XDG_DATA_HOME/dzgui
|
# XDG_DATA_HOME/dzgui
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
lock = lock_acquire() # noqa
|
lock = lock_acquire() # noqa
|
||||||
|
|
||||||
@@ -85,7 +88,9 @@ def main() -> None:
|
|||||||
migrate_cols_file(XDG.columns)
|
migrate_cols_file(XDG.columns)
|
||||||
copy_state_files(xdg_paths["XDG_STATE_HOME"])
|
copy_state_files(xdg_paths["XDG_STATE_HOME"])
|
||||||
|
|
||||||
_format = "%(asctime)s␞%(levelname)s␞%(filename)s::%(funcName)s::%(lineno)s␞%(message)s"
|
_format = (
|
||||||
|
"%(asctime)s␞%(levelname)s␞%(filename)s::%(funcName)s::%(lineno)s␞%(message)s"
|
||||||
|
)
|
||||||
logging.basicConfig(filename=XDG.debug, format=_format, level=logging.DEBUG)
|
logging.basicConfig(filename=XDG.debug, format=_format, level=logging.DEBUG)
|
||||||
with open(XDG.debug, "w") as f:
|
with open(XDG.debug, "w") as f:
|
||||||
f.truncate(0)
|
f.truncate(0)
|
||||||
@@ -126,7 +131,7 @@ def main() -> None:
|
|||||||
local_coords,
|
local_coords,
|
||||||
version,
|
version,
|
||||||
allow,
|
allow,
|
||||||
XDG
|
XDG,
|
||||||
)
|
)
|
||||||
print("All OK. Loading UI...")
|
print("All OK. Loading UI...")
|
||||||
App(prefs)
|
App(prefs)
|
||||||
+10
-6
@@ -4,19 +4,20 @@ from math import radians, cos, sin, asin, sqrt
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from dzgui.util.ip import GeolocationError, get_coords
|
from dzgui.util.ip import GeolocationError, get_coords
|
||||||
from dzgui.util.localize import number
|
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version("Gtk", "3.0")
|
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.util.ip import Coords
|
from dzgui.const.enum import ServerTab
|
||||||
from dzgui.controllers.mc import Controller
|
from dzgui.controllers.mc import Controller
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Haversine():
|
|
||||||
|
class Haversine:
|
||||||
def __init__(self, lat1: float, lon1: float, lat2: float, lon2: float) -> None:
|
def __init__(self, lat1: float, lon1: float, lat2: float, lon2: float) -> None:
|
||||||
|
|
||||||
R = 6371 * 1000
|
R = 6371 * 1000
|
||||||
@@ -26,7 +27,7 @@ class Haversine():
|
|||||||
lat1 = radians(lat1)
|
lat1 = radians(lat1)
|
||||||
lat2 = radians(lat2)
|
lat2 = radians(lat2)
|
||||||
|
|
||||||
a = sin(dLat/2) ** 2 + cos(lat1) * cos(lat2) * sin(dLon/2) ** 2
|
a = sin(dLat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dLon / 2) ** 2
|
||||||
c = 2 * asin(sqrt(a))
|
c = 2 * asin(sqrt(a))
|
||||||
|
|
||||||
self.dist = R * c
|
self.dist = R * c
|
||||||
@@ -37,15 +38,18 @@ class Haversine():
|
|||||||
def as_miles(self) -> float:
|
def as_miles(self) -> float:
|
||||||
return self.dist / 1609.344
|
return self.dist / 1609.344
|
||||||
|
|
||||||
|
|
||||||
class CalcDist(multiprocessing.Process):
|
class CalcDist(multiprocessing.Process):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
addr: str,
|
addr: str,
|
||||||
|
enum: "ServerTab",
|
||||||
result_queue: multiprocessing.Queue,
|
result_queue: multiprocessing.Queue,
|
||||||
controller: "Controller",
|
controller: "Controller",
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
self.enum = enum
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.result_queue = result_queue
|
self.result_queue = result_queue
|
||||||
self.addr = addr
|
self.addr = addr
|
||||||
@@ -55,11 +59,11 @@ class CalcDist(multiprocessing.Process):
|
|||||||
cache = self.controller.get_dist_cache()
|
cache = self.controller.get_dist_cache()
|
||||||
if self.addr in cache:
|
if self.addr in cache:
|
||||||
logger.info(f"Address '{self.addr}' already in cache")
|
logger.info(f"Address '{self.addr}' already in cache")
|
||||||
self.result_queue.put([self.addr, cache[self.addr]])
|
self.result_queue.put([self.addr, cache[self.addr], self.enum])
|
||||||
return
|
return
|
||||||
|
|
||||||
dist = self.compare(self.ip)
|
dist = self.compare(self.ip)
|
||||||
self.result_queue.put([self.addr, dist])
|
self.result_queue.put([self.addr, dist, self.enum])
|
||||||
|
|
||||||
def compare(self, remote: str) -> int | None:
|
def compare(self, remote: str) -> int | None:
|
||||||
prefs = self.controller.get_prefs()
|
prefs = self.controller.get_prefs()
|
||||||
|
|||||||
+32
-26
@@ -1,13 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
#import multiprocessing
|
|
||||||
import signal
|
import signal
|
||||||
#import threading
|
|
||||||
import typing # noqa
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
#from concurrent.futures import wait
|
|
||||||
#from concurrent.futures import ThreadPoolExecutor
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Literal
|
from typing import TYPE_CHECKING, Literal
|
||||||
|
|
||||||
from dzgui.const.enum import NotebookPage
|
from dzgui.const.enum import NotebookPage
|
||||||
@@ -37,6 +31,7 @@ if TYPE_CHECKING:
|
|||||||
from dzgui.config.userprefs import UserPrefs
|
from dzgui.config.userprefs import UserPrefs
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -46,10 +41,10 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
|
|
||||||
# TODO: move to controller
|
# TODO: move to controller
|
||||||
# kilometer cache; note, user may change measurement it partway through, flush cache
|
# kilometer cache; note, user may change measurement it partway through, flush cache
|
||||||
#cache: dict[str, int] = {}
|
# cache: dict[str, int] = {}
|
||||||
|
|
||||||
## TODO: move to configs/servers
|
## TODO: move to configs/servers
|
||||||
#def query_history() -> list | None:
|
# def query_history() -> list | None:
|
||||||
# history_file = MainController.get_prefs().paths.history
|
# history_file = MainController.get_prefs().paths.history
|
||||||
# try:
|
# try:
|
||||||
# with open(history_file, "r") as f:
|
# with open(history_file, "r") as f:
|
||||||
@@ -58,7 +53,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# rows = None
|
# rows = None
|
||||||
# return rows
|
# return rows
|
||||||
#
|
#
|
||||||
#def process_tree_option(choice: RowType) -> None:
|
# def process_tree_option(choice: RowType) -> None:
|
||||||
# # server tables
|
# # server tables
|
||||||
# if command == RowType.RESOLVE_IP:
|
# if command == RowType.RESOLVE_IP:
|
||||||
# record = treeview.get_record()
|
# record = treeview.get_record()
|
||||||
@@ -91,18 +86,18 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# return
|
# return
|
||||||
#
|
#
|
||||||
## TODO: belongs in model
|
## TODO: belongs in model
|
||||||
#def str_to_record(record: str) -> Record | None:
|
# def str_to_record(record: str) -> Record | None:
|
||||||
# r = record.split(":")
|
# r = record.split(":")
|
||||||
# if len(r) != 3:
|
# if len(r) != 3:
|
||||||
# return None
|
# return None
|
||||||
# return Record(r[0], int(r[1]), int(r[2]))
|
# return Record(r[0], int(r[1]), int(r[2]))
|
||||||
#
|
#
|
||||||
## TODO: ibid
|
## TODO: ibid
|
||||||
#def record_to_str(record: Record) -> str:
|
# def record_to_str(record: Record) -> str:
|
||||||
# return f"{record.ip}:{record.gameport}:{record.qport}"
|
# return f"{record.ip}:{record.gameport}:{record.qport}"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def connect_by_ip(enum: RowType, response: str) -> None:
|
# def connect_by_ip(enum: RowType, response: str) -> None:
|
||||||
# def _prep(response: str) -> None:
|
# def _prep(response: str) -> None:
|
||||||
# record = Servers.validate_ip(response)
|
# record = Servers.validate_ip(response)
|
||||||
# proc = treeview.prepare_connection(record)
|
# proc = treeview.prepare_connection(record)
|
||||||
@@ -114,7 +109,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# return
|
# return
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def connect_by_id(enum: RowType, uid: str, key: str) -> None:
|
# def connect_by_id(enum: RowType, uid: str, key: str) -> None:
|
||||||
# def _prep(key: str, response: str) -> None:
|
# def _prep(key: str, response: str) -> None:
|
||||||
# # TODO: if response is non numeric, raise dialog
|
# # TODO: if response is non numeric, raise dialog
|
||||||
# if response.isnumeric() is False:
|
# if response.isnumeric() is False:
|
||||||
@@ -139,6 +134,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
class OuterWindow(Gtk.Window):
|
class OuterWindow(Gtk.Window):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__(title=APP_NAME, border_width=10, icon_name=APP_NAME_LOWER)
|
super().__init__(title=APP_NAME, border_width=10, icon_name=APP_NAME_LOWER)
|
||||||
@@ -168,9 +164,7 @@ class OuterWindow(Gtk.Window):
|
|||||||
MainController.loaded = True
|
MainController.loaded = True
|
||||||
MainController.populate_model()
|
MainController.populate_model()
|
||||||
|
|
||||||
def _on_delete_event(
|
def _on_delete_event(self, window: "OuterWindow", event: Gdk.EventKey) -> None:
|
||||||
self, window: "OuterWindow", event: Gdk.EventKey
|
|
||||||
) -> None:
|
|
||||||
self.halt_proc_and_quit()
|
self.halt_proc_and_quit()
|
||||||
|
|
||||||
def halt_proc_and_quit(self) -> None:
|
def halt_proc_and_quit(self) -> None:
|
||||||
@@ -316,7 +310,7 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore
|
|||||||
MainController.set_crumbs(crumbs)
|
MainController.set_crumbs(crumbs)
|
||||||
|
|
||||||
if status is False:
|
if status is False:
|
||||||
MainController.set_statusbar("")
|
MainController.set_statusbar("", "")
|
||||||
if enum is NotebookPage.SERVERS:
|
if enum is NotebookPage.SERVERS:
|
||||||
MainController.present_servers()
|
MainController.present_servers()
|
||||||
|
|
||||||
@@ -351,8 +345,20 @@ class Grid(Gtk.Grid):
|
|||||||
els = (
|
els = (
|
||||||
(self.crumb_box, self.notebook, Gtk.PositionType.TOP, MAX_COLS, SINGLE_ROW),
|
(self.crumb_box, self.notebook, Gtk.PositionType.TOP, MAX_COLS, SINGLE_ROW),
|
||||||
(self.conpan, self.notebook, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW),
|
(self.conpan, self.notebook, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW),
|
||||||
(self.statusbar, self.conpan, Gtk.PositionType.BOTTOM, MAX_COLS, SINGLE_ROW),
|
(
|
||||||
(self.right_panel, self.notebook, Gtk.PositionType.RIGHT, SINGLE_COL, MAX_ROWS),
|
self.statusbar,
|
||||||
|
self.conpan,
|
||||||
|
Gtk.PositionType.BOTTOM,
|
||||||
|
MAX_COLS,
|
||||||
|
SINGLE_ROW,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
self.right_panel,
|
||||||
|
self.notebook,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
SINGLE_COL,
|
||||||
|
MAX_ROWS,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
for el, sibling, pos, h_span, v_span in els:
|
for el, sibling, pos, h_span, v_span in els:
|
||||||
self.attach_next_to(el, sibling, pos, h_span, v_span)
|
self.attach_next_to(el, sibling, pos, h_span, v_span)
|
||||||
@@ -372,7 +378,7 @@ class Grid(Gtk.Grid):
|
|||||||
def toggle_refresh_button(self, state: bool) -> None:
|
def toggle_refresh_button(self, state: bool) -> None:
|
||||||
self.right_panel.refresh_button.set_visible(state)
|
self.right_panel.refresh_button.set_visible(state)
|
||||||
|
|
||||||
# TODO make this method internal to Statusbar
|
# TODO: make this method internal to Statusbar
|
||||||
def get_breadcrumbs(self) -> str:
|
def get_breadcrumbs(self) -> str:
|
||||||
return self.breadcrumbs.get_text()
|
return self.breadcrumbs.get_text()
|
||||||
|
|
||||||
@@ -397,9 +403,7 @@ class App(Gtk.Application):
|
|||||||
)
|
)
|
||||||
self.win.add_accel_group(accel)
|
self.win.add_accel_group(accel)
|
||||||
|
|
||||||
GLib.unix_signal_add(
|
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._catch_sigint)
|
||||||
GLib.PRIORITY_DEFAULT, signal.SIGINT, self._catch_sigint
|
|
||||||
)
|
|
||||||
Gtk.main()
|
Gtk.main()
|
||||||
|
|
||||||
def _catch_sigint(self) -> Literal[True]:
|
def _catch_sigint(self) -> Literal[True]:
|
||||||
@@ -415,9 +419,11 @@ class App(Gtk.Application):
|
|||||||
) -> None:
|
) -> None:
|
||||||
self.win.halt_proc_and_quit()
|
self.win.halt_proc_and_quit()
|
||||||
|
|
||||||
|
|
||||||
MainController = Controller()
|
MainController = Controller()
|
||||||
|
|
||||||
# TODO: icon sanity check, log result
|
# TODO: icon sanity check, log result
|
||||||
#theme = Gtk.IconTheme.get_default()
|
# theme = Gtk.IconTheme.get_default()
|
||||||
#icons = theme.list_icons(None)
|
# icons = theme.list_icons(None)
|
||||||
#print("steam_tray_mono" in icons)
|
# print("steam_tray_mono" in icons)
|
||||||
|
# FIXME:
|
||||||
@@ -93,6 +93,9 @@ class RefreshButton(IconTextButton):
|
|||||||
self.connect("clicked", self._on_refresh_clicked)
|
self.connect("clicked", self._on_refresh_clicked)
|
||||||
|
|
||||||
def _on_refresh_clicked(self, button: Self) -> None:
|
def _on_refresh_clicked(self, button: Self) -> None:
|
||||||
|
# TODO: get page enum
|
||||||
|
print(self.controller.mediator.notebook.get_page_by_enum())
|
||||||
|
# if .MODS, .LOG, .OPTIONS, reload in place
|
||||||
self.set_sensitive(False)
|
self.set_sensitive(False)
|
||||||
self.show_time(True)
|
self.show_time(True)
|
||||||
GLib.timeout_add_seconds(1, self.decrement)
|
GLib.timeout_add_seconds(1, self.decrement)
|
||||||
|
|||||||
@@ -26,13 +26,14 @@ class InfoEventBox(Gtk.EventBox):
|
|||||||
self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing
|
self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing
|
||||||
) -> None:
|
) -> None:
|
||||||
self.icon.set_opacity(1)
|
self.icon.set_opacity(1)
|
||||||
self.parent.controller.set_statusbar(self.text)
|
self.parent.controller.set_statusbar(self.text, "Options")
|
||||||
|
|
||||||
def _on_leave_tooltip(
|
def _on_leave_tooltip(
|
||||||
self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing
|
self, eventbox: Gtk.EventBox, eventcrossing: Gdk.EventCrossing
|
||||||
) -> None:
|
) -> None:
|
||||||
self.icon.set_opacity(0.8)
|
self.icon.set_opacity(0.8)
|
||||||
self.parent.controller.set_statusbar("")
|
#self.parent.controller.set_statusbar("", "Options")
|
||||||
|
self.parent.controller.remove_statusbar("Options")
|
||||||
|
|
||||||
def set_text(self, text: str) -> None:
|
def set_text(self, text: str) -> None:
|
||||||
self.text = text
|
self.text = text
|
||||||
@@ -19,6 +19,7 @@ class Statusbar(Gtk.Grid):
|
|||||||
|
|
||||||
help_text = strings.statusbar_helptext
|
help_text = strings.statusbar_helptext
|
||||||
|
|
||||||
|
self.context: int
|
||||||
self.statusbar = Gtk.Statusbar()
|
self.statusbar = Gtk.Statusbar()
|
||||||
|
|
||||||
self.spinner = Gtk.Spinner()
|
self.spinner = Gtk.Spinner()
|
||||||
@@ -31,7 +32,7 @@ class Statusbar(Gtk.Grid):
|
|||||||
self.attach_next_to(self.spinner, self.statusbar, Gtk.PositionType.RIGHT, 3, 1)
|
self.attach_next_to(self.spinner, self.statusbar, Gtk.PositionType.RIGHT, 3, 1)
|
||||||
self.attach_next_to(self.status_right_label, self.spinner, Gtk.PositionType.RIGHT, 3, 1)
|
self.attach_next_to(self.status_right_label, self.spinner, Gtk.PositionType.RIGHT, 3, 1)
|
||||||
|
|
||||||
self.set_text(help_text)
|
self.set_text(help_text, "Help")
|
||||||
self.players = ""
|
self.players = ""
|
||||||
|
|
||||||
def get_text(self) -> str:
|
def get_text(self) -> str:
|
||||||
@@ -39,20 +40,41 @@ class Statusbar(Gtk.Grid):
|
|||||||
label = area.get_children()[0]
|
label = area.get_children()[0]
|
||||||
return label.get_text()
|
return label.get_text()
|
||||||
|
|
||||||
def set_text(self, string: str) -> None:
|
def set_text(self, string: str, context: str) -> None:
|
||||||
if string is None:
|
# if string is None:
|
||||||
return
|
# return
|
||||||
meta = self.statusbar.get_context_id("Statusbar")
|
meta = self.statusbar.get_context_id(context)
|
||||||
|
#tv = self.controller.get_active_treeview()
|
||||||
|
#cur_context = tv.get_enum()
|
||||||
|
#cid = self.get_context_by_enum(cur_context)
|
||||||
|
#if cid != meta:
|
||||||
|
# print("requested: ", meta)
|
||||||
|
# print("current: ", cid)
|
||||||
|
# return
|
||||||
# TODO: substacks
|
# TODO: substacks
|
||||||
# get_context_id(ServerTab)
|
# get_context_id(ServerTab)
|
||||||
self.statusbar.push(meta, string)
|
self.statusbar.push(meta, string)
|
||||||
|
#self.set_context(meta)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: type checking
|
||||||
|
# def get_context_by_enum(self, context: "ServerTab") -> int:
|
||||||
|
# cid = self.statusbar.get_context_id(str(context))
|
||||||
|
# # TODO: substacks
|
||||||
|
# return cid
|
||||||
|
#
|
||||||
|
# def get_context(self) -> int:
|
||||||
|
# return self.context
|
||||||
|
#
|
||||||
|
# def set_context(self, context: int) -> None:
|
||||||
|
# self.context = context
|
||||||
|
|
||||||
def refresh(self, row: "RowType") -> None:
|
def refresh(self, row: "RowType") -> None:
|
||||||
if row is None:
|
if row is None:
|
||||||
formatted = ""
|
formatted = ""
|
||||||
else:
|
else:
|
||||||
formatted = self.format_metadata(row)
|
formatted = self.format_metadata(row)
|
||||||
self.set_text(formatted)
|
self.set_text(formatted, "Help")
|
||||||
|
|
||||||
def append_distance(self, dist: str) -> None:
|
def append_distance(self, dist: str) -> None:
|
||||||
# TODO: process strings in controller
|
# TODO: process strings in controller
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class ServerNotebook(Gtk.ScrolledWindow):
|
|||||||
def _on_page_changed(self, notebook: Gtk.Notebook, child: Gtk.Widget, index: int) -> None:
|
def _on_page_changed(self, notebook: Gtk.Notebook, child: Gtk.Widget, index: int) -> None:
|
||||||
if self.controller.loaded is False:
|
if self.controller.loaded is False:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# self.controller.remove_statusbar("Servers")
|
||||||
# TODO: abstract
|
# TODO: abstract
|
||||||
label = self.notebook.get_tab_label_text(child)
|
label = self.notebook.get_tab_label_text(child)
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,24 @@
|
|||||||
import logging
|
import logging
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import subprocess
|
|
||||||
from typing import Self
|
from typing import Self
|
||||||
|
|
||||||
import gi
|
from dzgui.const.enum import ContextMenu, ContextMenuGroup, FilterMode, ServerTab
|
||||||
gi.require_version("Gtk", "3.0")
|
|
||||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
|
||||||
|
|
||||||
from dzgui.const.enum import (
|
|
||||||
ContextMenu,
|
|
||||||
ContextMenuGroup,
|
|
||||||
RowType,
|
|
||||||
)
|
|
||||||
from dzgui.const.constants import UDP_PORT
|
|
||||||
from dzgui.const.enum import FilterMode, ServerTab
|
|
||||||
from dzgui.api.servers import Record
|
from dzgui.api.servers import Record
|
||||||
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.keys import is_navkey
|
from dzgui.util.keys import is_navkey
|
||||||
from dzgui.util import strings
|
from dzgui.util import strings
|
||||||
from typing import Any, 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
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -31,6 +26,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
# TODO: restore missing methods
|
# TODO: restore missing methods
|
||||||
|
|
||||||
|
|
||||||
class EnumeratedMenuItem(Gtk.MenuItem):
|
class EnumeratedMenuItem(Gtk.MenuItem):
|
||||||
def __init__(self, enum: ContextMenu):
|
def __init__(self, enum: ContextMenu):
|
||||||
super().__init__(label=enum.dict["label"])
|
super().__init__(label=enum.dict["label"])
|
||||||
@@ -38,10 +34,11 @@ class EnumeratedMenuItem(Gtk.MenuItem):
|
|||||||
|
|
||||||
|
|
||||||
class ServerTreeView(TreeView):
|
class ServerTreeView(TreeView):
|
||||||
__gsignals__ = {
|
__gsignals__ = {"on_distcalc_started": (GObject.SignalFlags.RUN_FIRST, None, ())}
|
||||||
"on_distcalc_started": (GObject.SignalFlags.RUN_FIRST, None, ())
|
|
||||||
}
|
def __init__(
|
||||||
def __init__(self, controller: "Controller", enum: ServerTab, menu: ContextMenuGroup) -> None:
|
self, controller: "Controller", enum: ServerTab, menu: ContextMenuGroup
|
||||||
|
) -> None:
|
||||||
super().__init__(controller)
|
super().__init__(controller)
|
||||||
|
|
||||||
QUEUE_CHECK_DELAY = 200
|
QUEUE_CHECK_DELAY = 200
|
||||||
@@ -181,11 +178,11 @@ class ServerTreeView(TreeView):
|
|||||||
case Gdk.KEY_j:
|
case Gdk.KEY_j:
|
||||||
if ind == len(children) - 1:
|
if ind == len(children) - 1:
|
||||||
return True
|
return True
|
||||||
menu.select_item(children[ind+1])
|
menu.select_item(children[ind + 1])
|
||||||
case Gdk.KEY_k:
|
case Gdk.KEY_k:
|
||||||
if ind - 1 < 0:
|
if ind - 1 < 0:
|
||||||
return True
|
return True
|
||||||
menu.select_item(children[ind-1])
|
menu.select_item(children[ind - 1])
|
||||||
case Gdk.KEY_g:
|
case Gdk.KEY_g:
|
||||||
menu.select_item(children[0])
|
menu.select_item(children[0])
|
||||||
case Gdk.KEY_G:
|
case Gdk.KEY_G:
|
||||||
@@ -207,9 +204,6 @@ class ServerTreeView(TreeView):
|
|||||||
"""
|
"""
|
||||||
Propagate width change to other tabs
|
Propagate width change to other tabs
|
||||||
"""
|
"""
|
||||||
title = col.get_title()
|
|
||||||
size = col.get_width()
|
|
||||||
|
|
||||||
# NOTE: get final width after drag action completes
|
# NOTE: get final width after drag action completes
|
||||||
GLib.idle_add(self.controller.propagate_column_width, col)
|
GLib.idle_add(self.controller.propagate_column_width, col)
|
||||||
|
|
||||||
@@ -223,8 +217,9 @@ class ServerTreeView(TreeView):
|
|||||||
return
|
return
|
||||||
# TODO:
|
# TODO:
|
||||||
self.controller.mediator.statusbar.spinner.start()
|
self.controller.mediator.statusbar.spinner.start()
|
||||||
ip = record.ip
|
self.current_proc = CalcDist(
|
||||||
self.current_proc = CalcDist(record.ip, self.queue, self.controller)
|
record.ip, self.get_enum(), self.queue, self.controller
|
||||||
|
)
|
||||||
self.current_proc.start()
|
self.current_proc.start()
|
||||||
|
|
||||||
def _check_result_queue(self) -> Literal[True]:
|
def _check_result_queue(self) -> Literal[True]:
|
||||||
@@ -235,13 +230,15 @@ class ServerTreeView(TreeView):
|
|||||||
latest_result = self.queue.get()
|
latest_result = self.queue.get()
|
||||||
|
|
||||||
cache = self.controller.get_dist_cache()
|
cache = self.controller.get_dist_cache()
|
||||||
|
|
||||||
if latest_result:
|
if latest_result:
|
||||||
|
# NOTE: if CalcDist was spawned on other tab
|
||||||
addr = latest_result[0]
|
addr = latest_result[0]
|
||||||
haversine = latest_result[1]
|
haversine = latest_result[1]
|
||||||
if addr not in cache:
|
if addr not in cache:
|
||||||
cache[addr] = haversine
|
cache[addr] = haversine
|
||||||
# FIXME
|
# FIXME
|
||||||
self.controller.set_statusbar_dist(haversine)
|
self.controller.set_statusbar_dist(haversine, self.get_enum())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _on_server_keypress(
|
def _on_server_keypress(
|
||||||
@@ -308,7 +305,7 @@ class ServerTreeView(TreeView):
|
|||||||
mod_context_items = [ContextMenu.OPEN_WORKSHOP, ContextMenu.DELETE_MOD]
|
mod_context_items = [ContextMenu.OPEN_WORKSHOP, ContextMenu.DELETE_MOD]
|
||||||
|
|
||||||
# TODO: dynamic menu entries
|
# TODO: dynamic menu entries
|
||||||
#for row in items:
|
# for row in items:
|
||||||
# if row == ContextMenu.ADD_SERVER:
|
# if row == ContextMenu.ADD_SERVER:
|
||||||
# if self.is_in_favs():
|
# if self.is_in_favs():
|
||||||
# row = ContextMenu.REMOVE_SERVER
|
# row = ContextMenu.REMOVE_SERVER
|
||||||
@@ -326,17 +323,13 @@ class ServerTreeView(TreeView):
|
|||||||
if event.type is Gdk.EventType.KEY_PRESS and event.keyval is Gdk.KEY_l:
|
if event.type is Gdk.EventType.KEY_PRESS and event.keyval is Gdk.KEY_l:
|
||||||
if self.is_selection_empty():
|
if self.is_selection_empty():
|
||||||
return
|
return
|
||||||
self.menu.popup_at_widget(
|
self.menu.popup_at_widget(widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST)
|
||||||
widget, Gdk.Gravity.CENTER, Gdk.Gravity.WEST
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.menu.popup_at_pointer(event)
|
self.menu.popup_at_pointer(event)
|
||||||
self.menu.select_first(False)
|
self.menu.select_first(False)
|
||||||
|
|
||||||
def _parent_row_activated(self,
|
def _parent_row_activated(
|
||||||
tree: TreeView,
|
self, tree: TreeView, path: Gtk.TreePath, column: Gtk.TreeViewColumn
|
||||||
path: Gtk.TreePath,
|
|
||||||
column: Gtk.TreeViewColumn
|
|
||||||
) -> None:
|
) -> None:
|
||||||
# TODO: process server connection
|
# TODO: process server connection
|
||||||
# TODO: get record
|
# TODO: get record
|
||||||
|
|||||||
Reference in new issue
Block a user