コード例 #1
0
ファイル: information.py プロジェクト: elfalem/quodlibet
    def _album(self, song, box):
        if "album" not in song:
            return
        text = ["<span size='x-large'><i>%s</i></span>"
                % util.escape(song.comma("album"))]
        secondary = []
        if "discnumber" in song:
            secondary.append(_("Disc %s") % song["discnumber"])
        if "discsubtitle" in song:
            secondary.append("<i>%s</i>" %
                             util.escape(song.comma("discsubtitle")))
        if "tracknumber" in song:
            secondary.append(_("Track %s") % song["tracknumber"])
        if secondary:
            text.append(" - ".join(secondary))

        if "date" in song:
            text.append(util.escape(song.comma("date")))

        if "organization" in song or "labelid" in song:
            t = util.escape(song.comma("~organization~labelid"))
            text.append(t)

        if "producer" in song:
            text.append(_("Produced by %s") % (
                util.escape(song.comma("producer"))))

        w = Label(markup="\n".join(text), ellipsize=True)
        hb = Gtk.HBox(spacing=12)

        hb.pack_start(w, True, True, 0)
        box.pack_start(Frame(tag("album"), hb), False, False, 0)

        cover = ReactiveCoverImage(song=song)
        hb.pack_start(cover, False, True, 0)
コード例 #2
0
ファイル: information.py プロジェクト: LudoBike/quodlibet
 def _title(self, songs, box):
     song = songs[0]
     self.title = text = song["album"]
     markup = "<i>%s</i>" % util.escape(text)
     if "date" in song:
         markup += " <small>(%s)</small>" % util.escape(song("~year"))
     box.pack_start(TitleLabel(markup, is_markup=True), False, False, 0)
コード例 #3
0
ファイル: tracknumbers.py プロジェクト: silkecho/glowing-silk
 def __save_files(self, parent, model, library):
     win = WritingWindow(parent, len(model))
     was_changed = []
     for row in model:
         song = row[0]
         track = row[2]
         if song.get("tracknumber") == track:
             win.step()
             continue
         if not song.valid() and not qltk.ConfirmAction(
             win, _("Tag may not be accurate"),
             _("<b>%s</b> changed while the program was running. "
               "Saving without refreshing your library may "
               "overwrite other changes to the song.\n\n"
               "Save this song anyway?") %(
             util.escape(util.fsdecode(song("~basename"))))
             ).run():
             break
         song["tracknumber"] = track
         try: song.write()
         except:
             util.print_exc()
             qltk.ErrorMessage(
                 win, _("Unable to save song"),
                 _("Saving <b>%s</b> failed. The file may be "
                   "read-only, corrupted, or you do not have "
                   "permission to edit it.")%(
                 util.escape(util.fsdecode(song('~basename'))))).run()
             library.reload(song, changed=was_changed)
             break
         was_changed.append(song)
         if win.step(): break
     library.changed(was_changed)
     win.destroy()
コード例 #4
0
ファイル: information.py プロジェクト: elfalem/quodlibet
 def _description(self, songs, box):
     text = []
     cur_disc = songs[0]("~#disc", 1) - 1
     cur_part = None
     cur_track = songs[0]("~#track", 1) - 1
     for song in songs:
         track = song("~#track", 0)
         disc = song("~#disc", 0)
         part = song.get("part")
         if disc != cur_disc:
             if cur_disc:
                 text.append("")
             cur_track = song("~#track", 1) - 1
             cur_part = None
             cur_disc = disc
             if disc:
                 text.append("%s" % (_("Disc %s") % disc))
         if part != cur_part:
             ts = "    " * bool(disc)
             cur_part = part
             if part:
                 text.append("%s%s" % (ts, util.escape(part)))
         cur_track += 1
         ts = "    " * (bool(disc) + bool(part))
         while cur_track < track:
             text.append("{ts}{cur: >2}. {text}".format(
                 ts=ts, cur=cur_track, text=_("Track unavailable")))
             cur_track += 1
         markup = util.escape(song.comma("~title~version"))
         text.append("{ts}{cur: >2}. <i>{text}</i>".format(
                 ts=ts, cur=track, text=markup))
     l = Label(markup="\n".join(text), ellipsize=True)
     box.pack_start(Frame(_("Track List"), l), False, False, 0)
コード例 #5
0
ファイル: information.py プロジェクト: elfalem/quodlibet
    def _additional(self, song, box):
        if "website" not in song and "comment" not in song:
            return
        data = []

        if "comment" in song:
            comments = song.list("comment")
            markups = ["<i>%s</i>" % c for c in comments]
            data.append(("comment", markups))

        if "website" in song:
            markups = ["<a href=\"%(url)s\">%(text)s</a>" %
                       {"text": util.escape(website),
                        "url": util.escape(website)}
                       for website in song.list("website")]
            data.append(("website", markups))

        table = Table(1)
        for i, (key, markups) in enumerate(data):
            title = readable(key, plural=len(markups) > 1)
            lab = Label(markup=util.capitalize(util.escape(title) + ":"))
            table.attach(lab, 0, 1, i, i + 1, xoptions=Gtk.AttachOptions.FILL)
            lab = Label(markup="\n".join(markups), ellipsize=True)
            table.attach(lab, 1, 2, i, i + 1)
        box.pack_start(Frame(_("Additional"), table), False, False, 0)
コード例 #6
0
ファイル: information.py プロジェクト: urielz/quodlibet
 def _description(self, songs, box):
     text = []
     cur_disc = songs[0]("~#disc", 1) - 1
     cur_part = None
     cur_track = songs[0]("~#track", 1) - 1
     for song in songs:
         track = song("~#track", 0)
         disc = song("~#disc", 0)
         part = song.get("part")
         if disc != cur_disc:
             if cur_disc:
                 text.append("")
             cur_track = song("~#track", 1) - 1
             cur_part = None
             cur_disc = disc
             if disc:
                 text.append("<b>%s</b>" % (_("Disc %s") % disc))
         if part != cur_part:
             ts = "    " * bool(disc)
             cur_part = part
             if part:
                 text.append("%s<b>%s</b>" % (ts, util.escape(part)))
         cur_track += 1
         ts = "    " * (bool(disc) + bool(part))
         while cur_track < track:
             text.append("%s<b>%d.</b> <i>%s</i>" % (
                 ts, cur_track, _("Track unavailable")))
             cur_track += 1
         text.append("%s<b>%d.</b> %s" % (
             ts, track, util.escape(song.comma("~title~version"))))
     l = Label()
     l.set_markup("\n".join(text))
     l.set_ellipsize(Pango.EllipsizeMode.END)
     box.pack_start(Frame(_("Track List"), l), False, False, 0)
コード例 #7
0
ファイル: media.py プロジェクト: silkecho/glowing-silk
 def cell_data(col, render, model, iter):
     device = model[iter][0]
     if device.is_connected():
         render.markup = "<b>%s</b>" % util.escape(device['name'])
     else:
         render.markup = util.escape(device['name'])
     render.set_property('markup', render.markup)
コード例 #8
0
ファイル: information.py プロジェクト: silkecho/glowing-silk
    def _album(self, song, box):
        if "album" not in song: return
        w = Label("")
        text = []
        text.append("<i>%s</i>" % util.escape(song.comma("album")))
        if "date" in song:
            text[-1] += " (%s)" % util.escape(song.comma("date"))
        secondary = []
        if "discnumber" in song:
            secondary.append(_("Disc %s") % song["discnumber"])
        if "discsubtitle" in song:
            secondary.append("<i>%s</i>" %
                             util.escape(song.comma("discsubtitle")))
        if "tracknumber" in song:
            secondary.append(_("Track %s") % song["tracknumber"])
        if secondary: text.append(" - ".join(secondary))

        if "organization" in song or "labelid" in song:
            t = util.escape(song.comma("~organization~labelid"))
            text.append(t)

        if "producer" in song:
            text.append("Produced by %s" %(
                util.escape(song.comma("producer"))))

        w.set_markup("\n".join(text))
        w.set_ellipsize(pango.ELLIPSIZE_END)
        hb = gtk.HBox(spacing=12)

        cover = CoverImage(song=song)
        if cover: hb.pack_start(cover, expand=False)
        else: cover.destroy()

        hb.pack_start(w)
        box.pack_start(Frame(tag("album"), hb), expand=False, fill=False)
コード例 #9
0
ファイル: _audio.py プロジェクト: vrasidas/quodlibet
    def website(self):
        """Look for a URL in the audio metadata, or a Google search
        if no URL can be found."""

        if "website" in self:
            return self.list("website")[0]
        for cont in self.list("contact") + self.list("comment"):
            c = cont.lower()
            if (c.startswith("http://") or c.startswith("https://") or
                    c.startswith("www.")):
                return cont
            elif c.startswith("//www."):
                return "http:" + cont
        else:
            text = "http://www.google.com/search?q="
            esc = lambda c: ord(c) > 127 and '%%%x' % ord(c) or c
            if "labelid" in self:
                text += ''.join(map(esc, self["labelid"]))
            else:
                artist = util.escape("+".join(self("artist").split()))
                album = util.escape("+".join(self("album").split()))
                artist = encode(artist)
                album = encode(album)
                artist = "%22" + ''.join(map(esc, artist)) + "%22"
                album = "%22" + ''.join(map(esc, album)) + "%22"
                text += artist + "+" + album
            text += "&ie=UTF8"
            return text
コード例 #10
0
ファイル: media.py プロジェクト: urielz/quodlibet
    def __init__(self, parent, device):
        super(DeviceProperties, self).__init__(
            title=_("Device Properties"),
            transient_for=qltk.get_top_parent(parent))

        self.add_icon_button(_("_Close"), Icons.WINDOW_CLOSE,
                             Gtk.ResponseType.CLOSE)
        self.set_default_size(400, -1)
        self.connect('response', self.__close)

        table = Gtk.Table()
        table.set_border_width(8)
        table.set_row_spacings(8)
        table.set_col_spacings(8)
        self.vbox.pack_start(table, False, True, 0)

        props = []

        props.append((_("Device:"), device.block_device, None))
        mountpoint = util.escape(
            device.mountpoint or ("<i>%s</i>" % _("Not mounted")))
        props.append((_("Mount point:"), mountpoint, None))

        props.append((None, None, None))

        entry = Gtk.Entry()
        entry.set_text(device['name'])
        props.append((_("_Name:"), entry, 'name'))

        y = 0
        for title, value, key in props + device.Properties():
            if title is None:
                table.attach(Gtk.HSeparator(), 0, 2, y, y + 1)
            else:
                if key and isinstance(value, Gtk.CheckButton):
                    value.set_label(title)
                    value.set_use_underline(True)
                    value.connect('toggled', self.__changed, key, device)
                    table.attach(value, 0, 2, y, y + 1,
                                 xoptions=Gtk.AttachOptions.FILL)
                else:
                    label = Gtk.Label()
                    label.set_markup("<b>%s</b>" % util.escape(title))
                    label.set_alignment(0.0, 0.5)
                    table.attach(label, 0, 1, y, y + 1,
                                 xoptions=Gtk.AttachOptions.FILL)
                    if key and isinstance(value, Gtk.Widget):
                        widget = value
                        label.set_mnemonic_widget(widget)
                        label.set_use_underline(True)
                        widget.connect('changed', self.__changed, key, device)
                    else:
                        widget = Gtk.Label(label=value)
                        widget.set_use_markup(True)
                        widget.set_selectable(True)
                        widget.set_alignment(0.0, 0.5)
                    table.attach(widget, 1, 2, y, y + 1)
            y += 1
        self.get_child().show_all()
コード例 #11
0
ファイル: information.py プロジェクト: urielz/quodlibet
    def _album(self, songs, box):
        text = []

        discs = {}
        for song in songs:
            try:
                discs[song("~#disc")] = int(
                    song["tracknumber"].split("/")[1])
            except (AttributeError, ValueError, IndexError, KeyError):
                discs[song("~#disc")] = max([
                    song("~#track", discs.get(song("~#disc"), 0))])
        tracks = sum(discs.values())
        discs = len(discs)
        length = sum([song.get("~#length", 0) for song in songs])

        if tracks == 0 or tracks < len(songs):
            tracks = len(songs)

        parts = []
        if discs > 1:
            parts.append(
                ngettext("%d disc", "%d discs", discs) % discs)
        parts.append(
                ngettext("%d track", "%d tracks", tracks) % tracks)
        if tracks != len(songs):
            parts.append(ngettext("%d selected", "%d selected",
                len(songs)) % len(songs))

        text.append(", ".join(parts))
        text.append(util.format_time_preferred(length))

        if "location" in song:
            text.append(util.escape(song["location"]))
        if "organization" in song or "labelid" in song:
            t = util.escape(song.comma("~organization~labelid"))
            text.append(t)

        if "producer" in song:
            text.append(_("Produced by %s") % (
                util.escape(song.comma("producer"))))

        w = Label("")
        w.set_ellipsize(Pango.EllipsizeMode.END)
        w.set_markup("\n".join(text))
        hb = Gtk.HBox(spacing=12)

        cover = CoverImage()
        cover.set_property('no-show-all', True)
        hb.pack_start(cover, False, True, 0)

        def show_cover(cover, success):
            if success:
                cover.show()
            cover.disconnect(signal_id)
        signal_id = cover.connect('cover-visible', show_cover)
        cover.set_song(song)

        hb.pack_start(w, True, True, 0)
        box.pack_start(hb, False, False, 0)
コード例 #12
0
ファイル: debugwindow.py プロジェクト: ZDBioHazard/quodlibet
 def cdf(column, cell, model, iter, data):
     row = model[iter]
     filename = fsn2text(unexpand(row[0]))
     function = row[1]
     line = row[2]
     cell.set_property(
         "markup", "<b>%s</b> line %d\n\t%s" % (
             util.escape(function), line, util.escape(filename)))
コード例 #13
0
ファイル: quodlibetwindow.py プロジェクト: virtuald/quodlibet
    def __init__(self, parent, player_error):
        add_full_stop = lambda s: s and (s.rstrip(".") + ".")
        description = add_full_stop(util.escape(player_error.short_desc))
        details = add_full_stop(util.escape(player_error.long_desc or ""))
        if details:
            description += " " + details

        super(PlaybackErrorDialog, self).__init__(parent, _("Playback Error"), description)
コード例 #14
0
ファイル: data_editors.py プロジェクト: urielz/quodlibet
 def __cdf(self, column, cell, model, iter, data):
     row = model[iter]
     obj = row[0]
     obj_name = util.escape(obj.name)
     obj_description = util.escape(str(obj))
     markup = '<b>%s</b>\n%s' % (obj_name, obj_description)
     cell.markup = markup
     cell.set_property('markup', markup)
コード例 #15
0
ファイル: telepathy_status.py プロジェクト: Muges/quodlibet
    def PluginPreferences(self, parent):
        outer_vb = Gtk.VBox(spacing=12)
        vb = Gtk.VBox(spacing=12)

        # Playing
        hb = Gtk.HBox(spacing=6)
        entry = UndoEntry()
        entry.set_text(self.config_get(self.CFG_PAT_PLAYING,
                                       self.DEFAULT_PAT))
        entry.connect('changed', self.config_entry_changed,
                      self.CFG_PAT_PLAYING)
        lbl = Gtk.Label(label=_("Playing:"))
        entry.set_tooltip_markup(_("Status text when a song is started. "
                                 "Accepts QL Patterns e.g. %s")
                                 % util.monospace(
                                        util.escape("<~artist~title>")))
        lbl.set_mnemonic_widget(entry)
        hb.pack_start(lbl, False, True, 0)
        hb.pack_start(entry, True, True, 0)
        vb.pack_start(hb, True, True, 0)

        # Paused
        hb = Gtk.HBox(spacing=6)
        entry = UndoEntry()
        entry.set_text(self.config_get(self.CFG_PAT_PAUSED,
                                    self.DEFAULT_PAT_PAUSED))
        entry.connect('changed', self.config_entry_changed,
                      self.CFG_PAT_PAUSED)
        lbl = Gtk.Label(label=_("Paused:"))
        entry.set_tooltip_markup(_("Status text when a song is paused. "
                                   "Accepts QL Patterns e.g. %s")
                                   % util.monospace(
                                        util.escape("<~artist~title>")))
        lbl.set_mnemonic_widget(entry)
        hb.pack_start(lbl, False, True, 0)
        hb.pack_start(entry, True, True, 0)
        vb.pack_start(hb, True, True, 0)

        # No Song
        hb = Gtk.HBox(spacing=6)
        entry = UndoEntry()
        entry.set_text(self.config_get(self.CFG_STATUS_SONGLESS, ""))
        entry.connect('changed', self.config_entry_changed,
                      self.CFG_STATUS_SONGLESS)
        entry.set_tooltip_text(
                _("Plain text for status when there is no current song"))
        lbl = Gtk.Label(label=_("No song:"))
        lbl.set_mnemonic_widget(entry)
        hb.pack_start(lbl, False, True, 0)
        hb.pack_start(entry, True, True, 0)
        vb.pack_start(hb, True, True, 0)

        # Frame
        frame = qltk.Frame(_("Status Patterns"), child=vb)
        outer_vb.pack_start(frame, False, True, 0)

        return outer_vb
コード例 #16
0
ファイル: information.py プロジェクト: urielz/quodlibet
 def _title(self, song, box):
     l = Label()
     text = "<big><b>%s</b></big>" % util.escape(song.comma("title"))
     if "version" in song:
         text += "\n" + util.escape(song.comma("version"))
     l.set_markup(text)
     l.set_ellipsize(Pango.EllipsizeMode.END)
     box.pack_start(l, False, False, 0)
     self.title = song.comma("title")
コード例 #17
0
ファイル: information.py プロジェクト: silkecho/glowing-silk
 def _title(self, song, box):
     l = Label()
     text = "<big><b>%s</b></big>" % util.escape(song.comma("title"))
     if "version" in song:
         text += "\n" + util.escape(song.comma("version"))
     l.set_markup(text)
     l.set_ellipsize(pango.ELLIPSIZE_END)
     box.pack_start(l, expand=False, fill=False)
     self.title = song.comma("title")
コード例 #18
0
ファイル: language.py プロジェクト: ZDBioHazard/quodlibet
 def cell_func(combo, render, model, iter_, *args):
     value = model.get_value(iter_)
     if value is None:
         text = escape(_("System Default"))
     else:
         if value == u"C":
             value = u"en"
         text = "%s <span weight='light'>(%s)</span>" % (
             escape(value),
             escape(iso639.translate(value.split("_", 1)[0])))
     render.set_property("markup", text)
コード例 #19
0
ファイル: edittags.py プロジェクト: faubiguy/quodlibet
    def get_markup(self):
        """Returns pango markup for displaying"""

        if self.shared and self.complete:
            return util.escape(self.text)
        elif self.shared:
            return "\n".join(
                ["%s<i> (%s)</i>" % (util.escape(s), util.escape(self._paren())) for s in self.text.split("\n")]
            )
        else:
            return "<i>(%s)</i>" % util.escape(self._paren())
コード例 #20
0
ファイル: media.py プロジェクト: silkecho/glowing-silk
    def __init__(self, parent, device):
        super(DeviceProperties, self).__init__(
            _("Device Properties"), qltk.get_top_parent(parent),
            buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
        self.set_default_size(400, -1)
        self.connect('response', self.__close)

        table = gtk.Table()
        table.set_border_width(8)
        table.set_row_spacings(8)
        table.set_col_spacings(8)
        self.vbox.pack_start(table, expand=False)

        props = []

        props.append((_("Device:"), device.dev, None))
        mountpoint = util.escape(
            device.mountpoint or ("<i>%s</i>" % _("Not mounted")))
        props.append((_("Mount Point:"), mountpoint, None))

        props.append((None, None, None))

        entry = gtk.Entry()
        entry.set_text(device['name'])
        props.append((_("_Name:"), entry, 'name'))

        y = 0
        for title, value, key in props + device.Properties():
            if title == None:
                table.attach(gtk.HSeparator(), 0, 2, y, y + 1)
            else:
                if key and isinstance(value, gtk.CheckButton):
                    value.set_label(title)
                    value.set_use_underline(True)
                    value.connect('toggled', self.__changed, key, device)
                    table.attach(value, 0, 2, y, y + 1, xoptions=gtk.FILL)
                else:
                    label = gtk.Label()
                    label.set_markup("<b>%s</b>" % util.escape(title))
                    label.set_alignment(0.0, 0.5)
                    table.attach(label, 0, 1, y, y + 1, xoptions=gtk.FILL)
                    if key and isinstance(value, gtk.Widget):
                        widget = value
                        label.set_mnemonic_widget(widget)
                        label.set_use_underline(True)
                        widget.connect('changed', self.__changed, key, device)
                    else:
                        widget = gtk.Label(value)
                        widget.set_use_markup(True)
                        widget.set_selectable(True)
                        widget.set_alignment(0.0, 0.5)
                    table.attach(widget, 1, 2, y, y + 1)
            y += 1
        self.show_all()
コード例 #21
0
ファイル: media.py プロジェクト: silkecho/glowing-silk
    def __copy_songs(self, songlist, songs):
        model, iter = self.__view.get_selection().get_selected()
        if not iter: return False

        device = model[iter][0]
        if not self.__check_device(device, _("Unable to copy songs")):
            return False

        self.__busy = True

        wlb = self.__statusbar
        wlb.setup(len(songs), _("Copying <b>%(song)s</b>"), { 'song': '' })
        wlb.show()

        model = songlist.get_model()
        for song in songs:
            label = util.escape(song('~artist~title'))
            if wlb.step(song=label):
                wlb.hide()
                break

            if len(model) > 0:
                songlist.scroll_to_cell(model[-1].path)
            while gtk.events_pending(): gtk.main_iteration()

            space, free = device.get_space()
            if free < os.path.getsize(song['~filename']):
                wlb.hide()
                qltk.WarningMessage(
                    self, _("Unable to copy song"),
                    _("There is not enough free space for this song.")
                ).run()
                break

            status = device.copy(songlist, song)
            if isinstance(status, AudioFile):
                model.append([status])
                try: self.__cache[device.bid].append(song)
                except KeyError: pass
                self.__refresh_space(device)
            else:
                msg = _("<b>%s</b> could not be copied.") % label
                if type(status) == unicode:
                    msg += "\n\n" + util.escape(status)
                qltk.WarningMessage(self, _("Unable to copy song"), msg).run()

        if device.cleanup and not device.cleanup(wlb, 'copy'):
            pass
        else:
            wlb.hide()

        self.__busy = False
        return True
コード例 #22
0
ファイル: media.py プロジェクト: ZDBioHazard/quodlibet
    def __copy_songs(self, songs):
        model, iter = self.__view.get_selection().get_selected()
        if not iter:
            return False

        device = model[iter][0]
        if not self.__check_device(device, _("Unable to copy songs")):
            return False

        self.__busy = True

        wlb = self.__statusbar
        wlb.setup(
            len(songs),
            _("Copying %(song)s") % {'song': '<b>%(song)s</b>'},
            {'song': ''})
        wlb.show()

        for song in songs:
            label = util.escape(song('~artist~title'))
            if wlb.step(song=label):
                wlb.hide()
                break

            space, free = device.get_space()
            if free < os.path.getsize(song['~filename']):
                wlb.hide()
                qltk.WarningMessage(
                    self, _("Unable to copy song"),
                    _("There is not enough free space for this song.")
                ).run()
                break

            status = device.copy(self, song)
            if isinstance(status, AudioFile):
                try:
                    self.__cache[device.bid].append(song)
                except KeyError:
                    pass
                self.__refresh_space(device)
            else:
                msg = _("%s could not be copied.") % util.bold(label)
                if type(status) == text_type:
                    msg += "\n\n" + util.escape(status)
                qltk.WarningMessage(self, _("Unable to copy song"), msg).run()

        if device.cleanup and not device.cleanup(wlb, 'copy'):
            pass
        else:
            wlb.hide()

        self.__busy = False
        return True
コード例 #23
0
ファイル: qlscrobbler.py プロジェクト: LudoBike/quodlibet
    def send_handshake(self, show_dialog=False):
        # construct url
        stamp = int(time.time())
        auth = md5(self.password.encode("utf-8") +
                   str(stamp).encode("utf-8")).hexdigest()
        url = "%s/?hs=true&p=%s&c=%s&v=%s&u=%s&a=%s&t=%d" % (
                    self.base_url, self.PROTOCOL_VERSION, self.CLIENT,
                    self.CLIENT_VERSION, self.username, auth, stamp)
        print_d("Sending handshake to service.")

        try:
            resp = urlopen(url)
        except UrllibError:
            if show_dialog:
                self.quick_dialog(
                    _("Could not contact service '%s'.") %
                    util.escape(self.base_url), Gtk.MessageType.ERROR)
            else:
                print_d("Could not contact service. Queueing submissions.")
            return False
        except ValueError:
            self.quick_dialog(_("Authentication failed: invalid URL."),
                Gtk.MessageType.ERROR)
            self.broken = True
            return False

        # check response
        lines = resp.read().decode("utf-8", "ignore").rstrip().split("\n")
        status = lines.pop(0)
        print_d("Handshake status: %s" % status)

        if status == "OK":
            self.session_id, self.nowplaying_url, self.submit_url = lines
            self.handshake_sent = True
            print_d("Session ID: %s, NP URL: %s, Submit URL: %s" % (
                self.session_id, self.nowplaying_url, self.submit_url))
            return True
        elif status == "BADAUTH":
            self.quick_dialog(_("Authentication failed: Invalid username '%s' "
                            "or bad password.") % util.escape(self.username),
                            Gtk.MessageType.ERROR)
            self.broken = True
        elif status == "BANNED":
            self.quick_dialog(_("Client is banned. Contact the author."),
                              Gtk.MessageType.ERROR)
            self.broken = True
        elif status == "BADTIME":
            self.quick_dialog(_("Wrong system time. Submissions may fail "
                            "until it is corrected."), Gtk.MessageType.ERROR)
        else:  # "FAILED"
            self.quick_dialog(util.escape(status), Gtk.MessageType.ERROR)
        self.changed()
        return False
コード例 #24
0
ファイル: tagsfrompath.py プロジェクト: silkecho/glowing-silk
    def __save(self, addreplace, library):
        pattern_text = self.combo.child.get_text().decode('utf-8')
        pattern = TagsFromPattern(pattern_text)
        model = self.view.get_model()
        add = bool(addreplace.get_active())
        win = WritingWindow(self, len(model))

        was_changed = []

        for row in (model or []):
            song = row[0]
            changed = False
            if not song.valid() and not qltk.ConfirmAction(
                self, _("Tag may not be accurate"),
                _("<b>%s</b> changed while the program was running. "
                  "Saving without refreshing your library may "
                  "overwrite other changes to the song.\n\n"
                  "Save this song anyway?") %(
                util.escape(util.fsdecode(song("~basename"))))
                ).run():
                break

            for i, h in enumerate(pattern.headers):
                if row[i + 2]:
                    text = row[i + 2].decode("utf-8")
                    if not add or h not in song or not song.multiple_values:
                        song[h] = text
                        changed = True
                    else:
                        for val in text.split("\n"):
                            if val not in song.list(h):
                                song.add(h, val)
                                changed = True

            if changed:
                try: song.write()
                except:
                    qltk.ErrorMessage(
                        self, _("Unable to edit song"),
                        _("Saving <b>%s</b> failed. The file "
                          "may be read-only, corrupted, or you "
                          "do not have permission to edit it.")%(
                        util.escape(util.fsdecode(song('~basename'))))
                        ).run()
                    library.reload(song, changed=was_changed)
                    break
                was_changed.append(song)

            if win.step(): break

        win.destroy()
        library.changed(was_changed)
        self.save.set_sensitive(False)
コード例 #25
0
ファイル: renamefiles.py プロジェクト: mistotebe/quodlibet
    def __rename(self, library):
        model = self.view.get_model()
        win = WritingWindow(self, len(model))
        win.show()
        was_changed = set()
        skip_all = False
        self.view.freeze_child_notify()

        for entry in model.itervalues():
            song = entry.song
            new_name = entry.new_name
            old_name = entry.name
            if new_name is None:
                continue

            try:
                library.rename(song, fsnative(new_name), changed=was_changed)
            except Exception:
                util.print_exc()
                if skip_all:
                    continue
                RESPONSE_SKIP_ALL = 1
                msg = qltk.Message(
                    Gtk.MessageType.ERROR, win, _("Unable to rename file"),
                    _("Renaming <b>%(old-name)s</b> to <b>%(new-name)s</b> "
                      "failed. Possibly the target file already exists, "
                      "or you do not have permission to make the "
                      "new file or remove the old one.") % {
                        "old-name": util.escape(old_name),
                        "new-name": util.escape(new_name),
                      },
                    buttons=Gtk.ButtonsType.NONE)
                msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL)
                msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP,
                                    Gtk.ResponseType.CANCEL)
                msg.add_button(_("_Continue"), Gtk.ResponseType.OK)
                msg.set_default_response(Gtk.ResponseType.OK)
                resp = msg.run()
                skip_all |= (resp == RESPONSE_SKIP_ALL)
                # Preserve old behavior: shift-click is Ignore All
                mods = Gdk.Display.get_default().get_pointer()[3]
                skip_all |= mods & Gdk.ModifierType.SHIFT_MASK
                library.reload(song, changed=was_changed)
                if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL:
                    break
            if win.step():
                break

        self.view.thaw_child_notify()
        win.destroy()
        library.changed(was_changed)
        self.save.set_sensitive(False)
コード例 #26
0
ファイル: information.py プロジェクト: silkecho/glowing-silk
    def _album(self, songs, box):
        text = []

        discs = {}
        for song in songs:
            try:
                discs[song("~#disc")] = int(
                    song["tracknumber"].split("/")[1])
            except (AttributeError, ValueError, IndexError, KeyError):
                discs[song("~#disc")] = max([
                    song("~#track", discs.get(song("~#disc"), 0))])
        tracks = sum(discs.values())
        discs = len(discs)
        length = sum([song.get("~#length", 0) for song in songs])

        if tracks == 0 or tracks < len(songs): tracks = len(songs)

        parts = []
        if discs > 1:
            parts.append(
                ngettext("%d disc", "%d discs", discs) % discs)
        parts.append(
                ngettext("%d track", "%d tracks", tracks) % tracks)
        if tracks != len(songs):
            parts.append(ngettext("%d selected", "%d selected",
                len(songs)) % len(songs))

        text.append(", ".join(parts))
        text.append(util.format_time_long(length))

        if "location" in song:
            text.append(util.escape(song["location"]))
        if "organization" in song or "labelid" in song:
            t = util.escape(song.comma("~organization~labelid"))
            text.append(t)

        if "producer" in song:
            text.append(_("Produced by %s") %(
                util.escape(song.comma("producer"))))

        w = Label("")
        w.set_ellipsize(pango.ELLIPSIZE_END)
        w.set_markup("\n".join(text))
        hb = gtk.HBox(spacing=12)

        cover = CoverImage(song=song)
        if cover: hb.pack_start(cover, expand=False)
        else: cover.destroy()

        hb.pack_start(w)
        box.pack_start(hb, expand=False, fill=False)
コード例 #27
0
ファイル: widgets.py プロジェクト: bernd-wechner/quodlibet
        def celldata(layout, cell, model, iter_, data):
            release = model.get_value(iter_)

            extra_info = ", ".join(
                filter(None, [util.escape(release.date),
                util.escape(release.country),
                util.escape(release.medium_format),
                util.escape(release.labelid)]))

            artist_names = [a.name for a in release.artists]
            disc_count = release.disc_count
            track_count = release.track_count

            discs_format = ngettext(
                "%d disc", "%d discs", disc_count) % disc_count
            tracks_format = ngettext(
                "%d track", "%d tracks", track_count) % track_count

            markup = "<b>%s</b>\n%s - %s, %s (%s)" % (
                    util.escape(release.title),
                    util.escape(", ".join(artist_names)),
                    util.escape(discs_format),
                    util.escape(tracks_format),
                    extra_info)
            cell.set_property('markup', markup)
コード例 #28
0
ファイル: brainz.py プロジェクト: mistotebe/quodlibet
 def celldata(layout, cell, model, iter, data):
     release = model[iter][0]
     if not release:
         return
     date = release.getEarliestReleaseDate()
     if date:
         date = '%s, ' % date
     else:
         date = ''
     markup = "<b>%s</b>\n%s - %s%s tracks" % (
             util.escape(release.title),
             util.escape(release.artist.name),
             date, release.tracksCount)
     cell.set_property('markup', markup)
コード例 #29
0
 def plugin_songs(self, songs):
     # Check this is a launch, not a configure
     if self.com_index:
         com = self.get_data(self.com_index)
         print_d("Running %s" % com)
         try:
             com.run(songs)
         except Exception, err:
             print_e("Couldn't run command %s: %s %s at"
                     % (com.name, type(err), err))
             ErrorMessage(
                 self.plugin_window,
                 _("Unable to run custom command %s" %
                   util.escape(self.com_index)),
                 util.escape(str(err))).run()
コード例 #30
0
ファイル: edittags.py プロジェクト: silkecho/glowing-silk
    def __add_new_tag(self, model, tag, value):
        if tag in self.__songinfo and not self.__songinfo.multiple_values:
            title = _("Unable to add tag")
            msg = _(
                "Unable to add <b>%s</b>\n\nThe files currently" " selected do not support multiple values."
            ) % util.escape(tag)
            qltk.ErrorMessage(self, title, msg).run()
            return

        iters = [row.iter for row in model if row[TAG] == tag]
        row = [tag, util.escape(value), True, True, False, None, False, None]
        if len(iters):
            model.insert_after(iters[-1], row=row)
        else:
            model.append(row=row)
コード例 #31
0
    def set_plugin(self, plugin):
        label = self.desc

        if plugin is None:
            label.set_markup("")
        else:
            name = util.escape(plugin.name)
            text = "<big><b>%s</b></big>" % name
            if plugin.description:
                text += "<span font='4'>\n\n</span>"
                text += plugin.description
            label.set_markup(text)
            label.connect("activate-link", show_uri)

        frame = self.prefs

        if frame.get_child():
            frame.get_child().destroy()

        if plugin is not None:
            instance_or_cls = plugin.get_instance() or plugin.cls

            if plugin and hasattr(instance_or_cls, 'PluginPreferences'):
                try:
                    prefs = instance_or_cls.PluginPreferences(self)
                except:
                    util.print_exc()
                    frame.hide()
                else:
                    if isinstance(prefs, Gtk.Window):
                        b = Button(_("_Preferences"), Icons.PREFERENCES_SYSTEM)
                        connect_obj(b, 'clicked', Gtk.Window.show, prefs)
                        connect_obj(b, 'destroy', Gtk.Window.destroy, prefs)
                        frame.add(b)
                        frame.get_child().set_border_width(6)
                    else:
                        frame.add(prefs)
                    frame.show_all()
        else:
            frame.hide()
コード例 #32
0
    def __preview(self, songs):
        model = self.view.get_model()
        if songs is None:
            songs = [row[0] for row in model]
        pattern = self.combo.get_child().get_text().decode("utf-8")

        try:
            pattern = FileFromPattern(pattern)
        except ValueError:
            qltk.ErrorMessage(
                self, _("Path is not absolute"),
                _("The pattern\n\t<b>%s</b>\ncontains / but "
                  "does not start from root. To avoid misnamed "
                  "folders, root your pattern by starting "
                  "it with / or ~/.") % (util.escape(pattern))).run()
            return
        else:
            if self.combo.get_child().get_text():
                self.combo.prepend_text(self.combo.get_child().get_text())
                self.combo.write(const.NBP)

        orignames = [song["~filename"] for song in songs]
        newnames = [fsdecode(fsencode(pattern.format(song))) for song in songs]
        for f in self.filters:
            if f.active:
                newnames = f.filter_list(orignames, newnames)

        model.clear()
        for song, newname in zip(songs, newnames):
            basename = fsdecode(song("~basename"))
            model.append(row=[song, basename, newname])
        self.preview.set_sensitive(False)
        self.save.set_sensitive(bool(self.combo.get_child().get_text()))
        for song in songs:
            if not song.is_file:
                self.set_sensitive(False)
                break
        else:
            self.set_sensitive(True)
コード例 #33
0
    def __add_stations(self, irfs: Collection[IRFile], uri: str) -> None:
        print_d(f"Got {len(irfs)} station(s) from {uri}")
        assert self.__fav_stations is not None
        if not irfs:
            msg = ErrorMessage(
                self, _("No stations found"),
                _("No Internet radio stations were found at %s.") %
                util.escape(uri))
            msg.run()
            return

        fav_uris = {af("~uri") for af in self.__fav_stations}
        irfs = {af for af in irfs if af("~uri") not in fav_uris}
        if irfs:
            print_d(f"Adding {irfs} to favourites")
            self.__fav_stations.add(irfs)
        else:
            message = WarningMessage(
                self,
                _("Nothing to add"),
                _("All stations listed are already in your library."))
            message.run()
コード例 #34
0
    def __add_tag(self, activator, model, library):
        add = AddTagDialog(self, self.__songinfo.can_change(), library)

        while True:
            resp = add.run()
            if resp != Gtk.ResponseType.OK:
                break
            tag = add.get_tag()
            value = add.get_value()
            if tag in massagers.tags:
                value = massagers.tags[tag].validate(value)
            if not self.__songinfo.can_change(tag):
                title = _("Invalid tag")
                msg = _("Invalid tag <b>%s</b>\n\nThe files currently"
                        " selected do not support editing this tag."
                        ) % util.escape(tag)
                qltk.ErrorMessage(self, title, msg).run()
            else:
                self.__add_new_tag(model, tag, value)
                break

        add.destroy()
コード例 #35
0
def confirm_remove_playlist_dialog_invoke(
    parent, playlist, Confirmer=ConfirmationPrompt):
    """Creates and invokes a confirmation dialog that asks the user whether or not
       to go forth with the deletion of the selected playlist.

       Confirmer needs to accept the arguments for constructing a dialog,
       have a run-method returning a response, and have a RESPONSE_INVOKE
       attribute.

       returns the result of comparing the result of run to RESPONSE_INVOKE
    """
    title = (_("Are you sure you want to delete the playlist '%s'?")
             % escape(playlist.name))
    description = (_("All information about the selected playlist "
                     "will be deleted and can not be restored."))
    ok_text = _("_Delete")
    ok_icon = Icons.EDIT_DELETE

    dialog = Confirmer(parent, title, description, ok_text, ok_icon)
    prompt = dialog.run()
    response = (prompt == Confirmer.RESPONSE_INVOKE)
    return response
コード例 #36
0
    def _file(self, song, box):
        def ftime(t):
            if t == 0:
                return _("Unknown")
            else:
                timestr = time.strftime("%c", time.localtime(t))
                encoding = util.get_locale_encoding()
                return timestr.decode(encoding)

        fn = fsdecode(unexpand(song["~filename"]))
        length = util.format_time_long(song.get("~#length", 0))
        size = util.format_size(
            song.get("~#filesize") or filesize(song["~filename"]))
        mtime = ftime(util.path.mtime(song["~filename"]))
        bitrate = song.get("~#bitrate", 0)
        if bitrate != 0:
            bitrate = _("%d kbps") % int(bitrate)
        else:
            bitrate = False

        t = Gtk.Table(n_rows=4, n_columns=2)
        t.set_col_spacings(6)
        t.set_homogeneous(False)
        table = [(_("length"), length), (_("file size"), size),
                 (_("modified"), mtime)]
        if bitrate:
            table.insert(1, (_("bitrate"), bitrate))
        fnlab = Label(fn)
        fnlab.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
        t.attach(fnlab, 0, 2, 0, 1, xoptions=Gtk.AttachOptions.FILL)
        for i, (l, r) in enumerate(table):
            l = "<b>%s</b>" % util.capitalize(util.escape(l) + ":")
            lab = Label()
            lab.set_markup(l)
            t.attach(lab, 0, 1, i + 1, i + 2, xoptions=Gtk.AttachOptions.FILL)
            t.attach(Label(r), 1, 2, i + 1, i + 2)

        box.pack_start(Frame(_("File"), t), False, False, 0)
コード例 #37
0
def check_wrapper_changed(library, parent, songs):
    need_write = [s for s in songs if s._needs_write]

    if need_write:
        win = WritingWindow(parent, len(need_write))
        win.show()
        for song in need_write:
            try:
                song._song.write()
            except AudioFileError as e:
                qltk.ErrorMessage(
                    None, _("Unable to edit song"),
                    _("Saving <b>%s</b> failed. The file "
                      "may be read-only, corrupted, or you "
                      "do not have permission to edit it.") %
                    util.escape(song('~basename'))).run()
                print_w("Couldn't save song %s (%s)" % (song("~filename"), e))

            if win.step():
                break
        win.destroy()

    _inform_library_of_changed(library, songs)
コード例 #38
0
    def _library(self, song, box):
        def counter(i):
            if i == 0:
                return _("Never")
            else:
                return ngettext("%(n)d time", "%(n)d times", i) % {"n": i}

        def ftime(t):
            if t == 0:
                return _("Unknown")
            else:
                timestr = time.strftime("%c", time.localtime(t))
                return timestr.decode(const.ENCODING)

        playcount = counter(song.get("~#playcount", 0))
        skipcount = counter(song.get("~#skipcount", 0))
        lastplayed = ftime(song.get("~#lastplayed", 0))
        if lastplayed == _("Unknown"):
            lastplayed = _("Never")
        added = ftime(song.get("~#added", 0))
        rating = song("~rating")

        t = Gtk.Table(5, 2)
        t.set_col_spacings(6)
        t.set_homogeneous(False)
        table = [(_("added"), added), (_("last played"), lastplayed),
                 (_("plays"), playcount), (_("skips"), skipcount),
                 (_("rating"), rating)]

        for i, (l, r) in enumerate(table):
            l = "<b>%s</b>" % util.capitalize(util.escape(l) + ":")
            lab = Label()
            lab.set_markup(l)
            t.attach(lab, 0, 1, i + 1, i + 2, xoptions=Gtk.AttachOptions.FILL)
            t.attach(Label(r), 1, 2, i + 1, i + 2)

        box.pack_start(Frame(_("Library"), t), False, False, 0)
コード例 #39
0
def add_station(uri):
    """Fetches the URI content and extracts IRFiles
    Returns None in error, else a possibly filled list of stations"""

    irfs = []
    if isinstance(uri, unicode):
        uri = uri.encode('utf-8')

    if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"):
        try:
            sock = urlopen(uri)
        except EnvironmentError as e:
            print_d("Got %s from %s" % (uri, e))
            encoding = util.get_locale_encoding()
            try:
                err = e.strerror.decode(encoding, 'replace')
            except TypeError:
                err = e.strerror[1].decode(encoding, 'replace')
            except AttributeError:
                # Give up and display the exception - may be useful HTTP info
                err = str(e)
            ErrorMessage(None, _("Unable to add station"), escape(err)).run()
            return None

        if uri.lower().endswith(".pls"):
            irfs = ParsePLS(sock)
        elif uri.lower().endswith(".m3u"):
            irfs = ParseM3U(sock)

        sock.close()
    else:
        try:
            irfs = [IRFile(uri)]
        except ValueError as err:
            ErrorMessage(None, _("Unable to add station"), err).run()

    return irfs
コード例 #40
0
ファイル: information.py プロジェクト: darthoctopus/quodlibet
    def _file(self, song, box):
        def ftime(t):
            if t == 0:
                return _("Unknown")
            else:
                return text_type(time.strftime("%c", time.localtime(t)))

        fn = fsn2text(unexpand(song["~filename"]))
        length = util.format_time_preferred(song.get("~#length", 0))
        size = util.format_size(
            song.get("~#filesize") or filesize(song["~filename"]))
        mtime = ftime(util.path.mtime(song["~filename"]))
        format_ = song("~format")
        codec = song("~codec")
        encoding = song.comma("~encoding")
        bitrate = song("~bitrate")

        table = [(_("path"), fn), (_("length"), length),
                 (_("format"), format_), (_("codec"), codec),
                 (_("encoding"), encoding), (_("bitrate"), bitrate),
                 (_("file size"), size), (_("modified"), mtime)]
        t = Table(len(table))

        for i, (tag_, text) in enumerate(table):
            tag_ = util.capitalize(util.escape(tag_) + ":")
            lab = Label(text)
            lab.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
            t.attach(Label(tag_),
                     0,
                     1,
                     i,
                     i + 1,
                     xoptions=Gtk.AttachOptions.FILL)
            t.attach(lab, 1, 2, i, i + 1)

        box.pack_start(Frame(_("File"), t), False, False, 0)
コード例 #41
0
    def _people(self, song, box):
        data = []
        if "artist" in song:
            title = (_("artist") if len(song.list("artist")) == 1
                     else _("artists"))
            title = util.capitalize(title)
            data.append((title, song["artist"]))
        for tag_ in ["performer", "lyricist", "arranger", "composer",
                     "conductor", "author"]:
            if tag_ in song:
                name = (tag(tag_) if len(song.list(tag_)) == 1
                        else readable(tag_, plural=True))
                data.append((name, song[tag_]))
        performers = defaultdict(list)
        for tag_ in song:
            if "performer:" in tag_:
                for person in song.list(tag_):
                    role = util.title(tag_.split(':', 1)[1])
                    performers[role].append(person)

        if performers:
            text = '\n'.join("%s (%s)" % (', '.join(names), part)
                             for part, names in performers.iteritems())

            name = (tag("performer") if len(performers) == 1
                    else _("performers"))
            data.append((name, text))

        table = Table(len(data))
        for i, (key, text) in enumerate(data):
            key = util.capitalize(util.escape(key) + ":")
            table.attach(Label(markup=key), 0, 1, i, i + 1,
                         xoptions=Gtk.AttachOptions.FILL)
            label = Label(text, ellipsize=True)
            table.attach(label, 1, 2, i, i + 1)
        box.pack_start(Frame(tag("~people"), table), False, False, 0)
コード例 #42
0
        def celldata(layout, cell, model, iter_, data):
            release = model.get_value(iter_)

            extra_info = ", ".join(
                filter(None, [util.escape(release.date),
                util.escape(release.country),
                util.escape(release.medium_format)]))

            artist_names = [a.name for a in release.artists]
            disc_count = release.disc_count
            track_count = release.track_count

            discs_format = ngettext(
                "%d disc", "%d discs", disc_count) % disc_count
            tracks_format = ngettext(
                "%d track", "%d tracks", track_count) % track_count

            markup = "<b>%s</b>\n%s - %s, %s (%s)" % (
                    util.escape(release.title),
                    util.escape(", ".join(artist_names)),
                    util.escape(discs_format),
                    util.escape(tracks_format),
                    extra_info)
            cell.set_property('markup', markup)
コード例 #43
0
ファイル: edittags.py プロジェクト: mikechen66/QuodLibet
 def get_shared_text(self):
     if self.shared:
         return util.escape(self.text)
     return ''
コード例 #44
0
 def __make_row(cls, song):
     """Construct GTK row for a song, with all columns"""
     return [song] + [util.escape(str(f(song.comma(tag)))) for
                      (tag, f) in cls.TAG_MAP]
コード例 #45
0
 def cell_data(col, render, model, iter, data):
     if model[iter][0].changed:
         render.markup = "<b>%s</b>" % util.escape(model[iter][0].name)
     else:
         render.markup = util.escape(model[iter][0].name)
     render.set_property('markup', render.markup)
コード例 #46
0
EXPAND = Gtk.AttachOptions.EXPAND
FILL = Gtk.AttachOptions.FILL


class Config(object):
    STATUS_SONGLESS = 'no_song_text', ""
    PAT_PLAYING = 'playing_pattern', "♫ <~artist~title> ♫"
    PAT_PAUSED = 'paused_pattern', "<~artist~title> [%s]" % _("paused")
    HOST = 'host', "localhost"
    PORT = 'port', 1883
    TOPIC = 'topic', 'quodlibet/now-playing'


_ACCEPTS_PATTERNS = (_("Accepts QL Patterns e.g. %s") %
                     monospace(escape('<~artist~title>')))


class MqttPublisherPlugin(EventPlugin, PluginConfigMixin):
    PLUGIN_ID = "MQTT Status"
    PLUGIN_NAME = _("MQTT Publisher")
    PLUGIN_DESC = _("Publishes status messages to an MQTT topic.")
    PLUGIN_ICON = Icons.FACE_SMILE

    def on_connect(self, client, userdata, flags, rc):
        """Callback for when the client receives a
        CONNACK response from the server."""
        print_d("Connected to %s at %s:%d with result code %s" %
                (self.topic, self.host, self.port, rc))

    def _subscribe(self, client, topic):
コード例 #47
0
 def test_roundtrip(self):
     for s in ["foo&amp;", "<&>", "&", "&amp;", "<&testing&amp;>amp;"]:
         esc = util.escape(s)
         self.failIfEqual(s, esc)
         self.failUnlessEqual(s, util.unescape(esc))
コード例 #48
0
ファイル: information.py プロジェクト: darthoctopus/quodlibet
 def _title(self, songs, box):
     self.title = ngettext("%d song", "%d songs", len(songs)) % len(songs)
     markup = util.escape(self.title)
     box.pack_start(TitleLabel(markup, is_markup=True), False, False, 0)
コード例 #49
0
    def __save_files(self, save, revert, model, library):
        updated = {}
        deleted = {}
        added = {}
        renamed = {}
        for row in model:
            if row[EDITED] and not (row[DELETED] or row[RENAMED]):
                if row[ORIGVALUE] is not None:
                    updated.setdefault(row[TAG], [])
                    updated[row[TAG]].append(
                        (decode(row[VALUE]), decode(row[ORIGVALUE])))
                else:
                    added.setdefault(row[TAG], [])
                    added[row[TAG]].append(decode(row[VALUE]))
            if row[EDITED] and row[DELETED]:
                if row[ORIGVALUE] is not None:
                    deleted.setdefault(row[TAG], [])
                    deleted[row[TAG]].append(decode(row[ORIGVALUE]))

            if row[EDITED] and row[RENAMED] and not row[DELETED]:
                renamed.setdefault(row[TAG], [])
                renamed[row[TAG]].append(
                    (decode(row[ORIGTAG]), decode(row[VALUE]),
                     decode(row[ORIGVALUE])))

        was_changed = set()
        songs = self.__songinfo.songs
        win = WritingWindow(self, len(songs))
        win.show()
        for song in songs:
            if not song.valid() and not qltk.ConfirmAction(
                    self, _("Tag may not be accurate"),
                    _("<b>%s</b> changed while the program was running. "
                      "Saving without refreshing your library may "
                      "overwrite other changes to the song.\n\n"
                      "Save this song anyway?") %
                    util.escape(util.fsdecode(song("~basename")))).run():
                break

            changed = False
            for key, values in updated.iteritems():
                for (new_value, old_value) in values:
                    new_value = util.unescape(new_value)
                    if song.can_change(key):
                        if old_value is None:
                            song.add(key, new_value)
                        else:
                            song.change(key, old_value, new_value)
                        changed = True
            for key, values in added.iteritems():
                for value in values:
                    value = util.unescape(value)
                    if song.can_change(key):
                        song.add(key, value)
                        changed = True
            for key, values in deleted.iteritems():
                for value in values:
                    value = util.unescape(value)
                    if song.can_change(key) and key in song:
                        song.remove(key, value)
                        changed = True
            save_rename = []
            for new_tag, values in renamed.iteritems():
                for old_tag, new_value, old_value in values:
                    old_tag = util.unescape(old_tag)
                    old_value = util.unescape(old_value)
                    new_value = util.unescape(new_value)
                    if (song.can_change(new_tag) and song.can_change(old_tag)
                            and old_tag in song):
                        if not is_special(new_value):
                            song.remove(old_tag, old_value)
                            save_rename.append((new_tag, new_value))
                        elif is_missing(new_value):
                            value = strip_missing(old_value)
                            song.remove(old_tag, old_value)
                            save_rename.append((new_tag, new_value))
                        else:
                            save_rename.append((new_tag, song[old_tag]))
                            song.remove(old_tag, None)
                        changed = True
            for tag, value in save_rename:
                song.add(tag, value)

            if changed:
                try:
                    song.write()
                except:
                    util.print_exc()
                    qltk.ErrorMessage(
                        self, _("Unable to save song"),
                        _("Saving <b>%s</b> failed. The file "
                          "may be read-only, corrupted, or you "
                          "do not have permission to edit it.") %
                        (util.escape(fsdecode(song('~basename'))))).run()
                    library.reload(song, changed=was_changed)
                    break
                was_changed.add(song)

            if win.step():
                break

        win.destroy()
        library.changed(was_changed)
        for b in [save, revert]:
            b.set_sensitive(False)
コード例 #50
0
    def __preview(self, songs):
        if songs is None:
            songs = [row[0].song for row in (self.view.get_model() or [])]

        if songs:
            pattern_text = self.combo.get_child().get_text().decode("utf-8")
        else:
            pattern_text = ""
        try:
            pattern = TagsFromPattern(pattern_text)
        except re.error:
            qltk.ErrorMessage(
                self, _("Invalid pattern"),
                _("The pattern\n\t<b>%s</b>\nis invalid. "
                  "Possibly it contains the same tag twice or "
                  "it has unbalanced brackets (&lt; / &gt;).") %
                (util.escape(pattern_text))).run()
            return
        else:
            if pattern_text:
                self.combo.prepend_text(pattern_text)
                self.combo.write(const.TBP)

        invalid = []

        for header in pattern.headers:
            if not min([song.can_change(header) for song in songs]):
                invalid.append(header)
        if len(invalid) and songs:
            if len(invalid) == 1:
                title = _("Invalid tag")
                msg = _("Invalid tag <b>%s</b>\n\nThe files currently"
                        " selected do not support editing this tag.")
            else:
                title = _("Invalid tags")
                msg = _("Invalid tags <b>%s</b>\n\nThe files currently"
                        " selected do not support editing these tags.")
            qltk.ErrorMessage(self, title, msg % ", ".join(invalid)).run()
            pattern = TagsFromPattern("")

        self.view.set_model(None)
        model = ObjectStore()
        for col in self.view.get_columns():
            self.view.remove_column(col)

        render = Gtk.CellRendererText()
        col = TreeViewColumn(_('File'), render)
        col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)

        def cell_data_file(column, cell, model, iter_, data):
            entry = model.get_value(iter_)
            cell.set_property("text", entry.name)

        col.set_cell_data_func(render, cell_data_file)

        def cell_data_header(column, cell, model, iter_, header):
            entry = model.get_value(iter_)
            cell.set_property("text", entry.get_match(header))

        self.view.append_column(col)
        for i, header in enumerate(pattern.headers):
            render = Gtk.CellRendererText()
            render.set_property('editable', True)
            render.connect('edited', self.__row_edited, model, header)
            escaped_title = header.replace("_", "__")
            col = Gtk.TreeViewColumn(escaped_title, render)
            col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
            col.set_cell_data_func(render, cell_data_header, header)
            self.view.append_column(col)

        for song in songs:
            entry = ListEntry(song)
            match = pattern.match(song)
            for h in pattern.headers:
                text = match.get(h, '')
                for f in self.filter_box.filters:
                    if f.active:
                        text = f.filter(h, text)
                if not song.can_multiple_values(h):
                    text = u", ".join(text.split("\n"))
                entry.matches[h] = text
            model.append([entry])

        # save for last to potentially save time
        if songs:
            self.view.set_model(model)
        self.preview.set_sensitive(False)
        self.save.set_sensitive(len(pattern.headers) > 0)
コード例 #51
0
ファイル: information.py プロジェクト: darthoctopus/quodlibet
 def _title(self, song, box):
     text = song.comma("title")
     if "version" in song:
         text += "\n" + util.escape(song.comma("version"))
     box.pack_start(TitleLabel(text), False, False, 0)
     self.title = song.comma("title")
コード例 #52
0
 def escape_data(data):
     for rep in ('\n', '\t', '\r', '\v'):
         data = data.replace(rep, ' ')
     return util.escape(' '.join(data.split()))
コード例 #53
0
ファイル: _pattern.py プロジェクト: mistotebe/quodlibet
 def _format(self, key, value):
     return util.escape(value)
コード例 #54
0
ファイル: information.py プロジェクト: darthoctopus/quodlibet
 def __init__(self, text, is_markup=False):
     super(TitleLabel, self).__init__()
     self.set_ellipsize(Pango.EllipsizeMode.END)
     markup = text if is_markup else ("<i>%s</i>" % util.escape(text))
     text = "<span size='xx-large'>%s</span>" % markup
     self.set_markup(text)
コード例 #55
0
    def __init__(self):
        super(PatternEditor, self).__init__(spacing=6)

        self.__headers = headers = {}
        buttons = []

        group = None
        for tags in self.PRESETS:
            tied = "~" + "~".join(tags)
            group = Gtk.RadioButton(group=group,
                                    label="_" + util.tag(tied),
                                    use_underline=True)
            headers[group] = tags
            buttons.append(group)

        group = Gtk.RadioButton(group=group,
                                label=_("_Custom"),
                                use_underline=True)
        self.__custom = group
        headers[group] = []
        buttons.append(group)

        button_box = Gtk.HBox(spacing=6)
        self.__model = model = Gtk.ListStore(str)

        radio_box = Gtk.VBox(spacing=6)
        for button in buttons:
            radio_box.pack_start(button, False, True, 0)
            button.connect('toggled', self.__toggled, button_box, model)

        self.pack_start(radio_box, False, True, 0)

        tooltip = _("Tag pattern with optional markup "
                    "e.g. <tt>composer</tt> or\n<tt>%s</tt>" %
                    escape(self._COMPLEX_PATTERN_EXAMPLE))
        cb = TagsComboBoxEntry(self.COMPLETION, tooltip_markup=tooltip)

        view = BaseView(model=model)
        view.set_reorderable(True)
        view.set_headers_visible(False)

        ctrl_box = Gtk.VBox(spacing=6)

        add = Button(_("_Add"), Icons.LIST_ADD)
        ctrl_box.pack_start(add, False, True, 0)
        add.connect('clicked', self.__add, model, cb)

        remove = Button(_("_Remove"), Icons.LIST_REMOVE)
        ctrl_box.pack_start(remove, False, True, 0)
        remove.connect('clicked', self.__remove, view)

        selection = view.get_selection()
        selection.connect('changed', self.__selection_changed, remove)
        selection.emit('changed')

        sw = Gtk.ScrolledWindow()
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        sw.set_shadow_type(Gtk.ShadowType.IN)
        sw.add(view)

        edit_box = Gtk.VBox(spacing=6)
        edit_box.pack_start(cb, False, True, 0)
        edit_box.pack_start(sw, True, True, 0)

        button_box.pack_start(edit_box, True, True, 0)
        button_box.pack_start(ctrl_box, False, True, 0)
        self.pack_start(button_box, True, True, 0)

        render = Gtk.CellRendererText()
        render.set_property("editable", True)

        def edited_cb(render, path, text, model):
            model[path][0] = text

        render.connect("edited", edited_cb, model)

        column = Gtk.TreeViewColumn(None, render, text=0)
        view.append_column(column)
コード例 #56
0
 def __str__(self):
     return util.escape(self)
コード例 #57
0
 def f(v):
     return "<b>%s</b>" % escape(format_version(v))
コード例 #58
0
 def test_escape_empty(self):
     self.failUnlessEqual(util.escape(""), "")
コード例 #59
0
    def PluginPreferences(self, song):
        def changed_cb(hscale, key):
            val = hscale.get_value()
            self.weights[key] = val
            config.set("plugins", "randomalbum_%s" % key, val)

        def delay_changed_cb(spin):
            self.delay = int(spin.get_value())
            config.set("plugins", "randomalbum_delay", str(self.delay))

        def toggled_cb(check, widgets):
            self.use_weights = check.get_active()
            for w in widgets:
                w.set_sensitive(self.use_weights)
            config.set("plugins", "randomalbum_use_weights",
                       str(int(self.use_weights)))

        vbox = Gtk.VBox(spacing=12)
        table = Gtk.Table(n_rows=len(self.keys) + 1, n_columns=3)
        table.set_border_width(3)

        hbox = Gtk.HBox(spacing=6)
        spin = Gtk.SpinButton(
            adjustment=Gtk.Adjustment.new(self.delay, 0, 3600, 1, 10, 0))
        spin.connect("value-changed", delay_changed_cb)
        hbox.pack_start(spin, False, True, 0)
        lbl = Gtk.Label(label=_("seconds before starting next album"))
        hbox.pack_start(lbl, False, True, 0)
        vbox.pack_start(hbox, True, True, 0)

        frame = Gtk.Frame(label=_("Weights"))

        check = Gtk.CheckButton(label=_("Play some albums more than others"))
        vbox.pack_start(check, False, True, 0)
        # Toggle both frame and contained table; frame doesn't always work?
        check.connect("toggled", toggled_cb, [frame, table])
        check.set_active(self.use_weights)
        toggled_cb(check, [frame, table])

        frame.add(table)
        vbox.pack_start(frame, True, True, 0)

        # Less label
        less_lbl = Gtk.Label()
        arr = Gtk.Arrow(arrow_type=Gtk.ArrowType.LEFT,
                        shadow_type=Gtk.ShadowType.OUT)
        less_lbl.set_markup("<i>%s</i>" % util.escape(_("avoid")))
        less_lbl.set_alignment(0, 0)
        hb = Gtk.HBox(spacing=0)
        hb.pack_start(arr, False, True, 0)
        hb.pack_start(less_lbl, True, True, 0)
        table.attach(hb,
                     1,
                     2,
                     0,
                     1,
                     xpadding=3,
                     xoptions=Gtk.AttachOptions.FILL)
        # More label
        more_lbl = Gtk.Label()
        arr = Gtk.Arrow(arrow_type=Gtk.ArrowType.RIGHT,
                        shadow_type=Gtk.ShadowType.OUT)
        more_lbl.set_markup("<i>%s</i>" % util.escape(_("prefer")))
        more_lbl.set_alignment(1, 0)
        hb = Gtk.HBox(spacing=0)
        hb.pack_end(arr, False, True, 0)
        hb.pack_end(more_lbl, True, True, 0)
        table.attach(hb,
                     2,
                     3,
                     0,
                     1,
                     xpadding=3,
                     xoptions=Gtk.AttachOptions.FILL)

        for (idx, (key, text, func)) in enumerate(self.keys):
            lbl = Gtk.Label(label=text)
            lbl.set_alignment(0, 0)
            table.attach(lbl,
                         0,
                         1,
                         idx + 1,
                         idx + 2,
                         xoptions=Gtk.AttachOptions.FILL,
                         xpadding=3,
                         ypadding=3)
            adj = Gtk.Adjustment(lower=-1.0, upper=1.0, step_increment=0.1)
            hscale = Gtk.HScale(adjustment=adj)
            hscale.set_value(self.weights[key])
            hscale.set_draw_value(False)
            hscale.set_show_fill_level(False)
            hscale.connect("value-changed", changed_cb, key)
            lbl.set_mnemonic_widget(hscale)
            table.attach(hscale,
                         1,
                         3,
                         idx + 1,
                         idx + 2,
                         xpadding=3,
                         ypadding=3)

        return vbox
コード例 #60
0
ファイル: information.py プロジェクト: darthoctopus/quodlibet
 def format(args):
     date, song, album = args
     markup = "<big><i>%s</i></big>" % util.escape(album)
     return "%s (%s)" % (markup, date[:4]) if date else markup