diff --git a/src/mpdevil.py b/src/mpdevil.py index 4763ff3..65730c0 100755 --- a/src/mpdevil.py +++ b/src/mpdevil.py @@ -2274,7 +2274,10 @@ class Browser(Gtk.Paned): ############ class PlaylistPopover(Gtk.Popover): - __gsignals__={"playlist-changed": (GObject.SignalFlags.RUN_FIRST, None, ())} + __gsignals__={ + "playlist-changed": (GObject.SignalFlags.RUN_FIRST, None, (str, int, int)), + "playlist-deleted": (GObject.SignalFlags.RUN_FIRST, None, (int, int)), + } def __init__(self, client): super().__init__() self._client=client @@ -2320,13 +2323,13 @@ class PlaylistPopover(Gtk.Popover): def _on_delete_button_clicked(self, *args): self._client.rm(self._name) self.popdown() - self.emit("playlist-changed") + self.emit("playlist-deleted", self._rect.x, self._rect.y) def _on_save_button_clicked(self, *args): self._client.rm(self._name) self._client.save(self._name) self.popdown() - self.emit("playlist-changed") + self.emit("playlist-changed", self._name, self._rect.x, self._rect.y) class PlaylistsPopover(Gtk.Popover): def __init__(self, client, label): @@ -2335,8 +2338,8 @@ class PlaylistsPopover(Gtk.Popover): # widgets self._entry=Gtk.Entry() - save_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("document-save-symbolic", Gtk.IconSize.BUTTON), sensitive=False) - save_button.get_style_context().add_class("suggested-action") + self._add_button=Gtk.Button(image=Gtk.Image.new_from_icon_name("list-add-symbolic", Gtk.IconSize.BUTTON), sensitive=False) + self._add_button.get_style_context().add_class("suggested-action") clear_button=Gtk.Button( image=Gtk.Image.new_from_icon_name("edit-clear-symbolic", Gtk.IconSize.BUTTON), tooltip_text=_("Clear playlist"), @@ -2346,7 +2349,9 @@ class PlaylistsPopover(Gtk.Popover): clear_button.get_style_context().add_class("destructive-action") # treeview + # display name, name self._store=Gtk.ListStore(str, str) + self._store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self._treeview=Gtk.TreeView(model=self._store, search_column=-1, activate_on_single_click=True, headers_visible=False) renderer_text=Gtk.CellRendererText(width_chars=80, ellipsize=Pango.EllipsizeMode.END, ellipsize_set=True, ypad=6) column=Gtk.TreeViewColumn("", renderer_text, markup=0) @@ -2361,12 +2366,13 @@ class PlaylistsPopover(Gtk.Popover): self._playlist_popover=PlaylistPopover(self._client) # connect - self._entry.connect("activate", self._save) - self._entry.connect("changed", lambda label: save_button.set_sensitive(bool(label.get_text()))) - save_button.connect("clicked", self._save) + self._entry.connect("activate", self._add) + self._entry.connect("changed", self._on_entry_changed) + self._add_button.connect("clicked", self._add) self._treeview.connect("row-activated", self._on_row_activated) self._treeview.connect("button-press-event", self._on_button_press_event) - self._playlist_popover.connect("playlist-changed", self._refresh) + self._playlist_popover.connect("playlist-changed", self._on_playlist_changed) + self._playlist_popover.connect("playlist-deleted", self._on_playlist_deleted) # packing hbox0=Gtk.Box(spacing=6) @@ -2374,7 +2380,7 @@ class PlaylistsPopover(Gtk.Popover): hbox0.pack_end(clear_button, False, False, 0) hbox=Gtk.Box(spacing=6) hbox.pack_start(self._entry, True, True, 0) - hbox.pack_start(save_button, False, False, 0) + hbox.pack_start(self._add_button, False, False, 0) vbox=Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, border_width=6) vbox.pack_start(hbox, False, False, 0) vbox.pack_end(hbox0, False, False, 0) @@ -2382,28 +2388,30 @@ class PlaylistsPopover(Gtk.Popover): self.add(vbox) vbox.show_all() - def _refresh(self, *args): + def _refresh(self): self._store.clear() - self._client.restrict_tagtypes() - for playlist in sorted(self._client.listplaylists(), key=lambda x: locale.strxfrm(x["playlist"])): - name=playlist["playlist"] - metadata=self._client.listplaylistinfo(name) - duration=Duration(sum((float(x["duration"]) for x in metadata))) - length=len(metadata) - translated_string=ngettext("{number} song ({duration})", "{number} songs ({duration})", length) - formatted_string=translated_string.format(number=length, duration=duration) - self._store.insert_with_valuesv(-1, range(2), - [f"{GLib.markup_escape_text(name)} • {GLib.markup_escape_text(formatted_string)}", name]) - self._client.tagtypes("all") + for playlist in self._client.listplaylists(): + self._store.insert_with_valuesv(-1, range(2), (self._get_display_name(playlist["playlist"]), playlist["playlist"])) - def _save(self, *args): - if self._entry.get_text(): - try: - self._client.save(self._entry.get_text()) - except: - self._client.rm(self._entry.get_text()) - self._client.save(self._entry.get_text()) - self._refresh() + def _get_display_name(self, name): + self._client.restrict_tagtypes() + metadata=self._client.listplaylistinfo(name) + self._client.tagtypes("all") + duration=Duration(sum((float(x["duration"]) for x in metadata))) + length=len(metadata) + translated_string=ngettext("{number} song ({duration})", "{number} songs ({duration})", length) + formatted_string=translated_string.format(number=length, duration=duration) + return f"{GLib.markup_escape_text(name)} • {GLib.markup_escape_text(formatted_string)}" + + def _add(self, *args): + if self._add_button.get_sensitive(): + name=self._entry.get_text() + self._client.save(name) + self._store.insert_with_valuesv(-1, range(2), (self._get_display_name(name), name)) + + def _on_entry_changed(self, *args): + name=self._entry.get_text() + self._add_button.set_sensitive(name and not name in (x["playlist"] for x in self._client.listplaylists())) def _on_row_activated(self, widget, path, view_column): self._client.stored_to_playlist(self._store[path][1]) @@ -2419,6 +2427,12 @@ class PlaylistsPopover(Gtk.Popover): elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: self._playlist_popover.open(widget, self._store[path][1], event.x, event.y) + def _on_playlist_changed(self, widget, name, x, y): + self._store.set(self._store.get_iter(self._treeview.get_path_at_pos(x, y)[0]), 0, self._get_display_name(name), 1, name) + + def _on_playlist_deleted(self, widget, x, y): + self._store.remove(self._store.get_iter(self._treeview.get_path_at_pos(x, y)[0])) + def open(self, widget): window=self.get_toplevel() self._scroll.set_max_content_height(window.get_size()[1]//2)