Пример #1
0
 def build(self, init=False):
     self.tasklists = self.model.tasklists()
     self.listbox = ListWidget(u"  Please select a list", self.tasklists, self.on_list_select)
     self.build_body()
     if init:
         self.set_top(self.mbody)
         self.build_header("Sandook(ToDo)")
         self.build_footer(self.config.get_help_text())
         self.frame = urwid.Frame(self.top, header=self.header, footer=self.footer)
     else:
         self.update_footer("Status:")
         self.update_header("Sandook(ToDo)")
     self.tasks_visible = False
Пример #2
0
class App(object):
    def __init__(self, config, model, logw):
        self.logw = lambda msg: logw(basename(__file__) + ": " + str(msg))
        self.model = model
        self.csignal = CSignal()
        self.config = config
        self.bindings = self.config.get_key_bindings()
        self.tasklists = []
        self.current_tasklist = None
        self.tasks = []
        self.mbody = None
        self.help_visible = False
        self.tasks_visible = False
        self.build(init=True)
        self.setup_signals()
        self.dirty = False
        self.timer = Timer(2, self.on_timer)
        self.idle_time = 0
        self.show_completed = False

    def build_body(self):
        self.filler = urwid.Filler(self.listbox, valign="middle", height=("relative", 100), top=2, min_height=10)
        if self.mbody is not None:
            self.mbody.original_widget = self.filler
        else:
            # TODO: check logic
            self.mbody = urwid.AttrMap(
                urwid.Filler(self.listbox, valign="middle", height=("relative", 100), top=2, min_height=10), "body"
            )

    def build_tasks(self):
        self.walker = urwid.SimpleListWalker(self.tasks)
        self.listbox = urwid.ListBox(self.walker)
        self.update_header("Tasklist: " + self.current_tasklist_title)
        self.build_body()
        self.tasks_visible = True

    def build(self, init=False):
        self.tasklists = self.model.tasklists()
        self.listbox = ListWidget(u"  Please select a list", self.tasklists, self.on_list_select)
        self.build_body()
        if init:
            self.set_top(self.mbody)
            self.build_header("Sandook(ToDo)")
            self.build_footer(self.config.get_help_text())
            self.frame = urwid.Frame(self.top, header=self.header, footer=self.footer)
        else:
            self.update_footer("Status:")
            self.update_header("Sandook(ToDo)")
        self.tasks_visible = False

    def build_edit_tasklist(self, sel_tasklist):
        qbox = QuestionBoxW(
            question=u"Rename TaskList",
            edit_text=sel_tasklist[1],
            button_text="Edit",
            callback=self.on_sel_tasklist_edit,
            cancel_button_text="Cancel",
            cancel_callback=self.on_tasklist_edit_cancel,
        )
        self.mbody.original_widget = qbox

    def build_add_tasklist(self):
        qbox = QuestionBoxW(
            question=u"New TaskList name",
            edit_text=" ",
            button_text="Add",
            callback=self.on_tasklist_add,
            cancel_button_text="Cancel",
            cancel_callback=self.on_tasklist_add_cancel,
        )
        self.mbody.original_widget = qbox

    def build_delete_tasklist(self, sel_tasklist):
        qbox = QuestionBoxW(
            question=u"Are you sure, you want to delete the tasklist '%s'? This will also delete"
            u"all the tasks." % sel_tasklist[1],
            edit_text="",
            button_text="Yes",
            callback=self.on_tasklist_delete,
            cancel_button_text="No",
            cancel_callback=self.on_tasklist_delete_cancel,
        )
        self.mbody.original_widget = qbox

    def build_delete_task(self):
        sel_task = self.listbox.focus
        self._original_w = self.mbody.original_widget
        qbox = QuestionBoxW(
            question=u"Are you sure, you want to delete the task: '%s'?"
            u" You can also mark it as complete" % sel_task.title,
            edit_text="",
            button_text="Yes",
            callback=self.on_task_delete,
            cancel_button_text="No",
            cancel_callback=self.on_task_delete_cancel,
        )
        self.mbody.original_widget = qbox

    def build_help_dialog(self):
        self._original_w = self.mbody.original_widget
        helpd = HelpDialog(config=self.config, callback=self.on_help_exit)
        self.mbody.original_widget = helpd
        self.help_visible = True

    def build_header(self, header):
        self.header = urwid.AttrMap(
            urwid.Pile([urwid.Text(("header", header), align="center", wrap="any"), urwid.Divider(div_char=".")]),
            "header",
        )

    def build_footer(self, help_text):
        self.footer = urwid.AttrMap(
            urwid.Columns(
                [
                    urwid.Padding(urwid.Text(u"Status"), width=("relative", 70), align="left"),
                    urwid.Padding(
                        urwid.Text(u"For Commands, press : %s  " % help_text),
                        width="pack",
                        min_width=len(help_text) + 24,
                        align="right",
                    ),
                ],
                dividechars=2,
                focus_column=0,
            ),
            "footer",
        )

    def update_header(self, text):
        # This needs to be modified if footer structure is changed.
        self.header.original_widget.contents[0][0].set_text(text)

    def update_footer(self, text, trim=True):
        # This needs to be modified if footer structure is changed.
        ftext = text[:25] + "..." if (len(text) > 28 and trim) else text
        self.footer.original_widget.contents[0][0].original_widget.set_text(ftext)
        if not trim:
            # Indicates an error has occured.
            self.footer.set_attr_map({None: "error"})

    def set_top(self, widget):
        self.top = urwid.Overlay(
            widget,
            urwid.SolidFill(" "),
            align="center",
            width=("relative", 95),
            valign="middle",
            height=("relative", 95),
            min_width=20,
            min_height=10,
        )

    def setup_signals(self):
        urwid.connect_signal(self.csignal, "task_complete", self.on_task_completed)
        urwid.connect_signal(self.csignal, "add_item", self.on_add_item)
        urwid.connect_signal(self.csignal, "move_up", self.on_move_up)
        urwid.connect_signal(self.csignal, "move_down", self.on_move_down)
        urwid.connect_signal(self.csignal, "input_recv", self.on_input_recv)
        urwid.connect_signal(self.csignal, "show_tasklists", self.on_show_tasklists)
        urwid.connect_signal(self.csignal, "toggle_complete", self.on_toggle_complete)
        urwid.connect_signal(self.csignal, "delete_task", self.build_delete_task)

    def exit_program(self, button):
        self.cancel_timer_thread()
        self.save()
        urwid.ExitMainLoop()

    def on_show_tasklists(self):
        self.save()
        self.build()

    def on_toggle_complete(self):
        self.show_completed = not self.show_completed
        self.tasks = []
        self.build_taskwidgets()

    def on_help_exit(self, button):
        self.help_visible = False
        self.mbody.original_widget = self._original_w

    def on_tasklist_add(self, button, arg):
        self.logw("Add tasklist " + arg)
        self.model.add_tasklist(title=arg)
        self.build()

    def on_tasklist_add_cancel(self, button, arg):
        self.logw("Cancel tasklist add")
        self.build()

    def on_tasklist_edit_cancel(self, button, arg):
        self.logw("Cancel tasklist edit")
        self.build()

    def on_tasklist_delete(self, button, arg):
        self.logw("Delete tasklist " + str(self.sel_tasklist_edit[1]))
        self.model.delete_tasklist(self.sel_tasklist_edit[0])
        self.build()

    def on_task_delete(self, button, arg):
        self.logw("Delete task*  " + str(self.listbox.focus.title))
        self.logw("Delete task* :  " + str(self.listbox.focus.taskid) + " " + self.current_tasklist)
        self.model.delete_task(self.current_tasklist, self.listbox.focus.taskid)
        self.tasks = []
        self.build_taskwidgets()

    def on_tasklist_delete_cancel(self, button, arg):
        self.logw("Cancel tasklist delete")
        self.build()

    def on_task_delete_cancel(self, button, arg):
        self.logw("Cancel task delete")
        self.mbody.original_widget = self._original_w

    def on_task_enter(self, button, arg):
        curr_task = self.listbox.focus
        self.model.update_task(self.current_tasklist, curr_task.taskid, title=curr_task.title)
        self.update_footer("Saved: %s" % arg[1])

    def keystroke(self, key):
        self.logw("Pres: keypress %s " % key)
        if key in self.bindings["show_help"] and not self.help_visible:
            self.build_help_dialog()
        elif self.tasks_visible:
            self.listbox.focus.keypress(None, key)
        else:
            if key in self.bindings["tasklist_edit"] and not self.help_visible:
                self.sel_tasklist_edit = self.listbox.focus_tasklist_id()
                self.logw(key + str(self.sel_tasklist_edit[0:2]))
                self.build_edit_tasklist(self.sel_tasklist_edit)
            elif key in self.bindings["tasklist_add"] and not self.help_visible:
                self.build_add_tasklist()
            elif key in self.bindings["tasklist_delete"] and not self.help_visible:
                self.sel_tasklist_edit = self.listbox.focus_tasklist_id()
                self.logw(key + str(self.sel_tasklist_edit[0:2]))
                self.build_delete_tasklist(self.sel_tasklist_edit)

    def on_sel_tasklist_edit(self, button, arg):
        self.logw("On_Sel_tasklist_edit  " + arg)
        self.model.update_tasklist(self.sel_tasklist_edit[0], title=arg)
        self.save()
        self.build()

    def on_list_select(self, button, arg):
        self.current_tasklist = arg[0]
        self.current_tasklist_title = arg[1]
        self.logw("Select tasklist %s :" % arg)
        self.tasks = []
        self.build_taskwidgets()

    def build_taskwidgets(self):
        ret_tasks = self.model.tasks(self.current_tasklist)
        for item in ret_tasks:
            self.logw(item)
            comp = False if item[3] == "" else True
            item_list = list(item)
            item_list[3] = comp
            self.logw(" show_completed %s, comp %s::  " % (str(self.show_completed), str(comp)))
            if not (self.show_completed and comp):
                self.logw(" adding Task::  " + str(item_list))
                self.tasks.append(
                    TaskWidget(
                        task=item_list,
                        callback=self.on_task_enter,
                        change_callback=self.on_input_recv,
                        signal=self.csignal,
                        bindings=self.bindings,
                        logw=self.logw,
                    )
                )

        # Check is self.tasks is empty. If yes, create one
        if len(self.tasks) == 0:
            self.on_add_item()
        self.build_tasks()

    def on_timer(self):
        self.idle_time += 1
        if self.idle_time > 4:
            self.idle_time = 0
            self.logw("save() called")
            self.save()
        else:
            self.timer = Timer(2, self.on_timer)
            self.timer.start()

    def on_input_recv(self, button, arg):
        self.logw("Pres : input received, clearing dirty data\n")
        self.dirty = False
        self.idle_time = 0
        if hasattr(self, "timer"):
            self.logw("thread exists")
            if self.timer.isAlive():
                self.logw("Thread is active, cancel thread")
                self.timer.cancel()
        self.timer = Timer(2, self.on_timer)
        self.timer.start()
        self.logw("thread started:")

    def save(self):
        if not self.dirty:
            self.logw("save this shit!!")
            if self.tasks_visible:
                for twidget in self.tasks:
                    self.logw("Test save count (tasks) " + str(twidget.values()))
                    tt = twidget.values()
                    task_title = tt[1]
                    comp = "x" if not tt[3] else utils.now()
                    # Only save tasks which are not empty
                    if len(task_title) > 0:
                        self.model.update_task(
                            self.current_tasklist, tt[0], title=task_title, position=tt[2], completed=comp
                        )
            self.model.save()
            self.dirty = False
        else:
            self.logw("Dirty data exists: CANNOT *save* this shit!!")

    def on_move_up(self):
        pos = self.listbox.focus_position
        if (pos - 1) < 0:
            return
        self.logw("Pres:  Move up item")
        tw = self.walker.pop(pos)
        pos -= 1
        self.walker.insert(pos, tw)
        self.listbox.focus_position = pos

    def on_move_down(self):
        pos = self.listbox.focus_position
        if (pos + 1) > len(self.walker.positions()) - 1:
            return
        self.logw("Pres:  Move down item")
        tw = self.walker.pop(pos)
        pos += 1
        self.walker.insert(pos, tw)
        self.listbox.focus_position = pos

    def on_add_item(self):
        if not self.dirty:
            self.logw("Add new item")
            nt = self.model.add_task(self.current_tasklist, title="")
            comp = False if nt.completed == "" else True
            tw = TaskWidget(
                [nt.id, nt.title, nt.position, comp],
                callback=self.on_task_enter,
                change_callback=self.on_input_recv,
                signal=self.csignal,
                bindings=self.bindings,
                logw=self.logw,
            )
            self.tasks.append(tw)
            pos = self.listbox.focus_position + 1
            self.walker.insert(pos, tw)
            self.listbox.focus_position = pos
            self.dirty = True
        else:
            self.logw("Dirty data exists: Cannot add new item")

    def on_task_completed(self):
        taskid = self.listbox.focus.taskid
        completed = self.listbox.focus.values()[3]
        self.logw(
            " Received Signal,  Will mark the task %s as complete: %s" % (self.listbox.focus.taskid, str(completed))
        )
        comp_val = "x" if not completed else utils.now()
        self.model.update_task(self.current_tasklist, taskid, completed=comp_val)
        update_text = "complete" if completed else "uncomplete"
        self.update_footer('Task "%s" marked as %s' % (self.listbox.focus.title, update_text))

    def cancel_timer_thread(self):
        if self.timer and self.timer.isAlive():
            self.timer.cancel()

    def main(self):
        try:
            self.loop = urwid.MainLoop(
                self.frame, palette=self.config.get_palette(), unhandled_input=self.keystroke, handle_mouse=False
            )
            self.loop.screen.set_terminal_properties(256)
            self.loop.run()
        except (KeyboardInterrupt, SystemExit):
            self.exit_program(None)