mirror of
https://github.com/aclist/dztui.git
synced 2026-11-09 03:20:44 +01:00
feat: dzgui 7 alpha
This commit is contained in:
1 parent
1acdbd58c5
commit
2e5b771137
150 files changed
+10359
No files matched your search
@@ -0,0 +1,35 @@
|
||||
import textwrap
|
||||
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk # noqa E402
|
||||
|
||||
class EarlyAlertDialog(Gtk.MessageDialog):
|
||||
def __init__(self, string):
|
||||
# TODO: strings
|
||||
super().__init__(
|
||||
title="DZGUI - Dialog",
|
||||
flags=0,
|
||||
text="ERROR",
|
||||
transient_for=None,
|
||||
buttons=Gtk.ButtonsType.OK
|
||||
)
|
||||
ok = self.action_area.get_children()[0]
|
||||
ok.set_label("OK")
|
||||
ok.connect("clicked", Gtk.main_quit)
|
||||
|
||||
msg = textwrap.fill(string, 50)
|
||||
self.format_secondary_text(msg)
|
||||
|
||||
self.action_area.set_margin_bottom(20)
|
||||
self.outer = self.get_content_area()
|
||||
self.outer.set_margin_start(30)
|
||||
self.outer.set_margin_end(30)
|
||||
|
||||
self.set_default_size(250, 100)
|
||||
|
||||
self.connect("delete-event", Gtk.main_quit)
|
||||
self.connect("destroy", Gtk.main_quit)
|
||||
|
||||
self.show_all()
|
||||
Gtk.main()
|
||||
@@ -0,0 +1,80 @@
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
||||
|
||||
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, 0)
|
||||
|
||||
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, 0)
|
||||
|
||||
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
|
||||
@@ -0,0 +1,34 @@
|
||||
from pathlib import Path
|
||||
|
||||
import gi # noqa E402
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Gdk, GLib, GObject
|
||||
|
||||
from dzgui.util.strings import picker
|
||||
|
||||
|
||||
class FilePicker(Gtk.FileChooserDialog):
|
||||
def __init__(self, parent: Gtk.Window) -> None:
|
||||
super().__init__(
|
||||
title=picker.title,
|
||||
action=Gtk.FileChooserAction.SAVE,
|
||||
parent=parent,
|
||||
resizable=True,
|
||||
)
|
||||
self.add_buttons("_Cancel", Gtk.ResponseType.CANCEL)
|
||||
self.add_buttons("_Save", Gtk.ResponseType.OK)
|
||||
self.set_default_response(Gtk.ResponseType.OK)
|
||||
|
||||
self.set_current_name(picker.placeholder)
|
||||
|
||||
def pick_file(self) -> Path | None:
|
||||
res = self.run()
|
||||
if res in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
self.destroy()
|
||||
return None
|
||||
if res == Gtk.ResponseType.OK:
|
||||
file = self.get_filename()
|
||||
if file is not None:
|
||||
self.destroy()
|
||||
return Path(file)
|
||||
return None
|
||||
@@ -0,0 +1,104 @@
|
||||
import textwrap
|
||||
from typing import Any, Literal, TYPE_CHECKING
|
||||
|
||||
from dzgui.const.constants import NO_EXPAND, NO_FILL
|
||||
from dzgui.const.enum import Popup, ButtonType, NotebookPage
|
||||
from dzgui.util import strings
|
||||
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dzgui.controllers.mc import Controller
|
||||
|
||||
class GenericDialog(Gtk.MessageDialog):
|
||||
def __init__(self, controller: "Controller", text: str, mode: Popup):
|
||||
match mode:
|
||||
case Popup.WAIT:
|
||||
dialog_type = Gtk.MessageType.INFO
|
||||
button_type = Gtk.ButtonsType.NONE
|
||||
header_text = strings.wait
|
||||
case Popup.NOTIFY | Popup.RETURN | Popup.QUIT:
|
||||
dialog_type = Gtk.MessageType.INFO
|
||||
button_type = Gtk.ButtonsType.OK
|
||||
header_text = strings.notice
|
||||
case Popup.CONFIRM:
|
||||
dialog_type = Gtk.MessageType.QUESTION
|
||||
button_type = Gtk.ButtonsType.OK_CANCEL
|
||||
header_text = strings.confirmation
|
||||
case Popup.ENTRY:
|
||||
dialog_type = Gtk.MessageType.QUESTION
|
||||
button_type = Gtk.ButtonsType.OK_CANCEL
|
||||
header_text = strings.input_required
|
||||
case Popup.MODLIST:
|
||||
dialog_type = Gtk.MessageType.INFO
|
||||
button_type = Gtk.ButtonsType.OK
|
||||
header_text = strings.modlist
|
||||
case Popup.DETAILS:
|
||||
dialog_type = Gtk.MessageType.INFO
|
||||
button_type = Gtk.ButtonsType.OK
|
||||
header_text = strings.server_details
|
||||
|
||||
# NOTE: steam deck prints <2> if dialog title is same as window title
|
||||
Gtk.MessageDialog.__init__(
|
||||
self,
|
||||
transient_for=controller.mediator.window,
|
||||
message_type=dialog_type,
|
||||
buttons=button_type,
|
||||
text=header_text,
|
||||
secondary_text=textwrap.fill(text, 50),
|
||||
title=strings.dialog_header,
|
||||
modal=True,
|
||||
)
|
||||
|
||||
self.controller = controller
|
||||
|
||||
if mode == Popup.WAIT:
|
||||
dialogBox = self.get_content_area()
|
||||
spinner = Gtk.Spinner()
|
||||
dialogBox.pack_end(spinner, NO_EXPAND, NO_FILL, 0)
|
||||
spinner.start()
|
||||
self.connect("delete-event", self._on_dialog_delete)
|
||||
|
||||
if mode == Popup.RETURN:
|
||||
button_label = strings.main_menu
|
||||
ok = self.action_area.get_children()[0]
|
||||
ok.set_label(button_label)
|
||||
ok.connect("clicked", self._return_to_main_menu)
|
||||
self.connect("delete-event", self._return_to_main_menu)
|
||||
|
||||
if mode == Popup.QUIT:
|
||||
button_label = strings.exit_app
|
||||
ok = self.action_area.get_children()[0]
|
||||
ok.set_label(button_label)
|
||||
ok.connect("clicked", self._quit)
|
||||
self.connect("delete-event", self._quit)
|
||||
|
||||
self.set_default_response(Gtk.ResponseType.OK)
|
||||
self.set_size_request(500, 0)
|
||||
self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
|
||||
|
||||
self.action_area.set_layout(Gtk.ButtonBoxStyle.CENTER)
|
||||
self.action_area.set_margin_bottom(20)
|
||||
self.outer = self.get_content_area()
|
||||
self.outer.set_margin_start(30)
|
||||
self.outer.set_margin_end(30)
|
||||
|
||||
def _quit(self, *args: Any) -> None:
|
||||
self.controller.save_res_and_quit()
|
||||
|
||||
def _on_dialog_delete(
|
||||
self, response_id: Gtk.ResponseType, event: Gdk.Event
|
||||
) -> Literal[True]:
|
||||
"""
|
||||
Prevent manual dialog destruction
|
||||
"""
|
||||
return True
|
||||
|
||||
def _return_to_main_menu(self, widget: Gtk.Widget) -> None:
|
||||
self.controller.open_page(NotebookPage.MAIN)
|
||||
|
||||
def update_label(self, text: str) -> None:
|
||||
self.format_secondary_text(text)
|
||||
@@ -0,0 +1,152 @@
|
||||
from typing import Self
|
||||
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
||||
|
||||
from dzgui.util.import strings
|
||||
|
||||
class LanDialog(Gtk.MessageDialog):
|
||||
"""
|
||||
Performs integer validation on the provided port
|
||||
and blocks if out of range. Returns None if user cancels
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
super().__init__(
|
||||
transient_for=AppNav.window, #FIXME
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.INFO,
|
||||
buttons=Gtk.ButtonsType.OK_CANCEL,
|
||||
text=strings.scan_servers,
|
||||
secondary_text=strings.select_port,
|
||||
title=strings.dialog_header,
|
||||
modal=True,
|
||||
)
|
||||
|
||||
self.set_size_request(500, 0)
|
||||
self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
|
||||
|
||||
buttons = [
|
||||
(strings.default_port, Port.DEFAULT),
|
||||
(strings.custom_port, Port.CUSTOM),
|
||||
]
|
||||
|
||||
self.button_box = Gtk.Box()
|
||||
self.button_box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
self.button_box.active_button = None
|
||||
|
||||
for k, v in buttons:
|
||||
button = Gtk.RadioButton(label=k)
|
||||
button.port = v
|
||||
button.connect("toggled", self._on_button_toggled)
|
||||
self.button_box.add(button)
|
||||
if v == Port.DEFAULT:
|
||||
self.button_box.active_button = button
|
||||
else:
|
||||
button.join_group(self.button_box.active_button)
|
||||
|
||||
self.entry = Gtk.Entry()
|
||||
self.button_box.add(self.entry)
|
||||
self.entry.set_no_show_all(True)
|
||||
|
||||
# TODO: strings
|
||||
self.warn_label = Gtk.Label(label="Invalid port")
|
||||
self.warn_label.set_no_show_all(True)
|
||||
self.button_box.add(self.warn_label)
|
||||
|
||||
content = self.get_content_area()
|
||||
content.pack_start(self.button_box, NO_EXPAND, NO_FILL, 0)
|
||||
content.set_margin_start(30)
|
||||
content.set_margin_end(30)
|
||||
content.show_all()
|
||||
|
||||
self.action_area.set_layout(Gtk.ButtonBoxStyle.CENTER)
|
||||
self.action_area.set_margin_bottom(20)
|
||||
|
||||
self.port = None
|
||||
self.ok = self.action_area.get_children()[1]
|
||||
|
||||
self.connect("response", self._on_dialog_response)
|
||||
self.connect("key-press-event", self._on_keypress)
|
||||
self.connect("delete-event", self.restore_context)
|
||||
|
||||
self.entry.connect("insert-text", self._on_text_typed)
|
||||
self.entry.get_property("buffer").connect(
|
||||
"deleted-text", self._on_text_deleted
|
||||
)
|
||||
|
||||
def _validate(self, text: str) -> None:
|
||||
state = ip.is_valid_port(text)
|
||||
self.ok.set_sensitive(not state)
|
||||
self.warn_label.set_visible(state)
|
||||
|
||||
# TODO: can put in validation method
|
||||
if len(text) == 0:
|
||||
self.warn_label.set_visible(False)
|
||||
|
||||
def _on_text_deleted(
|
||||
self, buffer: Gtk.EntryBuffer, position: int, chars: int
|
||||
) -> None:
|
||||
text = buffer.get_text()
|
||||
self._validate(text)
|
||||
|
||||
def _on_text_typed(
|
||||
self, entry: Gtk.Entry, text: str, length: int, pos: int) -> None:
|
||||
self._validate(entry.get_text() + text)
|
||||
|
||||
def restore_context(self, *args: Any) -> None:
|
||||
context = WindowContext.MAIN_MENU
|
||||
AppNav.treeview.set_view(context)
|
||||
|
||||
def _on_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> None:
|
||||
if event.keyval == Gdk.KEY_Return:
|
||||
if self.ok.is_sensitive():
|
||||
self.response(Gtk.ResponseType.OK)
|
||||
if self.button_box.get_children()[0].is_focus():
|
||||
self.response(Gtk.ResponseType.OK)
|
||||
else:
|
||||
self.restore_context()
|
||||
|
||||
if event.keyval == Gdk.KEY_Up:
|
||||
self.ok.set_sensitive(True)
|
||||
self.entry.set_text("")
|
||||
self.button_box.get_children()[0].grab_focus()
|
||||
|
||||
def _on_dialog_response(
|
||||
self, dialog: Self, response: Gtk.ResponseType
|
||||
) -> None:
|
||||
cancel_events = [
|
||||
Gtk.ResponseType.CLOSE,
|
||||
Gtk.ResponseType.CANCEL,
|
||||
Gtk.ResponseType.DELETE_EVENT,
|
||||
]
|
||||
|
||||
if response in cancel_events:
|
||||
self.restore_context()
|
||||
return
|
||||
|
||||
string = self.entry.get_text()
|
||||
port = self.button_box.active_button.port
|
||||
|
||||
match port:
|
||||
case Port.DEFAULT:
|
||||
self.port = UDP_PORT
|
||||
case Port.CUSTOM:
|
||||
if ip.is_valid_port(string):
|
||||
self.stop_emission_by_name("response")
|
||||
else:
|
||||
self.port = int(string)
|
||||
|
||||
def get_selected_port(self) -> int:
|
||||
return self.port
|
||||
|
||||
def _on_button_toggled(self, button: Gtk.Button) -> None:
|
||||
if button.get_active():
|
||||
self.button_box.active_button = button
|
||||
match button.port:
|
||||
case Port.DEFAULT:
|
||||
self.entry.set_visible(False)
|
||||
case Port.CUSTOM:
|
||||
self.entry.set_visible(True)
|
||||
self.entry.grab_focus()
|
||||
self.ok.set_sensitive(False)
|
||||
@@ -0,0 +1,54 @@
|
||||
import textwrap
|
||||
from typing import Self, TYPE_CHECKING
|
||||
|
||||
from dzgui.const.enum import Popup, Preferences
|
||||
from dzgui.const.constants import NO_EXPAND, NO_FILL
|
||||
from dzgui.util.open_links import open_user_workshop
|
||||
from dzgui.views.dialogs.generic import GenericDialog
|
||||
from dzgui.views.components.web_button import WebButton
|
||||
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dzgui.controllers.mc import Controller
|
||||
|
||||
|
||||
class WorkshopLinkDialog(GenericDialog):
|
||||
def __init__(self, controller: "Controller", text: str, button_label: str, uid: str):
|
||||
super().__init__(controller, text, Popup.NOTIFY)
|
||||
|
||||
text = textwrap.dedent(text)
|
||||
self.dialogBox = self.get_content_area()
|
||||
self.set_default_response(Gtk.ResponseType.OK)
|
||||
self.set_size_request(500, 0)
|
||||
|
||||
"""
|
||||
If the user's ID was successfully parsed from loginusers,
|
||||
a clickable link to their workshop subscriptions is added
|
||||
"""
|
||||
if uid is not None:
|
||||
button = WebButton(label=button_label)
|
||||
button.set_margin_start(60)
|
||||
button.set_margin_end(60)
|
||||
button.connect("clicked", self._on_button_clicked, uid)
|
||||
self.dialogBox.pack_end(button, NO_EXPAND, NO_FILL, 0)
|
||||
|
||||
self.show_all()
|
||||
self.connect("response", self._on_dialog_response)
|
||||
|
||||
def _on_button_clicked(self, button: Gtk.Button, uid: str) -> None:
|
||||
# TODO: currently checks user id on instantiation
|
||||
client = self.controller.query_config(Preferences.CLIENT)
|
||||
open_user_workshop(uid, client)
|
||||
|
||||
def _on_dialog_response(
|
||||
self, dialog: Self, resp: Gtk.ResponseType
|
||||
) -> None:
|
||||
match resp:
|
||||
case Gtk.ResponseType.DELETE_EVENT:
|
||||
return
|
||||
case Gtk.ResponseType.OK:
|
||||
self.destroy()
|
||||
@@ -0,0 +1,102 @@
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
||||
|
||||
from dzgui.const.enum import Popup
|
||||
|
||||
class ServerDetailsDialog(GenericDialog):
|
||||
def __init__(self, server_name: str, ip: str, qport: int):
|
||||
super().__init__(server_name, Popup.DETAILS)
|
||||
|
||||
dialog_box = self.get_content_area()
|
||||
self.set_default_response(Gtk.ResponseType.OK)
|
||||
self.set_size_request(800, 700)
|
||||
|
||||
self.ip = ip.split(":")[0]
|
||||
self.qport = qport
|
||||
self.store = Gtk.ListStore(str, str, Pango.Weight)
|
||||
|
||||
self.view = Gtk.TreeView(
|
||||
enable_search=False,
|
||||
search_column=-1,
|
||||
headers_visible=False,
|
||||
fixed_height_mode=True,
|
||||
)
|
||||
self.view.connect("row-activated", self._on_row_activated)
|
||||
|
||||
for i, column_title in enumerate(["Item", "Details"]):
|
||||
renderer = Gtk.CellRendererText(xalign=0)
|
||||
if i == 0:
|
||||
column = Gtk.TreeViewColumn(
|
||||
column_title, renderer, text=i, weight=2
|
||||
)
|
||||
else:
|
||||
column = Gtk.TreeViewColumn(column_title, renderer, text=i)
|
||||
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
|
||||
if i != 2:
|
||||
self.view.append_column(column)
|
||||
column.set_sort_column_id(i)
|
||||
column.set_expand(True)
|
||||
|
||||
scrollable_tree = Gtk.ScrolledWindow()
|
||||
scrollable_tree.add(self.view)
|
||||
scrollable_tree.set_size_request(700, 200)
|
||||
|
||||
scrollable_message = Gtk.ScrolledWindow()
|
||||
desc = Gtk.Label(label=strings.server_message, valign=Gtk.Align.START)
|
||||
css.add_class(desc, "details-heading")
|
||||
box = Gtk.Box(
|
||||
orientation=Gtk.Orientation.VERTICAL, halign=Gtk.Align.CENTER
|
||||
)
|
||||
self.description = Gtk.Label(
|
||||
justify=Gtk.Justification.CENTER, wrap=True
|
||||
)
|
||||
sep = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
|
||||
sep.set_margin_bottom(10)
|
||||
for el in desc, sep, self.description:
|
||||
box.add(el)
|
||||
scrollable_message.add(box)
|
||||
|
||||
dialog_box.pack_start(scrollable_tree, EXPAND, FILL, 0)
|
||||
dialog_box.pack_start(scrollable_message, EXPAND, FILL, 0)
|
||||
|
||||
self.wait_dialog = GenericDialog(strings.details, Popup.WAIT)
|
||||
self.wait_dialog.show_all()
|
||||
thread = threading.Thread(
|
||||
target=self._background, args=(self.wait_dialog, ip, qport)
|
||||
)
|
||||
thread.start()
|
||||
|
||||
def _on_row_activated(
|
||||
self,
|
||||
treeview: Gtk.TreeView,
|
||||
tree_iter: Gtk.TreeIter,
|
||||
col: Gtk.TreeViewColumn,
|
||||
) -> None:
|
||||
self.destroy()
|
||||
|
||||
def _load(self) -> None:
|
||||
if self.wait_dialog:
|
||||
self.wait_dialog.destroy()
|
||||
if self.success is False:
|
||||
AppNav.window.spawn_dialog(strings.server_error, Popup.NOTIFY)
|
||||
return
|
||||
self.show_all()
|
||||
self.run()
|
||||
self.destroy()
|
||||
|
||||
def _background(
|
||||
self, dialog: "GenericDialog", ip: str, qport: int
|
||||
) -> None:
|
||||
response = Servers.details(self.ip, self.qport)
|
||||
if response.success:
|
||||
for row in response.data:
|
||||
self.store.append(row + [Pango.Weight.BOLD])
|
||||
self.view.set_model(self.store)
|
||||
|
||||
text = response.description
|
||||
text = format_hyperlinks(text)
|
||||
self.description.set_markup(text)
|
||||
|
||||
self.success = response.success
|
||||
GLib.idle_add(self._load)
|
||||
@@ -0,0 +1,94 @@
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa
|
||||
|
||||
class ModDialog(GenericDialog):
|
||||
def __init__(self, record: str):
|
||||
# TODO: center secondary text
|
||||
msg = strings.workshop
|
||||
super().__init__(textwrap.dedent(msg), Popup.MODLIST)
|
||||
|
||||
dialogBox = self.get_content_area()
|
||||
self.set_default_response(Gtk.ResponseType.OK)
|
||||
self.set_size_request(800, 500)
|
||||
|
||||
self.scrollable = Gtk.ScrolledWindow()
|
||||
self.view = Gtk.TreeView(
|
||||
enable_search=False, search_column=-1, fixed_height_mode=True
|
||||
)
|
||||
self.scrollable.add(self.view)
|
||||
set_surrounding_margins(self.scrollable, 20)
|
||||
|
||||
self.view.connect("row-activated", self._on_row_activated)
|
||||
|
||||
for i, column_title in enumerate(strings.server_mod_cols):
|
||||
renderer = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END)
|
||||
column = Gtk.TreeViewColumn(column_title, renderer, text=i)
|
||||
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
|
||||
self.view.append_column(column)
|
||||
column.set_sort_column_id(i)
|
||||
match column_title:
|
||||
case strings.mod:
|
||||
column.set_fixed_width(350)
|
||||
case strings.id:
|
||||
column.set_fixed_width(200)
|
||||
case _:
|
||||
pass
|
||||
dialogBox.pack_end(self.scrollable, EXPAND, FILL, 0)
|
||||
|
||||
wait_dialog = GenericDialog(strings.modlist, Popup.WAIT)
|
||||
wait_dialog.show_all()
|
||||
thread = threading.Thread(
|
||||
target=self._background, args=(wait_dialog, record)
|
||||
)
|
||||
thread.start()
|
||||
|
||||
# TODO: why are we passing record here?
|
||||
def _background(self, dialog: "GenericDialog", record: str) -> None:
|
||||
def _load():
|
||||
dialog.destroy()
|
||||
# TODO: natively implement
|
||||
#if data.returncode == 1:
|
||||
# AppNav.window.spawn_dialog(strings.server_error, Popup.NOTIFY)
|
||||
# return
|
||||
self.show_all()
|
||||
self.set_markup(f"Modlist ({mod_count} mods)")
|
||||
self.run()
|
||||
self.destroy()
|
||||
|
||||
record = AppNav.treeview.get_record()
|
||||
if not record:
|
||||
return
|
||||
|
||||
# TODO: thread
|
||||
try:
|
||||
# TODO: get default_steam_path from config
|
||||
modlist = get_server_modlist(record)
|
||||
mod_count = self._parse_modlist_rows(modlist)
|
||||
except Exception:
|
||||
# TODO: needs to pop error dialog
|
||||
mod_count = 0
|
||||
modlist_store.clear()
|
||||
self.view.set_model(modlist_store)
|
||||
GLib.idle_add(_load)
|
||||
|
||||
def _parse_modlist_rows(self, rows: list) -> bool | int:
|
||||
for row in rows:
|
||||
modlist_store.append(row)
|
||||
return len(rows)
|
||||
|
||||
def _on_row_activated(
|
||||
self,
|
||||
treeview: Gtk.TreeView,
|
||||
tree_iter: Gtk.TreeIter,
|
||||
col: Gtk.TreeViewColumn,
|
||||
) -> None:
|
||||
select = treeview.get_selection()
|
||||
sels = select.get_selected_rows()
|
||||
(model, pathlist) = sels
|
||||
if len(pathlist) < 1:
|
||||
return
|
||||
path = pathlist[0]
|
||||
tree_iter = model.get_iter(path)
|
||||
mod_id = model.get_value(tree_iter, 1)
|
||||
call_bash_func("open_workshop_page", mod_id)
|
||||
@@ -0,0 +1,18 @@
|
||||
import gi
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk # noqa
|
||||
|
||||
class Watcher(Gtk.Dialog):
|
||||
def __init__():
|
||||
super().__init__()
|
||||
pass
|
||||
|
||||
def bump_progress(self):
|
||||
self.set_secondary_text("FOO")
|
||||
|
||||
#w = Watcher()
|
||||
#thread = threading()
|
||||
## compute here
|
||||
#GLib.idle_add(self._bump_progress)
|
||||
## raise window:
|
||||
#Gdk.present_with_time(Gdk.CURRENT_TIME)
|
||||
Reference in new issue
Block a user