mirror of
https://github.com/aclist/dztui.git
synced 2026-10-30 14:42:54 +01:00
feat: live input validation
This commit is contained in:
1 parent
8a1c5bea6c
commit
3c82b71f76
8 files changed
+71
-38
No files matched your search
@@ -151,11 +151,9 @@ class ModelManager:
|
|||||||
if prior_map == "All maps":
|
if prior_map == "All maps":
|
||||||
rows = self.filter_map(filters)
|
rows = self.filter_map(filters)
|
||||||
else:
|
else:
|
||||||
AppNav.right_panel.ping.set_sensitive(True)
|
|
||||||
rows = self.filter_toggle_on(filters, *args)
|
rows = self.filter_toggle_on(filters, *args)
|
||||||
|
|
||||||
case FilterMode.KEYWORD:
|
case FilterMode.KEYWORD:
|
||||||
AppNav.right_panel.ping.set_sensitive(True)
|
|
||||||
rows = self.filter_toggle_on(filters, *args)
|
rows = self.filter_toggle_on(filters, *args)
|
||||||
|
|
||||||
case FilterMode.TOGGLE_OFF:
|
case FilterMode.TOGGLE_OFF:
|
||||||
@@ -164,7 +162,6 @@ class ModelManager:
|
|||||||
rows = self.filtered
|
rows = self.filtered
|
||||||
|
|
||||||
case FilterMode.TOGGLE_ON:
|
case FilterMode.TOGGLE_ON:
|
||||||
AppNav.right_panel.ping.set_sensitive(True)
|
|
||||||
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:
|
||||||
|
|||||||
+8
-1
@@ -11,11 +11,18 @@ def add_class(widget: Gtk.Widget, label: str) -> None:
|
|||||||
context = widget.get_style_context()
|
context = widget.get_style_context()
|
||||||
context.add_class(label)
|
context.add_class(label)
|
||||||
|
|
||||||
# TODO: def remove_class()
|
|
||||||
|
def remove_class(widget: Gtk.Widget, label: str) -> None:
|
||||||
|
context = widget.get_style_context()
|
||||||
|
context.remove_class(label)
|
||||||
|
|
||||||
|
|
||||||
def load_css() -> None:
|
def load_css() -> None:
|
||||||
# TODO: consider storing this in a data file
|
# TODO: consider storing this in a data file
|
||||||
css = """
|
css = """
|
||||||
|
.invalid-entry {
|
||||||
|
border-color: red;
|
||||||
|
}
|
||||||
.frame {
|
.frame {
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-11
@@ -80,14 +80,9 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# return rows
|
# return rows
|
||||||
#
|
#
|
||||||
#def process_tree_option(choice: RowType) -> None:
|
#def process_tree_option(choice: RowType) -> None:
|
||||||
# context = AppNav.treeview.view
|
|
||||||
# command = choice
|
|
||||||
# cmd_string = command.dict["label"]
|
|
||||||
# logger.info(f"Parsing tree option '{command}' for the context '{context}'")
|
|
||||||
#
|
|
||||||
# # server tables
|
# # server tables
|
||||||
# if command == RowType.RESOLVE_IP:
|
# if command == RowType.RESOLVE_IP:
|
||||||
# record = AppNav.treeview.get_record()
|
# record = treeview.get_record()
|
||||||
# wait_msg = command.dict["wait_msg"]
|
# wait_msg = command.dict["wait_msg"]
|
||||||
# show_wait_dialog = True
|
# show_wait_dialog = True
|
||||||
#
|
#
|
||||||
@@ -103,12 +98,12 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# if command == RowType.QUICK_CONNECT:
|
# if command == RowType.QUICK_CONNECT:
|
||||||
# record = MainController.query_config(Preferences.FAV_SRV)
|
# record = MainController.query_config(Preferences.FAV_SRV)
|
||||||
# if record == "":
|
# if record == "":
|
||||||
# AppNav.window.spawn_dialog("No favorite server currently set", Popup.NOTIFY)
|
# spawn_dialog("No favorite server currently set", Popup.NOTIFY)
|
||||||
# return
|
# return
|
||||||
#
|
#
|
||||||
# record = str_to_record(record)
|
# record = str_to_record(record)
|
||||||
# thread_new_with_dialog(
|
# thread_new_with_dialog(
|
||||||
# AppNav.treeview.prepare_connection,
|
# treeview.prepare_connection,
|
||||||
# parse_shell_output,
|
# parse_shell_output,
|
||||||
# "Querying server",
|
# "Querying server",
|
||||||
# command,
|
# command,
|
||||||
@@ -131,7 +126,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
#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 = AppNav.treeview.prepare_connection(record)
|
# proc = treeview.prepare_connection(record)
|
||||||
# return proc
|
# return proc
|
||||||
#
|
#
|
||||||
# thread_new_with_dialog(
|
# thread_new_with_dialog(
|
||||||
@@ -155,7 +150,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# logger.critical(e)
|
# logger.critical(e)
|
||||||
# # raise dialog
|
# # raise dialog
|
||||||
# return
|
# return
|
||||||
# # proc = AppNav.treeview.prepare_connection(record)
|
# # proc = treeview.prepare_connection(record)
|
||||||
# # return proc
|
# # return proc
|
||||||
#
|
#
|
||||||
# #thread_new_with_dialog(
|
# #thread_new_with_dialog(
|
||||||
@@ -172,7 +167,7 @@ warnings.filterwarnings("ignore", ".*g_value_get_int", Warning)
|
|||||||
# if enum == RowType.CONN_BY_ID:
|
# if enum == RowType.CONN_BY_ID:
|
||||||
# key = MainController.query_config(Preferences.BM)
|
# key = MainController.query_config(Preferences.BM)
|
||||||
# if len(key) == 0:
|
# if len(key) == 0:
|
||||||
# AppNav.window.spawn_dialog(
|
# spawn_dialog(
|
||||||
# "No Battlemetrics API key is set; see Options", Popup.NOTIFY
|
# "No Battlemetrics API key is set; see Options", Popup.NOTIFY
|
||||||
# )
|
# )
|
||||||
# return
|
# return
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from dzgui.api.servers import validate_ip
|
||||||
|
from dzgui.util.css import add_class, remove_class
|
||||||
from dzgui.util.strings import connect_panel
|
from dzgui.util.strings import connect_panel
|
||||||
from dzgui.views.components.buttons import WebButton
|
from dzgui.views.components.buttons import WebButton
|
||||||
from dzgui.views.components.labels import BoldLabel
|
from dzgui.views.components.labels import BoldLabel
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import Gtk # noqa E402
|
from gi.repository import Gtk, Gdk # noqa E402
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from dzgui.controllers.mc import Controller
|
from dzgui.controllers.mc import Controller
|
||||||
@@ -17,6 +19,7 @@ class ConnectPanel(Gtk.Frame):
|
|||||||
|
|
||||||
COLS = 1
|
COLS = 1
|
||||||
ROWS = 1
|
ROWS = 1
|
||||||
|
self.classname = "invalid-entry"
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
self.entry = Gtk.Entry(
|
self.entry = Gtk.Entry(
|
||||||
@@ -24,14 +27,16 @@ class ConnectPanel(Gtk.Frame):
|
|||||||
hexpand=True,
|
hexpand=True,
|
||||||
tooltip_text=connect_panel.entry_tooltip
|
tooltip_text=connect_panel.entry_tooltip
|
||||||
)
|
)
|
||||||
|
self.entry.connect("key-press-event", self._on_entry_keypress)
|
||||||
|
self.entry.connect("changed", self._on_text_changed)
|
||||||
|
|
||||||
# TODO: get ip as well?
|
# TODO: get ip as well?
|
||||||
user_fav = self.controller.get_favorite_label()
|
user_fav = self.controller.get_favorite_label()
|
||||||
|
|
||||||
server_name = user_fav if user_fav is not None else connect_panel.no_fav
|
server_name = user_fav if user_fav is not None else connect_panel.no_fav
|
||||||
|
self.fav_label = Gtk.Label(label=server_name, halign=Gtk.Align.START)
|
||||||
scrollable_label = Gtk.ScrolledWindow()
|
scrollable_label = Gtk.ScrolledWindow()
|
||||||
label = Gtk.Label(label=server_name, halign=Gtk.Align.START)
|
scrollable_label.add(self.fav_label)
|
||||||
scrollable_label.add(label)
|
|
||||||
|
|
||||||
self.fav_button = Gtk.Button(label=connect_panel.connect,
|
self.fav_button = Gtk.Button(label=connect_panel.connect,
|
||||||
tooltip_text=connect_panel.connect_tooltip
|
tooltip_text=connect_panel.connect_tooltip
|
||||||
@@ -70,3 +75,39 @@ class ConnectPanel(Gtk.Frame):
|
|||||||
self.grid.attach_next_to(el, sibling, pos, h_span, v_span)
|
self.grid.attach_next_to(el, sibling, pos, h_span, v_span)
|
||||||
|
|
||||||
self.add(self.grid)
|
self.add(self.grid)
|
||||||
|
|
||||||
|
def mark_valid(self) -> None:
|
||||||
|
self.conn_server.set_sensitive(True)
|
||||||
|
self.add_server.set_sensitive(True)
|
||||||
|
remove_class(self.entry, self.classname)
|
||||||
|
|
||||||
|
def mark_invalid(self) -> None:
|
||||||
|
self.conn_server.set_sensitive(False)
|
||||||
|
self.add_server.set_sensitive(False)
|
||||||
|
add_class(self.entry, self.classname)
|
||||||
|
|
||||||
|
def _on_text_changed(self, entry: Gtk.Entry) -> None:
|
||||||
|
text = entry.get_text()
|
||||||
|
if len(text) < 1:
|
||||||
|
self.conn_server.set_sensitive(False)
|
||||||
|
self.add_server.set_sensitive(False)
|
||||||
|
remove_class(entry, self.classname)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
validate_ip(text)
|
||||||
|
self.mark_valid()
|
||||||
|
except Exception as e:
|
||||||
|
if text.isdigit():
|
||||||
|
self.mark_valid()
|
||||||
|
else:
|
||||||
|
self.mark_invalid()
|
||||||
|
|
||||||
|
def set_fav_label(self, text: str) -> None:
|
||||||
|
# TODO: called by controller when changing fav
|
||||||
|
self.fav_label.set_text(text)
|
||||||
|
|
||||||
|
def _on_entry_keypress(self, entry: Gtk.Entry, event: Gdk.EventKey) -> None:
|
||||||
|
if event.keyval == Gdk.KEY_Escape:
|
||||||
|
# NOTE: unselect text
|
||||||
|
entry.select_region(0, 0)
|
||||||
|
self.controller.grab_active_treeview()
|
||||||
@@ -108,9 +108,8 @@ class FilterPanel(Gtk.Box):
|
|||||||
def set_unique_maps(self, maps: list) -> None:
|
def set_unique_maps(self, maps: list) -> None:
|
||||||
if len(maps) < 1:
|
if len(maps) < 1:
|
||||||
return
|
return
|
||||||
# FIXME: clear typehints
|
u_maps = set([row[1] for row in maps])
|
||||||
u_maps = set([row[1] for row in maps]) # type: ignore
|
u_maps = sorted(u_maps)
|
||||||
u_maps = sorted(u_maps) # type: ignore
|
|
||||||
for m in u_maps:
|
for m in u_maps:
|
||||||
self.controller.append_map([m])
|
self.controller.append_map([m])
|
||||||
self.maps_hr.append(m)
|
self.maps_hr.append(m)
|
||||||
@@ -124,13 +123,6 @@ class FilterPanel(Gtk.Box):
|
|||||||
filters.append(k)
|
filters.append(k)
|
||||||
return tuple(filters)
|
return tuple(filters)
|
||||||
|
|
||||||
# used on personal/local server lists
|
|
||||||
def enable_all_filters(self) -> None:
|
|
||||||
for check in self.checks:
|
|
||||||
check.set_active(True)
|
|
||||||
for k in self.enabled_filters:
|
|
||||||
self.enabled_filters[k] = True
|
|
||||||
|
|
||||||
def reinit_panel(self) -> None:
|
def reinit_panel(self) -> None:
|
||||||
self.keyword_entry.set_text("")
|
self.keyword_entry.set_text("")
|
||||||
self.keyword_filter = ""
|
self.keyword_filter = ""
|
||||||
|
|||||||
@@ -52,10 +52,9 @@ class RightPanel(Gtk.Box):
|
|||||||
def _on_refresh_clicked(self, button: RefreshButton) -> None:
|
def _on_refresh_clicked(self, button: RefreshButton) -> None:
|
||||||
self.controller.refresh_tree()
|
self.controller.refresh_tree()
|
||||||
|
|
||||||
|
# TODO: reference
|
||||||
#def _on_ping_clicked(self, button: Gtk.Button) -> None:
|
#def _on_ping_clicked(self, button: Gtk.Button) -> None:
|
||||||
# # TODO
|
|
||||||
# block_signals()
|
# block_signals()
|
||||||
|
|
||||||
# def _update_pings():
|
# def _update_pings():
|
||||||
# # TODO
|
# # TODO
|
||||||
# rows = ModelManager.get_filtered()
|
# rows = ModelManager.get_filtered()
|
||||||
@@ -71,17 +70,17 @@ class RightPanel(Gtk.Box):
|
|||||||
# temp_model[path][9] = res.ping
|
# temp_model[path][9] = res.ping
|
||||||
# ModelManager.ping_cache[res.addr] = res.ping
|
# ModelManager.ping_cache[res.addr] = res.ping
|
||||||
# # TODO: drop/rewrite
|
# # TODO: drop/rewrite
|
||||||
# self.AppNav.treeview.set_model(temp_model)
|
# treeview.set_model(temp_model)
|
||||||
# self.AppNav.treeview.wait_dialog.destroy()
|
# treeview.wait_dialog.destroy()
|
||||||
# self.AppNav.treeview.grab_focus()
|
# treeview.grab_focus()
|
||||||
|
|
||||||
# # TODO:
|
# # TODO:
|
||||||
# unblock_signals()
|
# unblock_signals()
|
||||||
|
|
||||||
# temp_model = self.AppNav.treeview.get_model()
|
# temp_model = self.AppNav.treeview.get_model()
|
||||||
# self.AppNav.treeview.set_model(None)
|
# treeview.set_model(None)
|
||||||
# self.AppNav.treeview.wait_dialog = GenericDialog("Pinging servers", Popup.WAIT)
|
# treeview.wait_dialog = GenericDialog("Pinging servers", Popup.WAIT)
|
||||||
# self.AppNav.treeview.wait_dialog.show_all()
|
# treeview.wait_dialog.show_all()
|
||||||
# thread = threading.Thread(target=_update_pings, args=())
|
# thread = threading.Thread(target=_update_pings, args=())
|
||||||
# thread.start()
|
# thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -76,14 +76,14 @@ class ModDialog(GenericDialog):
|
|||||||
# dialog.destroy()
|
# dialog.destroy()
|
||||||
# # TODO: natively implemented
|
# # TODO: natively implemented
|
||||||
# #if data.returncode == 1:
|
# #if data.returncode == 1:
|
||||||
# # AppNav.window.spawn_dialog(strings.server_error, Popup.NOTIFY)
|
# # spawn_dialog(strings.server_error, Popup.NOTIFY)
|
||||||
# # return
|
# # return
|
||||||
# self.show_all()
|
# self.show_all()
|
||||||
# self.set_markup(f"Modlist ({mod_count} mods)")
|
# self.set_markup(f"Modlist ({mod_count} mods)")
|
||||||
# self.run()
|
# self.run()
|
||||||
# self.destroy()
|
# self.destroy()
|
||||||
|
|
||||||
# record = AppNav.treeview.get_record()
|
# record = treeview.get_record()
|
||||||
# if not record:
|
# if not record:
|
||||||
# return
|
# return
|
||||||
|
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ class ServerTreeView(TreeView):
|
|||||||
self.controller.mediator.grid.right_panel.filters_vbox.keyword_entry.grab_focus()
|
self.controller.mediator.grid.right_panel.filters_vbox.keyword_entry.grab_focus()
|
||||||
case Gdk.KEY_m:
|
case Gdk.KEY_m:
|
||||||
self.controller.mediator.grid.right_panel.filters_vbox.maps_entry.grab_focus()
|
self.controller.mediator.grid.right_panel.filters_vbox.maps_entry.grab_focus()
|
||||||
|
case Gdk.KEY_i:
|
||||||
|
self.controller.mediator.grid.conpan.entry.grab_focus()
|
||||||
else:
|
else:
|
||||||
match event.keyval:
|
match event.keyval:
|
||||||
case Gdk.KEY_l | Gdk.KEY_Right:
|
case Gdk.KEY_l | Gdk.KEY_Right:
|
||||||
|
|||||||
Reference in new issue
Block a user