From 8737e3308ac1e1c3a6a3c6ce7884adfcb70678d5 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 9 Apr 2021 22:07:38 +0200 Subject: [PATCH] Work on text ui --- nomadnet/NomadNetworkApp.py | 77 ++++++++++++++++++++++++++--- nomadnet/ui/TextUI.py | 98 ++++++++++++++++++++++++++++++++----- nomadnet/ui/__init__.py | 23 +++++++-- nomadnet/vendor/quotes.py | 1 + setup.py | 2 +- 5 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 nomadnet/vendor/quotes.py diff --git a/nomadnet/NomadNetworkApp.py b/nomadnet/NomadNetworkApp.py index e8c9fc5..a4c519c 100644 --- a/nomadnet/NomadNetworkApp.py +++ b/nomadnet/NomadNetworkApp.py @@ -32,8 +32,9 @@ class NomadNetworkApp: NomadNetworkApp._shared_instance = self self.configpath = self.configdir+"/config" + self.logfilepath = self.configdir+"/logfile" self.storagepath = self.configdir+"/storage" - self.identitypath = self.configdir+"/storage/identity" + self.identitypath = self.configdir+"/storage/identity" self.cachepath = self.configdir+"/storage/cache" self.resourcepath = self.configdir+"/storage/resources" @@ -49,6 +50,12 @@ class NomadNetworkApp: if os.path.isfile(self.configpath): try: self.config = ConfigObj(self.configpath) + try: + self.applyConfig() + except Exception as e: + RNS.log("The configuration file is invalid. The contained exception was: "+str(e), RNS.LOG_ERROR) + nomadnet.panic() + RNS.log("Configuration loaded from "+self.configpath) except Exception as e: RNS.log("Could not parse the configuration at "+self.configpath, RNS.LOG_ERROR) @@ -57,9 +64,7 @@ class NomadNetworkApp: else: RNS.log("Could not load config file, creating default configuration file...") self.createDefaultConfig() - RNS.log("Default config file created. Make any necessary changes in "+self.configdir+"/config and start Nomad Network Client again.") - RNS.log("Exiting now!") - exit(1) + if os.path.isfile(self.identitypath): try: @@ -82,9 +87,9 @@ class NomadNetworkApp: except Exception as e: RNS.log("Could not create and save a new Primary Identity", RNS.LOG_ERROR) RNS.log("The contained exception was: %s" % (str(e)), RNS.LOG_ERROR) - RNS.panic() + nomadnet.panic() + - self.applyConfig() self.rns = RNS.Reticulum(configdir = rnsconfigdir) atexit.register(self.exit_handler) @@ -111,6 +116,14 @@ class NomadNetworkApp: RNS.loglevel = 0 if RNS.loglevel > 7: RNS.loglevel = 7 + if option == "destination": + if value.lower() == "file": + RNS.logdest = RNS.LOG_FILE + if "logfile" in self.config["logging"]: + self.logfilepath = self.config["logging"]["logfile"] + RNS.logfile = self.logfilepath + else: + RNS.logdest = RNS.LOG_STDOUT if "client" in self.config: for option in self.config["client"]: @@ -128,6 +141,39 @@ class NomadNetworkApp: self.uimode = nomadnet.ui.UI_MENU if value == "text": self.uimode = nomadnet.ui.UI_TEXT + if "textui" in self.config: + if not "intro_time" in self.config["textui"]: + self.config["textui"]["intro_time"] = 1 + else: + self.config["textui"]["intro_time"] = self.config["textui"].as_int("intro_time") + + if not "colormode" in self.config["textui"]: + self.config["textui"]["colormode"] = nomadnet.ui.COLORMODE_16 + else: + if self.config["textui"]["colormode"].lower() == "monochrome": + self.config["textui"]["colormode"] = nomadnet.ui.COLORMODE_MONO + elif self.config["textui"]["colormode"].lower() == "16": + self.config["textui"]["colormode"] = nomadnet.ui.COLORMODE_16 + elif self.config["textui"]["colormode"].lower() == "88": + self.config["textui"]["colormode"] = nomadnet.ui.COLORMODE_88 + elif self.config["textui"]["colormode"].lower() == "256": + self.config["textui"]["colormode"] = nomadnet.ui.COLORMODE_256 + elif self.config["textui"]["colormode"].lower() == "24bit": + self.config["textui"]["colormode"] = nomadnet.ui.COLORMODE_TRUE + else: + raise ValueError("The selected Text UI color mode is invalid") + + if not "theme" in self.config["textui"]: + self.config["textui"]["theme"] = nomadnet.ui.THEME_DARK + else: + if self.config["textui"]["theme"].lower() == "dark": + self.config["textui"]["theme"] = nomadnet.ui.THEME_DARK + elif self.config["textui"]["theme"].lower() == "light": + self.config["textui"]["theme"] = nomadnet.ui.THEME_LIGHT + else: + raise ValueError("The selected Text UI theme is invalid") + else: + raise KeyError("Text UI selected in configuration file, but no [textui] section found") if value == "graphical": self.uimode = nomadnet.ui.UI_GRAPHICAL if value == "web": @@ -170,12 +216,31 @@ __default_nomadnet_config__ = '''# This is the default Nomad Network config file # 7: Extreme logging loglevel = 4 +destination = file [client] enable_client = Yes user_interface = text +[textui] + +intro_time = 1 + +# Specify the number of colors to use +# valid colormodes are: +# monochrome, 16, 88, 256 and 24bit +# +# The default is a conservative 88 colors, +# but 256 colors can probably be used on +# most terminals. Some terminals + +# colormode = monochrome +# colormode = 16 +colormode = 88 +# colormode = 256 +# colormode = 24bit + [node] enable_node = No diff --git a/nomadnet/ui/TextUI.py b/nomadnet/ui/TextUI.py index 00c40e0..3af84d1 100644 --- a/nomadnet/ui/TextUI.py +++ b/nomadnet/ui/TextUI.py @@ -1,14 +1,15 @@ import RNS -from nomadnet import NomadNetworkApp import importlib +import time + +from nomadnet import NomadNetworkApp +from nomadnet.ui import * class TextUI: def __init__(self): self.app = NomadNetworkApp.get_shared_instance() - self.loop = None - self.main_widget = None if importlib.util.find_spec("urwid") != None: import urwid @@ -17,23 +18,98 @@ class TextUI: RNS.log("You can install it with the command: pip3 install urwid", RNS.LOG_ERROR) nomadnet.panic() - loop = urwid.MainLoop(self.build_intro()) - loop.run() + urwid.set_encoding("UTF-8") - def build_intro(self): + intro_timeout = self.app.config["textui"]["intro_time"] + colormode = self.app.config["textui"]["colormode"] + theme = self.app.config["textui"]["theme"] + + palette = nomadnet.ui.THEMES[theme] + + self.screen = urwid.raw_display.Screen() + self.screen.register_palette(palette) + + self.main_display = DemoDisplay(self, self.app) + + if intro_timeout > 0: + self.intro_display = IntroDisplay(self.app) + initial_widget = self.intro_display.widget + else: + initial_widget = self.main_display.widget + + self.loop = urwid.MainLoop(initial_widget, screen=self.screen) + + if intro_timeout > 0: + self.loop.set_alarm_in(intro_timeout, self.display_main) + + self.set_colormode(colormode) + + self.loop.run() + + def set_colormode(self, colormode): + self.screen.set_terminal_properties(colormode) + self.screen.reset_default_terminal_palette() + + def display_main(self, loop, user_data): + self.loop.widget = self.main_display.widget + + +class DemoDisplay(): + def __init__(self, ui, app): import urwid + def color_mono(btn): + ui.set_colormode(nomadnet.ui.COLORMODE_MONO) + + def color_16(btn): + ui.set_colormode(nomadnet.ui.COLORMODE_16) + + def color_88(btn): + ui.set_colormode(nomadnet.ui.COLORMODE_88) + + def color_8bit(btn): + ui.set_colormode(nomadnet.ui.COLORMODE_256) + + def color_true(btn): + ui.set_colormode(nomadnet.ui.COLORMODE_TRUE) + + pile = urwid.Pile([ + urwid.Text(("heading", "This is a heading")), + urwid.Text(("body_text", "Hello World \U0001F332")), + urwid.Button(("buttons", "Monochrome"), color_mono), + urwid.Button(("buttons", "16 color"), color_16), + urwid.Button(("buttons", "88 color"), color_88), + urwid.Button(("buttons", "256 color"), color_8bit), + urwid.Button(("buttons", "True color"), color_true), + ]) + + self.widget = urwid.Filler(pile, 'top') + +class MainDisplay(): + def __init__(self, app): + import urwid + + pile = urwid.Pile([ + urwid.Text(("body_text", "Hello World \U0001F332")), + ]) + + self.widget = urwid.Filler(pile, 'top') + +class IntroDisplay(): + def __init__(self, app): + import urwid + self.app = app + font = urwid.font.HalfBlock5x4Font() - big_text = "Nomad Network" - big_text = urwid.BigText(("intro_bigtext", big_text), font) + big_text = urwid.BigText(("intro_title", "Nomad Network"), font) big_text = urwid.Padding(big_text, align="center", width="clip") intro = urwid.Pile([ big_text, - urwid.Text(["Version %s" % (str(self.app.version))], align="center"), + urwid.Text(("Version %s" % (str(self.app.version))), align="center"), urwid.Divider(), - urwid.Text(("intro_smalltext", "-= Starting =-"), align="center"), + urwid.Text(("-= Starting =- "), align="center"), ]) - return urwid.Filler(intro) \ No newline at end of file + self.widget = urwid.Filler(intro) \ No newline at end of file diff --git a/nomadnet/ui/__init__.py b/nomadnet/ui/__init__.py index e6e561d..2a6def6 100644 --- a/nomadnet/ui/__init__.py +++ b/nomadnet/ui/__init__.py @@ -8,16 +8,33 @@ from .TextUI import TextUI from .GraphicalUI import GraphicalUI from .WebUI import WebUI +modules = glob.glob(os.path.dirname(__file__)+"/*.py") +__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')] + + UI_NONE = 0x00 UI_MENU = 0x01 UI_TEXT = 0x02 UI_GRAPHICAL = 0x03 UI_WEB = 0x04 - UI_MODES = [UI_MENU, UI_TEXT, UI_GRAPHICAL, UI_WEB] -modules = glob.glob(os.path.dirname(__file__)+"/*.py") -__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')] +COLORMODE_MONO = 1 +COLORMODE_16 = 16 +COLORMODE_88 = 88 +COLORMODE_256 = 256 +COLORMODE_TRUE = 2**24 +THEME_DARK = 0x01 +THEME_LIGHT = 0x02 + +THEMES = { + THEME_DARK: [ + # Style name # 16-color style # Monochrome style # 88, 256 and true-color style + ('heading', 'light gray,underline', 'default', 'underline', 'g93,underline', 'default'), + ('body_text', 'white', 'default', 'default', '#0a0', 'default'), + ('buttons', 'light green,bold', 'default', 'default', '#00a533', 'default') + ] +} def spawn(uimode): if uimode in UI_MODES: diff --git a/nomadnet/vendor/quotes.py b/nomadnet/vendor/quotes.py new file mode 100644 index 0000000..834e574 --- /dev/null +++ b/nomadnet/vendor/quotes.py @@ -0,0 +1 @@ +quotes = [("I want the wisdom that wise men revere. I want more.", "Faithless")] \ No newline at end of file diff --git a/setup.py b/setup.py index 5f9e98d..fe3a290 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,6 @@ setuptools.setup( entry_points= { 'console_scripts': ['nomadnet=nomadnet:main'] }, - install_requires=['rns', 'lxmf'], + install_requires=['rns', 'lxmf', 'urwid@2.1.2'], python_requires='>=3.5', ) \ No newline at end of file