From 5620e794321b46547a61bc05376d8d1f224fe6d2 Mon Sep 17 00:00:00 2001 From: Valentijn Date: Mon, 24 Sep 2018 14:55:19 +0200 Subject: [PATCH] Use slugs instead of names; Backup commands; Filter on search & settings pages --- clay/core/config.yaml | 4 -- clay/ui/urwid/__init__.py | 11 +++-- clay/ui/urwid/hotkeys.py | 30 ++++++++++++++ clay/ui/urwid/pages/search.py | 7 +++- clay/ui/urwid/pages/settings.py | 2 +- clay/ui/urwid/songlist.py | 71 ++++----------------------------- 6 files changed, 51 insertions(+), 74 deletions(-) diff --git a/clay/core/config.yaml b/clay/core/config.yaml index e66e484..f516387 100644 --- a/clay/core/config.yaml +++ b/clay/core/config.yaml @@ -36,10 +36,6 @@ hotkeys: song_view: start_filtering: / end_filtering: esc - move_to_beginning: home - move_to_end: end - move_up: up - move_down: down hide_context_menu: m general_page: diff --git a/clay/ui/urwid/__init__.py b/clay/ui/urwid/__init__.py index 9f3e27f..fc8814b 100644 --- a/clay/ui/urwid/__init__.py +++ b/clay/ui/urwid/__init__.py @@ -9,7 +9,7 @@ from .clipboard import copy from .hotkeys import hotkey_manager from .notifications import notification_area from .playbar import PlayBar -from .songlist import SongListBox, filter_out +from .songlist import SongListBox from .pages import * @@ -174,6 +174,11 @@ class AppWidget(urwid.Frame): """ Switch to a different tab. """ + try: + self.current_page.songlist.end_filtering() + except AttributeError as e: + pass + page = [page for page in self.pages if page.slug == slug][0] self.current_page = page self.contents['body'] = (page, None) @@ -214,9 +219,6 @@ class AppWidget(urwid.Frame): Handle keypress. Can switch tabs, control playback, flags, notifications and app state. """ - if filter_out(key): - return super(AppWidget, self).keypress(size, key) - hotkey_manager.keypress("global", self, super(AppWidget, self), size, key) return None @@ -250,6 +252,7 @@ class AppWidget(urwid.Frame): def show_settings(self): """ Show settings page. """ + self.set_page('settings') @staticmethod diff --git a/clay/ui/urwid/hotkeys.py b/clay/ui/urwid/hotkeys.py index f8c74fd..95bca08 100644 --- a/clay/ui/urwid/hotkeys.py +++ b/clay/ui/urwid/hotkeys.py @@ -5,6 +5,8 @@ Requires "gi" package and "Gtk" & "Keybinder" modules. # pylint: disable=broad-except from clay.core import settings_manager, logger +from string import ascii_letters, digits + def report_error(exc): "Print an error message to the debug screen" logger.error("{0}: {1}".format(exc.__class__.__name__, exc)) @@ -17,6 +19,7 @@ class _HotkeyManager(object): def __init__(self): self._hotkeys = self._parse_hotkeys() self.config = None + self.filtering = False def _parse_hotkeys(self): """ @@ -42,6 +45,33 @@ class _HotkeyManager(object): return hotkeys def keypress(self, name, caller, super_, size, key): + """ + Processes a key and sends the appropiated command back. + + Returns: + the letter pressed if Clay is filtering, the command or, in case a modifier key is pressed, + the command associated with the letter after the modifier key. + """ + split_keys = key.split() + if split_keys[0] == 'meta' or split_keys[0] == 'ctrl': + self.filtering = False + return self._lookup_key(name, caller, super_, size, ''.join(split_keys[1:])) + + if not self.filtering: + return self._lookup_key(name, caller, super_, size, key) + + if key == 'backspace' or key == 'tab' or key in ascii_letters + digits + ' _-.,?()[]\'': + if name == 'song_view': + ret = caller.perform_filtering(key) + else: + ret = super_.keypress(size, key) + + else: + ret = self._lookup_key(name, caller, super_, size, key) + + return ret + + def _lookup_key(self, name, caller, super_, size, key): """ Process the pressed key by looking it up in the configuration file diff --git a/clay/ui/urwid/pages/search.py b/clay/ui/urwid/pages/search.py index 60e16a4..e65c0bc 100644 --- a/clay/ui/urwid/pages/search.py +++ b/clay/ui/urwid/pages/search.py @@ -40,6 +40,7 @@ class SearchBox(urwid.Columns): """ Send a message to urwid to search the filled in search query """ + urwid.emit_signal(self, 'search-requested', self.query.edit_text) @@ -71,7 +72,7 @@ class SearchPage(urwid.Pile, AbstractPage): def __init__(self, app): self.app = app self.songlist = SongListBox(app) - + self._focus_position = 0 self.search_box = SearchBox() urwid.connect_signal(self.search_box, 'search-requested', self.perform_search) @@ -102,9 +103,11 @@ class SearchPage(urwid.Pile, AbstractPage): self.app.redraw() def activate(self): - pass + hotkey_manager.filtering = True def keypress(self, size, key): + hotkey_manager.filtering = (self.focus == self.search_box) + if key == 'tab': if self.focus == self.search_box: self.focus_position = 2 diff --git a/clay/ui/urwid/pages/settings.py b/clay/ui/urwid/pages/settings.py index f82f61c..3dc030d 100644 --- a/clay/ui/urwid/pages/settings.py +++ b/clay/ui/urwid/pages/settings.py @@ -197,4 +197,4 @@ class SettingsPage(urwid.Columns, AbstractPage): self.app.log_in() def activate(self): - pass + hotkey_manager.filtering = True diff --git a/clay/ui/urwid/songlist.py b/clay/ui/urwid/songlist.py index 1a5a27f..1eb14cf 100644 --- a/clay/ui/urwid/songlist.py +++ b/clay/ui/urwid/songlist.py @@ -25,13 +25,6 @@ from .clipboard import copy player = get_player() # pylint: disable=invalid-name -FILTERING = False -def filter_out(key): - """ - Checks whether the keypress should be sent to the filter instead - """ - return FILTERING and (key == 'backspace' or key in (ascii_letters + digits + ' _-.,?!()[]\'')) - class SongListItem(urwid.Pile): """ Widget that represents single song item. @@ -183,9 +176,6 @@ class SongListItem(urwid.Pile): """ Handle keypress. """ - if filter_out(key): - return super(SongListItem, self).keypress(size, key) - return hotkey_manager.keypress("song_item", self, super(SongListItem, self), size, key) def mouse_event(self, size, event, button, col, row, focus): @@ -440,7 +430,7 @@ class SongListBox(urwid.Frame): self.list_box = urwid.ListBox(self.walker) self.filter_prefix = '> ' self.filter_query = '' - self.filter_box = urwid.Text(self.filter_prefix) + self.filter_box = urwid.Text('') self.filter_info = urwid.Text('') self.filter_panel = urwid.Columns([ self.filter_box, @@ -469,16 +459,14 @@ class SongListBox(urwid.Frame): """ Starts filtering the song view """ - global FILTERING - - if not FILTERING: + if not hotkey_manager.filtering: self.content.contents = [ (self.list_box, ('weight', 1)), (self.filter_panel, ('pack', None)) ] self.app.append_cancel_action(self.end_filtering) self.filter_query = '' - FILTERING = True + hotkey_manager.filtering = True self.tracks_walker[:] = self.walker self.filter_box.set_text(self.filter_prefix) @@ -501,7 +489,7 @@ class SongListBox(urwid.Frame): self.walker[:] = matches self.walker.set_focus(0) - if self.app.current_page.name == 'Library': + if self.app.current_page.slug == 'library': self.update_indexes() def get_filtered_items(self): @@ -520,14 +508,12 @@ class SongListBox(urwid.Frame): """ Exit filtering mode. """ - global FILTERING - if not FILTERING: + if self.filter_box.text == '': return - self.content.contents = [ (self.list_box, ('weight', 1)) ] - FILTERING = False + hotkey_manager.filtering = False self.filter_box.set_text('') self.filter_info.set_text('') self.walker[:] = self.tracks_walker @@ -596,12 +582,12 @@ class SongListBox(urwid.Frame): # There are some pages like search library where overwriting the queue # doesn't make much sense. We can also assume that someone searching # for a specific song also wants to append. - elif (page.append or FILTERING) and page.name != 'Queue': + elif (page.append or hotkey_manager.filtering) and page.slug != 'queue': self.item_append_requested(songitem) else: player.load_queue(self.tracks, songitem.index) - if FILTERING: + if hotkey_manager.filtering and page.slug != 'search': self.walker[:] = self.get_filtered_items() @staticmethod @@ -736,49 +722,8 @@ class SongListBox(urwid.Frame): songlistitem.set_index(i) def keypress(self, size, key): - if filter_out(key): - self.perform_filtering(key) - return hotkey_manager.keypress("song_view", self, super(SongListBox, self), size, key) - def move_to_beginning(self): - """Move to the focus to beginning of the songlist""" - self.list_box.set_focus(0, 'below') - return False - - def move_to_end(self): - """Move to the focus to end of the songlist""" - self.list_box.set_focus(-1, 'above') - return False - - def move_up(self): - """Move the focus an item up in the playlist""" - _, index = self.walker.get_focus() - - if index is None: - return False - - if index <= 0: - self.list_box.set_focus(len(self.walker) - 1, 'below') - else: - self.list_box.set_focus(index - 1, 'above') - - return False - - def move_down(self): - """Move the focus an item down in the playlist """ - _, index = self.walker.get_focus() - - if index is None: - return False - - if index >= len(self.walker) - 1: - self.list_box.set_focus(0, 'above') - else: - self.list_box.set_focus(index + 1, 'below') - - return False - def mouse_event(self, size, event, button, col, row, focus): """ Handle mouse event.