|
|
|
@ -868,6 +868,14 @@ class Client(MPDClient):
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def show_in_file_manager(self, uri):
|
|
|
|
|
if (path:=self.get_absolute_path(uri)) is not None:
|
|
|
|
|
file=Gio.File.new_for_path(path)
|
|
|
|
|
bus=Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
|
|
|
|
proxy=Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, "org.freedesktop.FileManager1",
|
|
|
|
|
"/org/freedesktop/FileManager1", "org.freedesktop.FileManager1", None)
|
|
|
|
|
proxy.call_sync("ShowItems", GLib.Variant("(ass)", ((file.get_uri(),),"")), Gio.DBusCallFlags.NONE, 500, None)
|
|
|
|
|
|
|
|
|
|
def toggle_play(self):
|
|
|
|
|
status=self.status()
|
|
|
|
|
if status["state"] == "play":
|
|
|
|
@ -1258,7 +1266,7 @@ class TreeView(Gtk.TreeView):
|
|
|
|
|
return (rect.x+rect.width//2, max(min(cell.y+cell.height//2, rect.y+rect.height), rect.y))
|
|
|
|
|
|
|
|
|
|
def save_set_cursor(self, *args, **kwargs):
|
|
|
|
|
# The standard set_cursor function should scroll normally, but it dosen't work as it should when the treeview is not completely
|
|
|
|
|
# The standard set_cursor function should scroll normally, but it doesn't work as it should when the treeview is not completely
|
|
|
|
|
# initialized. This usually happens when the program is freshly started and the treeview isn't done with its internal tasks.
|
|
|
|
|
# See: https://lazka.github.io/pgi-docs/GLib-2.0/constants.html#GLib.PRIORITY_HIGH_IDLE
|
|
|
|
|
# Running set_cursor with a lower priority ensures that the treeview is done before it gets scrolled.
|
|
|
|
@ -1273,91 +1281,6 @@ class AutoSizedIcon(Gtk.Image):
|
|
|
|
|
super().__init__(icon_name=icon_name)
|
|
|
|
|
settings.bind(settings_key, self, "pixel-size", Gio.SettingsBindFlags.GET)
|
|
|
|
|
|
|
|
|
|
class SongPopover(Gtk.Popover):
|
|
|
|
|
def __init__(self, client, show_buttons=True):
|
|
|
|
|
super().__init__(position=Gtk.PositionType.BOTTOM)
|
|
|
|
|
self._client=client
|
|
|
|
|
self._rect=Gdk.Rectangle()
|
|
|
|
|
self._uri=None
|
|
|
|
|
|
|
|
|
|
# buttons
|
|
|
|
|
hbox=Gtk.Box(spacing=6)
|
|
|
|
|
self._open_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("folder-open-symbolic", Gtk.IconSize.BUTTON),
|
|
|
|
|
tooltip_text=_("Show in file manager"))
|
|
|
|
|
hbox.pack_end(self._open_button, False, False, 0)
|
|
|
|
|
if show_buttons:
|
|
|
|
|
button_box=Gtk.ButtonBox(layout_style=Gtk.ButtonBoxStyle.EXPAND)
|
|
|
|
|
data=((_("Append"), "list-add-symbolic", "append"), (_("Play"), "media-playback-start-symbolic", "play"))
|
|
|
|
|
for tooltip, icon, mode in data:
|
|
|
|
|
button=Gtk.Button(tooltip_text=tooltip, image=Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.BUTTON))
|
|
|
|
|
button.connect("clicked", self._on_button_clicked, mode)
|
|
|
|
|
button_box.pack_start(button, True, True, 0)
|
|
|
|
|
hbox.pack_end(button_box, False, False, 0)
|
|
|
|
|
|
|
|
|
|
# treeview
|
|
|
|
|
# (tag, display-value, tooltip)
|
|
|
|
|
self._store=Gtk.ListStore(str, str, str)
|
|
|
|
|
self._treeview=Gtk.TreeView(model=self._store, headers_visible=False, search_column=-1, tooltip_column=2, can_focus=False)
|
|
|
|
|
self._treeview.get_selection().set_mode(Gtk.SelectionMode.NONE)
|
|
|
|
|
|
|
|
|
|
# columns
|
|
|
|
|
renderer_text=Gtk.CellRendererText(width_chars=50, ellipsize=Pango.EllipsizeMode.MIDDLE, ellipsize_set=True)
|
|
|
|
|
renderer_text_ralign=Gtk.CellRendererText(xalign=1.0, weight=Pango.Weight.BOLD)
|
|
|
|
|
column_tag=Gtk.TreeViewColumn(_("MPD-Tag"), renderer_text_ralign, text=0)
|
|
|
|
|
column_tag.set_property("resizable", False)
|
|
|
|
|
self._treeview.append_column(column_tag)
|
|
|
|
|
column_value=Gtk.TreeViewColumn(_("Value"), renderer_text, text=1)
|
|
|
|
|
column_value.set_property("resizable", False)
|
|
|
|
|
self._treeview.append_column(column_value)
|
|
|
|
|
|
|
|
|
|
# scroll
|
|
|
|
|
self._scroll=Gtk.ScrolledWindow(child=self._treeview, propagate_natural_height=True)
|
|
|
|
|
self._scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
|
|
|
|
|
|
|
|
|
|
# connect
|
|
|
|
|
self._open_button.connect("clicked", self._on_open_button_clicked)
|
|
|
|
|
|
|
|
|
|
# packing
|
|
|
|
|
frame=Gtk.Frame(child=self._scroll)
|
|
|
|
|
vbox=Gtk.Box(orientation=Gtk.Orientation.VERTICAL, border_width=6, spacing=6)
|
|
|
|
|
vbox.pack_start(frame, True, True, 0)
|
|
|
|
|
vbox.pack_end(hbox, False, False, 0)
|
|
|
|
|
self.add(vbox)
|
|
|
|
|
vbox.show_all()
|
|
|
|
|
|
|
|
|
|
def open(self, uri, widget, x, y):
|
|
|
|
|
self._uri=uri
|
|
|
|
|
self._rect.x,self._rect.y=x,y
|
|
|
|
|
self.set_pointing_to(self._rect)
|
|
|
|
|
self.set_relative_to(widget)
|
|
|
|
|
window=self.get_toplevel()
|
|
|
|
|
self._scroll.set_max_content_height(window.get_size()[1]//2)
|
|
|
|
|
self._store.clear()
|
|
|
|
|
song=self._client.lsinfo(uri)[0]
|
|
|
|
|
for tag, value in song.items():
|
|
|
|
|
if tag == "duration":
|
|
|
|
|
self._store.append([tag+":", str(value), locale.str(value)])
|
|
|
|
|
elif tag in ("last-modified", "format"):
|
|
|
|
|
self._store.append([tag+":", str(value), value.raw()])
|
|
|
|
|
else:
|
|
|
|
|
self._store.append([tag+":", str(value), GLib.markup_escape_text(str(value))])
|
|
|
|
|
abs_path=self._client.get_absolute_path(uri)
|
|
|
|
|
self._open_button.set_sensitive(abs_path is not None) # show open with button when song is on the same computer
|
|
|
|
|
self.popup()
|
|
|
|
|
self._treeview.columns_autosize()
|
|
|
|
|
|
|
|
|
|
def _on_open_button_clicked(self, *args):
|
|
|
|
|
self.popdown()
|
|
|
|
|
file=Gio.File.new_for_path(self._client.get_absolute_path(self._uri))
|
|
|
|
|
bus=Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
|
|
|
|
proxy=Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, "org.freedesktop.FileManager1",
|
|
|
|
|
"/org/freedesktop/FileManager1", "org.freedesktop.FileManager1", None)
|
|
|
|
|
proxy.call_sync("ShowItems", GLib.Variant("(ass)", ((file.get_uri(),),"")), Gio.DBusCallFlags.NONE, 500, None)
|
|
|
|
|
|
|
|
|
|
def _on_button_clicked(self, widget, mode):
|
|
|
|
|
self._client.files_to_playlist([self._uri], mode)
|
|
|
|
|
self.popdown()
|
|
|
|
|
|
|
|
|
|
class SongsList(TreeView):
|
|
|
|
|
def __init__(self, client):
|
|
|
|
|
super().__init__(activate_on_single_click=True, headers_visible=False, enable_search=False, search_column=4)
|
|
|
|
@ -1400,20 +1323,46 @@ class SongsList(TreeView):
|
|
|
|
|
button.connect("clicked", self._on_button_clicked, mode)
|
|
|
|
|
self.buttons.pack_start(button, True, True, 0)
|
|
|
|
|
|
|
|
|
|
# song popover
|
|
|
|
|
self._song_popover=SongPopover(self._client)
|
|
|
|
|
# menu
|
|
|
|
|
action_group=Gio.SimpleActionGroup()
|
|
|
|
|
action=Gio.SimpleAction.new("append", None)
|
|
|
|
|
action.connect("activate", lambda *args: self._client.files_to_playlist([self._store[self.get_cursor()[0]][3]], "append"))
|
|
|
|
|
action_group.add_action(action)
|
|
|
|
|
action=Gio.SimpleAction.new("play", None)
|
|
|
|
|
action.connect("activate", lambda *args: self._client.files_to_playlist([self._store[self.get_cursor()[0]][3]], "play"))
|
|
|
|
|
action_group.add_action(action)
|
|
|
|
|
self._show_action=Gio.SimpleAction.new("show", None)
|
|
|
|
|
self._show_action.connect("activate", lambda *args: self._client.show_in_file_manager(self._store[self.get_cursor()[0]][3]))
|
|
|
|
|
action_group.add_action(self._show_action)
|
|
|
|
|
self.insert_action_group("menu", action_group)
|
|
|
|
|
menu=Gio.Menu()
|
|
|
|
|
menu.append(_("Append"), "menu.append")
|
|
|
|
|
menu.append(_("Play"), "menu.play")
|
|
|
|
|
subsection=Gio.Menu()
|
|
|
|
|
subsection.append(_("Show in file manager"), "menu.show")
|
|
|
|
|
menu.append_section(None, subsection)
|
|
|
|
|
self._menu=Gtk.Popover.new_from_model(self, menu)
|
|
|
|
|
self._menu.set_position(Gtk.PositionType.BOTTOM)
|
|
|
|
|
|
|
|
|
|
# connect
|
|
|
|
|
self.connect("row-activated", self._on_row_activated)
|
|
|
|
|
self.connect("button-press-event", self._on_button_press_event)
|
|
|
|
|
self.connect("key-press-event", self._on_key_press_event)
|
|
|
|
|
|
|
|
|
|
def clear(self):
|
|
|
|
|
self._song_popover.popdown()
|
|
|
|
|
self._menu.popdown()
|
|
|
|
|
self._store.clear()
|
|
|
|
|
|
|
|
|
|
def append(self, track, title, duration, file, search_string=""):
|
|
|
|
|
self._store.insert_with_valuesv(-1, range(5), [track, title, duration, file, search_string])
|
|
|
|
|
|
|
|
|
|
def _open_menu(self, uri, x, y):
|
|
|
|
|
rect=Gdk.Rectangle()
|
|
|
|
|
rect.x,rect.y=x,y
|
|
|
|
|
self._menu.set_pointing_to(rect)
|
|
|
|
|
self._show_action.set_enabled(self._client.get_absolute_path(uri) is not None)
|
|
|
|
|
self._menu.popup()
|
|
|
|
|
|
|
|
|
|
def _on_row_activated(self, widget, path, view_column):
|
|
|
|
|
self._client.files_to_playlist([self._store[path][3]], "play")
|
|
|
|
|
|
|
|
|
@ -1427,19 +1376,19 @@ class SongsList(TreeView):
|
|
|
|
|
elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS:
|
|
|
|
|
uri=self._store[path][3]
|
|
|
|
|
point=self.convert_bin_window_to_widget_coords(event.x,event.y)
|
|
|
|
|
self._song_popover.open(uri, widget, *point)
|
|
|
|
|
self._open_menu(uri, *point)
|
|
|
|
|
|
|
|
|
|
def _on_key_press_event(self, widget, event):
|
|
|
|
|
if event.state & Gdk.ModifierType.CONTROL_MASK and event.keyval == Gdk.keyval_from_name("plus"):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
self._client.files_to_playlist([self._store[path][3]], "append")
|
|
|
|
|
elif event.keyval == Gdk.keyval_from_name("Menu"):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
self._open_menu(self._store[path][3], *self.get_popover_point(path))
|
|
|
|
|
|
|
|
|
|
def _on_button_clicked(self, widget, mode):
|
|
|
|
|
self._client.files_to_playlist((row[3] for row in self._store), mode)
|
|
|
|
|
|
|
|
|
|
def show_info(self):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
self._song_popover.open(self._store[path][3], self, *self.get_popover_point(path))
|
|
|
|
|
|
|
|
|
|
def add_to_playlist(self, mode):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
self._client.files_to_playlist([self._store[path][3]], mode)
|
|
|
|
|
|
|
|
|
|
##########
|
|
|
|
|
# search #
|
|
|
|
|
##########
|
|
|
|
@ -2059,7 +2008,6 @@ class AlbumView(Gtk.Box):
|
|
|
|
|
|
|
|
|
|
# close button
|
|
|
|
|
close_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("go-previous-symbolic", Gtk.IconSize.BUTTON), halign=Gtk.Align.START)
|
|
|
|
|
close_button.set_focus_on_click(False)
|
|
|
|
|
|
|
|
|
|
# connect
|
|
|
|
|
self.connect("hide", lambda *args: print("test"))
|
|
|
|
@ -2228,23 +2176,49 @@ class PlaylistView(TreeView):
|
|
|
|
|
self._column_title=columns[1]
|
|
|
|
|
self._column_title.set_property("expand", True)
|
|
|
|
|
|
|
|
|
|
# song popover
|
|
|
|
|
self._song_popover=SongPopover(self._client, show_buttons=False)
|
|
|
|
|
# menu
|
|
|
|
|
action_group=Gio.SimpleActionGroup()
|
|
|
|
|
action=Gio.SimpleAction.new("remove", None)
|
|
|
|
|
action.connect("activate", lambda *args: self._store.remove(self._store.get_iter(self.get_cursor()[0])))
|
|
|
|
|
action_group.add_action(action)
|
|
|
|
|
self._show_action=Gio.SimpleAction.new("show", None)
|
|
|
|
|
self._show_action.connect("activate", lambda *args: self._client.show_in_file_manager(self._store[self.get_cursor()[0]][3]))
|
|
|
|
|
action_group.add_action(self._show_action)
|
|
|
|
|
self.insert_action_group("menu", action_group)
|
|
|
|
|
menu=Gio.Menu()
|
|
|
|
|
menu.append(_("Remove song"), "menu.remove")
|
|
|
|
|
menu.append(_("Clean playlist"), "mpd.clean")
|
|
|
|
|
menu.append(_("Clear playlist"), "mpd.clear")
|
|
|
|
|
subsection=Gio.Menu()
|
|
|
|
|
subsection.append(_("Show in file manager"), "menu.show")
|
|
|
|
|
menu.append_section(None, subsection)
|
|
|
|
|
self._menu=Gtk.Popover.new_from_model(self, menu)
|
|
|
|
|
self._menu.set_position(Gtk.PositionType.BOTTOM)
|
|
|
|
|
|
|
|
|
|
# connect
|
|
|
|
|
self.connect("row-activated", self._on_row_activated)
|
|
|
|
|
self.connect("button-press-event", self._on_button_press_event)
|
|
|
|
|
self.connect("key-release-event", self._on_key_release_event)
|
|
|
|
|
self.connect("key-press-event", self._on_key_press_event)
|
|
|
|
|
self._row_deleted=self._store.connect("row-deleted", self._on_row_deleted)
|
|
|
|
|
self._row_inserted=self._store.connect("row-inserted", self._on_row_inserted)
|
|
|
|
|
|
|
|
|
|
self._client.emitter.connect("playlist", self._on_playlist_changed)
|
|
|
|
|
self._client.emitter.connect("current_song", self._on_song_changed)
|
|
|
|
|
self._client.emitter.connect("disconnected", self._on_disconnected)
|
|
|
|
|
self._client.emitter.connect("connected", self._on_connected)
|
|
|
|
|
|
|
|
|
|
def scroll_to_selected_title(self):
|
|
|
|
|
if (path:=self.get_property("selected-path")) is not None:
|
|
|
|
|
self._scroll_to_path(path)
|
|
|
|
|
|
|
|
|
|
def _open_menu(self, uri, x, y):
|
|
|
|
|
rect=Gdk.Rectangle()
|
|
|
|
|
rect.x,rect.y=x,y
|
|
|
|
|
self._menu.set_pointing_to(rect)
|
|
|
|
|
self._show_action.set_enabled(self._client.get_absolute_path(uri) is not None)
|
|
|
|
|
self._menu.popup()
|
|
|
|
|
|
|
|
|
|
def _clear(self, *args):
|
|
|
|
|
self._song_popover.popdown()
|
|
|
|
|
self._menu.popdown()
|
|
|
|
|
self._playlist_version=None
|
|
|
|
|
self.set_property("selected-path", None)
|
|
|
|
|
self._store.handler_block(self._row_inserted)
|
|
|
|
@ -2278,12 +2252,9 @@ class PlaylistView(TreeView):
|
|
|
|
|
def _scroll_to_path(self, path):
|
|
|
|
|
self.save_scroll_to_cell(path, None, True, 0.25)
|
|
|
|
|
|
|
|
|
|
def scroll_to_selected_title(self):
|
|
|
|
|
if (path:=self.get_property("selected-path")) is not None:
|
|
|
|
|
self._scroll_to_path(path)
|
|
|
|
|
|
|
|
|
|
def _refresh_selection(self): # Gtk.TreePath(len(self._store) is used to generate an invalid TreePath (needed to unset cursor)
|
|
|
|
|
self.set_cursor(Gtk.TreePath(len(self._store)), None, False)
|
|
|
|
|
if not self._menu.get_visible():
|
|
|
|
|
self.set_cursor(Gtk.TreePath(len(self._store)), None, False)
|
|
|
|
|
song=self._client.status().get("song")
|
|
|
|
|
if song is None:
|
|
|
|
|
self._unselect()
|
|
|
|
@ -2298,15 +2269,15 @@ class PlaylistView(TreeView):
|
|
|
|
|
self._delete(path)
|
|
|
|
|
elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS:
|
|
|
|
|
point=self.convert_bin_window_to_widget_coords(event.x,event.y)
|
|
|
|
|
self._song_popover.open(self._store[path][3], widget, *point)
|
|
|
|
|
self._open_menu(self._store[path][3], *point)
|
|
|
|
|
|
|
|
|
|
def _on_key_release_event(self, widget, event):
|
|
|
|
|
def _on_key_press_event(self, widget, event):
|
|
|
|
|
if event.keyval == Gdk.keyval_from_name("Delete"):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
try:
|
|
|
|
|
self._delete(path)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
self._delete(path)
|
|
|
|
|
elif event.keyval == Gdk.keyval_from_name("Menu"):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
self._open_menu(self._store[path][3], *self.get_popover_point(path))
|
|
|
|
|
|
|
|
|
|
def _on_row_deleted(self, model, path): # sync treeview to mpd
|
|
|
|
|
try:
|
|
|
|
@ -2335,7 +2306,7 @@ class PlaylistView(TreeView):
|
|
|
|
|
def _on_playlist_changed(self, emitter, version):
|
|
|
|
|
self._store.handler_block(self._row_inserted)
|
|
|
|
|
self._store.handler_block(self._row_deleted)
|
|
|
|
|
self._song_popover.popdown()
|
|
|
|
|
self._menu.popdown()
|
|
|
|
|
self._unselect()
|
|
|
|
|
self._client.restrict_tagtypes("track", "title", "artist", "album", "date")
|
|
|
|
|
songs=[]
|
|
|
|
@ -2387,10 +2358,6 @@ class PlaylistView(TreeView):
|
|
|
|
|
def _select_function(self, selection, model, path, path_currently_selected):
|
|
|
|
|
return (path == self.get_property("selected-path")) == (not path_currently_selected)
|
|
|
|
|
|
|
|
|
|
def show_info(self):
|
|
|
|
|
if (path:=self.get_cursor()[0]) is not None:
|
|
|
|
|
self._song_popover.open(self._store[path][3], self, *self.get_popover_point(path))
|
|
|
|
|
|
|
|
|
|
class PlaylistWindow(Gtk.Overlay):
|
|
|
|
|
def __init__(self, client, settings):
|
|
|
|
|
super().__init__()
|
|
|
|
@ -3033,7 +3000,7 @@ class MPDActionGroup(Gio.SimpleActionGroup):
|
|
|
|
|
self._client=client
|
|
|
|
|
|
|
|
|
|
# actions
|
|
|
|
|
self._disable_on_stop_data=("next","prev","seek-forward","seek-backward")
|
|
|
|
|
self._disable_on_stop_data=("next","prev","seek-forward","seek-backward", "clean")
|
|
|
|
|
self._enable_on_reconnect_data=("toggle-play","stop","clear","update","repeat","random","single","consume","single-oneshot")
|
|
|
|
|
self._data=self._disable_on_stop_data+self._enable_on_reconnect_data
|
|
|
|
|
for name in self._data:
|
|
|
|
@ -3064,6 +3031,9 @@ class MPDActionGroup(Gio.SimpleActionGroup):
|
|
|
|
|
def _on_seek_backward(self, action, param):
|
|
|
|
|
self._client.seekcur("-10")
|
|
|
|
|
|
|
|
|
|
def _on_clean(self, action, param):
|
|
|
|
|
self._client.files_to_playlist([self._client.currentsong()["file"]], "enqueue")
|
|
|
|
|
|
|
|
|
|
def _on_clear(self, action, param):
|
|
|
|
|
self._client.clear()
|
|
|
|
|
|
|
|
|
@ -3180,18 +3150,11 @@ class MainWindow(Gtk.ApplicationWindow):
|
|
|
|
|
self._size=None # needed for window size saving
|
|
|
|
|
|
|
|
|
|
# actions
|
|
|
|
|
simple_actions_data=(
|
|
|
|
|
"settings","connection-settings","stats","help","menu",
|
|
|
|
|
"toggle-lyrics","back-to-current-album","toggle-search","show-info"
|
|
|
|
|
)
|
|
|
|
|
simple_actions_data=("settings","connection-settings","stats","help","menu","toggle-lyrics","back-to-current-album","toggle-search")
|
|
|
|
|
for name in simple_actions_data:
|
|
|
|
|
action=Gio.SimpleAction.new(name, None)
|
|
|
|
|
action.connect("activate", getattr(self, ("_on_"+name.replace("-","_"))))
|
|
|
|
|
self.add_action(action)
|
|
|
|
|
for name in ("append","play"):
|
|
|
|
|
action=Gio.SimpleAction.new(name, None)
|
|
|
|
|
action.connect("activate", self._on_add_to_playlist, name)
|
|
|
|
|
self.add_action(action)
|
|
|
|
|
self.add_action(self._settings.create_action("mini-player"))
|
|
|
|
|
self.add_action(self._settings.create_action("genre-filter"))
|
|
|
|
|
|
|
|
|
@ -3379,16 +3342,6 @@ class MainWindow(Gtk.ApplicationWindow):
|
|
|
|
|
def _on_menu(self, action, param):
|
|
|
|
|
self._menu_button.emit("clicked")
|
|
|
|
|
|
|
|
|
|
def _on_show_info(self, action, param):
|
|
|
|
|
widget=self.get_focus()
|
|
|
|
|
if hasattr(widget, "show_info") and callable(widget.show_info):
|
|
|
|
|
widget.show_info()
|
|
|
|
|
|
|
|
|
|
def _on_add_to_playlist(self, action, param, mode):
|
|
|
|
|
widget=self.get_focus()
|
|
|
|
|
if hasattr(widget, "add_to_playlist") and callable(widget.add_to_playlist):
|
|
|
|
|
widget.add_to_playlist(mode)
|
|
|
|
|
|
|
|
|
|
def _on_search_button_toggled(self, button):
|
|
|
|
|
if button.get_active():
|
|
|
|
|
self._stack.set_visible_child_name("search")
|
|
|
|
@ -3502,7 +3455,6 @@ class mpdevil(Gtk.Application):
|
|
|
|
|
action_accels=(
|
|
|
|
|
("app.quit", ["<Control>q"]),("win.mini-player", ["<Control>m"]),("win.help", ["F1"]),("win.menu", ["F10"]),
|
|
|
|
|
("win.show-help-overlay", ["<Control>question"]),("win.toggle-lyrics", ["<Control>l"]),
|
|
|
|
|
("win.show-info", ["<Control>i","Menu"]),("win.append", ["<Control>plus"]),("win.play", ["<Control>p"]),
|
|
|
|
|
("win.genre-filter", ["<Control>g"]),("win.back-to-current-album", ["Escape"]),("win.toggle-search", ["<Control>f"]),
|
|
|
|
|
("mpd.update", ["F5"]),("mpd.clear", ["<Shift>Delete"]),("mpd.toggle-play", ["space"]),("mpd.stop", ["<Shift>space"]),
|
|
|
|
|
("mpd.next", ["<Alt>Down"]),("mpd.prev", ["<Alt>Up"]),("mpd.repeat", ["<Control>r"]),("mpd.random", ["<Control>n"]),
|
|
|
|
|