Commit ef360c2f authored by Jacek Sowiński's avatar Jacek Sowiński

Execute commands on multiple items marked with 'm'

1. 'm' can be reconfigured to any other key (action: 'mark').
2. Using 'mark' on already marked todo item will unmark it.
3. 'esc' key will clear whole selection.
4. Command will be executed on **all** marked items in **all** columns.
parent d2ba87c3
...@@ -79,6 +79,7 @@ x = cmd do {} ...@@ -79,6 +79,7 @@ x = cmd do {}
pp = postpone pp = postpone
ps = postpone_s ps = postpone_s
pr = pri pr = pri
m = mark
0 = first_column 0 = first_column
$ = last_column $ = last_column
h = prev_column h = prev_column
......
...@@ -125,6 +125,7 @@ class _Config: ...@@ -125,6 +125,7 @@ class _Config:
'e': 'cmd edit {}', 'e': 'cmd edit {}',
'u': 'cmd revert', 'u': 'cmd revert',
'x': 'cmd do {}', 'x': 'cmd do {}',
'm': 'mark',
'pp': 'postpone', 'pp': 'postpone',
'ps': 'postpone_s', 'ps': 'postpone_s',
'pr': 'pri', 'pr': 'pri',
......
...@@ -96,6 +96,8 @@ class UIApplication(CLIApplicationBase): ...@@ -96,6 +96,8 @@ class UIApplication(CLIApplicationBase):
self.todofile = TodoFile.TodoFile(config().todotxt()) self.todofile = TodoFile.TodoFile(config().todotxt())
self.todolist = TodoList.TodoList(self.todofile.read()) self.todolist = TodoList.TodoList(self.todofile.read())
self.pending_todos = []
self.columns = urwid.Columns([], dividechars=0, min_width=COLUMN_WIDTH) self.columns = urwid.Columns([], dividechars=0, min_width=COLUMN_WIDTH)
self.commandline = CommandLineWidget('topydo> ') self.commandline = CommandLineWidget('topydo> ')
self.keystate_widget = KeystateWidget() self.keystate_widget = KeystateWidget()
...@@ -169,6 +171,9 @@ class UIApplication(CLIApplicationBase): ...@@ -169,6 +171,9 @@ class UIApplication(CLIApplicationBase):
""" """
Executes a command, given as a string. Executes a command, given as a string.
""" """
if '{}' in p_command:
todos = ' '.join(self.pending_todos)
p_command = p_command.format(todos)
p_output = p_output or self._output p_output = p_output or self._output
p_command = shlex.split(p_command) p_command = shlex.split(p_command)
(subcommand, args) = get_subcommand(p_command) (subcommand, args) = get_subcommand(p_command)
...@@ -187,6 +192,8 @@ class UIApplication(CLIApplicationBase): ...@@ -187,6 +192,8 @@ class UIApplication(CLIApplicationBase):
if command.execute() != False: if command.execute() != False:
self._post_execute() self._post_execute()
self._clear_pending_todos()
except TypeError: except TypeError:
# TODO: show error message # TODO: show error message
pass pass
...@@ -277,6 +284,7 @@ class UIApplication(CLIApplicationBase): ...@@ -277,6 +284,7 @@ class UIApplication(CLIApplicationBase):
def _handle_input(self, p_input): def _handle_input(self, p_input):
dispatch = { dispatch = {
':': self._focus_commandline, ':': self._focus_commandline,
'esc': self._clear_pending_todos,
} }
try: try:
...@@ -334,6 +342,9 @@ class UIApplication(CLIApplicationBase): ...@@ -334,6 +342,9 @@ class UIApplication(CLIApplicationBase):
urwid.connect_signal(todolist, 'remove_pending_action', self._remove_alarm) urwid.connect_signal(todolist, 'remove_pending_action', self._remove_alarm)
urwid.connect_signal(todolist, 'column_action', self._column_action_handler) urwid.connect_signal(todolist, 'column_action', self._column_action_handler)
urwid.connect_signal(todolist, 'show_keystate', self._print_keystate) urwid.connect_signal(todolist, 'show_keystate', self._print_keystate)
urwid.connect_signal(todolist, 'append_pending_todos', self._pending_todos_handler)
urwid.connect_signal(todolist, 'check_pending_todos', self._is_pending)
urwid.connect_signal(todolist, 'clear_pending_todos', self._clear_pending_todos)
options = self.columns.options( options = self.columns.options(
width_type='given', width_type='given',
...@@ -450,6 +461,25 @@ class UIApplication(CLIApplicationBase): ...@@ -450,6 +461,25 @@ class UIApplication(CLIApplicationBase):
return sz return sz
def _clear_pending_todos(self, p_refresh=True):
self.pending_todos = []
if p_refresh:
self._update_all_columns()
def _is_pending(self):
if len(self.pending_todos) > 0:
return True
else:
return False
def _pending_todos_handler(self, p_todo_id):
if p_todo_id not in self.pending_todos:
self.pending_todos.append(p_todo_id)
return True
else:
self.pending_todos.remove(p_todo_id)
return False
def run(self): def run(self):
layout = columns() layout = columns()
if len(layout) > 0: if len(layout) > 0:
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import urwid import urwid
from topydo.ui.TodoWidget import TodoWidget from topydo.ui.TodoWidget import TodoWidget, markup
from topydo.lib.Utils import translate_key_to_config from topydo.lib.Utils import translate_key_to_config
...@@ -62,6 +62,9 @@ class TodoListWidget(urwid.LineBox): ...@@ -62,6 +62,9 @@ class TodoListWidget(urwid.LineBox):
'remove_pending_action', 'remove_pending_action',
'column_action', 'column_action',
'show_keystate', 'show_keystate',
'append_pending_todos',
'check_pending_todos',
'clear_pending_todos',
]) ])
@property @property
...@@ -199,6 +202,17 @@ class TodoListWidget(urwid.LineBox): ...@@ -199,6 +202,17 @@ class TodoListWidget(urwid.LineBox):
def selectable(self): def selectable(self):
return True return True
def _append_pending_todos(self):
try:
todo = self.listbox.focus.todo
todo_id = str(self.view.todolist.number(todo))
result = urwid.emit_signal(self, 'append_pending_todos', todo_id)
attr_spec = {None: markup(todo, result)}
self.listbox.focus.widget.set_attr_map(attr_spec)
except AttributeError:
# No todo item selected
pass
def _execute_on_selected(self, p_cmd_str, p_execute_signal): def _execute_on_selected(self, p_cmd_str, p_execute_signal):
""" """
Executes command specified by p_cmd_str on selected todo item. Executes command specified by p_cmd_str on selected todo item.
...@@ -213,7 +227,13 @@ class TodoListWidget(urwid.LineBox): ...@@ -213,7 +227,13 @@ class TodoListWidget(urwid.LineBox):
todo = self.listbox.focus.todo todo = self.listbox.focus.todo
todo_id = str(self.view.todolist.number(todo)) todo_id = str(self.view.todolist.number(todo))
urwid.emit_signal(self, p_execute_signal, p_cmd_str.format(todo_id)) result = urwid.emit_signal(self, 'check_pending_todos')
if result:
cmd = p_cmd_str
else:
cmd = p_cmd_str.format(todo_id)
urwid.emit_signal(self, p_execute_signal, cmd)
# force screen redraw after editing # force screen redraw after editing
if p_cmd_str.startswith('edit'): if p_cmd_str.startswith('edit'):
...@@ -250,8 +270,8 @@ class TodoListWidget(urwid.LineBox): ...@@ -250,8 +270,8 @@ class TodoListWidget(urwid.LineBox):
Currently supported actions are: 'up', 'down', 'home', 'end', Currently supported actions are: 'up', 'down', 'home', 'end',
'first_column', 'last_column', 'prev_column', 'next_column', 'first_column', 'last_column', 'prev_column', 'next_column',
'append_column', 'insert_column', 'edit_column', 'delete_column', 'append_column', 'insert_column', 'edit_column', 'delete_column',
'copy_column', swap_right', 'swap_left', 'postpone', 'postpone_s' and 'copy_column', swap_right', 'swap_left', 'postpone', 'postpone_s', 'pri'
'pri'. and 'mark'.
""" """
column_actions = ['first_column', column_actions = ['first_column',
'last_column', 'last_column',
...@@ -278,6 +298,8 @@ class TodoListWidget(urwid.LineBox): ...@@ -278,6 +298,8 @@ class TodoListWidget(urwid.LineBox):
pass pass
elif p_action_str == 'pri': elif p_action_str == 'pri':
pass pass
elif p_action_str == 'mark':
self._append_pending_todos()
def _add_pending_action(self, p_action, p_size): def _add_pending_action(self, p_action, p_size):
""" """
......
...@@ -35,7 +35,8 @@ def _to_urwid_color(p_color): ...@@ -35,7 +35,8 @@ def _to_urwid_color(p_color):
else: else:
return 'h{}'.format(p_color.color) return 'h{}'.format(p_color.color)
def _markup(p_todo, p_focus):
def markup(p_todo, p_focus):
""" """
Returns an attribute spec for the colors that correspond to the given todo Returns an attribute spec for the colors that correspond to the given todo
item. item.
...@@ -83,8 +84,8 @@ class TodoWidget(urwid.WidgetWrap): ...@@ -83,8 +84,8 @@ class TodoWidget(urwid.WidgetWrap):
self.widget = urwid.AttrMap( self.widget = urwid.AttrMap(
self.columns, self.columns,
_markup(p_todo, False), # no focus markup(p_todo, False), # no focus
_markup(p_todo, True) # focus markup(p_todo, True) # focus
) )
super().__init__(self.widget) super().__init__(self.widget)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment