def test_toggle(self): config.set("memory", "bar", "on") c = ConfigCheckMenuItem("dummy", "memory", "bar") c.set_active(True) self.failUnless(config.getboolean("memory", "bar") and c.get_active()) c.set_active(False) while gtk.events_pending(): gtk.main_iteration() self.failIf(config.getboolean("memory", "bar") or c.get_active())
def previous(self): """Go to the previous song""" keep_songs = config.getboolean("memory", "queue_keep_songs", False) q_ignore = config.getboolean("memory", "queue_ignore", False) if q_ignore or self.pl.sourced or not keep_songs: self.pl.previous() else: self.q.previous() self._check_sourced()
def ConfigCheckButton(cls, label, name, default=False): """ Create a new `ConfigCheckButton` for `name`, pre-populated correctly """ option = cls._config_key(name) try: config.getboolean(PM.CONFIG_SECTION, option) except config.Error: cls.config_set(name, default) return ConfigCheckButton(label, PM.CONFIG_SECTION, option, populate=True)
def next_ended(self): """Switch to the next song (action comes from the user)""" keep_songs = config.getboolean("memory", "queue_keep_songs", False) q_ignore = config.getboolean("memory", "queue_ignore", False) if (self.q.is_empty() or (q_ignore and not (keep_songs and self.q.sourced))): self.pl.next_ended() else: self.q.next_ended() self._check_sourced()
def __search_func(self, model, column, key, iter_, data): album = model.get_album(iter_) if album is None: return config.getboolean("browsers", "covergrid_all", False) key = key.decode('utf-8').lower() title = album.title.lower() if key in title: return False if config.getboolean("browsers", "album_substrings"): people = (p.lower() for p in album.list("~people")) for person in people: if key in person: return False return True
def __init__(self, parent): 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(400, 270) self.set_transient_for(qltk.get_top_parent(parent)) box = gtk.VBox(spacing=6) cb = ConfigCheckButton( _("Show album _covers"), "browsers", "album_covers") cb.set_active(config.getboolean("browsers", "album_covers")) gobject_weak(cb.connect, 'toggled', lambda s: AlbumList.toggle_covers()) box.pack_start(cb, expand=False) cb = ConfigCheckButton( _("Inline _search includes people"), "browsers", "album_substrings") cb.set_active(config.getboolean("browsers", "album_substrings")) box.pack_start(cb, expand=False) vbox = gtk.VBox(spacing=6) label = gtk.Label() label.set_alignment(0.0, 0.5) edit = PatternEditBox(PATTERN) edit.text = AlbumList._pattern_text gobject_weak(edit.apply.connect, 'clicked', self.__set_pattern, edit) gobject_weak(edit.buffer.connect_object, 'changed', self.__preview_pattern, edit, label, parent=edit) vbox.pack_start(label, expand=False) vbox.pack_start(edit) self.__preview_pattern(edit, label) f = qltk.Frame(_("Album Display"), child=vbox) box.pack_start(f) 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.BUTTONBOX_END) b.pack_start(close) main_box.pack_start(box) main_box.pack_start(b, expand=False) self.add(main_box) close.grab_focus() self.show_all()
def __button_press(self, view, event, librarian): if event.button != Gdk.BUTTON_PRIMARY: return x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: return True if event.window != self.get_bin_window(): return False if col.header_name == "~rating": if not config.getboolean("browsers", "rating_click"): return song = view.get_model()[path][0] l = Gtk.Label() l.show() l.set_text(config.RATINGS.full_symbol) width = l.get_preferred_size()[1].width l.destroy() if not width: return False precision = config.RATINGS.precision count = int(float(cellx - 5) / width) + 1 rating = max(0.0, min(1.0, count * precision)) if rating <= precision and song("~#rating") == precision: rating = 0.0 self.__set_rating(rating, [song], librarian)
def __about_to_finish_sync(self): """Returns a tuple (ok, next_song). ok is True if the next song should be set. """ print_d("About to finish (sync)") # Chained oggs falsely trigger a gapless transition. # At least for radio streams we can safely ignore it because # transitions don't occur there. # https://github.com/quodlibet/quodlibet/issues/1454 # https://bugzilla.gnome.org/show_bug.cgi?id=695474 if self.song.multisong: print_d("multisong: ignore about to finish") return (False, None) if config.getboolean("player", "gst_disable_gapless"): print_d("Gapless disabled") return (False, None) # this can trigger twice, see issue 987 if self._in_gapless_transition: return (False, None) self._in_gapless_transition = True print_d("Select next song in mainloop..") self._source.next_ended() print_d("..done.") return (True, self._source.current)
def refresh_panes(self): self.multi_paned.destroy() # Fill in the pane list. The last pane reports back to us. self._panes = [self] for header in reversed(get_headers()): pane = Pane(self._library, header, self._panes[0]) pane.connect('row-activated', lambda *x: self.songs_activated()) self._panes.insert(0, pane) self._panes.pop() # remove self # Put the panes in scrollable windows sws = [] for pane in self._panes: sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(pane) sws.append(sw) self.multi_paned.set_widgets(sws) self.multi_paned.show_all() self.main_box.pack1(self.multi_paned.get_paned(), True, False) self.__star = {} for p in self._panes: tags = [t for t in p.tags if not t.startswith("~#")] self.__star.update(dict.fromkeys(tags)) self.set_wide_mode(config.getboolean("browsers", "pane_wide_mode"))
def iter_backends(): if config.getboolean("settings", "disable_mmkeys"): return try: from .gnome import GnomeBackend, GnomeBackendOldName, MateBackend except MMKeysImportError: pass else: yield GnomeBackend yield GnomeBackendOldName yield MateBackend try: from .keybinder import KeybinderBackend except MMKeysImportError: pass else: yield KeybinderBackend try: from .winhook import WinHookBackend except MMKeysImportError: pass else: yield WinHookBackend try: from .osx import OSXBackend except MMKeysImportError: pass else: yield OSXBackend
def plugin_songs(self, songs): value = -1 while not 0 <= value <= 1: input_string = GetStringDialog( self.plugin_window, self.PLUGIN_NAME, _("Please give your desired rating on a scale " "from 0.0 to 1.0"), _("_Apply"), Icons.NONE).run() if input_string is None: return try: value = float(input_string) except ValueError: continue count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): confirm_dialog = ConfirmRateMultipleDialog(self.plugin_window, _("Change _Rating"), count, value) if confirm_dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value
def __about_to_finish_sync(self): """Returns the next song uri to play or None""" print_d("About to finish (sync)") # Chained oggs falsely trigger a gapless transition. # At least for radio streams we can safely ignore it because # transitions don't occur there. # https://github.com/quodlibet/quodlibet/issues/1454 # https://bugzilla.gnome.org/show_bug.cgi?id=695474 if self.song.multisong: print_d("multisong: ignore about to finish") return # mod + gapless deadlocks # https://github.com/quodlibet/quodlibet/issues/2780 if isinstance(self.song, ModFile): return if config.getboolean("player", "gst_disable_gapless"): print_d("Gapless disabled") return # this can trigger twice, see issue 987 if self._in_gapless_transition: return self._in_gapless_transition = True print_d("Select next song in mainloop..") self._source.next_ended() print_d("..done.") song = self._source.current if song is not None: return song("~uri")
def refresh_panes(self): hbox = self.main_box.get_child1() if hbox: hbox.destroy() hbox = Gtk.HBox(spacing=6) hbox.set_homogeneous(True) # Fill in the pane list. The last pane reports back to us. self._panes = [self] for header in reversed(get_headers()): pane = Pane(self._library, header, self._panes[0]) self._panes.insert(0, pane) self._panes.pop() # remove self for pane in self._panes: pane.connect('row-activated', lambda *x: self.songs_activated()) sw = ScrolledWindow() sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(pane) hbox.pack_start(sw, True, True, 0) self.main_box.pack1(hbox, True, False) hbox.show_all() self.__star = {} for p in self._panes: tags = [t for t in p.tags if not t.startswith("~#")] self.__star.update(dict.fromkeys(tags)) self.set_wide_mode(config.getboolean("browsers", "pane_wide_mode"))
def __init__(self): try: self.accounts = config.get('plugins', self.c_accounts).split() except: self.accounts = [] config.set('plugins', self.c_accounts, '') try: self.paused = config.getboolean('plugins', self.c_paused) except: self.paused = True config.set('plugins', self.c_paused, 'True') try: self.statuses = config.get('plugins', self.c_statuses).split() except: self.statuses = ['online', 'chat'] config.set('plugins', self.c_statuses, join(self.statuses)) try: self.pattern = config.get('plugins', self.c_pattern) except: self.pattern = '<artist> - <title>' config.set('plugins', self.c_pattern, self.pattern) quodlibet.quit_add(0, self.quit) self.interface = None self.current = ''
def do_draw(self, cairo_context): pixbuf = self._get_pixbuf() if not pixbuf: return alloc = self.get_allocation() width, height = alloc.width, alloc.height scale_factor = get_scale_factor(self) width *= scale_factor height *= scale_factor if self._path: if width < 2 or height < 2: return round_thumbs = config.getboolean("albumart", "round") pixbuf = scale( pixbuf, (width - 2 * scale_factor, height - 2 * scale_factor)) pixbuf = add_border_widget(pixbuf, self, None, round_thumbs) else: pixbuf = scale(pixbuf, (width, height)) style_context = self.get_style_context() pbosf = get_pbosf_for_pixbuf(self, pixbuf) pbosf_render(style_context, cairo_context, pbosf, 0, 0)
def iter_backends(): try: from .gnome import GnomeBackend, MateBackend except MMKeysImportError: pass else: yield GnomeBackend yield MateBackend try: from .keybinder import KeybinderBackend except MMKeysImportError: pass else: yield KeybinderBackend try: from .pyhook import PyHookBackend except MMKeysImportError: pass else: yield PyHookBackend if config.getboolean("settings", "osx_mmkeys"): try: from .osx import OSXBackend except MMKeysImportError: pass else: yield OSXBackend
def __init__(self, library): super(SearchBar, self).__init__() self.set_spacing(6) self.set_orientation(Gtk.Orientation.VERTICAL) self._query = None self._library = library completion = LibraryTagCompletion(library.librarian) self.accelerators = Gtk.AccelGroup() show_limit = config.getboolean("browsers", "search_limit") sbb = LimitSearchBarBox(completion=completion, accel_group=self.accelerators, show_limit=show_limit) sbb.connect('query-changed', self.__text_parse) sbb.connect('focus-out', self.__focus) self._sb_box = sbb prefs = PreferencesButton(sbb) sbb.pack_start(prefs, False, True, 0) align = Align(sbb, left=6, right=6, top=6) self.pack_start(align, False, True, 0) self.connect('destroy', self.__destroy) self.show_all()
def __key_press(self, songlist, event, librarian): rating_accels = [ "<Primary>%d" % i for i in range( min(10, config.RATINGS.number + 1))] if (qltk.is_accel(event, *rating_accels) and config.getboolean("browsers", "rating_hotkeys")): rating = int(chr(event.keyval)) * config.RATINGS.precision self.__set_rating(rating, self.get_selected_songs(), librarian) return True elif qltk.is_accel(event, "<Primary>Return", "<Primary>KP_Enter"): self.__enqueue(self.get_selected_songs()) return True elif qltk.is_accel(event, "<Primary>F"): self.emit('start-interactive-search') return True elif qltk.is_accel(event, "<Primary>Delete"): songs = self.get_selected_songs() if songs: trash_songs(self, songs, librarian) return True elif qltk.is_accel(event, "<alt>Return"): songs = self.get_selected_songs() if songs: window = SongProperties(librarian, songs, parent=self) window.show() return True elif qltk.is_accel(event, "<Primary>I"): songs = self.get_selected_songs() if songs: window = Information(librarian, songs, self) window.show() return True return False
def next(self): """Switch to the next song""" keep_songs = config.getboolean("memory", "queue_keep_songs", False) q_disable = config.getboolean("memory", "queue_disable", False) if (self.q.is_empty() or q_disable or (keep_songs and not self.q.sourced)): self.pl.next() if q_disable and self.q.sourced: # The go_to is to make sure the playlist begins playing # when the queue is disabled while being sourced self.go_to(self.pl.current) else: self.q.next() self._check_sourced()
def __clear_queue(self, activator): self.model.clear() stop_queue = config.getboolean("memory", "queue_stop_once_empty", False) if stop_queue: app.player_options.stop_after = True
def __update_image(self): height = self.__size if not height: return if self.__resize: height = min(self.__max_size, height) width = self.__max_size else: width = height if self.__path is None: pixbuf = self.__get_no_cover(width, height) else: try: round_thumbs = config.getboolean("albumart", "round") pixbuf = thumbnails.get_thumbnail(self.__path, (width, height)) pixbuf = thumbnails.add_border(pixbuf, 80, round_thumbs) except gobject.GError: pixbuf = self.__get_no_cover(width, height) self.set_from_pixbuf(pixbuf) if self.__resize: self.__ignore = True self.__sig = self.connect_after("size-allocate", self.__stop_ignore)
def __button_press(self, view, event, librarian): if event.button != Gdk.BUTTON_PRIMARY: return x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: return True if event.window != self.get_bin_window(): return False if col.header_name == "~rating": if not config.getboolean("browsers", "rating_click"): return song = view.get_model()[path][0] l = Gtk.Label() l.show() l.set_text(config.RATINGS.full_symbol) width = l.get_preferred_size()[1].width l.destroy() if not width: return False precision = config.RATINGS.precision count = int(float(cellx - 5) / width) + 1 rating = max(0.0, min(1.0, count * precision)) if (rating <= precision and song("~#rating") == precision): rating = 0.0 self.__set_rating(rating, [song], librarian)
def iter_backends(): if config.getboolean("settings", "disable_mmkeys"): return try: from .gnome import GnomeBackend, MateBackend except MMKeysImportError: pass else: yield GnomeBackend yield MateBackend try: from .keybinder import KeybinderBackend except MMKeysImportError: pass else: yield KeybinderBackend try: from .winhook import WinHookBackend except MMKeysImportError: pass else: yield WinHookBackend try: from .osx import OSXBackend except MMKeysImportError: pass else: yield OSXBackend
def bind_config(self, section, option): self.set_active(config.getboolean(section, option)) def toggled_cb(*args): config.set(section, option, self.get_active()) self.connect('toggled', toggled_cb)
def plugin_songs(self, songs): value = -1 while not 0 <= value <= 1: input_string = GetStringDialog( self.plugin_window, self.PLUGIN_NAME, _("Please give your desired rating on a scale " "from 0.0 to 1.0"), _("_Apply"), Icons.NONE ).run() if input_string is None: return try: value = float(input_string) except ValueError: continue count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): confirm_dialog = ConfirmRateMultipleDialog( self.plugin_window, count, value) if confirm_dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value
def __init__(self): super(FilterCheckButton, self).__init__(self._label, self._section, self._key) try: self.set_active(config.getboolean(self._section, self._key)) except: pass connect_obj(self, "toggled", self.emit, "preview")
def __init__(self, parent, library): super(TagsFromPath, self).__init__(spacing=6) self.set_border_width(12) hbox = Gtk.HBox(spacing=6) cbes_defaults = TBP_EXAMPLES.split("\n") self.combo = ComboBoxEntrySave(TBP, cbes_defaults, title=_("Path Patterns"), edit_title=_(u"Edit saved patterns…")) self.combo.show_all() hbox.pack_start(self.combo, True, True, 0) self.preview = qltk.Button(_("_Preview"), Icons.VIEW_REFRESH) self.preview.show() hbox.pack_start(self.preview, False, True, 0) self.pack_start(hbox, False, True, 0) self.combo.get_child().connect('changed', self._changed) model = ObjectStore() self.view = Gtk.TreeView(model=model) self.view.show() sw = Gtk.ScrolledWindow() sw.set_shadow_type(Gtk.ShadowType.IN) sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) sw.add(self.view) self.pack_start(sw, True, True, 0) vbox = Gtk.VBox() addreplace = Gtk.ComboBoxText() addreplace.append_text(_("Tags replace existing ones")) addreplace.append_text(_("Tags are added to existing ones")) addreplace.set_active(config.getboolean("tagsfrompath", "add")) addreplace.connect('changed', self.__add_changed) vbox.pack_start(addreplace, True, True, 0) addreplace.show() self.pack_start(vbox, False, True, 0) filter_box = FilterPluginBox(self.handler, self.FILTERS) filter_box.connect("preview", self.__filter_preview) filter_box.connect("changed", self.__filter_changed) self.filter_box = filter_box self.pack_start(filter_box, False, True, 0) # Save button self.save = qltk.Button(_("Save"), Icons.DOCUMENT_SAVE) self.save.show() bbox = Gtk.HButtonBox() bbox.set_layout(Gtk.ButtonBoxStyle.END) bbox.pack_start(self.save, True, True, 0) self.pack_start(bbox, False, True, 0) connect_obj(self.preview, 'clicked', self.__preview, None) connect_obj(parent, 'changed', self.__class__.__preview, self) # Save changes connect_obj(self.save, 'clicked', self.__save, addreplace, library) for child in self.get_children(): child.show()
def __init__(self, label, section, option, populate=False, tooltip=None): super(ConfigCheckButton, self).__init__(label=label, use_underline=True) if populate: self.set_active(config.getboolean(section, option)) if tooltip: self.set_tooltip_text(tooltip) self.connect('toggled', ConfigCheckButton.__toggled, section, option)
def __init__(self): super(FilterCheckButton, self).__init__(self._label, self._section, self._key) try: self.set_active(config.getboolean(self._section, self._key)) except: pass connect_obj(self, 'toggled', self.emit, 'preview')
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 __window_map(self, win, *args): visible = config.getboolean("plugins", "icon_window_visible", False) config.set("plugins", "icon_window_visible", "true") # Only restore window state on start if not visible and self.__first_map: self.__hide_window()
def __init__(self, activator): super(Preferences, self).__init__(spacing=12) self.set_border_width(6) combo = Gtk.ComboBoxText() combo.append_text(_("Scroll wheel adjusts volume\n" "Shift and scroll wheel changes song")) combo.append_text(_("Scroll wheel changes song\n" "Shift and scroll wheel adjusts volume")) combo.set_active(int( config.getboolean("plugins", "icon_modifier_swap", False))) combo.connect('changed', self.__changed_combo) self.pack_start(qltk.Frame(_("Scroll _Wheel"), child=combo), True, True, 0) box = Gtk.VBox(spacing=12) table = Gtk.Table(2, 4) table.set_row_spacings(6) table.set_col_spacings(12) cbs = [] for i, tag in enumerate([ "genre", "artist", "album", "discnumber", "part", "tracknumber", "title", "version"]): cb = Gtk.CheckButton(util.tag(tag)) cb.tag = tag cbs.append(cb) table.attach(cb, i % 3, i % 3 + 1, i // 3, i // 3 + 1) box.pack_start(table, True, True, 0) entry = Gtk.Entry() box.pack_start(entry, False, True, 0) preview = Gtk.Label() preview.set_ellipsize(Pango.EllipsizeMode.END) ev = Gtk.EventBox() ev.add(preview) box.pack_start(ev, False, True, 0) frame = qltk.Frame(_("Tooltip Display"), child=box) frame.get_label_widget().set_mnemonic_widget(entry) self.pack_start(frame, True, True, 0) for cb in cbs: cb.connect('toggled', self.__changed_cb, cbs, entry) entry.connect( 'changed', self.__changed_entry, cbs, preview) try: entry.set_text(config.get("plugins", "icon_tooltip")) except: entry.set_text( "<album|<album~discnumber~part~tracknumber~title~version>|" "<artist~title~version>>") for child in self.get_children(): child.show_all()
def PluginPreferences(self): box = Gtk.HBox() ccb = ConfigCheckButton( _("Automatically start playing " "double-clicked songs"), 'plugins', 'queue_only_autoplay') autoplay = config.getboolean('plugins', 'queue_only_autoplay', False) ccb.set_active(autoplay) box.pack_start(qltk.Frame(_("Preferences"), child=ccb), True, True, 0) return box
def __set_rating(self, value, songs, librarian): count = len(songs) if count > 1 and config.getboolean("browsers", "rating_confirm_multiple"): dialog = ConfirmRateMultipleDialog(self, count, value) if dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value librarian.changed(songs)
def use_trash(): """If the current platform supports moving files into a trash can.""" # TODO: Use the glib API for trashing which supports trashing there if is_flatpak(): return False return (os.name == "posix" and sys.platform != "darwin" and not config.getboolean("settings", "bypass_trash"))
def __init__(self, label, section, option, populate=False, tooltip=None, default=True): super(ConfigCheckButton, self).__init__(label=label, use_underline=True) if populate: self.set_active(config.getboolean(section, option, default)) if tooltip: self.set_tooltip_text(tooltip) self.connect('toggled', ConfigCheckButton.__toggled, section, option)
def test_get(self): config.set("foo", "int", "1") config.set("foo", "float", "1.25") config.set("foo", "str", "foobar") config.set("foo", "bool", "True") self.failUnlessEqual(config.getint("foo", "int"), 1) self.failUnlessEqual(config.getfloat("foo", "float"), 1.25) self.failUnlessEqual(config.get("foo", "str"), "foobar") self.failUnlessEqual(config.getboolean("foo", "bool"), True)
def create_repeat(orders): repeat = ToggledPlayOrderMenu( Icons.MEDIA_PLAYLIST_REPEAT, orders=orders, current_order=self.__get_repeat_class(), enabled=config.getboolean("memory", "repeat", False), tooltip=_("Toggle repeat mode")) repeat.connect('changed', self.__repeat_updated) repeat.connect('toggled', self.__repeat_toggled) return repeat
def PluginPreferences(self, parent): prefer_lbl = _("Store cover into the directory of song") prefer_key = 'prefer_song_dir' grid = Gtk.Grid.new() prefer_cb = ConfigCheckButton(prefer_lbl, 'albumart', prefer_key) prefer_cb.set_active(config.getboolean('albumart', prefer_key, False)) grid.attach(prefer_cb, 0, 0, 1, 1) return grid
def __set_rating(self, value, songs, librarian): count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): dialog = ConfirmRateMultipleDialog(self, count, value) if dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value librarian.changed(songs)
def enabled(self): if not config.getboolean("editing", "save_to_songs"): config.set("editing", "save_to_songs", True) warning_text = _("The following setting was enabled as it's " "required for this plugin to work:\n\n%s") setting_name = _("Save ratings and play _counts in tags") Message(Gtk.MessageType.INFO, app.window, _("Settings updated"), warning_text % setting_name.replace("_", "")).run()
def create_shuffle(orders): shuffle = ToggledPlayOrderMenu( Icons.MEDIA_PLAYLIST_SHUFFLE, orders=orders, current_order=self.__get_shuffle_class(), enabled=(config.getboolean("memory", "shuffle", False)), tooltip=_("Toggle shuffle mode")) shuffle.connect('changed', self.__shuffle_updated) shuffle.connect('toggled', self.__shuffle_toggled) return shuffle
def __init__(self): super().__init__(self._label, self._section, self._key, tooltip=self._tooltip) try: self.set_active(config.getboolean(self._section, self._key)) except: pass connect_obj(self, 'toggled', self.emit, 'preview')
def set_rating(self, value, songs, librarian): count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): dialog = ConfirmRateMultipleDialog(self, count, value) if dialog.run() != gtk.RESPONSE_YES: return for song in songs: song["~#rating"] = value librarian.changed([song])
def __keep_songs_activated(self, activator): keep_song = config.getboolean("memory", "queue_keep_songs", False) if keep_song: self.queue.set_first_column_type(CurrentColumn) else: for col in self.queue.get_columns(): # Remove the CurrentColum if it exists if isinstance(col, CurrentColumn): self.queue.set_first_column_type(None) break
def __update_queue_stop(self, player, song, stopped, model): enabled = config.getboolean("memory", "queue_stop_at_end", False) songs_left = len(model.get()) queue_empty = songs_left == 0 and song is self._last_queue_song queue_finished = (self._curr_song_index and self._curr_song_index + 1 >= songs_left) if (enabled and not stopped and (queue_empty or queue_finished)): app.player.stop() else: self.queue_finished = False
def boolean_config(section, option, label, tooltip): def on_reverted(*args): config.reset(section, option) button.set_active(config.getboolean(section, option)) def __toggled(self, section, option): config.set(section, option, str(bool(self.get_active())).lower()) default = config.getboolean(section, option) button = Gtk.CheckButton() button.set_active(config.getboolean(section, option, default)) button.set_tooltip_text(tooltip) button.connect('toggled', __toggled, section, option) revert = Gtk.Button() revert.add(Gtk.Image.new_from_icon_name(Icons.DOCUMENT_REVERT, Gtk.IconSize.BUTTON)) revert.connect("clicked", on_reverted) lbl = Gtk.Label(label=label, use_underline=True) lbl.set_mnemonic_widget(button) return lbl, button, revert
def __jump_to_current(self, explicit, songlist=None, force_scroll=False): """Select/scroll to the current playing song in the playlist. If it can't be found tell the browser to properly fill the playlist with an appropriate selection containing the song. explicit means that the jump request comes from the user and not from an event like song-started. songlist is the songlist to be jumped within. Usually the main song list or the queue. If None, the currently sourced songlist will be used. force_scroll will ask the browser to refill the playlist in any case. """ def idle_jump_to(song, select): ok = songlist.jump_to_song(song, select=select) if ok: songlist.grab_focus() return False if not songlist: if (config.getboolean("memory", "queue_keep_songs") and self.qexpander.queue.sourced): songlist = self.qexpander.queue else: songlist = self.songlist if app.player is None: return song = app.player.song # We are not playing a song if song is None: return if not force_scroll: ok = songlist.jump_to_song(song, select=explicit) else: assert explicit ok = False if ok: songlist.grab_focus() elif explicit: # if we can't find it and the user requested it, try harder self.browser.scroll(song) # We need to wait until the browser has finished # scrolling/filling and the songlist is ready. # Not perfect, but works for now. GLib.idle_add(idle_jump_to, song, explicit, priority=GLib.PRIORITY_LOW)
def set_tag(self, tag, library): if not config.getboolean("settings", "eager_search"): return elif tag is None: return elif tag in ("bpm date discnumber isrc originaldate recordingdate " "tracknumber title").split() + MACHINE_TAGS: return elif tag in formats.PEOPLE: tag = "~people" copool.add(self.__fill_tag, tag, library)
def _update(self, songs=None): if songs is None: songs = self.__songinfo.songs else: self.__songinfo = AudioFileGroup(songs) songinfo = self.__songinfo keys = list(songinfo.keys()) default_tags = get_default_tags() keys = set(keys + default_tags) def custom_sort(key): try: prio = default_tags.index(key) except ValueError: prio = len(default_tags) return (prio, tagsortkey(key)) if not config.getboolean("editing", "alltags"): keys = filter(lambda k: k not in MACHINE_TAGS, keys) if not songs: keys = [] with self._view.without_model() as model: model.clear() for tag in sorted(keys, key=custom_sort): canedit = songinfo.can_change(tag) # default tags if tag not in songinfo: entry = ListEntry(tag, Comment(u"")) entry.canedit = canedit model.append(row=[entry]) continue for value in songinfo[tag]: entry = ListEntry(tag, value) entry.origvalue = value entry.edited = False entry.canedit = canedit entry.deleted = False entry.renamed = False entry.origtag = "" model.append(row=[entry]) self._buttonbox.set_sensitive(bool(songinfo.can_change())) self._revert.set_sensitive(False) self._remove.set_sensitive(False) self._save.set_sensitive(False) self._add.set_sensitive(bool(songs)) self._parent.set_pending(None)
def set_rating(self, value, songs, librarian): count = len(songs) if (count > 1 and config.getboolean("browsers", "rating_confirm_multiple")): parent = qltk.get_menu_item_top_parent(self) dialog = ConfirmRateMultipleDialog(parent, _("Change _Rating"), count, value) if dialog.run() != Gtk.ResponseType.YES: return for song in songs: song["~#rating"] = value librarian.changed(songs)
def __song_started(self, player, song): self.__update_title(player) for wid in ["Jump", "Next", "EditTags", "Information", "EditBookmarks", "AddBookmark", "StopAfter"]: self.ui.get_widget( '/Menu/Control/' + wid).set_sensitive(bool(song)) # don't jump on stream changes (player.info != player.song) if song and player.song is song and not self.songlist._activated and \ config.getboolean("settings", "jump") and self.songlist.sourced: self.__jump_to_current(False)
def __text_changed(self, *args): # the combobox has an active entry selected -> no timeout # todo: we need a timeout when the selection changed because # of keyboard input (up/down arrows) if self.__combo.get_active() != -1: self.__filter_changed() return if not config.getboolean('settings', 'eager_search'): return self.__deferred_changed()