Options menu

pull/4/head
Blake DeMarcy 2017-04-10 06:05:20 -05:00
parent f4ddb18470
commit 88f43d023a
1 changed files with 161 additions and 45 deletions

View File

@ -68,6 +68,7 @@ class App(object):
} }
colors = [ colors = [
("default", "default", "default"),
("bar", "light magenta", "default"), ("bar", "light magenta", "default"),
("button", "light red", "default"), ("button", "light red", "default"),
("dim", "dark gray", "default"), ("dim", "dark gray", "default"),
@ -91,10 +92,10 @@ class App(object):
self.walker = urwid.SimpleFocusListWalker([]) self.walker = urwid.SimpleFocusListWalker([])
self.loop = urwid.MainLoop(urwid.Frame( self.loop = urwid.MainLoop(urwid.Frame(
urwid.LineBox(ActionBox(self.walker), urwid.LineBox(
ActionBox(self.walker),
title=self.prefs["frame_title"], title=self.prefs["frame_title"],
tlcorner="@", trcorner="@", blcorner="@", brcorner="@", **frame_theme()
tline="=", bline="=", lline="|", rline="|"
)), colors) )), colors)
self.index() self.index()
@ -286,18 +287,88 @@ class App(object):
self.walker += self.make_message_body(message) self.walker += self.make_message_body(message)
def refresh(self): def refresh(self, bottom=False):
if self.mode == "index": if self.mode == "index":
return self.index() return self.index()
self.thread_load(None, self.thread["thread_id"]) self.thread_load(None, self.thread["thread_id"])
self.loop.widget.body.base_widget.set_focus(len(self.walker) - 1) if bottom:
self.loop.widget.body.base_widget.set_focus(len(self.walker) - 5)
def back(self): def back(self):
if self.mode == "thread": if app.mode == "index":
frilly_exit()
elif app.mode == "thread":
self.index() self.index()
def set_new_editor(self, button, value, key):
if value == False:
return
elif key == "internal":
key = None
self.prefs.update({"editor": key})
bbjrc("update", **self.prefs)
def set_editor_mode(self, button, value):
self.prefs["integrate_external_editor"] = value
bbjrc("update", **self.prefs)
def options_menu(self):
editor_buttons = []
edit_mode = []
urwid.RadioButton(
editor_buttons, "Internal",
state=not self.prefs["editor"],
on_state_change=self.set_new_editor,
user_data="internal")
for editor in editors:
urwid.RadioButton(
editor_buttons, editor.title(),
state=self.prefs["editor"] == editor,
on_state_change=self.set_new_editor,
user_data=editor)
urwid.RadioButton(
edit_mode, "Integrate",
state=self.prefs["integrate_external_editor"],
on_state_change=self.set_editor_mode)
urwid.RadioButton(
edit_mode, "Overthrow",
state=not self.prefs["integrate_external_editor"])
widget = OptionsMenu(
urwid.Filler(
urwid.Pile([
urwid.AttrMap(urwid.Text("Text editor:"), "button"),
urwid.Divider(),
*editor_buttons,
urwid.Divider("-"),
urwid.AttrMap(urwid.Text("External text editor mode:"), "button"),
urwid.Text("If you have problems using an external text editor, "
"set this to Overthrow."),
urwid.Divider(),
*edit_mode,
urwid.Divider("-"),
]), "top"),
title="BBJ Options",
**frame_theme()
)
self.loop.widget = urwid.Overlay(
widget, self.loop.widget,
align="center",
valign="middle",
width=30,
height=(self.loop.screen_size[1] - 10)
)
def footer_prompt(self, text, callback, *callback_args, extra_text=None): def footer_prompt(self, text, callback, *callback_args, extra_text=None):
text = "(%s)> " % text text = "(%s)> " % text
widget = urwid.Columns([ widget = urwid.Columns([
@ -312,12 +383,20 @@ class App(object):
]) ])
self.loop.widget.footer = widget self.loop.widget.footer = widget
app.loop.widget.focus_position = "footer" self.loop.widget.focus_position = "footer"
def reset_footer(self, *_, **__):
try:
self.set_footer(self.bars[self.mode])
self.loop.widget.focus_position = "body"
except:
# just keep trying until the widget can handle it
self.loop.set_alarm_in(0.5, self.reset_footer)
def temp_footer_message(self, string, duration=3): def temp_footer_message(self, string, duration=3):
self.loop.set_alarm_in( self.loop.set_alarm_in(duration, self.reset_footer)
duration, lambda x,y: self.set_footer(self.bars[self.mode]))
self.set_footer(string) self.set_footer(string)
@ -353,46 +432,52 @@ class App(object):
return self.temp_footer_message("EMPTY POST DISCARDED") return self.temp_footer_message("EMPTY POST DISCARDED")
params = {"body": body} params = {"body": body}
thread = False
if self.mode == "thread": if self.mode == "thread":
thread = True endpoint = "reply"
params.update({"thread_id": self.thread["thread_id"]}) params.update({"thread_id": self.thread["thread_id"]})
else: else:
endpoint = "create"
params.update({"title": title}) params.update({"title": title})
network.request("thread_" + ("reply" if thread else "create"), **params) network.request("thread_" + endpoint, **params)
return self.refresh() return self.refresh(True)
editor = ExternalEditor if self.prefs["editor"] else InternalEditor
if self.mode == "index": if self.mode == "index":
self.set_header('Composing "{}"', title) self.set_header('Composing "{}"', title)
if self.prefs["editor"]:
editor = ExternalEditor("thread_create", title=title)
self.set_footer("[F1]Abort [Save and quit to submit your thread]") self.set_footer("[F1]Abort [Save and quit to submit your thread]")
else:
editor = urwid.Filler(
InternalEditor("thread_create", title=title),
valign=urwid.TOP)
self.set_footer("[F1]Abort [F3]Send")
self.loop.widget = urwid.Overlay( self.loop.widget = urwid.Overlay(
urwid.LineBox( urwid.LineBox(
editor("thread_create", title=title), editor,
title=self.prefs["editor"], title=self.prefs["editor"] or "",
tlcorner="@", trcorner="@", blcorner="@", brcorner="@", **frame_theme()),
tline="-", bline="-", lline="|", rline="|"), self.loop.widget,
self.loop.widget, align="center", valign="middle", align="center",
valign="middle",
width=self.loop.screen_size[0] - 2, width=self.loop.screen_size[0] - 2,
height=(self.loop.screen_size[1] - 4)) height=(self.loop.screen_size[1] - 4))
elif self.mode == "thread": elif self.mode == "thread":
self.window_split=True self.window_split=True
self.set_header('Replying to "{}"', self.thread["title"]) self.set_header('Replying to "{}"', self.thread["title"])
if self.prefs["editor"]:
editor = ExternalEditor("thread_reply", thread_id=self.thread["thread_id"])
else:
editor = urwid.AttrMap(urwid.Filler(
InternalEditor("thread_reply", thread_id=self.thread["thread_id"]),
valign=urwid.TOP), "default")
self.loop.widget.footer = urwid.Pile([ self.loop.widget.footer = urwid.Pile([
urwid.AttrMap(urwid.Text(""), "bar"), urwid.AttrMap(urwid.Text(""), "bar"),
urwid.BoxAdapter( urwid.BoxAdapter(urwid.AttrMap(urwid.LineBox(
urwid.AttrMap( editor, **frame_theme()
urwid.LineBox( ), "bar"), self.loop.screen_size[1] // 2),])
editor(
"thread_reply",
thread_id=self.thread["thread_id"]),
tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
tline="-", bline="-", lline="|", rline="|"
), "bar"),
self.loop.screen_size[1] // 2),])
self.switch_editor() self.switch_editor()
@ -417,18 +502,28 @@ class FootPrompt(urwid.Edit):
class InternalEditor(urwid.Edit): class InternalEditor(urwid.Edit):
def __init__(self, endpoint, **params): def __init__(self, endpoint, **params):
super(InternalEditor, self).__init__() super(InternalEditor, self).__init__(multiline=True)
self.endpoint = endpoint self.endpoint = endpoint
self.params = params self.params = params
def keypress(self, size, key): def keypress(self, size, key):
if key not in ["f1", "f2"]: if key not in ["f1", "f2", "f3"]:
return super(InternalEditor, self).keypress(size, key) return super(InternalEditor, self).keypress(size, key)
elif key == "f1": elif key == "f1":
return app.close_editor() app.close_editor()
return app.refresh()
elif key == "f2": elif key == "f2":
return app.switch_editor() return app.switch_editor()
body = self.get_edit_text().strip()
app.close_editor()
if body:
self.params.update({"body": body})
network.request(self.endpoint, **self.params)
app.refresh(True)
else:
app.temp_footer_message("EMPTY POST DISCARDED")
class ExternalEditor(urwid.Terminal): class ExternalEditor(urwid.Terminal):
def __init__(self, endpoint, **params): def __init__(self, endpoint, **params):
@ -450,7 +545,7 @@ class ExternalEditor(urwid.Terminal):
os.remove(self.path) os.remove(self.path)
if self.params["body"]: if self.params["body"]:
network.request(self.endpoint, **self.params) network.request(self.endpoint, **self.params)
return app.refresh() return app.refresh(True)
else: else:
return app.temp_footer_message("EMPTY POST DISCARDED") return app.temp_footer_message("EMPTY POST DISCARDED")
@ -465,9 +560,21 @@ class ExternalEditor(urwid.Terminal):
app.switch_editor() app.switch_editor()
class OptionsMenu(urwid.LineBox):
def keypress(self, size, key):
super(OptionsMenu, self).keypress(size, key)
if key.lower() == "q":
app.loop.widget = app.loop.widget[0]
elif key in ["ctrl n", "j", "n"]:
return self.keypress(size, "down")
elif key in ["ctrl p", "k", "p"]:
return self.keypress(size, "up")
class ActionBox(urwid.ListBox): class ActionBox(urwid.ListBox):
""" """
The listwalker used by all the browsing pages. Handles keys. The listwalker used by all the browsing pages. Most of the application
takes place in an instance of this box. Handles many keybinds.
""" """
def keypress(self, size, key): def keypress(self, size, key):
super(ActionBox, self).keypress(size, key) super(ActionBox, self).keypress(size, key)
@ -495,25 +602,22 @@ class ActionBox(urwid.ListBox):
elif key in ["l", "right"]: elif key in ["l", "right"]:
self.keypress(size, "enter") self.keypress(size, "enter")
elif key.lower() == "b": elif key == "b":
self.change_focus(size, len(app.walker) - 1) self.change_focus(size, len(app.walker) - 1)
elif key.lower() == "t": elif key == "t":
self.change_focus(size, 0) self.change_focus(size, 0)
elif key == "c": elif key in ["c", "R", "+"]:
app.compose() app.compose()
elif key == "6":
app.set_footer(app.overthrow_ext_edit())
elif key == "r": elif key == "r":
app.refresh() app.refresh()
elif key == "o":
app.options_menu()
elif key.lower() == "q": elif key.lower() == "q":
if app.mode == "index":
frilly_exit()
else:
app.back() app.back()
@ -675,6 +779,18 @@ def log_in():
motherfucking_rainbows("~~welcome to the party, %s!~~" % network.user_name) motherfucking_rainbows("~~welcome to the party, %s!~~" % network.user_name)
def frame_theme(mode="default"):
"""
Return the kwargs for a frame theme.
"""
if mode == "default":
return dict(
tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
tline="=", bline="=", lline="|", rline="|"
)
def bbjrc(mode, **params): def bbjrc(mode, **params):
""" """
Maintains a user a preferences file, setting or returning Maintains a user a preferences file, setting or returning