From c612f31f42f8186be14fca5f7d576ef9fe5ca5e5 Mon Sep 17 00:00:00 2001 From: Benjamin Schaaf Date: Mon, 1 Feb 2021 18:38:18 +1100 Subject: [PATCH] WIP --- sublime_music/ui/player_controls/common.py | 60 +++++++++++++++++ sublime_music/ui/player_controls/desktop.py | 57 +--------------- sublime_music/ui/player_controls/mobile.py | 75 +++++++++------------ 3 files changed, 94 insertions(+), 98 deletions(-) diff --git a/sublime_music/ui/player_controls/common.py b/sublime_music/ui/player_controls/common.py index f30d9b4..46fce53 100644 --- a/sublime_music/ui/player_controls/common.py +++ b/sublime_music/ui/player_controls/common.py @@ -1,5 +1,9 @@ +from typing import List, Any + +from .. import util from ..common import IconButton, IconToggleButton, SpinnerImage, SpinnerPicture from .manager import Manager +from ...util import resolve_path from gi.repository import Gdk, GdkPixbuf, GLib, GObject, Gtk, Pango, Handy @@ -79,3 +83,59 @@ def create_label(manager: Manager, property: str, **kwargs): label = Gtk.Label(**kwargs) manager.bind_property(property, label, "label") return label + +def show_play_queue_popover(manager: Manager, relative_to, paths: List[str], pos_x: int, pos_y: int): + song_ids = [manager.play_queue_store[p][-1] for p in paths] + + remove_text = ( + "Remove " + util.pluralize("song", len(song_ids)) + " from queue" + ) + + def on_download_state_change(song_id: str): + # Refresh the entire window (no force) because the song could + # be in a list anywhere in the window. + manager.emit("refresh-window", {}, False) + + def on_remove_songs_click(_: Any): + manager.emit("songs-removed", [p.get_indices()[0] for p in paths]) + + util.show_song_popover( + song_ids, + pos_x, + pos_y, + relative_to, + manager.offline_mode, + on_download_state_change=on_download_state_change, + extra_menu_items=[ + (Gtk.ModelButton(text=remove_text), on_remove_songs_click), + ], + ) + +# Album Art column. This function defines what image to use for the play queue +# song icon. +def filename_to_pixbuf( + column: Any, + cell: Gtk.CellRendererPixbuf, + model: Gtk.ListStore, + tree_iter: Gtk.TreeIter, + flags: Any, +): + cell.set_property("sensitive", model.get_value(tree_iter, 0)) + filename = model.get_value(tree_iter, 1) + if not filename: + cell.set_property("icon_name", "") + return + + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(filename, 50, 50, True) + + # If this is the playing song, then overlay the play icon. + if model.get_value(tree_iter, 3): + play_overlay_pixbuf = GdkPixbuf.Pixbuf.new_from_file( + str(resolve_path("ui/images/play-queue-play.png")) + ) + + play_overlay_pixbuf.composite( + pixbuf, 0, 0, 50, 50, 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 200 + ) + + cell.set_property("pixbuf", pixbuf) diff --git a/sublime_music/ui/player_controls/desktop.py b/sublime_music/ui/player_controls/desktop.py index 73c76ee..8a83ffd 100644 --- a/sublime_music/ui/player_controls/desktop.py +++ b/sublime_music/ui/player_controls/desktop.py @@ -214,37 +214,13 @@ class Desktop(Gtk.Box): store, paths = tree.get_selection().get_selected_rows() allow_deselect = False - def on_download_state_change(song_id: str): - # Refresh the entire window (no force) because the song could - # be in a list anywhere in the window. - self.state.emit("refresh-window", {}, False) - # Use the new selection instead of the old one for calculating what # to do the right click on. if clicked_path[0] not in paths: paths = [clicked_path[0]] allow_deselect = True - song_ids = [self.play_queue_store[p][-1] for p in paths] - - remove_text = ( - "Remove " + util.pluralize("song", len(song_ids)) + " from queue" - ) - - def on_remove_songs_click(_: Any): - self.state.emit("songs-removed", [p.get_indices()[0] for p in paths]) - - util.show_song_popover( - song_ids, - event.x, - event.y, - tree, - self.offline_mode, - on_download_state_change=on_download_state_change, - extra_menu_items=[ - (Gtk.ModelButton(text=remove_text), on_remove_songs_click), - ], - ) + common.show_play_queue_popover(self.state, tree, paths, event.x, event.y) # If the click was on a selected row, don't deselect anything. if not allow_deselect: @@ -405,39 +381,10 @@ class Desktop(Gtk.Box): selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.set_select_function(lambda _, model, path, current: model[path[0]][0]) - # Album Art column. This function defines what image to use for the play queue - # song icon. - def filename_to_pixbuf( - column: Any, - cell: Gtk.CellRendererPixbuf, - model: Gtk.ListStore, - tree_iter: Gtk.TreeIter, - flags: Any, - ): - cell.set_property("sensitive", model.get_value(tree_iter, 0)) - filename = model.get_value(tree_iter, 1) - if not filename: - cell.set_property("icon_name", "") - return - - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(filename, 50, 50, True) - - # If this is the playing song, then overlay the play icon. - if model.get_value(tree_iter, 3): - play_overlay_pixbuf = GdkPixbuf.Pixbuf.new_from_file( - str(resolve_path("ui/images/play-queue-play.png")) - ) - - play_overlay_pixbuf.composite( - pixbuf, 0, 0, 50, 50, 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 200 - ) - - cell.set_property("pixbuf", pixbuf) - renderer = Gtk.CellRendererPixbuf() renderer.set_fixed_size(55, 60) column = Gtk.TreeViewColumn("", renderer) - column.set_cell_data_func(renderer, filename_to_pixbuf) + column.set_cell_data_func(renderer, common.filename_to_pixbuf) column.set_resizable(True) self.play_queue_list.append_column(column) diff --git a/sublime_music/ui/player_controls/mobile.py b/sublime_music/ui/player_controls/mobile.py index a579b94..6cabb9f 100644 --- a/sublime_music/ui/player_controls/mobile.py +++ b/sublime_music/ui/player_controls/mobile.py @@ -248,67 +248,56 @@ class MobileFlap(Handy.Flap): play_queue_scrollbox = Gtk.ScrolledWindow(vexpand=True) - self.play_queue_list = Gtk.TreeView( + play_queue_list = Gtk.TreeView( model=self.state.play_queue_store, reorderable=True, headers_visible=False, ) - self.play_queue_list.get_style_context().add_class("background") - - # Album Art column. This function defines what image to use for the play queue - # song icon. - def filename_to_pixbuf( - column: Any, - cell: Gtk.CellRendererPixbuf, - model: Gtk.ListStore, - tree_iter: Gtk.TreeIter, - flags: Any, - ): - cell.set_property("sensitive", model.get_value(tree_iter, 0)) - filename = model.get_value(tree_iter, 1) - if not filename: - cell.set_property("icon_name", "") - return - - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(filename, 50, 50, True) - - # If this is the playing song, then overlay the play icon. - if model.get_value(tree_iter, 3): - play_overlay_pixbuf = GdkPixbuf.Pixbuf.new_from_file( - str(resolve_path("ui/images/play-queue-play.png")) - ) - - play_overlay_pixbuf.composite( - pixbuf, 0, 0, 50, 50, 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 200 - ) - - cell.set_property("pixbuf", pixbuf) + play_queue_list.get_style_context().add_class("background") renderer = Gtk.CellRendererPixbuf() renderer.set_fixed_size(55, 60) column = Gtk.TreeViewColumn("", renderer) - column.set_cell_data_func(renderer, filename_to_pixbuf) + column.set_cell_data_func(renderer, common.filename_to_pixbuf) column.set_resizable(True) - self.play_queue_list.append_column(column) + play_queue_list.append_column(column) renderer = Gtk.CellRendererText(markup=True, ellipsize=Pango.EllipsizeMode.END) column = Gtk.TreeViewColumn("", renderer, markup=2, sensitive=0) column.set_expand(True) - self.play_queue_list.append_column(column) + play_queue_list.append_column(column) renderer = Gtk.CellRendererPixbuf(icon_name="view-more-symbolic") - renderer.set_fixed_size(30, 24) - column = Gtk.TreeViewColumn("", renderer) - column.set_resizable(True) - self.play_queue_list.append_column(column) + renderer.set_fixed_size(45, 60) + view_more_column = Gtk.TreeViewColumn("", renderer) + view_more_column.set_resizable(True) + play_queue_list.append_column(view_more_column) renderer = Gtk.CellRendererPixbuf(icon_name="window-close-symbolic") - renderer.set_fixed_size(30, 24) - column = Gtk.TreeViewColumn("", renderer) - column.set_resizable(True) - self.play_queue_list.append_column(column) + renderer.set_fixed_size(45, 60) + close_column = Gtk.TreeViewColumn("", renderer) + close_column.set_resizable(True) + play_queue_list.append_column(close_column) - play_queue_scrollbox.add(self.play_queue_list) + def on_play_queue_button_press(tree: Any, event: Gdk.EventButton) -> bool: + if event.button == 1: + clicked_path = tree.get_path_at_pos(event.x, event.y)[0] + song_idx = clicked_path.get_indices()[0] + + tree_width = tree.get_allocation().width + + if event.x > tree_width - close_column.get_width(): + self.state.emit("songs-removed", [song_idx]) + elif event.x > tree_width - close_column.get_width() - view_more_column.get_width(): + common.show_play_queue_popover(self.state, play_queue_list, [clicked_path], event.x, event.y) + else: + self.state.emit("song-clicked", song_idx, [m[-1] for m in self.state.play_queue_store], {"no_reshuffle": True}) + + return True + return False + play_queue_list.connect("button-press-event", on_play_queue_button_press) + + play_queue_scrollbox.add(play_queue_list) self.set_flap(play_queue_scrollbox) def on_play_queue_open(*_):