Settings app

settings-app
Marek Ventur 2018-08-27 22:20:51 +01:00
parent f7fefaa331
commit 0f3c2c0e7c
6 changed files with 113 additions and 66 deletions

View File

@ -6,22 +6,22 @@ To publish apps use https://badge.emfcamp.org"""
___license___ = "MIT"
___title___ = "Badge Store"
___dependencies___ = ["badge_store", "dialogs", "ugfx_helper", "app"]
___dependencies___ = ["badge_store", "dialogs", "ugfx_helper", "app", "database"]
___categories___ = ["System"]
___bootstrapped___ = True
import ugfx_helper
import os
import wifi
import ugfx_helper, os, database, wifi, app
from dialogs import *
import app
from lib.badge_store import BadgeStore
### VIEWS ###
ugfx_helper.init()
store = BadgeStore()
url = database.get("badge_store.url", "http://badgeserver.emfcamp.org/2018")
repo = database.get("badge_store.repo", "emfcamp/Mk4-Apps")
ref = database.get("badge_store.ref", "master")
store = BadgeStore(url=url, repo=repo, ref=ref)
title = "TiLDA Badge Store"
def clear():

View File

@ -66,7 +66,7 @@ def prompt_boolean(text, title="TiLDA", true_text="Yes", false_text="No", width
if button_no: button_no.destroy()
label.destroy()
def prompt_text(description, init_text = "", true_text="OK", false_text="Back", font=FONT_MEDIUM_BOLD, style=default_style_badge):
def prompt_text(description, init_text="", true_text="OK", false_text="Back", font=FONT_MEDIUM_BOLD, style=default_style_badge):
"""Shows a dialog and keyboard that allows the user to input/change a string
Returns None if user aborts with button B
@ -119,7 +119,7 @@ def prompt_text(description, init_text = "", true_text="OK", false_text="Back",
edit.destroy();
return
def prompt_option(options, index=0, text = "Please select one of the following:", title=None, select_text="OK", none_text=None):
def prompt_option(options, index=0, text = None, title=None, select_text="OK", none_text=None):
"""Shows a dialog prompting for one of multiple options
If none_text is specified the user can use the B or Menu button to skip the selection
@ -133,12 +133,15 @@ def prompt_option(options, index=0, text = "Please select one of the following:"
if title:
window.text(5, 10, title, TILDA_COLOR)
window.line(0, 25, ugfx.width() - 10, 25, ugfx.BLACK)
window.text(5, 30, text, ugfx.BLACK)
list_y = 50
list_y = 30
if text:
list_y += 20
window.text(5, 30, text, ugfx.BLACK)
else:
window.text(5, 10, text, ugfx.BLACK)
options_list = ugfx.List(5, list_y, ugfx.width() - 25, 180 - list_y, parent = window)
options_list = ugfx.List(5, list_y, ugfx.width() - 25, 260 - list_y, parent = window)
for option in options:
if isinstance(option, dict) and option["title"]:
@ -151,8 +154,8 @@ def prompt_option(options, index=0, text = "Please select one of the following:"
if none_text:
none_text = "B: " + none_text
button_select = ugfx.Button(5, ugfx.height() - 50, 140 if none_text else ugfx.width() - 25, 30 , select_text, parent=window)
button_none = ugfx.Button(ugfx.width() - 160, ugfx.height() - 50, 140, 30 , none_text, parent=window) if none_text else None
button_select = ugfx.Button(5, ugfx.height() - 50, 105 if none_text else 200, 30 , select_text, parent=window)
button_none = ugfx.Button(117, ugfx.height() - 50, 105, 30 , none_text, parent=window) if none_text else None
try:
while True:
@ -180,7 +183,7 @@ def prompt_option(options, index=0, text = "Please select one of the following:"
class WaitingMessage:
"""Shows a dialog with a certain message that can not be dismissed by the user"""
def __init__(self, text = "Please Wait...", title="TiLDA"):
def __init__(self, text="Please Wait...", title="TiLDA"):
self.window = ugfx.Container(30, 30, ugfx.width() - 60, ugfx.height() - 60)
self.window.show()
self.window.text(5, 10, title, TILDA_COLOR)

View File

@ -1,5 +1,7 @@
"""Library for sleep related functions"""
___license___ = "MIT"
import time
def sleep_ms(duration):

63
lib/stack_nav.py Normal file
View File

@ -0,0 +1,63 @@
"""A stack-based naviation system.
Maintains a stack of states through which a user can navigate.
Think Android's back button model.
Every screen is modeled as a function that takes one argument "state".
It can modify state and should either return
* None (which means go back one level)
* A new function (which adds to the stack)
* A keyword like NEXT_EXIT (exit nav) or NEXT_TOP (go to top of stack)
Children get a a shallow clone of the current state, going back will
lead to a screen with the original state.
"""
___dependencies___ = ["dialogs", "database"]
___license___ = "MIT"
import dialogs, database
NEXT_EXIT = "exit" # Leave navigation
NEXT_TOP = "init" # Go to top of stack
def nav(init_fn, init_state={}):
stack = [(init_fn, init_state)]
while stack:
(fn, state) = stack[-1] # peek
next_state = state.copy()
result = fn(next_state)
if callable(result):
stack.append((result, next_state))
elif result == NEXT_TOP:
stack = [(init_fn, init_state)]
elif result == NEXT_EXIT:
break
else:
stack.pop()
# A simple menu. Format of items is [{"foo":fn}, ...]
def selection(items, title="Settings", none_text="Back"):
items = [{"title": t, "function": fn} for (t, fn) in items.items()]
selection = dialogs.prompt_option(items, none_text=none_text, title=title)
if selection:
return selection["function"]
else:
return None
# A wrapper for a simple string menu
def change_string(title, getter_setter_function):
def inner(state):
value = getter_setter_function()
value = dialogs.prompt_text(title, init_text=value, true_text="Change", false_text="Back")
if value:
getter_setter_function(value)
return inner
# A wrapper for a database key
def change_database_string(title, key, default=""):
def inner(state):
value = database.get(key, default)
value = dialogs.prompt_text(title, init_text=value, true_text="Change", false_text="Back")
if value:
database.set(key, value)
return inner

View File

@ -0,0 +1,9 @@
from stack_nav import *
from database import *
def settings_badge_store(state):
return selection({
("API: %s" % get("badge_store.url", "http://badgeserver.emfcamp.org/2018")): change_database_string("Set API", "badge_store.url", "http://badgeserver.emfcamp.org/2018"),
("Repo: %s" % get("badge_store.repo", "emfcamp/Mk4-Apps")): change_database_string("Git repository", "badge_store.repo", "emfcamp/Mk4-Apps"),
("Ref: %s" % get("badge_store.ref", "master")): change_database_string("Set branch, tag or commit", "badge_store.ref", "master")
}, "Badge store settings")

View File

@ -6,71 +6,41 @@ Currently supports
* Pick default app
* Change badgestore repo/branch
Todo:
* timezone
"""
___name___ = "Settings"
___license___ = "MIT"
___dependencies___ = ["dialogs", "ugfx_helper", "database"]
___dependencies___ = ["dialogs", "ugfx_helper", "database", "app", "stack_nav", "wifi"]
___categories___ = ["System"]
___bootstrapped___ = True
import ugfx_helper, os, wifi, app, database
from settings.badge_store_settings import settings_badge_store
from dialogs import *
from stack_nav import *
### VIEWS ###
ugfx_helper.init()
title = "Settings"
def clear():
ugfx.clear(ugfx.html_color(ugfx.WHITE))
def settings_name(state):
pass
### SCREENS ###
def settings_startup_app(state):
pass
apps = app.get_apps()
print(apps)
selection = prompt_option([{"title": a.title, "app": a} for a in apps], text="Select App:", none_text="Back", title="Set startup app")
if selection:
app.write_launch_file(app.name, "default_app.txt")
def settings_wifi(state):
pass
def settings_badge_store(state):
pass
wifi.choose_wifi()
def settings_main(state):
menu_items = [
{"title": "Change Name", "function": settings_name},
{"title": "Wifi", "function": settings_wifi},
{"title": "Set startup app", "function": settings_startup_app},
{"title": "Change Badge Store", "function": settings_badge_store}
]
return selection({
"Homescreeen Name": change_database_string("Set your name", "name"),
"Wifi": settings_wifi,
"Startup app": settings_startup_app,
"Badge Store": settings_badge_store
}, none_text="Exit")
return prompt_option(menu_items, none_text="Exit", text="What do you want to do?", title=title)
# Todo: this might be useful in a lib
# A stack-based naviation system.
NEXT_EXIT = "exit" # Leave navigation
NEXT_INIT = "init" # Go to top of stack
def nav(init_fn, init_state={}):
stack = [(init_fn, init_state)]
while len(stack):
(fn, state) = stack[-1] # peek
next_state = state.clone()
print(next_state)
result = fn(next_state)
if callable(result):
stack.append((result, next_state))
elif result == NEXT_INIT:
stack = [(init_fn, init_state)]
elif result == NEXT_EXIT:
break
else:
stack.pop()
print("bye")
# Entry point
### ENTRY POINT ###
ugfx_helper.init()
nav(settings_main)
#show_app("launcher")