def __init__(self, browser, model): super(PreferencesButton, self).__init__() sort_orders = [ (_("_Title"), self.__compare_title), (_("_Artist"), self.__compare_artist), (_("_Date"), self.__compare_date), (_("_Original Date"), self.__compare_original_date), (_("_Genre"), self.__compare_genre), (_("_Rating"), self.__compare_rating), (_("_Playcount"), self.__compare_avgplaycount), ] menu = Gtk.Menu() sort_item = Gtk.MenuItem( label=_(u"Sort _by…"), use_underline=True) sort_menu = Gtk.Menu() active = config.getint('browsers', 'album_sort', 1) item = None for i, (label, func) in enumerate(sort_orders): item = RadioMenuItem(group=item, label=label, use_underline=True) model.set_sort_func(100 + i, func) if i == active: model.set_sort_column_id(100 + i, Gtk.SortType.ASCENDING) item.set_active(True) item.connect("toggled", util.DeferredSignal(self.__sort_toggled_cb), model, i) sort_menu.append(item) sort_item.set_submenu(sort_menu) menu.append(sort_item) pref_item = MenuItem(_("_Preferences"), Icons.PREFERENCES_SYSTEM) menu.append(pref_item) connect_obj(pref_item, "activate", Preferences, browser) menu.show_all() button = MenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) self.pack_start(button, True, True, 0)
def __init__(self, tag): super(TextColumn, self).__init__(tag) self._render = Gtk.CellRendererText() self.pack_start(self._render, True) self.set_cell_data_func(self._render, self._cdf) self.set_clickable(True) # We check once in a while if the font size has changed. If it has # we reset the min/fixed width and force at least one cell to update # (which might trigger other column size changes..) self._last_width = None self._force_update = False self._deferred_width_check = util.DeferredSignal( self._check_width_update, timeout=500) def on_tv_changed(column, old, new): if new is None: self._deferred_width_check.abort() else: self._deferred_width_check.call() self.connect("tree-view-changed", on_tv_changed)
def __init__(self, library): super(InternetRadio, self).__init__(spacing=12) self.set_orientation(Gtk.Orientation.VERTICAL) if not self.instances(): self._init(library) self._register_instance() self.connect('destroy', self.__destroy) completion = LibraryTagCompletion(self.__stations) self.accelerators = Gtk.AccelGroup() self.__searchbar = search = SearchBarBox(completion=completion, accel_group=self.accelerators) search.connect('query-changed', self.__filter_changed) menu = Gtk.Menu() new_item = MenuItem(_(u"_New Station…"), Icons.LIST_ADD) new_item.connect('activate', self.__add) menu.append(new_item) update_item = MenuItem(_("_Update Stations"), Icons.VIEW_REFRESH) update_item.connect('activate', self.__update) menu.append(update_item) menu.show_all() button = MenuButton(SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) def focus(widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() search.connect('focus-out', focus) # treeview scrolled_window = ScrolledWindow() scrolled_window.show() scrolled_window.set_shadow_type(Gtk.ShadowType.IN) self.view = view = AllTreeView() view.show() view.set_headers_visible(False) scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(view) model = Gtk.ListStore(int, str, str, str) model.append( row=[self.TYPE_ALL, Icons.FOLDER, "__all", _("All Stations")]) model.append(row=[self.TYPE_SEP, Icons.FOLDER, "", ""]) #Translators: Favorite radio stations model.append( row=[self.TYPE_FAV, Icons.FOLDER, "__fav", _("Favorites")]) model.append(row=[self.TYPE_SEP, Icons.FOLDER, "", ""]) filters = self.filters for text, k in sorted([(filters.text(k), k) for k in filters.keys()]): model.append(row=[self.TYPE_FILTER, Icons.EDIT_FIND, k, text]) model.append( row=[self.TYPE_NOCAT, Icons.FOLDER, "nocat", _("No Category")]) def separator(model, iter, data): return model[iter][self.TYPE] == self.TYPE_SEP view.set_row_separator_func(separator, None) def search_func(model, column, key, iter, data): return key.lower() not in model[iter][column].lower() view.set_search_column(self.NAME) view.set_search_equal_func(search_func, None) column = Gtk.TreeViewColumn("genres") column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) renderpb = Gtk.CellRendererPixbuf() renderpb.props.xpad = 3 column.pack_start(renderpb, False) column.add_attribute(renderpb, "icon-name", self.ICON_NAME) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) view.append_column(column) column.pack_start(render, True) column.add_attribute(render, "text", self.NAME) view.set_model(model) # selection selection = view.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) self.__changed_sig = connect_destroy( selection, 'changed', util.DeferredSignal(lambda x: self.activate())) box = Gtk.HBox(spacing=6) box.pack_start(search, True, True, 0) box.pack_start(button, False, True, 0) self._searchbox = Align(box, left=0, right=6, top=6) self._searchbox.show_all() def qbar_response(infobar, response_id): if response_id == infobar.RESPONSE_LOAD: self.__update() self.qbar = QuestionBar() self.qbar.connect("response", qbar_response) if self._is_library_empty(): self.qbar.show() pane = qltk.ConfigRHPaned("browsers", "internetradio_pos", 0.4) pane.show() pane.pack1(scrolled_window, resize=False, shrink=False) songbox = Gtk.VBox(spacing=6) songbox.pack_start(self._searchbox, False, True, 0) self._songpane_container = Gtk.VBox() self._songpane_container.show() songbox.pack_start(self._songpane_container, True, True, 0) songbox.pack_start(self.qbar, False, True, 0) songbox.show() pane.pack2(songbox, resize=True, shrink=False) self.pack_start(pane, True, True, 0) self.show()
def __init__(self, library, main): super(InternetRadio, self).__init__(spacing=12) if not self.instances(): self._init(library) self._register_instance() self.connect('destroy', self.__destroy) completion = LibraryTagCompletion(self.__stations) self.accelerators = Gtk.AccelGroup() self.__searchbar = search = SearchBarBox(completion=completion, accel_group=self.accelerators) gobject_weak(search.connect, 'query-changed', self.__filter_changed) menu = Gtk.Menu() new_item = MenuItem(_("_New Station..."), Gtk.STOCK_ADD) gobject_weak(new_item.connect, 'activate', self.__add) menu.append(new_item) update_item = MenuItem(_("_Update Stations"), Gtk.STOCK_REFRESH) gobject_weak(update_item.connect, 'activate', self.__update) menu.append(update_item) menu.show_all() button = MenuButton( SymbolicIconImage("emblem-system", Gtk.IconSize.MENU), arrow=True) button.set_menu(menu) def focus(widget, *args): qltk.get_top_parent(widget).songlist.grab_focus() gobject_weak(search.connect, 'focus-out', focus, parent=self) # treeview scrolled_window = ScrolledWindow() scrolled_window.set_shadow_type(Gtk.ShadowType.IN) self.view = view = AllTreeView() view.set_headers_visible(False) scrolled_window.set_policy( Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) scrolled_window.add(view) model = Gtk.ListStore(int, str, str, str) model.append(row=[self.TYPE_ALL, Gtk.STOCK_DIRECTORY, "__all", _("All Stations")]) model.append(row=[self.TYPE_SEP, Gtk.STOCK_DIRECTORY, "", ""]) #Translators: Favorite radio stations model.append(row=[self.TYPE_FAV, Gtk.STOCK_DIRECTORY, "__fav", _("Favorites")]) model.append(row=[self.TYPE_SEP, Gtk.STOCK_DIRECTORY, "", ""]) filters = self.filters for text, k in sorted([(filters.text(k), k) for k in filters.keys()]): model.append(row=[self.TYPE_FILTER, Gtk.STOCK_FIND, k, text]) model.append(row=[self.TYPE_NOCAT, Gtk.STOCK_DIRECTORY, "nocat", _("No Category")]) def separator(model, iter, data): return model[iter][self.TYPE] == self.TYPE_SEP view.set_row_separator_func(separator, None) def search_func(model, column, key, iter, data): return key.lower() not in model[iter][column].lower() view.set_search_column(self.NAME) view.set_search_equal_func(search_func, None) column = Gtk.TreeViewColumn("genres") column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) renderpb = Gtk.CellRendererPixbuf() renderpb.props.xpad = 3 column.pack_start(renderpb, False) column.add_attribute(renderpb, "stock_id", self.STOCK) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) view.append_column(column) column.pack_start(render, True) column.add_attribute(render, "text", self.NAME) view.set_model(model) # selection selection = view.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) self.__changed_sig = gobject_weak(selection.connect, 'changed', util.DeferredSignal(lambda x: self.activate()), parent=view) box = Gtk.HBox(spacing=6) box.pack_start(search, True, True, 0) box.pack_start(button, False, True, 0) if main: self.pack_start(Alignment(box, left=6, right=6, top=6), True, True, 0) else: self.pack_start(box, True, True, 0) self.__filter_list = scrolled_window def qbar_response(infobar, response_id): if response_id == infobar.RESPONSE_LOAD: self.__update() self.qbar = QuestionBar() self.qbar.connect("response", qbar_response) if self._is_library_empty(): self.qbar.show() self.show_all()
def __init__(self, library): Browser.__init__(self, spacing=6) self.set_orientation(Gtk.Orientation.VERTICAL) self.songcontainer = qltk.paned.ConfigRVPaned( "browsers", "covergrid_pos", 0.4) if config.getboolean("browsers", "covergrid_wide", False): self.songcontainer.set_orientation(Gtk.Orientation.HORIZONTAL) self._register_instance() if self.__model is None: self._init_model(library) self._cover_cancel = Gio.Cancellable() self.scrollwin = sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) model_sort = AlbumSortModel(model=self.__model) model_filter = AlbumFilterModel(child_model=model_sort) self.view = view = IconView(model_filter) #view.set_item_width(get_cover_size() + 12) self.view.set_row_spacing(config.getint("browsers", "row_spacing", 6)) self.view.set_column_spacing(config.getint("browsers", "column_spacing", 6)) self.view.set_item_padding(config.getint("browsers", "item_padding", 6)) self.view.set_has_tooltip(True) self.view.connect("query-tooltip", self._show_tooltip) self.__bg_filter = background_filter() self.__filter = None model_filter.set_visible_func(self.__parse_query) mag = config.getfloat("browsers", "covergrid_magnification", 3.) self.view.set_item_width(get_cover_size() * mag + 8) self.__cover = render = Gtk.CellRendererPixbuf() render.set_property('width', get_cover_size() * mag + 8) render.set_property('height', get_cover_size() * mag + 8) view.pack_start(render, False) def cell_data_pb(view, cell, model, iter_, no_cover): item = model.get_value(iter_) if item.album is None: surface = None elif item.cover: pixbuf = item.cover pixbuf = add_border_widget(pixbuf, self.view) surface = get_surface_for_pixbuf(self, pixbuf) # don't cache, too much state has an effect on the result self.__last_render_surface = None else: surface = no_cover if self.__last_render_surface == surface: return self.__last_render_surface = surface cell.set_property("surface", surface) view.set_cell_data_func(render, cell_data_pb, self._no_cover) self.__text_cells = render = Gtk.CellRendererText() render.set_visible(config.getboolean("browsers", "album_text", True)) render.set_property('alignment', Pango.Alignment.CENTER) render.set_property('xalign', 0.5) render.set_property('ellipsize', Pango.EllipsizeMode.END) view.pack_start(render, False) def cell_data(view, cell, model, iter_, data): album = model.get_album(iter_) if album is None: text = "<b>%s</b>" % _("All Albums") text += "\n" + ngettext("%d album", "%d albums", len(model) - 1) % (len(model) - 1) markup = text else: markup = self.display_pattern % album if self.__last_render == markup: return self.__last_render = markup cell.markup = markup cell.set_property('markup', markup) view.set_cell_data_func(render, cell_data, None) view.set_selection_mode(Gtk.SelectionMode.MULTIPLE) sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.add(view) view.connect('item-activated', self.__play_selection, None) self.__sig = connect_destroy( view, 'selection-changed', util.DeferredSignal(self.__update_songs, owner=self)) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, 1), ("text/uri-list", 0, 2)] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) view.connect("drag-data-get", self.__drag_data_get) # NOT WORKING connect_obj(view, 'button-press-event', self.__rightclick, view, library) connect_obj(view, 'popup-menu', self.__popup, view, library) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=AlbumTagCompletion(), accel_group=self.accelerators) search.connect('query-changed', self.__update_filter) connect_obj(search, 'focus-out', lambda w: w.grab_focus(), view) self.__search = search prefs = PreferencesButton(self, model_sort) search.pack_start(prefs, False, True, 0) self.pack_start(Align(search, left=6, top=6), False, True, 0) self.pack_start(sw, True, True, 0) self.connect("destroy", self.__destroy) self.enable_row_update(view, sw, self.view) self.__update_filter() self.connect('key-press-event', self.__key_pressed, library.librarian) if app.cover_manager: connect_destroy( app.cover_manager, "cover-changed", self._cover_changed) self.show_all()
def __init__(self, library): super(AlbumList, self).__init__(spacing=6) self.set_orientation(Gtk.Orientation.VERTICAL) self._register_instance() if self.__model is None: self._init_model(library) self._cover_cancel = Gio.Cancellable() sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) self.view = view = AllTreeView() view.set_headers_visible(False) model_sort = AlbumSortModel(model=self.__model) model_filter = AlbumFilterModel(child_model=model_sort) self.__bg_filter = background_filter() self.__filter = None model_filter.set_visible_func(self.__parse_query) render = Gtk.CellRendererPixbuf() self.__cover_column = column = Gtk.TreeViewColumn("covers", render) column.set_visible(config.getboolean("browsers", "album_covers")) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_fixed_width(get_cover_size() + 12) render.set_property('height', get_cover_size() + 8) render.set_property('width', get_cover_size() + 8) def cell_data_pb(column, cell, model, iter_, no_cover): item = model.get_value(iter_) if item.album is None: surface = None elif item.cover: pixbuf = item.cover pixbuf = add_border_widget(pixbuf, self.view) surface = get_surface_for_pixbuf(self, pixbuf) # don't cache, too much state has an effect on the result self.__last_render_surface = None else: surface = no_cover if self.__last_render_surface == surface: return self.__last_render_surface = surface cell.set_property("surface", surface) column.set_cell_data_func(render, cell_data_pb, self._no_cover) view.append_column(column) render = Gtk.CellRendererText() column = Gtk.TreeViewColumn("albums", render) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) if view.supports_hints(): render.set_property('ellipsize', Pango.EllipsizeMode.END) def cell_data(column, cell, model, iter_, data): album = model.get_album(iter_) if album is None: text = "<b>%s</b>\n" % _("All Albums") text += numeric_phrase("%d album", "%d albums", len(model) - 1) markup = text else: markup = self.display_pattern % album if self.__last_render == markup: return self.__last_render = markup cell.markup = markup cell.set_property('markup', markup) column.set_cell_data_func(render, cell_data) view.append_column(column) view.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) view.set_rules_hint(True) view.set_search_equal_func(self.__search_func, None) view.set_search_column(0) view.set_model(model_filter) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(view) view.connect('row-activated', self.__play_selection) self.__sig = view.connect( 'selection-changed', util.DeferredSignal(self.__update_songs, owner=view)) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, 1), ("text/uri-list", 0, 2)] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) view.connect("drag-data-get", self.__drag_data_get) connect_obj(view, 'popup-menu', self.__popup, view, library) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=AlbumTagCompletion(), accel_group=self.accelerators) search.connect('query-changed', self.__update_filter) connect_obj(search, 'focus-out', lambda w: w.grab_focus(), view) self.__search = search prefs = PreferencesButton(self, model_sort) search.pack_start(prefs, False, True, 0) self.pack_start(Align(search, left=6, top=6), False, True, 0) self.pack_start(sw, True, True, 0) self.connect("destroy", self.__destroy) self.enable_row_update(view, sw, self.__cover_column) self.connect('key-press-event', self.__key_pressed, library.librarian) if app.cover_manager: connect_destroy(app.cover_manager, "cover-changed", self._cover_changed) self.show_all()
def __init__(self, library, main): super(AlbumList, self).__init__(spacing=6) self._register_instance() if self.__model is None: self._init_model(library) sw = ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) self.view = view = AllTreeView() view.set_headers_visible(False) model_sort = AlbumSortModel(model=self.__model) model_filter = AlbumFilterModel(child_model=model_sort) self.__bg_filter = background_filter() self.__filter = None model_filter.set_visible_func(self.__parse_query) render = Gtk.CellRendererPixbuf() self.__cover_column = column = Gtk.TreeViewColumn("covers", render) column.set_visible(config.getboolean("browsers", "album_covers")) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_fixed_width(Album.COVER_SIZE + 12) render.set_property('height', Album.COVER_SIZE + 8) def cell_data_pb(column, cell, model, iter_, no_cover): album = model.get_album(iter_) if album is None: pixbuf = None elif album.cover: pixbuf = album.cover else: pixbuf = no_cover if self.__last_render_pb == pixbuf: return self.__last_render_pb = pixbuf cell.set_property('pixbuf', pixbuf) column.set_cell_data_func(render, cell_data_pb, self.__no_cover) view.append_column(column) render = Gtk.CellRendererText() column = Gtk.TreeViewColumn("albums", render) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) render.set_property('ellipsize', Pango.EllipsizeMode.END) def cell_data(column, cell, model, iter_, data): album = model.get_album(iter_) if album is None: text = "<b>%s</b>" % _("All Albums") text += "\n" + ngettext("%d album", "%d albums", len(model) - 1) % (len(model) - 1) markup = text else: markup = AlbumList._pattern % album if self.__last_render == markup: return self.__last_render = markup cell.markup = markup cell.set_property('markup', markup) column.set_cell_data_func(render, cell_data) view.append_column(column) view.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) view.set_rules_hint(True) view.set_search_equal_func(self.__search_func, None) view.set_search_column(0) view.set_model(model_filter) sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.add(view) if main: gobject_weak(view.connect, 'row-activated', self.__play_selection) self.__sig = gobject_weak( view.get_selection().connect, 'changed', util.DeferredSignal(self.__update_songs), parent=view) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, 1), ("text/uri-list", 0, 2)] targets = [Gtk.TargetEntry.new(*t) for t in targets] view.drag_source_set( Gdk.ModifierType.BUTTON1_MASK, targets, Gdk.DragAction.COPY) gobject_weak(view.connect, "drag-data-get", self.__drag_data_get) gobject_weak(view.connect_object, 'popup-menu', self.__popup, view, library) self.accelerators = Gtk.AccelGroup() search = SearchBarBox(completion=AlbumTagCompletion(), accel_group=self.accelerators) gobject_weak(search.connect, 'query-changed', self.__update_filter) gobject_weak(search.connect_object, 'focus-out', lambda w: w.grab_focus(), view) self.__search = search prefs = PreferencesButton(self, model_sort) search.pack_start(prefs, False, True, 0) if main: self.pack_start(Alignment(search, left=6, top=6), False, True, 0) else: self.pack_start(search, False, True, 0) self.pack_start(sw, True, True, 0) self.connect("destroy", self.__destroy) self.enable_row_update(view, sw, self.__cover_column) self.connect('key-press-event', self.__key_pressed, library.librarian) self.show_all()
def __init__(self, menu, library, player): super(QueueExpander, self).__init__() sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) self.queue = PlayQueue(library, player) sw.add(self.queue) outer = Gtk.HBox(spacing=12) left = Gtk.HBox(spacing=12) hb2 = Gtk.HBox(spacing=3) state_icon = PlaybackStatusIcon() state_icon.stop() state_icon.show() hb2.pack_start(state_icon, True, True, 0) name_label = Gtk.Label(label=_("_Queue"), use_underline=True) hb2.pack_start(name_label, True, True, 0) left.pack_start(hb2, False, True, 0) b = SmallImageButton( image=Gtk.Image.new_from_stock(Gtk.STOCK_CLEAR, Gtk.IconSize.MENU)) b.set_tooltip_text(_("Remove all songs from the queue")) b.connect('clicked', self.__clear_queue) b.hide() b.set_relief(Gtk.ReliefStyle.NONE) left.pack_start(b, False, False, 0) count_label = Gtk.Label() left.pack_start(count_label, False, True, 0) outer.pack_start(left, True, True, 0) close_button = SmallImageButton(image=SymbolicIconImage( "window-close", Gtk.IconSize.MENU), relief=Gtk.ReliefStyle.NONE) close_button.connect("clicked", lambda *x: self.hide()) outer.pack_start(close_button, False, False, 6) self.set_label_fill(True) cb = ConfigCheckButton(_("_Random"), "memory", "shufflequeue") cb.connect('toggled', self.__queue_shuffle, self.queue.model) cb.set_active(config.getboolean("memory", "shufflequeue")) left.pack_start(cb, False, True, 0) self.set_label_widget(outer) self.add(sw) self.connect_object('notify::expanded', self.__expand, cb, b) targets = [("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, DND_QL), ("text/uri-list", 0, DND_URI_LIST)] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) self.connect('drag-motion', self.__motion) self.connect('drag-data-received', self.__drag_data_received) self.show_all() self.queue.model.connect_after( 'row-inserted', util.DeferredSignal(self.__check_expand), count_label) self.queue.model.connect_after( 'row-deleted', util.DeferredSignal(self.__update_count), count_label) cb.hide() self.connect_object('notify::visible', self.__visible, cb, menu, b) self.__update_count(self.model, None, count_label) player.connect('song-started', self.__update_state_icon, state_icon) player.connect('paused', self.__update_state_icon_pause, state_icon, True) player.connect('unpaused', self.__update_state_icon_pause, state_icon, False) # to make the children clickable if mapped # ....no idea why, but works def hack(expander): label = expander.get_label_widget() if label: label.unmap() label.map() self.connect("map", hack)
def __init__(self, library, player): super(QueueExpander, self).__init__(spacing=3) sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) self.queue = PlayQueue(library, player) self.queue.props.expand = True sw.add(self.queue) add_css(self, ".ql-expanded title { margin-bottom: 5px; }") outer = ExpandBoxHack() left = Gtk.HBox(spacing=12) hb2 = Gtk.HBox(spacing=3) state_icon = PlaybackStatusIcon() state_icon.stop() state_icon.show() hb2.pack_start(state_icon, True, True, 0) name_label = Gtk.Label(label=_("_Queue"), use_underline=True) name_label.set_size_request(-1, 24) hb2.pack_start(name_label, True, True, 0) left.pack_start(hb2, False, True, 0) menu = Gtk.Menu() self.count_label = count_label = Gtk.Label() self.count_label.set_property("ellipsize", Pango.EllipsizeMode.END) self.count_label.set_width_chars(10) self.count_label.get_style_context().add_class("dim-label") left.pack_start(count_label, False, True, 0) outer.pack_start(left, True, True, 0) self.set_label_fill(True) rand_checkbox = ConfigCheckMenuItem( _("_Random"), "memory", "shufflequeue", populate=True) rand_checkbox.connect('toggled', self.__queue_shuffle) self.set_shuffled(rand_checkbox.get_active()) menu.append(rand_checkbox) stop_checkbox = ConfigCheckMenuItem( _("Stop at End"), "memory", "queue_stop_at_end", populate=True) menu.append(stop_checkbox) queue_ignore_cb = ConfigCheckMenuItem( _("Ignore"), "memory", "queue_ignore", populate=True) menu.append(queue_ignore_cb) keep_checkbox = ConfigCheckMenuItem( _("Keep Songs"), "memory", "queue_keep_songs", populate=True) keep_checkbox.set_tooltip_text( _("Keep songs in the queue after playing them")) keep_checkbox.connect("activate", self.__keep_songs_activated) menu.append(keep_checkbox) clear_item = MenuItem(_("_Clear Queue"), Icons.EDIT_CLEAR) menu.append(clear_item) clear_item.connect("activate", self.__clear_queue) button = SmallMenuButton( SymbolicIconImage(Icons.EMBLEM_SYSTEM, Gtk.IconSize.MENU), arrow=True) button.set_relief(Gtk.ReliefStyle.NONE) button.show_all() button.hide() button.set_no_show_all(True) menu.show_all() button.set_menu(menu) outer.pack_start(button, False, False, 0) close_button = SmallImageButton( image=SymbolicIconImage("window-close", Gtk.IconSize.MENU), relief=Gtk.ReliefStyle.NONE) close_button.connect("clicked", lambda *x: self.hide()) outer.pack_start(close_button, False, False, 6) self.set_label_widget(outer) self.add(sw) self.connect('notify::expanded', self.__expand, button) self.connect('notify::expanded', self.__expand, button) targets = [ ("text/x-quodlibet-songs", Gtk.TargetFlags.SAME_APP, DND_QL), ("text/uri-list", 0, DND_URI_LIST) ] targets = [Gtk.TargetEntry.new(*t) for t in targets] self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY) self.connect('drag-motion', self.__motion) self.connect('drag-data-received', self.__drag_data_received) self.queue.model.connect_after('row-inserted', util.DeferredSignal(self.__check_expand), count_label) self.queue.model.connect_after('row-deleted', util.DeferredSignal(self.__update_count), count_label) self.__update_count(self.model, None, count_label) connect_destroy( player, 'song-started', self.__update_state_icon, state_icon) connect_destroy( player, 'paused', self.__update_state_icon_pause, state_icon, True) connect_destroy( player, 'unpaused', self.__update_state_icon_pause, state_icon, False) connect_destroy( player, 'song-started', self.__song_started, self.queue.model) connect_destroy( player, 'song-ended', self.__update_queue_stop, self.queue.model) self._last_queue_song = None self._curr_song_index = None # to make the children clickable if mapped # ....no idea why, but works def hack(expander): label = expander.get_label_widget() if label: label.unmap() label.map() self.connect("map", hack) self.set_expanded(config.getboolean("memory", "queue_expanded")) self.notify("expanded") for child in self.get_children(): child.show_all()