NomadNet/nomadnet/ui/textui/Main.py
Aleksei Stepanov 77eca5d23e Use urwid constants for widgets instead of string equivalents
* Reduce `DeprecationWarning` amount:
  `get_focus` -> `focus_position` for `Frame` and `focus` for `Pile`
  `set_focus` -> use property `focus_position`
2024-01-18 11:58:22 +01:00

215 lines
8.0 KiB
Python

import RNS
from .Network import *
from .Conversations import *
from .Directory import *
from .Config import *
from .Map import *
from .Log import *
from .Guide import *
import urwid
class SubDisplays():
def __init__(self, app):
self.app = app
self.network_display = NetworkDisplay(self.app)
self.conversations_display = ConversationsDisplay(self.app)
self.directory_display = DirectoryDisplay(self.app)
self.config_display = ConfigDisplay(self.app)
self.map_display = MapDisplay(self.app)
self.log_display = LogDisplay(self.app)
self.guide_display = GuideDisplay(self.app)
if app.firstrun:
self.active_display = self.guide_display
else:
self.active_display = self.conversations_display
def active(self):
return self.active_display
class MenuButton(urwid.Button):
button_left = urwid.Text('[')
button_right = urwid.Text(']')
class MainFrame(urwid.Frame):
FOCUS_CHECK_TIMEOUT = 0.25
def __init__(self, body, header=None, footer=None, delegate=None):
self.delegate = delegate
self.current_focus = None
super().__init__(body, header, footer)
def keypress_focus_check(self, deferred=False):
current_focus = self.delegate.widget.get_focus_widgets()[-1]
if deferred:
if current_focus != self.current_focus:
self.focus_changed()
else:
def deferred_focus_check(loop, user_data):
self.keypress_focus_check(deferred=True)
self.delegate.app.ui.loop.set_alarm_in(MainFrame.FOCUS_CHECK_TIMEOUT, deferred_focus_check)
self.current_focus = current_focus
def focus_changed(self):
current_focus = self.delegate.widget.get_focus_widgets()[-1]
current_focus_path = self.delegate.widget.get_focus_path()
if len(current_focus_path) > 1:
if current_focus_path[0] == "body":
self.delegate.update_active_shortcuts()
if self.delegate.sub_displays.active() == self.delegate.sub_displays.conversations_display:
# Needed to refresh indicativelistbox styles on mouse focus change
self.delegate.sub_displays.conversations_display.focus_change_event()
def mouse_event(self, size, event, button, col, row, focus):
current_focus = self.delegate.widget.get_focus_widgets()[-1]
if current_focus != self.current_focus:
self.focus_changed()
self.current_focus = current_focus
return super(MainFrame, self).mouse_event(size, event, button, col, row, focus)
def keypress(self, size, key):
self.keypress_focus_check()
#if key == "ctrl q":
# raise urwid.ExitMainLoop
return super(MainFrame, self).keypress(size, key)
class MainDisplay():
def __init__(self, ui, app):
self.ui = ui
self.app = app
self.menu_display = MenuDisplay(self.app, self)
self.sub_displays = SubDisplays(self.app)
self.frame = MainFrame(self.sub_displays.active().widget, header=self.menu_display.widget, footer=self.sub_displays.active().shortcuts().widget, delegate=self)
self.widget = self.frame
def show_network(self, user_data):
self.sub_displays.active_display = self.sub_displays.network_display
self.update_active_sub_display()
self.sub_displays.network_display.start()
def show_conversations(self, user_data):
self.sub_displays.active_display = self.sub_displays.conversations_display
self.update_active_sub_display()
def show_directory(self, user_data):
self.sub_displays.active_display = self.sub_displays.directory_display
self.update_active_sub_display()
def show_map(self, user_data):
self.sub_displays.active_display = self.sub_displays.map_display
self.update_active_sub_display()
def show_config(self, user_data):
self.sub_displays.active_display = self.sub_displays.config_display
self.update_active_sub_display()
def show_log(self, user_data):
self.sub_displays.active_display = self.sub_displays.log_display
self.sub_displays.log_display.show()
self.update_active_sub_display()
def show_guide(self, user_data):
self.sub_displays.active_display = self.sub_displays.guide_display
self.update_active_sub_display()
def update_active_sub_display(self):
self.frame.contents["body"] = (self.sub_displays.active().widget, None)
self.update_active_shortcuts()
if self.sub_displays.active_display != self.sub_displays.log_display:
self.sub_displays.log_display.kill()
def update_active_shortcuts(self):
self.frame.contents["footer"] = (self.sub_displays.active().shortcuts().widget, None)
def request_redraw(self, extra_delay=0.0):
self.app.ui.loop.set_alarm_in(0.25+extra_delay, self.redraw_now)
def redraw_now(self, sender=None, data=None):
self.app.ui.loop.screen.clear()
#self.app.ui.loop.draw_screen()
def start(self):
self.menu_display.start()
def quit(self, sender=None):
logterm_pid = None
if True or RNS.vendor.platformutils.is_android():
if self.sub_displays.log_display != None and self.sub_displays.log_display.log_term != None:
if self.sub_displays.log_display.log_term.log_term != None:
logterm_pid = self.sub_displays.log_display.log_term.log_term.pid
if logterm_pid != None:
import os, signal
os.kill(logterm_pid, signal.SIGKILL)
raise urwid.ExitMainLoop
class MenuColumns(urwid.Columns):
def keypress(self, size, key):
if key == "tab" or key == "down":
self.handler.frame.focus_position = "body"
return super(MenuColumns, self).keypress(size, key)
class MenuDisplay():
UPDATE_INTERVAL = 2
def __init__(self, app, handler):
self.app = app
self.update_interval = MenuDisplay.UPDATE_INTERVAL
self.g = self.app.ui.glyphs
self.menu_indicator = urwid.Text("")
menu_text = (urwid.PACK, self.menu_indicator)
button_network = (11, MenuButton("Network", on_press=handler.show_network))
button_conversations = (17, MenuButton("Conversations", on_press=handler.show_conversations))
button_directory = (13, MenuButton("Directory", on_press=handler.show_directory))
button_map = (7, MenuButton("Map", on_press=handler.show_map))
button_log = (7, MenuButton("Log", on_press=handler.show_log))
button_config = (10, MenuButton("Config", on_press=handler.show_config))
button_guide = (9, MenuButton("Guide", on_press=handler.show_guide))
button_quit = (8, MenuButton("Quit", on_press=handler.quit))
# buttons = [menu_text, button_conversations, button_node, button_directory, button_map]
if self.app.config["textui"]["hide_guide"]:
buttons = [menu_text, button_conversations, button_network, button_log, button_config, button_quit]
else:
buttons = [menu_text, button_conversations, button_network, button_log, button_config, button_guide, button_quit]
columns = MenuColumns(buttons, dividechars=1)
columns.handler = handler
self.update_display()
self.widget = urwid.AttrMap(columns, "menubar")
def start(self):
self.update_display_job()
def update_display_job(self, event = None, sender = None):
self.update_display()
self.app.ui.loop.set_alarm_in(self.update_interval, self.update_display_job)
def update_display(self):
if self.app.has_unread_conversations():
self.indicate_unread()
else:
self.indicate_normal()
def indicate_normal(self):
self.menu_indicator.set_text(self.g["decoration_menu"])
def indicate_unread(self):
self.menu_indicator.set_text(self.g["unread_menu"])