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)
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, albums, parent, process_mode): super().__init__(title=_('ReplayGain Analyzer'), parent=parent) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_icon_button(_("_Save"), Icons.DOCUMENT_SAVE, Gtk.ResponseType.OK) self.process_mode = process_mode self.set_default_size(600, 400) self.set_border_width(6) hbox = Gtk.HBox(spacing=6) info = Gtk.Label() hbox.pack_start(info, True, True, 0) self.vbox.pack_start(hbox, False, False, 6) swin = Gtk.ScrolledWindow() swin.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) swin.set_shadow_type(Gtk.ShadowType.IN) self.vbox.pack_start(swin, True, True, 0) view = HintedTreeView() swin.add(view) def icon_cdf(column, cell, model, iter_, *args): item = model[iter_][0] if item.error: cell.set_property('icon-name', Icons.DIALOG_ERROR) else: cell.set_property('icon-name', Icons.NONE) column = Gtk.TreeViewColumn() column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) icon_render = Gtk.CellRendererPixbuf() column.pack_start(icon_render, True) column.set_cell_data_func(icon_render, icon_cdf) view.append_column(column) def track_cdf(column, cell, model, iter_, *args): item = model[iter_][0] cell.set_property('text', item.title) cell.set_sensitive(model[iter_][1]) # Translators: Combined track number/title column heading column = Gtk.TreeViewColumn(C_("track/title", "Track")) column.set_expand(True) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) track_render = Gtk.CellRendererText() track_render.set_property('ellipsize', Pango.EllipsizeMode.END) column.pack_start(track_render, True) column.set_cell_data_func(track_render, track_cdf) view.append_column(column) def progress_cdf(column, cell, model, iter_, *args): item = model[iter_][0] cell.set_property('value', int(item.progress * 100)) cell.set_sensitive(model[iter_][1]) column = Gtk.TreeViewColumn(_("Progress")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) progress_render = Gtk.CellRendererProgress() column.pack_start(progress_render, True) column.set_cell_data_func(progress_render, progress_cdf) view.append_column(column) def gain_cdf(column, cell, model, iter_, *args): item = model[iter_][0] if item.gain is None or not item.done: cell.set_property('text', "-") else: cell.set_property('text', "%.2f db" % item.gain) cell.set_sensitive(model[iter_][1]) column = Gtk.TreeViewColumn(_("Gain")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) gain_renderer = Gtk.CellRendererText() column.pack_start(gain_renderer, True) column.set_cell_data_func(gain_renderer, gain_cdf) view.append_column(column) def peak_cdf(column, cell, model, iter_, *args): item = model[iter_][0] if item.gain is None or not item.done: cell.set_property('text', "-") else: cell.set_property('text', "%.2f" % item.peak) cell.set_sensitive(model[iter_][1]) column = Gtk.TreeViewColumn(_("Peak")) column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) peak_renderer = Gtk.CellRendererText() column.pack_start(peak_renderer, True) column.set_cell_data_func(peak_renderer, peak_cdf) view.append_column(column) self.create_pipelines() self._timeout = None self._sigs = {} self._done = [] self.__fill_view(view, albums) num_to_process = sum(int(rga.should_process) for rga in self._todo) template = ngettext( "There is <b>%(to-process)s</b> album to update (of %(all)s)", "There are <b>%(to-process)s</b> albums to update (of %(all)s)", num_to_process) info.set_markup( template % { "to-process": format_int_locale(num_to_process), "all": format_int_locale(len(self._todo)), }) self.connect("destroy", self.__destroy) self.connect('response', self.__response)
def process_arguments(argv): from quodlibet.util.path import uri_is_valid from quodlibet import util from quodlibet import const actions = [] controls = [ "next", "previous", "play", "pause", "play-pause", "stop", "hide-window", "show-window", "toggle-window", "focus", "quit", "unfilter", "refresh", "force-previous" ] controls_opt = [ "seek", "repeat", "query", "volume", "filter", "set-rating", "set-browser", "open-browser", "shuffle", "song-list", "queue", "stop-after", "random", "repeat-type", "shuffle-type" ] options = util.OptionParser("Quod Libet", const.VERSION, _("a music library and player"), _("[option]")) options.add("print-playing", help=_("Print the playing song and exit")) options.add("start-playing", help=_("Begin playing immediately")) options.add("start-hidden", help=_("Don't show any windows on start")) for opt, help in [ ("next", _("Jump to next song")), ("previous", _("Jump to previous song or restart if near the beginning")), ("force-previous", _("Jump to previous song")), ("play", _("Start playback")), ("pause", _("Pause playback")), ("play-pause", _("Toggle play/pause mode")), ("stop", _("Stop playback")), ("volume-up", _("Turn up volume")), ("volume-down", _("Turn down volume")), ("status", _("Print player status")), ("hide-window", _("Hide main window")), ("show-window", _("Show main window")), ("toggle-window", _("Toggle main window visibility")), ("focus", _("Focus the running player")), ("unfilter", _("Remove active browser filters")), ("refresh", _("Refresh and rescan library")), ("list-browsers", _("List available browsers")), ("print-playlist", _("Print the current playlist")), ("print-queue", _("Print the contents of the queue")), ("print-query-text", _("Print the active text query")), ("no-plugins", _("Start without plugins")), ("run", _("Start Quod Libet if it isn't running")), ("quit", _("Exit Quod Libet")), ]: options.add(opt, help=help) for opt, help, arg in [ ("seek", _("Seek within the playing song"), _("[+|-][HH:]MM:SS")), ("shuffle", _("Set or toggle shuffle mode"), "0|1|t"), ("shuffle-type", _("Set shuffle mode type"), "random|weighted|off"), ("repeat", _("Turn repeat off, on, or toggle it"), "0|1|t"), ("repeat-type", _("Set repeat mode type"), "current|all|one|off"), ("volume", _("Set the volume"), "(+|-|)0..100"), ("query", _("Search your audio library"), _("query")), ("play-file", _("Play a file"), C_("command", "filename")), ("set-rating", _("Rate the playing song"), "0.0..1.0"), ("set-browser", _("Set the current browser"), "BrowserName"), ("stop-after", _("Stop after the playing song"), "0|1|t"), ("open-browser", _("Open a new browser"), "BrowserName"), ("queue", _("Show or hide the queue"), "on|off|t"), ("song-list", _("Show or hide the main song list (deprecated)"), "on|off|t"), ("random", _("Filter on a random value"), C_("command", "tag")), ("filter", _("Filter on a tag value"), _("tag=value")), ("enqueue", _("Enqueue a file or query"), "%s|%s" % (C_("command", "filename"), _("query"))), ("enqueue-files", _("Enqueue comma-separated files"), "%s[,%s..]" % (_("filename"), _("filename"))), ("print-query", _("Print filenames of results of query to stdout"), _("query")), ("unqueue", _("Unqueue a file or query"), "%s|%s" % (C_("command", "filename"), _("query"))), ]: options.add(opt, help=help, arg=arg) options.add("sm-config-prefix", arg="dummy") options.add("sm-client-id", arg="prefix") options.add("screen", arg="dummy") def is_vol(str): if len(str) == 1 and str[0] in '+-': return True return is_float(str) def is_time(str): if str[0] not in "+-0123456789": return False elif str[0] in "+-": str = str[1:] parts = str.split(":") if len(parts) > 3: return False else: return not (False in [p.isdigit() for p in parts]) def is_float(str): try: float(str) except ValueError: return False else: return True validators = { "shuffle": ["0", "1", "t", "on", "off", "toggle"].__contains__, "shuffle-type": ["random", "weighted", "off", "0"].__contains__, "repeat": ["0", "1", "t", "on", "off", "toggle"].__contains__, "repeat-type": ["current", "all", "one", "off", "0"].__contains__, "volume": is_vol, "seek": is_time, "set-rating": is_float, "stop-after": ["0", "1", "t"].__contains__, } cmds_todo = [] def queue(*args): cmds_todo.append(args) # XXX: to make startup work in case the desktop file isn't passed # a file path/uri if argv[-1] == "--play-file": argv = argv[:-1] opts, args = options.parse(argv[1:]) for command, arg in opts.items(): if command in controls: queue(command) elif command in controls_opt: if command in validators and not validators[command](arg): print_e(_("Invalid argument for '%s'.") % command) print_e(_("Try %s --help.") % fsn2text(argv[0])) exit_(True, notify_startup=True) else: queue(command, arg) elif command == "status": queue("status") elif command == "print-playlist": queue("dump-playlist") elif command == "print-queue": queue("dump-queue") elif command == "list-browsers": queue("dump-browsers") elif command == "volume-up": queue("volume +") elif command == "volume-down": queue("volume -") elif command == "enqueue" or command == "unqueue": try: filename = uri2fsn(arg) except ValueError: filename = arg queue(command, filename) elif command == "enqueue-files": queue(command, arg) elif command == "play-file": if uri_is_valid(arg) and arg.startswith("quodlibet://"): # TODO: allow handling of URIs without --play-file queue("uri-received", arg) else: try: filename = uri2fsn(arg) except ValueError: filename = arg filename = os.path.abspath(util.path.expanduser(arg)) queue("play-file", filename) elif command == "print-playing": try: queue("print-playing", args[0]) except IndexError: queue("print-playing") elif command == "print-query": queue(command, arg) elif command == "print-query-text": queue(command) elif command == "start-playing": actions.append(command) elif command == "start-hidden": actions.append(command) elif command == "no-plugins": actions.append(command) elif command == "run": actions.append(command) if cmds_todo: for cmd in cmds_todo: control(*cmd, **{"ignore_error": "run" in actions}) else: # this will exit if it succeeds control('focus', ignore_error=True) return actions, cmds_todo