summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-01-13 14:49:09 +0100
committerAnton Khirnov <anton@khirnov.net>2021-01-13 14:49:09 +0100
commit371bf6414bb181a3856648d877b9f1980da1bfd7 (patch)
tree5efbdfe8adf0ee60be4907e6aab5983595aa989b
parent0d994f1f53576f153c51db345283a17b03eea674 (diff)
thread: allow switching between multipart/alternative parts
-rw-r--r--alot/commands/thread.py10
-rw-r--r--alot/defaults/default.bindings1
-rw-r--r--alot/widgets/thread.py68
3 files changed, 61 insertions, 18 deletions
diff --git a/alot/commands/thread.py b/alot/commands/thread.py
index 9d67456b..178264c0 100644
--- a/alot/commands/thread.py
+++ b/alot/commands/thread.py
@@ -523,6 +523,9 @@ class EditNewCommand(Command):
arguments=[(['fold'], {'action': cargparse.ValidatedStoreAction,
'validator': cargparse.is_int_or_pm})])
@registerCommand(
+ MODE, 'cycle_alt', help='cycle among MIME alternative parts',
+ forced = {'cycle_alt' : True },)
+@registerCommand(
MODE, 'weight', help='change weight of the thread tree',
arguments=[(['weight'], {'action': cargparse.ValidatedStoreAction,
'validator': cargparse.is_int_or_pm})])
@@ -531,7 +534,8 @@ class ChangeDisplaymodeCommand(Command):
repeatable = True
def __init__(self, query=None, raw=None, all_headers=None,
- indent=None, fold = None, weight = None, **kwargs):
+ indent=None, fold = None, weight = None, cycle_alt = None,
+ **kwargs):
"""
:param query: notmuch query string used to filter messages to affect
:type query: str
@@ -552,6 +556,7 @@ class ChangeDisplaymodeCommand(Command):
self.indent = indent
self.fold = fold
self.weight = weight
+ self.cycle_alt = cycle_alt
Command.__init__(self, **kwargs)
def apply(self, ui):
@@ -619,6 +624,9 @@ class ChangeDisplaymodeCommand(Command):
else:
m.foldlevel = int(self.fold)
+ if self.cycle_alt:
+ m.cycle_alt()
+
@registerCommand(MODE, 'pipeto', arguments=[
(['cmd'], {'help': 'shellcommand to pipe to', 'nargs': '+'}),
diff --git a/alot/defaults/default.bindings b/alot/defaults/default.bindings
index cf64fc51..e28253ed 100644
--- a/alot/defaults/default.bindings
+++ b/alot/defaults/default.bindings
@@ -79,6 +79,7 @@ q = exit
s = save
r = reply
| = prompt 'pipeto '
+ @ = cycle_alt
'g j' = move next sibling
'g k' = move previous sibling
diff --git a/alot/widgets/thread.py b/alot/widgets/thread.py
index 3be17976..3da660a5 100644
--- a/alot/widgets/thread.py
+++ b/alot/widgets/thread.py
@@ -82,6 +82,13 @@ class _MIMEPartWidget(urwid.WidgetWrap):
self._fold_level = val_out
+ def cycle_alt(self):
+ if self._children is None:
+ return
+
+ for c in self._children:
+ c.cycle_alt()
+
class _CryptPartWidget(_MIMEPartWidget):
def __init__(self, mime_tree, alternative_pref):
children = None
@@ -136,6 +143,43 @@ class _MultiMixedWidget(_MIMEPartWidget):
def __init__(self, children):
super().__init__(urwid.Pile(children), children)
+class _MultiAltWidget(_MIMEPartWidget):
+ _cur_idx = None
+ _child_parts = None
+ _sel_placeholder = None
+
+ def __init__(self, child_widgets, child_parts, alternative_pref):
+ self._child_parts = child_parts
+
+ child_idx = None
+ for idx, ch in enumerate(child_parts):
+ if ch.content_type == alternative_pref:
+ child_idx = idx
+ break
+ if child_idx is None:
+ child_idx = 0
+
+ self._sel_placeholder = urwid.WidgetPlaceholder(urwid.Text(''))
+
+ body_wgt = urwid.LineBox(self._sel_placeholder)
+
+ super().__init__(body_wgt, child_widgets)
+
+ self._select_alt(child_idx)
+
+ def _select_alt(self, idx):
+ child_part = self._child_parts[idx]
+ child_wgt = self._children[idx]
+
+ self._w.set_title('Alternative MIME part %d/%d: %s' %
+ (idx + 1, len(self._children), child_part.content_type))
+ self._sel_placeholder.original_widget = child_wgt
+
+ self._cur_idx = idx
+
+ def cycle_alt(self):
+ self._select_alt((self._cur_idx + 1) % len(self._children))
+
class _Fold:
level = None
start = None
@@ -320,7 +364,7 @@ class _EmptyMessageWidget(_MIMEPartWidget):
body_wgt = urwid.Text('<<< No displayable content >>>', align = 'center')
super().__init__(body_wgt)
-def _handle_mixed(mime_tree, alternative_pref):
+def _handle_multipart(mime_tree, alternative_pref):
children = []
for child in mime_tree.children:
ch = _render_mime_tree(child, alternative_pref)
@@ -328,20 +372,10 @@ def _handle_mixed(mime_tree, alternative_pref):
children.append(ch)
if len(children) > 0:
+ if mime_tree.is_alternative:
+ return _MultiAltWidget(children, mime_tree.children, alternative_pref)
return _MultiMixedWidget(children)
-def _handle_alternative(mime_tree, alternative_pref):
- # TODO: switching between alternatives
- child = None
- for ch in mime_tree.children:
- if ch.content_type == alternative_pref:
- child = ch
- break
- if child is None:
- child = mime_tree.children[0]
-
- return _render_mime_tree(child, alternative_pref)
-
def _render_mime_tree(mime_tree, alternative_pref):
# handle encrypted/signed parts
if mime_tree.is_signed or mime_tree.is_encrypted:
@@ -349,10 +383,7 @@ def _render_mime_tree(mime_tree, alternative_pref):
if mime_tree.children is not None:
# multipart MIME parts
- if mime_tree.is_alternative:
- return _handle_alternative(mime_tree, alternative_pref)
-
- return _handle_mixed(mime_tree, alternative_pref)
+ return _handle_multipart(mime_tree, alternative_pref)
# no children - this is a leaf node
# skip attachment parts
@@ -580,6 +611,9 @@ class MessageWidget(urwid.WidgetWrap):
def foldlevel(self, val):
self._body_wgt.foldlevel = val
+ def cycle_alt(self):
+ self._body_wgt.cycle_alt()
+
def get_selected_attachment(self):
"""
If an AttachmentWidget is currently focused, return it. Otherwise return