reworked genre filter

This commit is contained in:
Martin Wagner 2021-10-06 18:03:14 +02:00
parent a4eba33bdc
commit 59af81866f
4 changed files with 193 additions and 44 deletions

View File

@ -1437,6 +1437,10 @@ class ScrolledFocusFrame(FocusFrame):
scroll=Gtk.ScrolledWindow() scroll=Gtk.ScrolledWindow()
scroll.add(widget) scroll.add(widget)
# allow hide/show without .show_all()
scroll.set_visible(True)
widget.set_visible(True)
self.add(scroll) self.add(scroll)
class SongPopover(Gtk.Popover): class SongPopover(Gtk.Popover):
@ -2485,42 +2489,32 @@ class AlbumWindow(FocusFrame):
class Browser(Gtk.Paned): class Browser(Gtk.Paned):
def __init__(self, client, settings): def __init__(self, client, settings):
super().__init__(orientation=Gtk.Orientation.HORIZONTAL) super().__init__()
self._client=client self._client=client
self._settings=settings self._settings=settings
# widgets # widgets
label=Gtk.Label(ellipsize=Pango.EllipsizeMode.MIDDLE)
self._genres_button=Gtk.ToggleButton(image=label, tooltip_text=_("Filter by genre"))
self._genre_select=GenreSelect(self._client) self._genre_select=GenreSelect(self._client)
self._artist_window=ArtistWindow(self._client, self._settings, self._genre_select) self._artist_window=ArtistWindow(self._client, self._settings, self._genre_select)
self._album_window=AlbumWindow(self._client, self._settings, self._artist_window) self._album_window=AlbumWindow(self._client, self._settings, self._artist_window)
genre_focus_frame=ScrolledFocusFrame(self._genre_select)
artist_focus_frame=ScrolledFocusFrame(self._artist_window)
# stacks # hide/show genre filter
self._artists_genres_stack=Gtk.Stack(transition_type=Gtk.StackTransitionType.OVER_RIGHT_LEFT) self._settings.bind("genre-filter", genre_focus_frame, "no-show-all", Gio.SettingsBindFlags.INVERT_BOOLEAN|Gio.SettingsBindFlags.GET)
self._artists_genres_stack.add_named(ScrolledFocusFrame(self._artist_window), "artists") self._settings.bind("genre-filter", genre_focus_frame, "visible", Gio.SettingsBindFlags.GET)
self._artists_genres_stack.add_named(ScrolledFocusFrame(self._genre_select), "genres") self._settings.connect("changed::genre-filter", self._on_genre_filter_changed)
# connect
self._genres_button.connect("toggled", self._on_genres_toggled)
self._genre_select.connect("item-selected", self._on_genre_chnaged)
self._client.emitter.connect("disconnected", self._on_disconnected)
self._client.emitter.connect("reconnected", self._on_reconnected)
# packing # packing
hbox=Gtk.Box(spacing=6, border_width=6) self.paned1=Gtk.Paned()
hbox.pack_start(self._genres_button, True, True, 0) self.paned1.pack1(artist_focus_frame, False, False)
vbox=Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.paned1.pack2(self._album_window, True, False)
vbox.pack_start(hbox, False, False, 0) self.pack1(genre_focus_frame, False, False)
vbox.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL), False, False, 0) self.pack2(self.paned1, True, False)
vbox.pack_start(self._artists_genres_stack, True, True, 0)
self.pack1(vbox, False, False)
self.pack2(self._album_window, True, False)
def back_to_current_album(self, force=False): def back_to_current_album(self, force=False):
song=self._client.currentsong() song=self._client.currentsong()
if song: if song:
self._genres_button.set_active(False)
# get artist name # get artist name
artist=song[self._settings.get_artist_type()][0] artist=song[self._settings.get_artist_type()][0]
# deactivate genre filter to show all artists (if needed) # deactivate genre filter to show all artists (if needed)
@ -2535,26 +2529,10 @@ class Browser(Gtk.Paned):
else: else:
self._genre_select.deactivate() self._genre_select.deactivate()
def _on_genres_toggled(self, widget): def _on_genre_filter_changed(self, settings, key):
if widget.get_active(): if self._client.connected():
self._artists_genres_stack.set_visible_child_name("genres") if not settings.get_boolean(key):
else: self._genre_select.deactivate()
self._artists_genres_stack.set_visible_child_name("artists")
def _on_reconnected(self, *args):
self._genres_button.set_sensitive(True)
def _on_disconnected(self, *args):
self._genres_button.set_active(False)
self._genres_button.set_sensitive(False)
def _on_genre_chnaged(self, *args):
genre=self._genre_select.get_selected()
if genre is None:
self._genres_button.get_image().set_text(self._genre_select.select_all_string)
else:
self._genres_button.get_image().set_text(genre)
self._genres_button.set_active(False)
############ ############
# playlist # # playlist #
@ -3601,6 +3579,7 @@ class ShortcutsWindow(Gtk.ShortcutsWindow):
("<Shift><Control>p", _("Cycle through profiles in reversed order"), None, window_group), ("<Shift><Control>p", _("Cycle through profiles in reversed order"), None, window_group),
("<Control>m", _("Toggle mini player"), None, window_group), ("<Control>m", _("Toggle mini player"), None, window_group),
("<Control>l", _("Toggle lyrics"), None, window_group), ("<Control>l", _("Toggle lyrics"), None, window_group),
("<Control>g", _("Toggle genre filter"), None, window_group),
("<Control>f", _("Toggle search"), None, window_group), ("<Control>f", _("Toggle search"), None, window_group),
("Escape", _("Back to current album"), None, window_group), ("Escape", _("Back to current album"), None, window_group),
("space", _("Play/Pause"), None, playback_group), ("space", _("Play/Pause"), None, playback_group),
@ -3709,6 +3688,7 @@ class MainWindow(Gtk.ApplicationWindow):
action.connect("activate", getattr(self, ("_on_"+name.replace("-","_")))) action.connect("activate", getattr(self, ("_on_"+name.replace("-","_"))))
self.add_action(action) self.add_action(action)
self.add_action(self._settings.create_action("mini-player")) self.add_action(self._settings.create_action("mini-player"))
self.add_action(self._settings.create_action("genre-filter"))
self.add_action(self._settings.create_action("active-profile")) self.add_action(self._settings.create_action("active-profile"))
# shortcuts # shortcuts
@ -3740,6 +3720,11 @@ class MainWindow(Gtk.ApplicationWindow):
self._back_button=Gtk.Button(image=icon("go-previous-symbolic"), tooltip_text=_("Back to current album"), no_show_all=True) self._back_button=Gtk.Button(image=icon("go-previous-symbolic"), tooltip_text=_("Back to current album"), no_show_all=True)
self._back_button.set_can_focus(False) self._back_button.set_can_focus(False)
self._settings.bind("mini-player", self._back_button, "visible", Gio.SettingsBindFlags.INVERT_BOOLEAN|Gio.SettingsBindFlags.GET) self._settings.bind("mini-player", self._back_button, "visible", Gio.SettingsBindFlags.INVERT_BOOLEAN|Gio.SettingsBindFlags.GET)
self._genre_button=Gtk.ToggleButton(
image=icon("org.mpdevil.mpdevil-genre-symbolic"), tooltip_text=_("Filter by genre"), no_show_all=True)
self._genre_button.set_can_focus(False)
self._settings.bind("mini-player", self._genre_button, "visible", Gio.SettingsBindFlags.INVERT_BOOLEAN|Gio.SettingsBindFlags.GET)
self._settings.bind("genre-filter", self._genre_button, "active", Gio.SettingsBindFlags.DEFAULT)
# stack # stack
self._stack=Gtk.Stack(transition_type=Gtk.StackTransitionType.CROSSFADE) self._stack=Gtk.Stack(transition_type=Gtk.StackTransitionType.CROSSFADE)
@ -3805,12 +3790,14 @@ class MainWindow(Gtk.ApplicationWindow):
self._header_bar.set_show_close_button(True) self._header_bar.set_show_close_button(True)
self.set_titlebar(self._header_bar) self.set_titlebar(self._header_bar)
self._header_bar.pack_start(self._back_button) self._header_bar.pack_start(self._back_button)
self._header_bar.pack_start(self._genre_button)
self._header_bar.pack_end(self._menu_button) self._header_bar.pack_end(self._menu_button)
self._header_bar.pack_end(self._search_button) self._header_bar.pack_end(self._search_button)
else: else:
action_bar.pack_start(self._back_button) action_bar.pack_start(self._back_button)
action_bar.pack_end(self._menu_button) action_bar.pack_end(self._menu_button)
action_bar.pack_end(self._search_button) action_bar.pack_end(self._search_button)
action_bar.pack_end(self._genre_button)
action_bar.pack_start(playback_control) action_bar.pack_start(playback_control)
action_bar.pack_start(seek_bar) action_bar.pack_start(seek_bar)
action_bar.pack_start(audio) action_bar.pack_start(audio)
@ -3836,8 +3823,9 @@ class MainWindow(Gtk.ApplicationWindow):
Gtk.main_iteration_do(True) Gtk.main_iteration_do(True)
# restore paned settings when window is visible (fixes a bug when window is maximized) # restore paned settings when window is visible (fixes a bug when window is maximized)
self._settings.bind("paned0", self._paned0, "position", Gio.SettingsBindFlags.DEFAULT) self._settings.bind("paned0", self._paned0, "position", Gio.SettingsBindFlags.DEFAULT)
self._settings.bind("paned1", self._browser, "position", Gio.SettingsBindFlags.DEFAULT) self._settings.bind("paned1", self._browser.paned1, "position", Gio.SettingsBindFlags.DEFAULT)
self._settings.bind("paned2", self._paned2, "position", Gio.SettingsBindFlags.DEFAULT) self._settings.bind("paned2", self._paned2, "position", Gio.SettingsBindFlags.DEFAULT)
self._settings.bind("paned3", self._browser, "position", Gio.SettingsBindFlags.DEFAULT)
# start client # start client
def callback(*args): def callback(*args):
@ -3947,6 +3935,7 @@ class MainWindow(Gtk.ApplicationWindow):
self.lookup_action(action).set_enabled(True) self.lookup_action(action).set_enabled(True)
self._search_button.set_sensitive(True) self._search_button.set_sensitive(True)
self._back_button.set_sensitive(True) self._back_button.set_sensitive(True)
self._genre_button.set_sensitive(True)
def _on_disconnected(self, *args): def _on_disconnected(self, *args):
self.set_title("mpdevil") self.set_title("mpdevil")
@ -3957,6 +3946,7 @@ class MainWindow(Gtk.ApplicationWindow):
self._search_button.set_active(False) self._search_button.set_active(False)
self._search_button.set_sensitive(False) self._search_button.set_sensitive(False)
self._back_button.set_sensitive(False) self._back_button.set_sensitive(False)
self._genre_button.set_sensitive(False)
def _on_size_allocate(self, widget, rect): def _on_size_allocate(self, widget, rect):
if not self.is_maximized() and not self._settings.get_boolean("mini-player"): if not self.is_maximized() and not self._settings.get_boolean("mini-player"):
@ -4011,7 +4001,7 @@ class mpdevil(Gtk.Application):
("mpd.consume", ["<Control>o"]),("mpd.seek-forward", ["KP_Multiply"]),("mpd.seek-backward", ["KP_Divide"]), ("mpd.consume", ["<Control>o"]),("mpd.seek-forward", ["KP_Multiply"]),("mpd.seek-backward", ["KP_Divide"]),
("win.profile-next", ["<Control>p"]),("win.profile-prev", ["<Shift><Control>p"]), ("win.profile-next", ["<Control>p"]),("win.profile-prev", ["<Shift><Control>p"]),
("win.show-info", ["<Control>i","Menu"]),("win.append", ["<Control>plus"]), ("win.show-info", ["<Control>i","Menu"]),("win.append", ["<Control>plus"]),
("win.play", ["<Control>Return"]),("win.enqueue", ["<Control>e"]) ("win.play", ["<Control>Return"]),("win.enqueue", ["<Control>e"]),("win.genre-filter", ["<Control>g"])
) )
for action, accels in action_accels: for action, accels in action_accels:
self.set_accels_for_action(action, accels) self.set_accels_for_action(action, accels)

View File

@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<filter id="a" x="0" y="0" width="1" height="1">
<feColorMatrix in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="b">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".3"/>
</g>
</mask>
<clipPath id="c">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="d">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".05"/>
</g>
</mask>
<clipPath id="e">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="f">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".05"/>
</g>
</mask>
<clipPath id="g">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="h">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".05"/>
</g>
</mask>
<clipPath id="i">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="j">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".05"/>
</g>
</mask>
<clipPath id="k">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="l">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".05"/>
</g>
</mask>
<clipPath id="m">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="n">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".05"/>
</g>
</mask>
<clipPath id="o">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="p">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".3"/>
</g>
</mask>
<clipPath id="q">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="r">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".5"/>
</g>
</mask>
<clipPath id="s">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="t">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".4"/>
</g>
</mask>
<clipPath id="u">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="v">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".4"/>
</g>
</mask>
<clipPath id="w">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="x">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".5"/>
</g>
</mask>
<clipPath id="y">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<mask id="z">
<g filter="url(#a)">
<path d="m0 0h16v16h-16z" fill-opacity=".5"/>
</g>
</mask>
<clipPath id="A">
<path d="m0 0h1024v800h-1024z"/>
</clipPath>
<path d="m2 2.867v5.2021l5.8015 5.8015c0.16256 0.16256 0.359 0.17611 0.51817 0.01694l5.534-5.534c0.19304-0.19305 0.1795-0.38948 0.01693-0.55204l-5.8015-5.8015h-5.2021c-0.40303 0-0.86701 0.42673-0.86701 0.86701zm2.601 0.83314c0.5114 0 0.92797 0.41657 0.92797 0.92797s-0.41657 0.92797-0.92797 0.92797c-0.5114 0-0.92797-0.41657-0.92797-0.92797s0.41657-0.92797 0.92797-0.92797z" fill="#2e3436" stroke-width=".86701"/>
<g transform="translate(-640 -624)" clip-path="url(#c)" mask="url(#b)">
<path d="m562.46 212.06h10.449c-1.1836 0.49219-1.2969 2.4609 0 3h-10.449z" fill="#2e3436"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#e)" mask="url(#d)">
<path d="m16 632h1v1h-1z" fill="#2e3436" fill-rule="evenodd"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#g)" mask="url(#f)">
<path d="m17 631h1v1h-1z" fill="#2e3436" fill-rule="evenodd"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#i)" mask="url(#h)">
<path d="m18 634h1v1h-1z" fill="#2e3436" fill-rule="evenodd"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#k)" mask="url(#j)">
<path d="m16 634h1v1h-1z" fill="#2e3436" fill-rule="evenodd"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#m)" mask="url(#l)">
<path d="m17 635h1v1h-1z" fill="#2e3436" fill-rule="evenodd"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#o)" mask="url(#n)">
<path d="m19 635h1v1h-1z" fill="#2e3436" fill-rule="evenodd"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#q)" mask="url(#p)">
<path d="m136 660v7h7v-7z" fill="#2e3436"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#s)" mask="url(#r)">
<path d="m199 642h3v12h-3z" fill="#2e3436"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#u)" mask="url(#t)">
<path d="m209.5 144.16c0.27734 0 0.5 0.22266 0.5 0.5v1c0 0.27734-0.22266 0.5-0.5 0.5s-0.5-0.22266-0.5-0.5v-1c0-0.27734 0.22266-0.5 0.5-0.5z" fill="#2e3436"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#w)" mask="url(#v)">
<path d="m206.5 144.16c0.27734 0 0.5 0.22266 0.5 0.5v1c0 0.27734-0.22266 0.5-0.5 0.5s-0.5-0.22266-0.5-0.5v-1c0-0.27734 0.22266-0.5 0.5-0.5z" fill="#2e3436"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#y)" mask="url(#x)">
<path d="m229.5 143.16c-0.54688 0-1 0.45703-1 1 0 0.54688 0.45312 1 1 1s1-0.45312 1-1c0-0.54297-0.45312-1-1-1z" fill="#2e3436"/>
</g>
<g transform="translate(-640 -624)" clip-path="url(#A)" mask="url(#z)">
<path d="m226.45 143.16c-0.51953 0-0.95312 0.43359-0.95312 0.95312v0.09375c0 0.51953 0.43359 0.95312 0.95312 0.95312h0.09375c0.51953 0 0.95312-0.43359 0.95312-0.95312v-0.09375c0-0.51953-0.43359-0.95312-0.95312-0.95312z" fill="#2e3436"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -28,6 +28,14 @@
<default>572</default> <default>572</default>
<summary>Default position of paned1/paned0 separator</summary> <summary>Default position of paned1/paned0 separator</summary>
</key> </key>
<key type="i" name="paned3">
<default>246</default>
<summary>Default position of genre/artist separator</summary>
</key>
<key type="b" name="genre-filter">
<default>false</default>
<summary>Show genre filter</summary>
</key>
<key type="b" name="mini-player"> <key type="b" name="mini-player">
<default>false</default> <default>false</default>
<summary>Start player in mini player mode</summary> <summary>Start player in mini player mode</summary>

View File

@ -24,6 +24,7 @@ DistUtilsExtra.auto.setup(
('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-single-symbolic.svg']), ('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-single-symbolic.svg']),
('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-consume-symbolic.svg']), ('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-consume-symbolic.svg']),
('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-consume-symbolic-rtl.svg']), ('share/icons/hicolor/scalable/status/', ['data/icons/scalable/org.mpdevil.mpdevil-consume-symbolic-rtl.svg']),
('share/icons/hicolor/scalable/actions/', ['data/icons/scalable/org.mpdevil.mpdevil-genre-symbolic.svg']),
], ],
) )