def PluginPreferences(self, *args): self.__init_defaults() hb = Gtk.HBox(spacing=6) label = Gtk.Label(label=_("_Theme:")) combo = Gtk.ComboBoxText() theme = config.get("plugins", self.CONFIG_THEME, None) combo.append_text(_("Default Theme")) themes = self.__get_themes() select = 0 for i, name in enumerate(sorted(themes)): combo.append_text(name) if name == theme: select = i + 1 combo.set_active(select) combo.connect('changed', self.__changed) dark_button = ConfigCheckButton(_("Prefer dark theme version"), "plugins", self.CONFIG_DARK, populate=True, default=self.__get_dark()) def dark_cb(button): self.__set_dark(button.get_active()) dark_button.connect('toggled', dark_cb) hb_button = ConfigCheckButton(_("Use header bars"), "plugins", self.CONFIG_HEADER_BAR, populate=True, default=self.__get_header_bar()) def hb_cb(button): self.__set_header_bar(button.get_active()) hb_button.connect('toggled', hb_cb) label.set_mnemonic_widget(combo) label.set_use_underline(True) hb.pack_start(label, False, True, 0) hb.pack_start(combo, False, True, 0) vbox = Gtk.VBox(spacing=6) vbox.pack_start(hb, False, True, 0) vbox.pack_start(dark_button, False, True, 0) vbox.pack_start(hb_button, False, True, 0) return qltk.Frame(_("Preferences"), child=vbox)
def PluginPreferences(self, *args): self.__init_defaults() hb = Gtk.HBox(spacing=6) label = Gtk.Label(label=_("_Theme:")) combo = Gtk.ComboBoxText() theme = config.get("plugins", self.CONFIG_THEME, None) combo.append_text(_("Default Theme")) themes = self.__get_themes() select = 0 for i, name in enumerate(sorted(themes)): combo.append_text(name) if name == theme: select = i + 1 combo.set_active(select) combo.connect('changed', self.__changed) dark_button = ConfigCheckButton( _("Prefer dark theme version"), "plugins", self.CONFIG_DARK, populate=True, default=self.__get_dark()) def dark_cb(button): self.__set_dark(button.get_active()) dark_button.connect('toggled', dark_cb) hb_button = ConfigCheckButton( _("Use header bars"), "plugins", self.CONFIG_HEADER_BAR, populate=True, default=self.__get_header_bar()) def hb_cb(button): self.__set_header_bar(button.get_active()) hb_button.connect('toggled', hb_cb) label.set_mnemonic_widget(combo) label.set_use_underline(True) hb.pack_start(label, False, True, 0) hb.pack_start(combo, False, True, 0) vbox = Gtk.VBox(spacing=6) vbox.pack_start(hb, False, True, 0) vbox.pack_start(dark_button, False, True, 0) vbox.pack_start(hb_button, False, True, 0) return qltk.Frame(_("Preferences"), child=vbox)
def __init__(self, browser): if self.is_not_unique(): return super(Preferences, self).__init__() self.set_border_width(12) self.set_title(_("Album List Preferences")) self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._PREVIEW_ITEM["~rating"] = format_rating(0.75) box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton( _("Show album _covers"), "browsers", "album_covers") cb.set_active(config.getboolean("browsers", "album_covers")) cb.connect('toggled', lambda s: browser.toggle_covers()) vbox.pack_start(cb, False, True, 0) cb = ConfigCheckButton( _("Inline _search includes people"), "browsers", "album_substrings") cb.set_active(config.getboolean("browsers", "album_substrings")) vbox.pack_start(cb, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) display_frame = self.edit_display_pane(browser, _("Album Display")) box.pack_start(display_frame, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() 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): def create_display_frame(): vbox = Gtk.VBox(spacing=6) model = Gtk.ListStore(str, str) def on_changed(combo): it = combo.get_active_iter() if it is None: return DURATION.format = model[it][0] app.window.songlist.info.refresh() app.window.qexpander.refresh() # TODO: refresh info windows ideally too (but see #2019) def draw_duration(column, cell, model, it, data): df, example = model[it] cell.set_property('text', example) for df in sorted(DurationFormat.values): # 4954s == longest ever CD, FWIW model.append([df, format_time_preferred(4954, df)]) duration = Gtk.ComboBox(model=model) cell = Gtk.CellRendererText() duration.pack_start(cell, True) duration.set_cell_data_func(cell, draw_duration, None) index = sorted(DurationFormat.values).index(DURATION.format) duration.set_active(index) duration.connect('changed', on_changed) hbox = Gtk.HBox(spacing=6) label = Gtk.Label(label=_("Duration totals") + ":", use_underline=True) label.set_mnemonic_widget(duration) hbox.pack_start(label, False, True, 0) hbox.pack_start(duration, False, True, 0) vbox.pack_start(hbox, False, True, 0) return qltk.Frame(_("Display"), child=vbox) def create_search_frame(): vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.validator) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text( _("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action return qltk.Frame(C_("heading", "Search"), child=vb) super().__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") self.pack_start(create_search_frame(), False, True, 0) self.pack_start(create_display_frame(), False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) vb = Gtk.VBox(spacing=6) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) preferred_image_filename_tooltip = _( "The album art image file(s) to use when available " "(supports wildcards). If you want to supply more " "than one, separate them with commas.") cb = CCB(_("_Preferred image filename(s):"), 'albumart', 'force_filename', populate=True, tooltip=preferred_image_filename_tooltip) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text(preferred_image_filename_tooltip) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def ratings_vbox(self): """Returns a new VBox containing all ratings widgets""" vb = Gtk.VBox(spacing=6) # Default Rating model = Gtk.ListStore(float) default_combo = Gtk.ComboBox(model=model) default_lab = Gtk.Label(label=_("_Default rating:")) default_lab.set_use_underline(True) default_lab.set_alignment(0, 0.5) def draw_rating(column, cell, model, it, data): num = model[it][0] text = "%0.2f: %s" % (num, util.format_rating(num)) cell.set_property('text', text) def default_rating_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.default = model[it][0] qltk.redraw_all_toplevels() def populate_default_rating_model(combo, num): model = combo.get_model() model.clear() deltas = [] default = RATINGS.default precision = RATINGS.precision for i in range(0, num + 1): r = i * precision model.append(row=[r]) deltas.append((abs(default - r), i)) active = sorted(deltas)[0][1] print_d("Choosing #%d (%.2f), closest to current %.2f" % (active, precision * active, default)) combo.set_active(active) cell = Gtk.CellRendererText() default_combo.pack_start(cell, True) default_combo.set_cell_data_func(cell, draw_rating, None) default_combo.connect('changed', default_rating_changed, model) default_lab.set_mnemonic_widget(default_combo) def refresh_default_combo(num): populate_default_rating_model(default_combo, num) # Rating Scale model = Gtk.ListStore(int) scale_combo = Gtk.ComboBox(model=model) scale_lab = Gtk.Label(label=_("Rating _scale:")) scale_lab.set_use_underline(True) scale_lab.set_mnemonic_widget(scale_combo) cell = Gtk.CellRendererText() scale_combo.pack_start(cell, False) num = RATINGS.number for i in [1, 2, 3, 4, 5, 6, 8, 10]: it = model.append(row=[i]) if i == num: scale_combo.set_active_iter(it) def draw_rating_scale(column, cell, model, it, data): num_stars = model[it][0] text = "%d: %s" % (num_stars, RATINGS.full_symbol * num_stars) cell.set_property('text', text) def rating_scale_changed(combo, model): it = combo.get_active_iter() if it is None: return RATINGS.number = num = model[it][0] refresh_default_combo(num) refresh_default_combo(RATINGS.number) scale_combo.set_cell_data_func(cell, draw_rating_scale, None) scale_combo.connect('changed', rating_scale_changed, model) default_align = Align(halign=Gtk.Align.START) default_align.add(default_lab) scale_align = Align(halign=Gtk.Align.START) scale_align.add(scale_lab) grid = Gtk.Grid(column_spacing=6, row_spacing=6) grid.add(scale_align) grid.add(scale_combo) grid.attach(default_align, 0, 1, 1, 1) grid.attach(default_combo, 1, 1, 1, 1) vb.pack_start(grid, False, False, 6) # Bayesian Factor bayesian_factor = config.getfloat("settings", "bayesian_rating_factor", 0.0) adj = Gtk.Adjustment.new(bayesian_factor, 0.0, 10.0, 0.5, 0.5, 0.0) bayes_spin = Gtk.SpinButton(adjustment=adj, numeric=True) bayes_spin.set_digits(1) bayes_spin.connect('changed', self.__changed_and_signal_library, 'settings', 'bayesian_rating_factor') bayes_spin.set_tooltip_text( _("Bayesian Average factor (C) for aggregated ratings.\n" "0 means a conventional average, higher values mean that " "albums with few tracks will have less extreme ratings. " "Changing this value triggers a re-calculation for all " "albums.")) bayes_label = Gtk.Label(label=_("_Bayesian averaging amount:")) bayes_label.set_use_underline(True) bayes_label.set_mnemonic_widget(bayes_spin) # Save Ratings hb = Gtk.HBox(spacing=6) hb.pack_start(bayes_label, False, True, 0) hb.pack_start(bayes_spin, False, True, 0) vb.pack_start(hb, True, True, 0) cb = CCB(_("Save ratings and play _counts in tags"), "editing", "save_to_songs", populate=True) def update_entry(widget, email_entry): email_entry.set_sensitive(widget.get_active()) vb.pack_start(cb, True, True, 0) hb = Gtk.HBox(spacing=6) lab = Gtk.Label(label=_("_Email:")) entry = UndoEntry() entry.set_tooltip_text(_("Ratings and play counts will be saved " "in tags for this email address")) entry.set_text(config.get("editing", "save_email")) entry.connect('changed', self.__changed, 'editing', 'save_email') # Disable the entry if not saving to tags cb.connect('clicked', update_entry, entry) update_entry(cb, entry) hb.pack_start(lab, False, True, 0) hb.pack_start(entry, True, True, 0) lab.set_mnemonic_widget(entry) lab.set_use_underline(True) vb.pack_start(hb, True, True, 0) return vb
def __init__(self, menu, library, player): super(QueueExpander, self).__init__() sw = ScrolledWindow() sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) sw.set_shadow_type(gtk.SHADOW_IN) self.queue = PlayQueue(library, player) sw.add(self.queue) hb = gtk.HBox(spacing=12) hb2 = gtk.HBox(spacing=3) state = gtk.image_new_from_stock( gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_MENU) hb2.pack_start(state) l = gtk.Label(_("_Queue")) hb2.pack_start(l) hb.pack_start(hb2) l.set_use_underline(True) clear = gtk.image_new_from_stock(gtk.STOCK_CLEAR, gtk.ICON_SIZE_MENU) b = gtk.Button() b.add(clear) b.set_tooltip_text(_("Remove all songs from the queue")) b.connect('clicked', self.__clear_queue) b.hide() b.set_relief(gtk.RELIEF_NONE) hb.pack_start(b, expand=False, fill=False) l2 = gtk.Label() hb.pack_start(l2) cb = ConfigCheckButton( _("_Random"), "memory", "shufflequeue") cb.connect('toggled', self.__queue_shuffle, self.queue.model) cb.set_active(config.getboolean("memory", "shufflequeue")) hb.pack_start(cb) self.set_label_widget(hb) self.add(sw) self.connect_object('notify::expanded', self.__expand, cb, b) targets = [("text/x-quodlibet-songs", gtk.TARGET_SAME_APP, 1), ("text/uri-list", 0, 2)] self.drag_dest_set(gtk.DEST_DEFAULT_ALL, targets, gtk.gdk.ACTION_COPY) self.connect('drag-motion', self.__motion) self.connect('drag-data-received', self.__drag_data_received) self.model = self.queue.model self.show_all() self.queue.model.connect_after('row-inserted', util.DeferredSignal(self.__check_expand), l2) self.queue.model.connect_after('row-deleted', util.DeferredSignal(self.__update_count), l2) cb.hide() self.connect_object('notify::visible', self.__visible, cb, menu, b) self.__update_count(self.model, None, l2) player.connect('song-started', self.__update_state_icon, state) player.connect('paused', self.__update_state_icon_pause, state, gtk.STOCK_MEDIA_PAUSE) player.connect('unpaused', self.__update_state_icon_pause, state, gtk.STOCK_MEDIA_PLAY) # 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, songs, title=None): super(SearchWindow, self).__init__(default_width=800, default_height=400, border_width=12, title=title) self._thread = AcoustidLookupThread(self.__lookup_cb) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) model = ObjectStore() self.view = view = ResultView() view.set_model(model) self.model = model self._iter_map = {} for song in songs: iter_ = self.model.append([SearchEntry(song)]) self._iter_map[song] = iter_ sw.add(view) self.pool = pool = FingerPrintPool() pool.connect("fingerprint-done", self.__fp_done_cb) pool.connect("fingerprint-error", self.__fp_error_cb) pool.connect("fingerprint-started", self.__fp_started_cb) for song in songs: pool.push(song) outer_box = Gtk.VBox(spacing=12) bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.set_spacing(6) self.__save = save = Button(_("_Save"), Icons.DOCUMENT_SAVE) save.connect("clicked", self.__on_save) save.set_sensitive(False) cancel = Button(_("_Cancel")) cancel.connect("clicked", lambda *x: self.destroy()) bbox.pack_start(save, True, True, 0) bbox.pack_start(cancel, True, True, 0) inner_box = Gtk.VBox(spacing=6) inner_box.pack_start(sw, True, True, 0) ccb = ConfigCheckButton(_("Write MusicBrainz tags"), "plugins", "fingerprint_write_mb_tags") ccb.set_active(get_write_mb_tags()) inner_box.pack_start(ccb, False, True, 0) ccb = ConfigCheckButton(_("Group by directory"), "plugins", "fingerprint_group_by_dir") ccb.set_active(get_group_by_dir()) ccb.connect("toggled", self.__group_toggled) self._group_ccb = ccb outer_box.pack_start(inner_box, True, True, 0) bottom_box = Gtk.HBox(spacing=12) mode_button = Gtk.ToggleButton(label=_("Album Mode")) mode_button.set_tooltip_text( _("Write album related tags and try to " "reduce the number of different album releases") ) mode_button.set_active(True) mode_button.connect("toggled", self.__mode_toggle) bottom_box.pack_start(mode_button, False, True, 0) bottom_box.pack_start(self._group_ccb, False, True, 0) bottom_box.pack_start(bbox, True, True, 0) outer_box.pack_start(bottom_box, False, True, 0) outer_box.show_all() self.add(outer_box) self.__album_mode = True self.__group_by_dir = True self._release_scores = {} self._directory_scores = {} self.__done = 0 self.connect("destroy", self.__destroy)
def __init__(self): super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") # Search vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.is_valid_color) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text(_("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action f = qltk.Frame(Q_("heading|Search"), child=vb) self.pack_start(f, False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) # Album Art vb = Gtk.VBox(spacing=6) c = CCB(_("_Use rounded corners on thumbnails"), 'albumart', 'round', populate=True, tooltip=_("Round the corners of album artwork thumbnail " "images. May require restart to take effect.")) vb.pack_start(c, False, True, 0) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) cb = CCB(_("_Fixed image filename:"), 'albumart', 'force_filename', populate=True, tooltip=_("The single image filename to use if " "selected")) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def __init__(self, player, debug=False): super().__init__(spacing=6) e = UndoEntry() e.set_tooltip_text( _("The GStreamer output pipeline used for " "playback. Leave blank for the default pipeline. " "In case the pipeline contains a sink, " "it will be used instead of the default one.")) e.set_text(config.get('player', 'gst_pipeline')) def changed(entry): config.set('player', 'gst_pipeline', entry.get_text()) e.connect('changed', changed) pipe_label = Gtk.Label(label=_('_Output pipeline:')) pipe_label.set_use_underline(True) pipe_label.set_mnemonic_widget(e) apply_button = Button(_("_Apply")) def format_buffer(scale, value): return _("%.1f seconds") % value def scale_changed(scale): duration_msec = int(scale.get_value() * 1000) player._set_buffer_duration(duration_msec) duration = config.getfloat("player", "gst_buffer") scale = Gtk.HScale.new( Gtk.Adjustment(value=duration, lower=0.2, upper=10)) scale.set_value_pos(Gtk.PositionType.RIGHT) scale.set_show_fill_level(True) scale.connect('format-value', format_buffer) scale.connect('value-changed', scale_changed) buffer_label = Gtk.Label(label=_('_Buffer duration:')) buffer_label.set_use_underline(True) buffer_label.set_mnemonic_widget(scale) def rebuild_pipeline(*args): player._rebuild_pipeline() apply_button.connect('clicked', rebuild_pipeline) gapless_button = ConfigCheckButton( _('Disable _gapless playback'), "player", "gst_disable_gapless", populate=True, tooltip=_( "Disabling gapless playback can avoid track changing problems " "with some GStreamer versions")) jack_button = ConfigCheckButton( _('Use JACK for playback if available'), "player", "gst_use_jack", populate=True, tooltip=_( "Uses `jackaudiosink` for playbin sink if it can be detected")) jack_connect = ConfigCheckButton( _('Auto-connect to JACK output devices'), "player", "gst_jack_auto_connect", populate=True, tooltip=_("Tells `jackaudiosink` to auto-connect")) def _jack_toggled(widget: ConfigCheckButton) -> None: jack_connect.set_sensitive(widget.get_active()) jack_button.connect("clicked", _jack_toggled) _jack_toggled(jack_button) widgets = [(pipe_label, e, apply_button), (buffer_label, scale, None)] table = Gtk.Table(n_rows=len(widgets) + 3, n_columns=3) table.set_col_spacings(6) table.set_row_spacings(6) for i, (left, middle, right) in enumerate(widgets): left.set_alignment(0.0, 0.5) table.attach(left, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) if right: table.attach(middle, 1, 2, i, i + 1) table.attach(right, 2, 3, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) else: table.attach(middle, 1, 3, i, i + 1) table.attach(gapless_button, 0, 3, 2, 3) table.attach(jack_button, 0, 3, 3, 4) table.attach(jack_connect, 0, 3, 4, 5) self.pack_start(table, True, True, 0) if debug: def print_bin(player): player._print_pipeline() b = Button("Print Pipeline", Icons.DIALOG_INFORMATION) connect_obj(b, 'clicked', print_bin, player) self.pack_start(b, True, True, 0)
def __init__(self): def create_display_frame(): vbox = Gtk.VBox(spacing=6) model = Gtk.ListStore(str, str) def on_changed(combo): it = combo.get_active_iter() if it is None: return DURATION.format = model[it][0] app.window.songlist.info.refresh() app.window.qexpander.refresh() # TODO: refresh info windows ideally too (but see #2019) def draw_duration(column, cell, model, it, data): df, example = model[it] cell.set_property('text', example) for df in sorted(DurationFormat.values): # 4954s == longest ever CD, FWIW model.append([df, format_time_preferred(4954, df)]) duration = Gtk.ComboBox(model=model) cell = Gtk.CellRendererText() duration.pack_start(cell, True) duration.set_cell_data_func(cell, draw_duration, None) index = sorted(DurationFormat.values).index(DURATION.format) duration.set_active(index) duration.connect('changed', on_changed) hbox = Gtk.HBox(spacing=6) label = Gtk.Label(label=_("Duration totals") + ":", use_underline=True) label.set_mnemonic_widget(duration) hbox.pack_start(label, False, True, 0) hbox.pack_start(duration, False, True, 0) vbox.pack_start(hbox, False, True, 0) return qltk.Frame(_("Display"), child=vbox) def create_search_frame(): vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.validator) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text( _("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action return qltk.Frame(C_("heading", "Search"), child=vb) super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") self.pack_start(create_search_frame(), False, True, 0) self.pack_start(create_display_frame(), False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) vb = Gtk.VBox(spacing=6) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) cb = CCB(_("_Fixed image filename:"), 'albumart', 'force_filename', populate=True, tooltip=_("The single image filename to use if " "selected")) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def __init__(self, browser): if self.is_not_unique(): return super(Preferences, self).__init__() self.set_border_width(12) self.set_title(_("Cover Grid Preferences")) self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._PREVIEW_ITEM["~rating"] = format_rating(0.75) self.mag_lock = False box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton( _("Show album _text"), "browsers", "album_text") cb.set_active(config.getboolean("browsers", "album_text")) cb.connect('toggled', lambda s: browser.toggle_text()) vbox.pack_start(cb, False, True, 0) cb2 = ConfigCheckButton( _("Show \"All Albums\" Item"), "browsers", "covergrid_all") cb2.set_active(config.getboolean("browsers", "covergrid_all", False)) cb2.connect('toggled', lambda s: browser.view.get_model().refilter()) vbox.pack_start(cb2, False, True, 0) cb3 = ConfigCheckButton( _("Wide Mode"), "browsers", "covergrid_wide") cb3.set_active(config.getboolean("browsers", "covergrid_wide", False)) cb3.connect('toggled', lambda s: browser.toggle_wide()) vbox.pack_start(cb3, False, True, 0) # Redraws the covers only when the user releases the slider def mag_button_press(*_): self.mag_lock = True def mag_button_release(mag, _): self.mag_lock = False mag_changed(mag) def mag_changed(mag): if self.mag_lock: return newmag = mag.get_value() oldmag = config.getfloat("browsers", "covergrid_magnification", 3.) if newmag == oldmag: print_d("Covergrid magnification haven't changed: {0}" .format(newmag)) return print_d('Covergrid magnification update from {0} to {1}' .format(oldmag, newmag)) config.set("browsers", "covergrid_magnification", mag.get_value()) browser.update_mag() mag_scale = Gtk.HScale( adjustment=Gtk.Adjustment.new(config.getfloat("browsers", "covergrid_magnification", 3), 0., 10., .5, .5, 0)) mag_scale.set_tooltip_text(_("Cover Magnification")) l = Gtk.Label(label=_("Cover Magnification")) mag_scale.set_value_pos(Gtk.PositionType.RIGHT) mag_scale.connect('button-press-event', mag_button_press) mag_scale.connect('button-release-event', mag_button_release) mag_scale.connect('value-changed', mag_changed) vbox.pack_start(l, False, True, 0) vbox.pack_start(mag_scale, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) display_frame = self.edit_display_pane(browser, _("Album Display")) box.pack_start(display_frame, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all()
def __init__(self, browser): if self.is_not_unique(): return super(Preferences, self).__init__() self.set_border_width(12) self.set_title(_("Album List Preferences") + " - Quod Libet") self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._EXAMPLE_ALBUM["~rating"] = format_rating(0.75) box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton(_("Show album _covers"), "browsers", "album_covers") cb.set_active(config.getboolean("browsers", "album_covers")) cb.connect('toggled', lambda s: browser.toggle_covers()) vbox.pack_start(cb, False, True, 0) cb = ConfigCheckButton(_("Inline _search includes people"), "browsers", "album_substrings") cb.set_active(config.getboolean("browsers", "album_substrings")) vbox.pack_start(cb, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) vbox = Gtk.VBox(spacing=6) label = Gtk.Label() label.set_alignment(0.0, 0.5) label.set_padding(6, 6) eb = Gtk.EventBox() eb.get_style_context().add_class("entry") eb.add(label) edit = PatternEditBox(PATTERN) edit.text = browser._pattern_text edit.apply.connect('clicked', self.__set_pattern, edit, browser) connect_obj(edit.buffer, 'changed', self.__preview_pattern, edit, label) vbox.pack_start(eb, False, True, 3) vbox.pack_start(edit, True, True, 0) self.__preview_pattern(edit, label) f = qltk.Frame(_("Album Display"), child=vbox) box.pack_start(f, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Gtk.Button(stock=Gtk.STOCK_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all()
def __init__(self): super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") # Search vb = Gtk.VBox(spacing=6) hb = Gtk.HBox(spacing=6) l = Gtk.Label(label=_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(QueryValidator) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text(_("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, False, True, 0) hb.pack_start(e, True, True, 0) vb.pack_start(hb, False, True, 0) # Translators: The heading of the preference group, no action f = qltk.Frame(C_("heading", "Search"), child=vb) self.pack_start(f, False, True, 0) # Ratings vb = Gtk.VBox(spacing=6) c1 = CCB(_("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True, tooltip=_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = CCB(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True, tooltip=_("Enable rating by clicking on the rating " "column in the song list")) vbox = Gtk.VBox(spacing=6) vbox.pack_start(c1, False, True, 0) vbox.pack_start(c2, False, True, 0) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, False, True, 0) vb = Gtk.VBox(spacing=6) # Filename choice algorithm config cb = CCB(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True, tooltip=_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, False, True, 0) hb = Gtk.HBox(spacing=3) cb = CCB(_("_Fixed image filename:"), 'albumart', 'force_filename', populate=True, tooltip=_("The single image filename to use if " "selected")) hb.pack_start(cb, False, True, 0) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry, True, True, 0) vb.pack_start(hb, False, True, 0) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def __init__(self): super(PreferencesWindow.Connection, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Connection") vbox = gtk.VBox(spacing=6) hb = gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("connection", "hostname")) e.connect('changed', self.__changed_tb, 'connection', 'hostname') e.set_tooltip_text( _("The MPD Host to Connect to")) l = gtk.Label(_("Hostname:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, expand=False) hb.pack_start(e) vbox.pack_start(hb, expand=False) hb = gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("connection", "port")) e.connect('changed', self.__changed_tb, 'connection', 'port') e.set_tooltip_text( _("Port of the MPD Host")) l = gtk.Label(_("Port:")) l.set_use_underline(True) l.set_mnemonic_widget(e) hb.pack_start(l, expand=False) hb.pack_start(e) vbox.pack_start(hb, expand=False) hb = gtk.HBox(spacing=6) e = UndoEntry() e.set_text(config.get("connection", "password")) e.connect('changed', self.__changed_tb, 'connection', 'password') e.set_tooltip_text( _("Password for the MPD Host (if necessary)")) e.set_visibility(False) l = gtk.Label(_("Password:"******"MPD Server Connection"), child=vbox) self.pack_start(f, expand=False) # player backend # if player.backend and hasattr(player.device, 'PlayerPreferences'): # player_prefs = player.device.PlayerPreferences() # f = qltk.Frame(_("Output Configuration"), child=player_prefs) # self.pack_start(f, expand=False) # replaygain fallback_gain = config.getfloat("player", "fallback_gain", 0.0) adj = gtk.Adjustment(fallback_gain, -12.0, 12.0, 0.5, 0.5, 0.0) fb_spin = gtk.SpinButton(adj) fb_spin.set_digits(1) fb_spin.connect('changed', self.__changed, 'player', 'fallback_gain') fb_spin.set_tooltip_text( _("If no Replay Gain information is available " "for a song, scale the volume by this value")) fb_label = gtk.Label(_("_Fall-back gain (dB):")) fb_label.set_use_underline(True) fb_label.set_mnemonic_widget(fb_spin) pre_amp_gain = config.getfloat("player", "pre_amp_gain", 0.0) adj = gtk.Adjustment(pre_amp_gain, -6, 6, 0.5, 0.5, 0.0) adj.connect('value-changed', self.__changed, 'player', 'pre_amp_gain') pre_spin = gtk.SpinButton(adj) pre_spin.set_digits(1) pre_spin.set_tooltip_text( _("Scale volume for all songs by this value, " "as long as the result will not clip")) pre_label = gtk.Label(_("_Pre-amp gain (dB):")) pre_label.set_use_underline(True) pre_label.set_mnemonic_widget(pre_spin) widgets = [pre_label, pre_spin, fb_label, fb_spin] c = ConfigCheckButton(_("_Enable Replay Gain volume adjustment"), "player", "replaygain", populate=True) c.connect('toggled', self.__toggled_gain, widgets) # packing table = gtk.Table(3, 2) table.set_col_spacings(6) table.set_row_spacings(6) table.attach(c, 0, 2, 0, 1) fb_label.set_alignment(0, 0.5) table.attach(fb_label, 0, 1, 1, 2, xoptions=0) pre_label.set_alignment(0, 0.5) table.attach(pre_label, 0, 1, 2, 3, xoptions=0) fb_align = gtk.Alignment(0, 0.5, 0, 1) fb_align.add(fb_spin) table.attach(fb_align, 1, 2, 1, 2) pre_align = gtk.Alignment(0, 0.5, 0, 1) pre_align.add(pre_spin) table.attach(pre_align, 1, 2, 2, 3) f = qltk.Frame(_("Replay Gain Volume Adjustment"), child=table) c.emit('toggled') self.pack_start(f, expand=False) self.show_all()
def __init__(self): super(PreferencesWindow.Browsers, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Browsers") # Search vb = gtk.VBox(spacing=6) hb = gtk.HBox(spacing=6) l = gtk.Label(_("_Global filter:")) l.set_use_underline(True) e = ValidatingEntry(Query.is_valid_color) e.set_text(config.get("browsers", "background")) e.connect('changed', self._entry, 'background', 'browsers') e.set_tooltip_text(_("Apply this query in addition to all others")) l.set_mnemonic_widget(e) hb.pack_start(l, expand=False) hb.pack_start(e) vb.pack_start(hb, expand=False) c = ConfigCheckButton(_("Search after _typing"), 'settings', 'eager_search', populate=True) c.set_tooltip_text(_("Show search results after the user " "stops typing.")) vb.pack_start(c, expand=False) # Translators: The heading of the preference group, no action f = qltk.Frame(Q_("heading|Search"), child=vb) self.pack_start(f, expand=False) # Ratings vb = gtk.VBox(spacing=6) c1 = ConfigCheckButton( _("Confirm _multiple ratings"), 'browsers', 'rating_confirm_multiple', populate=True) c1.set_tooltip_text(_("Ask for confirmation before changing the " "rating of multiple songs at once")) c2 = ConfigCheckButton(_("Enable _one-click ratings"), 'browsers', 'rating_click', populate=True) c2.set_tooltip_text(_("Enable rating by clicking on the rating " "column in the song list")) vbox = gtk.VBox(spacing=6) vbox.pack_start(c1, expand=False) vbox.pack_start(c2, expand=False) f = qltk.Frame(_("Ratings"), child=vbox) self.pack_start(f, expand=False) # Album Art vb = gtk.VBox(spacing=6) c = ConfigCheckButton(_("_Use rounded corners on thumbnails"), 'albumart', 'round', populate=True) c.set_tooltip_text(_("Round the corners of album artwork " "thumbnail images. May require restart to take effect.")) vb.pack_start(c, expand=False) # Filename choice algorithm config cb = ConfigCheckButton(_("Prefer _embedded art"), 'albumart', 'prefer_embedded', populate=True) cb.set_tooltip_text(_("Choose to use artwork embedded in the audio " "(where available) over other sources")) vb.pack_start(cb, expand=False) hb = gtk.HBox(spacing=3) cb = ConfigCheckButton(_("_Force image filename:"), 'albumart', 'force_filename', populate=True) hb.pack_start(cb, expand=False) entry = UndoEntry() entry.set_tooltip_text( _("The album art image file to use when forced")) entry.set_text(config.get("albumart", "filename")) entry.connect('changed', self.__changed_text, 'filename') # Disable entry when not forcing entry.set_sensitive(cb.get_active()) cb.connect('toggled', self.__toggled_force_filename, entry) hb.pack_start(entry) vb.pack_start(hb, expand=False) f = qltk.Frame(_("Album Art"), child=vb) self.pack_start(f, expand=False)
def __init__(self): super(PreferencesWindow.Player, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Playback") # player backend if app.player and hasattr(app.player, 'PlayerPreferences'): player_prefs = app.player.PlayerPreferences() f = qltk.Frame(_("Output Configuration"), child=player_prefs) self.pack_start(f, False, True, 0) # replaygain fallback_gain = config.getfloat("player", "fallback_gain", 0.0) adj = Gtk.Adjustment.new(fallback_gain, -12.0, 12.0, 0.5, 0.5, 0.0) fb_spin = Gtk.SpinButton(adjustment=adj) fb_spin.set_digits(1) fb_spin.connect('changed', self.__changed, 'player', 'fallback_gain') fb_spin.set_tooltip_text( _("If no Replay Gain information is available " "for a song, scale the volume by this value")) fb_label = Gtk.Label(label=_("_Fall-back gain (dB):")) fb_label.set_use_underline(True) fb_label.set_mnemonic_widget(fb_spin) pre_amp_gain = config.getfloat("player", "pre_amp_gain", 0.0) adj = Gtk.Adjustment.new(pre_amp_gain, -6, 6, 0.5, 0.5, 0.0) adj.connect('value-changed', self.__changed, 'player', 'pre_amp_gain') pre_spin = Gtk.SpinButton(adjustment=adj) pre_spin.set_digits(1) pre_spin.set_tooltip_text( _("Scale volume for all songs by this value, " "as long as the result will not clip")) pre_label = Gtk.Label(label=_("_Pre-amp gain (dB):")) pre_label.set_use_underline(True) pre_label.set_mnemonic_widget(pre_spin) widgets = [pre_label, pre_spin, fb_label, fb_spin] c = CCB(_("_Enable Replay Gain volume adjustment"), "player", "replaygain", populate=True) c.connect('toggled', self.__toggled_gain, widgets) # packing table = Gtk.Table.new(3, 2, False) table.set_col_spacings(6) table.set_row_spacings(6) table.attach(c, 0, 2, 0, 1) fb_label.set_alignment(0, 0.5) table.attach(fb_label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) pre_label.set_alignment(0, 0.5) table.attach(pre_label, 0, 1, 2, 3, xoptions=Gtk.AttachOptions.FILL) fb_align = Align(halign=Gtk.Align.START) fb_align.add(fb_spin) table.attach(fb_align, 1, 2, 1, 2) pre_align = Align(halign=Gtk.Align.START) pre_align.add(pre_spin) table.attach(pre_align, 1, 2, 2, 3) f = qltk.Frame(_("Replay Gain Volume Adjustment"), child=table) c.emit('toggled') self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
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(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=SymbolicIconImage(Icons.EDIT_CLEAR, Gtk.IconSize.MENU)) b.set_tooltip_text(_("Remove all songs from the queue")) b.connect('clicked', self.__clear_queue) b.set_no_show_all(True) b.set_relief(Gtk.ReliefStyle.NONE) left.pack_start(b, False, False, 0) self.count_label = 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")) cb.set_no_show_all(True) left.pack_start(cb, False, True, 0) self.set_label_widget(outer) self.add(sw) connect_obj(self, '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.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) connect_obj(self, 'notify::visible', self.__visible, cb, b) 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) # 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()
def __init__(self, browser): if self.is_not_unique(): return super().__init__() self.set_border_width(12) self.set_title(_("Cover Grid Preferences")) self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._PREVIEW_ITEM["~rating"] = format_rating(0.75) self.mag_lock = False box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton(_("Show album _text"), "browsers", "album_text") cb.set_active(config.getboolean("browsers", "album_text")) cb.connect('toggled', lambda s: browser.toggle_text()) vbox.pack_start(cb, False, True, 0) cb2 = ConfigCheckButton(_("Show \"All Albums\" Item"), "browsers", "covergrid_all") cb2.set_active(config.getboolean("browsers", "covergrid_all", True)) def refilter(s): mod = browser.view.get_model() if mod: mod.refilter() cb2.connect('toggled', refilter) vbox.pack_start(cb2, False, True, 0) cb3 = ConfigCheckButton(_("Wide Mode"), "browsers", "covergrid_wide") cb3.set_active(config.getboolean("browsers", "covergrid_wide", False)) cb3.connect('toggled', lambda s: browser.toggle_wide()) vbox.pack_start(cb3, False, True, 0) # Redraws the covers only when the user releases the slider def mag_button_press(*_): self.mag_lock = True def mag_button_release(mag, _): self.mag_lock = False mag_changed(mag) def mag_changed(mag): if self.mag_lock: return newmag = mag.get_value() oldmag = config.getfloat("browsers", "covergrid_magnification", 3.) if newmag == oldmag: print_d("Covergrid magnification haven't changed: {0}".format( newmag)) return print_d('Covergrid magnification update from {0} to {1}'.format( oldmag, newmag)) config.set("browsers", "covergrid_magnification", mag.get_value()) browser.update_mag() mag_scale = Gtk.HScale(adjustment=Gtk.Adjustment.new( config.getfloat("browsers", "covergrid_magnification", 3), 0., 10., .5, .5, 0)) mag_scale.set_tooltip_text(_("Cover Magnification")) l = Gtk.Label(label=_("Cover Magnification")) mag_scale.set_value_pos(Gtk.PositionType.RIGHT) mag_scale.connect('button-press-event', mag_button_press) mag_scale.connect('button-release-event', mag_button_release) mag_scale.connect('value-changed', mag_changed) vbox.pack_start(l, False, True, 0) vbox.pack_start(mag_scale, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) display_frame = self.edit_display_pane(browser, _("Album Display")) box.pack_start(display_frame, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all()
def __init__(self, songs, title=None): super().__init__( default_width=800, default_height=400, border_width=12, title=title) self._thread = AcoustidLookupThread(self.__lookup_cb) sw = Gtk.ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) model = ObjectStore() self.view = view = ResultView() view.set_model(model) self.model = model self._iter_map = {} for song in songs: iter_ = self.model.append([SearchEntry(song)]) self._iter_map[song] = iter_ sw.add(view) self.pool = pool = FingerPrintPool() pool.connect('fingerprint-done', self.__fp_done_cb) pool.connect('fingerprint-error', self.__fp_error_cb) pool.connect('fingerprint-started', self.__fp_started_cb) for song in songs: pool.push(song) outer_box = Gtk.VBox(spacing=12) bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.set_spacing(6) self.__save = save = Button(_("_Save"), Icons.DOCUMENT_SAVE) save.connect("clicked", self.__on_save) save.set_sensitive(False) cancel = Button(_("_Cancel")) cancel.connect("clicked", lambda *x: self.destroy()) bbox.pack_start(save, True, True, 0) bbox.pack_start(cancel, True, True, 0) inner_box = Gtk.VBox(spacing=6) inner_box.pack_start(sw, True, True, 0) ccb = ConfigCheckButton( _("Write MusicBrainz tags"), "plugins", "fingerprint_write_mb_tags") ccb.set_active(get_write_mb_tags()) inner_box.pack_start(ccb, False, True, 0) ccb = ConfigCheckButton( _("Group by directory"), "plugins", "fingerprint_group_by_dir") ccb.set_active(get_group_by_dir()) ccb.connect("toggled", self.__group_toggled) self._group_ccb = ccb outer_box.pack_start(inner_box, True, True, 0) bottom_box = Gtk.HBox(spacing=12) mode_button = Gtk.ToggleButton(label=_("Album Mode")) mode_button.set_tooltip_text( _("Write album related tags and try to " "reduce the number of different album releases")) mode_button.set_active(True) mode_button.connect("toggled", self.__mode_toggle) bottom_box.pack_start(mode_button, False, True, 0) bottom_box.pack_start(self._group_ccb, False, True, 0) bottom_box.pack_start(bbox, True, True, 0) outer_box.pack_start(bottom_box, False, True, 0) outer_box.show_all() self.add(outer_box) self.__album_mode = True self.__group_by_dir = True self._release_scores = {} self._directory_scores = {} self.__done = 0 self.connect("destroy", self.__destroy)
def __init__(self): super(PreferencesWindow.Player, self).__init__(spacing=12) self.set_border_width(12) self.title = _("Playback") # player backend if app.player and hasattr(app.player, 'PlayerPreferences'): player_prefs = app.player.PlayerPreferences() f = qltk.Frame(_("Output Configuration"), child=player_prefs) self.pack_start(f, False, True, 0) # replaygain fallback_gain = config.getfloat("player", "fallback_gain", 0.0) adj = Gtk.Adjustment.new(fallback_gain, -12.0, 12.0, 0.5, 0.5, 0.0) fb_spin = Gtk.SpinButton(adjustment=adj) fb_spin.set_digits(1) fb_spin.connect('changed', self.__changed, 'player', 'fallback_gain') fb_spin.set_tooltip_text( _("If no Replay Gain information is available " "for a song, scale the volume by this value")) fb_label = Gtk.Label(label=_("_Fall-back gain (dB):")) fb_label.set_use_underline(True) fb_label.set_mnemonic_widget(fb_spin) pre_amp_gain = config.getfloat("player", "pre_amp_gain", 0.0) adj = Gtk.Adjustment.new(pre_amp_gain, -6, 6, 0.5, 0.5, 0.0) adj.connect('value-changed', self.__changed, 'player', 'pre_amp_gain') pre_spin = Gtk.SpinButton(adjustment=adj) pre_spin.set_digits(1) pre_spin.set_tooltip_text( _("Scale volume for all songs by this value, " "as long as the result will not clip")) pre_label = Gtk.Label(label=_("_Pre-amp gain (dB):")) pre_label.set_use_underline(True) pre_label.set_mnemonic_widget(pre_spin) widgets = [pre_label, pre_spin, fb_label, fb_spin] c = CCB(_("_Enable Replay Gain volume adjustment"), "player", "replaygain", populate=True) c.connect('toggled', self.__toggled_gain, widgets) # packing table = Gtk.Table.new(3, 2, False) table.set_col_spacings(6) table.set_row_spacings(6) table.attach(c, 0, 2, 0, 1) fb_label.set_alignment(0, 0.5) table.attach(fb_label, 0, 1, 1, 2, xoptions=0) pre_label.set_alignment(0, 0.5) table.attach(pre_label, 0, 1, 2, 3, xoptions=0) fb_align = Gtk.Alignment.new(0, 0.5, 0, 1) fb_align.add(fb_spin) table.attach(fb_align, 1, 2, 1, 2) pre_align = Gtk.Alignment.new(0, 0.5, 0, 1) pre_align.add(pre_spin) table.attach(pre_align, 1, 2, 2, 3) f = qltk.Frame(_("Replay Gain Volume Adjustment"), child=table) c.emit('toggled') self.pack_start(f, False, True, 0) for child in self.get_children(): child.show_all()
def __init__(self, browser): if self.is_not_unique(): return super(Preferences, self).__init__() self.set_border_width(12) self.set_title(_("Album List Preferences") + " - Quod Libet") self.set_default_size(420, 380) self.set_transient_for(qltk.get_top_parent(browser)) # Do this config-driven setup at instance-time self._EXAMPLE_ALBUM["~rating"] = format_rating(0.75) box = Gtk.VBox(spacing=6) vbox = Gtk.VBox(spacing=6) cb = ConfigCheckButton( _("Show album _covers"), "browsers", "album_covers") cb.set_active(config.getboolean("browsers", "album_covers")) cb.connect('toggled', lambda s: browser.toggle_covers()) vbox.pack_start(cb, False, True, 0) cb = ConfigCheckButton( _("Inline _search includes people"), "browsers", "album_substrings") cb.set_active(config.getboolean("browsers", "album_substrings")) vbox.pack_start(cb, False, True, 0) f = qltk.Frame(_("Options"), child=vbox) box.pack_start(f, False, True, 12) vbox = Gtk.VBox(spacing=6) label = Gtk.Label() label.set_alignment(0.0, 0.5) label.set_padding(6, 6) eb = Gtk.EventBox() eb.get_style_context().add_class("entry") eb.add(label) edit = PatternEditBox(PATTERN) edit.text = browser._pattern_text edit.apply.connect('clicked', self.__set_pattern, edit, browser) connect_obj( edit.buffer, 'changed', self.__preview_pattern, edit, label) vbox.pack_start(eb, False, True, 3) vbox.pack_start(edit, True, True, 0) self.__preview_pattern(edit, label) f = qltk.Frame(_("Album Display"), child=vbox) box.pack_start(f, True, True, 0) main_box = Gtk.VBox(spacing=12) close = Button(_("_Close"), Icons.WINDOW_CLOSE) close.connect('clicked', lambda *x: self.destroy()) b = Gtk.HButtonBox() b.set_layout(Gtk.ButtonBoxStyle.END) b.pack_start(close, True, True, 0) main_box.pack_start(box, True, True, 0) self.use_header_bar() if not self.has_close_button(): main_box.pack_start(b, False, True, 0) self.add(main_box) close.grab_focus() self.show_all()
def __init__(self, parent, library): super(EditTags, self).__init__(spacing=12) self.title = _("Edit Tags") self.set_border_width(12) model = ObjectStore() view = RCMHintedTreeView(model=model) self._view = view selection = view.get_selection() render = Gtk.CellRendererPixbuf() column = TreeViewColumn() column.pack_start(render, True) column.set_fixed_width(24) column.set_expand(False) def cdf_write(col, rend, model, iter_, *args): entry = model.get_value(iter_) rend.set_property('sensitive', entry.edited or entry.deleted) if entry.canedit or entry.deleted: if entry.deleted: rend.set_property('icon-name', Icons.EDIT_DELETE) else: rend.set_property('icon-name', Icons.EDIT) else: rend.set_property('icon-name', Icons.CHANGES_PREVENT) column.set_cell_data_func(render, cdf_write) view.append_column(column) render = Gtk.CellRendererText() column = TreeViewColumn(title=_('Tag')) column.pack_start(render, True) def cell_data_tag(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.tag) cell.set_property("strikethrough", entry.deleted) column.set_cell_data_func(render, cell_data_tag) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) render.set_property('editable', True) render.connect('edited', self.__edit_tag_name, model) render.connect('editing-started', self.__tag_editing_started, model, library) view.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) render.set_property('editable', True) render.connect('edited', self.__edit_tag, model) render.connect('editing-started', self.__value_editing_started, model, library) column = TreeViewColumn(title=_('Value')) column.pack_start(render, True) def cell_data_value(column, cell, model, iter_, data): entry = model.get_value(iter_) markup = entry.value.get_markup() cell.markup = markup cell.set_property("markup", markup) cell.set_property("editable", entry.canedit) cell.set_property("strikethrough", entry.deleted) column.set_cell_data_func(render, cell_data_value) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) view.append_column(column) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(view) self.pack_start(sw, True, True, 0) cb = ConfigCheckButton( _("Show _programmatic tags"), 'editing', 'alltags', populate=True, tooltip=_("Access all tags, including machine-generated " "ones e.g. MusicBrainz or Replay Gain tags")) cb.connect('toggled', self.__all_tags_toggled) self.pack_start(cb, False, True, 0) # Add and Remove [tags] buttons buttonbox = Gtk.HBox(spacing=18) bbox1 = Gtk.HButtonBox() bbox1.set_spacing(6) bbox1.set_layout(Gtk.ButtonBoxStyle.START) add = qltk.Button(_("_Add"), Icons.LIST_ADD) add.set_focus_on_click(False) self._add = add add.connect('clicked', self.__add_tag, model, library) bbox1.pack_start(add, True, True, 0) # Remove button remove = qltk.Button(_("_Remove"), Icons.LIST_REMOVE) remove.set_focus_on_click(False) remove.connect('clicked', self.__remove_tag, view) remove.set_sensitive(False) self._remove = remove bbox1.pack_start(remove, True, True, 0) # Revert and save buttons # Both can have customised translated text (and thus accels) bbox2 = Gtk.HButtonBox() bbox2.set_spacing(6) bbox2.set_layout(Gtk.ButtonBoxStyle.END) # Translators: Revert button in the tag editor revert = Button(C_("edittags", "_Revert"), Icons.DOCUMENT_REVERT) self._revert = revert revert.set_sensitive(False) # Translators: Save button in the tag editor save = Button(C_("edittags", "_Save"), Icons.DOCUMENT_SAVE) save.set_sensitive(False) self._save = save bbox2.pack_start(revert, True, True, 0) bbox2.pack_start(save, True, True, 0) buttonbox.pack_start(bbox1, True, True, 0) buttonbox.pack_start(bbox2, True, True, 0) self.pack_start(buttonbox, False, True, 0) self._buttonbox = buttonbox parent.connect('changed', self.__parent_changed) revert.connect('clicked', lambda *x: self._update()) connect_obj(revert, 'clicked', parent.set_pending, None) save.connect('clicked', self.__save_files, revert, model, library) connect_obj(save, 'clicked', parent.set_pending, None) for sig in ['row-inserted', 'row-deleted', 'row-changed']: model.connect(sig, self.__enable_save, [save, revert]) connect_obj(model, sig, parent.set_pending, save) view.connect('popup-menu', self.__popup_menu, parent) view.connect('button-press-event', self.__button_press) view.connect('key-press-event', self.__view_key_press_event) selection.connect('changed', self.__tag_select, remove) selection.set_mode(Gtk.SelectionMode.MULTIPLE) self._parent = parent for child in self.get_children(): child.show_all()
def __init__(self, parent, library): super(EditTags, self).__init__(spacing=12) self.title = _("Edit Tags") self.set_border_width(12) model = ObjectStore() view = RCMHintedTreeView(model=model) self._view = view selection = view.get_selection() render = Gtk.CellRendererPixbuf() column = TreeViewColumn() column.pack_start(render, True) column.set_fixed_width(24) column.set_expand(False) def cdf_write(col, rend, model, iter_, *args): entry = model.get_value(iter_) rend.set_property('sensitive', entry.edited or entry.deleted) if entry.canedit or entry.deleted: if entry.deleted: rend.set_property('icon-name', Icons.EDIT_DELETE) else: rend.set_property('icon-name', Icons.EDIT) else: rend.set_property('icon-name', Icons.CHANGES_PREVENT) column.set_cell_data_func(render, cdf_write) view.append_column(column) render = Gtk.CellRendererText() column = TreeViewColumn(title=_('Tag')) column.pack_start(render, True) def cell_data_tag(column, cell, model, iter_, data): entry = model.get_value(iter_) cell.set_property("text", entry.tag) cell.set_property("strikethrough", entry.deleted) column.set_cell_data_func(render, cell_data_tag) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) render.set_property('editable', True) render.connect('edited', self.__edit_tag_name, model) render.connect( 'editing-started', self.__tag_editing_started, model, library) view.append_column(column) render = Gtk.CellRendererText() render.set_property('ellipsize', Pango.EllipsizeMode.END) render.set_property('editable', True) render.connect('edited', self.__edit_tag, model) render.connect( 'editing-started', self.__value_editing_started, model, library) column = TreeViewColumn(title=_('Value')) column.pack_start(render, True) def cell_data_value(column, cell, model, iter_, data): entry = model.get_value(iter_) markup = entry.value.get_markup() cell.markup = markup cell.set_property("markup", markup) cell.set_property("editable", entry.canedit) cell.set_property("strikethrough", entry.deleted) column.set_cell_data_func(render, cell_data_value) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) view.append_column(column) sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(view) self.pack_start(sw, True, True, 0) cb = ConfigCheckButton( _("Show _programmatic tags"), 'editing', 'alltags', populate=True, tooltip=_("Access all tags, including machine-generated " "ones e.g. MusicBrainz or Replay Gain tags")) cb.connect('toggled', self.__all_tags_toggled) self.pack_start(cb, False, True, 0) # Add and Remove [tags] buttons buttonbox = Gtk.HBox(spacing=18) bbox1 = Gtk.HButtonBox() bbox1.set_spacing(6) bbox1.set_layout(Gtk.ButtonBoxStyle.START) add = qltk.Button(_("_Add"), Icons.LIST_ADD) add.set_focus_on_click(False) self._add = add add.connect('clicked', self.__add_tag, model, library) bbox1.pack_start(add, True, True, 0) # Remove button remove = qltk.Button(_("_Remove"), Icons.LIST_REMOVE) remove.set_focus_on_click(False) remove.connect('clicked', self.__remove_tag, view) remove.set_sensitive(False) self._remove = remove bbox1.pack_start(remove, True, True, 0) # Revert and save buttons # Both can have customised translated text (and thus accels) bbox2 = Gtk.HButtonBox() bbox2.set_spacing(6) bbox2.set_layout(Gtk.ButtonBoxStyle.END) # Translators: Revert button in the tag editor revert = Button(C_("edittags", "_Revert"), Icons.DOCUMENT_REVERT) self._revert = revert revert.set_sensitive(False) # Translators: Save button in the tag editor save = Button(C_("edittags", "_Save"), Icons.DOCUMENT_SAVE) save.set_sensitive(False) self._save = save bbox2.pack_start(revert, True, True, 0) bbox2.pack_start(save, True, True, 0) buttonbox.pack_start(bbox1, True, True, 0) buttonbox.pack_start(bbox2, True, True, 0) self.pack_start(buttonbox, False, True, 0) self._buttonbox = buttonbox parent.connect('changed', self.__parent_changed) revert.connect('clicked', lambda *x: self._update()) connect_obj(revert, 'clicked', parent.set_pending, None) save.connect('clicked', self.__save_files, revert, model, library) connect_obj(save, 'clicked', parent.set_pending, None) for sig in ['row-inserted', 'row-deleted', 'row-changed']: model.connect(sig, self.__enable_save, [save, revert]) connect_obj(model, sig, parent.set_pending, save) view.connect('popup-menu', self.__popup_menu, parent) view.connect('button-press-event', self.__button_press) view.connect('key-press-event', self.__view_key_press_event) selection.connect('changed', self.__tag_select, remove) selection.set_mode(Gtk.SelectionMode.MULTIPLE) self._parent = parent for child in self.get_children(): child.show_all()