Exemplo n.º 1
0
 def setUp(self):
     config.RATINGS = config.HardCodedRatingsPrefs()
     self.failUnlessEqual(config.RATINGS.number, NUM_RATINGS)
     self.library = SongLibrary()
     self.library.librarian = SongLibrarian()
     self.af = AudioFile({"~filename": fsnative(u"/foo"), "~#rating": 1.0})
     self.af.sanitize()
     self.rmi = RatingsMenuItem([self.af], self.library)
Exemplo n.º 2
0
 def test_no_rating(self):
     af = AudioFile({"~filename": fsnative(u"/foobar"), 'artist': 'foo'})
     rmi = RatingsMenuItem([af], self.library)
     children = [
         mi for mi in rmi.get_submenu().get_children()
         if isinstance(mi, Gtk.CheckMenuItem)
     ]
     self.failIf(any([c.get_active() for c in children]))
Exemplo n.º 3
0
 def test_menuitem(self):
     library = SongLibrary()
     library.librarian = SongLibrarian()
     a = AudioFile({"~filename": fsnative(u"/foo")})
     a.sanitize()
     x = RatingsMenuItem([a], library)
     x.set_rating(0, [a], library)
     x.destroy()
     library.destroy()
     library.librarian.destroy()
    def Menu(self, header, browser, library):
        songs = self.get_selected_songs()
        if not songs:
            return

        can_filter = browser.can_filter

        menu = browser.Menu(songs, self, library)

        def Filter(t):
            # Translators: The substituted string is the name of the
            # selected column (a translated tag name).
            b = qltk.MenuItem(
                _("_Filter on %s") % util.tag(t, True), Gtk.STOCK_INDEX)
            b.connect_object('activate', self.__filter_on, t, songs, browser)
            return b

        header = util.tagsplit(header)[0]

        if can_filter("artist") or can_filter("album") or can_filter(header):
            menu.preseparate()

        if can_filter("artist"):
            menu.prepend(Filter("artist"))
        if can_filter("album"):
            menu.prepend(Filter("album"))
        if (header not in ["artist", "album"] and can_filter(header)):
            menu.prepend(Filter(header))

        ratings = RatingsMenuItem(songs, library)
        menu.preseparate()
        menu.prepend(ratings)
        menu.show_all()
        return menu
 def setUp(self):
     config.RATINGS = config.HardCodedRatingsPrefs()
     self.failUnlessEqual(config.RATINGS.number, NUM_RATINGS)
     self.library = SongLibrary()
     self.library.librarian = SongLibrarian()
     self.af = AudioFile({"~filename": fsnative(u"/foo"), "~#rating": 1.0})
     self.af.sanitize()
     self.rmi = RatingsMenuItem([self.af], self.library)
Exemplo n.º 6
0
class TRatingsMenuItem(TestCase):

    def setUp(self):
        config.RATINGS = config.HardCodedRatingsPrefs()
        self.failUnlessEqual(config.RATINGS.number, NUM_RATINGS)
        self.library = SongLibrary()
        self.library.librarian = SongLibrarian()
        self.af = AudioFile({"~filename": fsnative(u"/foo"), "~#rating": 1.0})
        self.af.sanitize()
        self.rmi = RatingsMenuItem([self.af], self.library)

    def tearDown(self):
        self.rmi.destroy()
        self.library.destroy()
        self.library.librarian.destroy()

    def test_menuitem_children(self):
        children = [mi for mi in self.rmi.get_submenu().get_children()
                    if isinstance(mi, Gtk.CheckMenuItem)]
        self.failUnlessEqual(len(children), NUM_RATINGS + 1)
        highest = children[-1]
        self.failUnlessEqual(highest.get_active(), True)
        self.failUnlessEqual(children[1].get_active(), False)

    def test_set_remove_rating(self):
        self.rmi.set_rating(0.5, [self.af], self.library)
        self.failUnless(self.af.has_rating)
        self.failUnlessEqual(self.af('~#rating'), 0.5)
        self.rmi.remove_rating([self.af], self.library)
        self.failIf(self.af.has_rating)
Exemplo n.º 7
0
 def test_menuitem(self):
     library = SongLibrary()
     library.librarian = SongLibrarian()
     a = AudioFile({"~filename": "/foo"})
     a.sanitize()
     x = RatingsMenuItem([a], library)
     x.set_rating(0, [a], library)
     x.destroy()
     library.destroy()
     library.librarian.destroy()
Exemplo n.º 8
0
class TRatingsMenuItem(TestCase):
    def setUp(self):
        config.RATINGS = config.HardCodedRatingsPrefs()
        self.failUnlessEqual(config.RATINGS.number, NUM_RATINGS)
        self.library = SongLibrary()
        self.library.librarian = SongLibrarian()
        self.af = AudioFile({"~filename": fsnative(u"/foo"), "~#rating": 1.0})
        self.af.sanitize()
        self.rmi = RatingsMenuItem([self.af], self.library)

    def tearDown(self):
        self.rmi.destroy()
        self.library.destroy()
        self.library.librarian.destroy()

    def test_menuitem_children(self):
        children = [
            mi for mi in self.rmi.get_submenu().get_children()
            if isinstance(mi, Gtk.CheckMenuItem)
        ]
        self.failUnlessEqual(len(children), NUM_RATINGS + 1)
        highest = children[-1]
        self.failUnlessEqual(highest.get_active(), True)
        self.failUnlessEqual(children[1].get_active(), False)

    def test_no_rating(self):
        af = AudioFile({"~filename": fsnative(u"/foobar"), 'artist': 'foo'})
        rmi = RatingsMenuItem([af], self.library)
        children = [
            mi for mi in rmi.get_submenu().get_children()
            if isinstance(mi, Gtk.CheckMenuItem)
        ]
        self.failIf(any([c.get_active() for c in children]))

    def test_set_remove_rating(self):
        self.rmi.set_rating(0.5, [self.af], self.library)
        self.failUnless(self.af.has_rating)
        self.failUnlessEqual(self.af('~#rating'), 0.5)
        self.rmi.remove_rating([self.af], self.library)
        self.failIf(self.af.has_rating)
Exemplo n.º 9
0
    def __init__(self,
                 library,
                 songs,
                 plugins=True,
                 playlists=True,
                 queue=True,
                 remove=True,
                 delete=False,
                 edit=True,
                 ratings=True,
                 show_files=True,
                 items=None,
                 accels=True,
                 removal_confirmer=None):
        super().__init__()
        # The library may actually be a librarian; if it is, use it,
        # otherwise find the real librarian.
        librarian = getattr(library, 'librarian', library)

        if ratings:
            ratings_item = RatingsMenuItem(songs, librarian)
            ratings_item.set_sensitive(bool(songs))
            self.append(ratings_item)
            self.separate()

        # external item groups
        for subitems in reversed(items or []):
            self.separate()
            for item in subitems:
                self.append(item)
            self.separate()

        if plugins:
            submenu = self.plugins.Menu(librarian, songs)
            if submenu is not None:
                b = qltk.MenuItem(_("_Plugins"), Icons.SYSTEM_RUN)
                b.set_sensitive(bool(songs))
                self.append(b)
                b.set_submenu(submenu)
                self.append(SeparatorMenuItem())

        in_lib = True
        can_add = True
        is_file = True
        for song in songs:
            if song not in library:
                in_lib = False
            if not song.can_add:
                can_add = False
            if not song.is_file:
                is_file = False

        if playlists:
            # Needed here to avoid a circular import; most browsers use
            # a SongsMenu, but SongsMenu needs access to the playlist
            # browser for this item.

            # FIXME: Two things are now importing browsers, so we need
            # some kind of inversion of control here.
            from quodlibet.browsers.playlists.menu import PlaylistMenu
            from quodlibet.browsers.playlists import PlaylistsBrowser
            try:
                submenu = PlaylistMenu(songs, PlaylistsBrowser.playlists())

                def on_new(widget, playlist):
                    PlaylistsBrowser.changed(playlist)

                submenu.connect('new', on_new)
            except AttributeError as e:
                print_w("Couldn't get Playlists menu: %s" % e)
            else:
                b = qltk.MenuItem(_("Play_lists"), Icons.FOLDER_DRAG_ACCEPT)
                b.set_sensitive(can_add and bool(songs))
                b.set_submenu(submenu)
                self.append(b)
        if queue:
            b = qltk.MenuItem(_("Add to _Queue"), Icons.LIST_ADD)

            def enqueue_cb(item, songs):
                songs = [s for s in songs if s.can_add]
                if songs:
                    from quodlibet import app
                    app.window.playlist.enqueue(songs)

            b.connect('activate', enqueue_cb, songs)
            if accels:
                qltk.add_fake_accel(b, "<Primary>Return")
            self.append(b)
            b.set_sensitive(can_add and bool(songs))

        if remove or delete:
            self.separate()

        if remove:
            self._confirm_song_removal = (removal_confirmer
                                          or confirm_song_removal_invoke)
            b = qltk.MenuItem(_("_Remove from Library…"), Icons.LIST_REMOVE)
            if callable(remove):
                b.connect('activate', lambda item: remove(songs))
            else:

                def remove_cb(item, songs, library):
                    parent = get_menu_item_top_parent(item)
                    if self._confirm_song_removal(parent, songs):
                        library.remove(songs)

                b.connect('activate', remove_cb, songs, library)
                b.set_sensitive(in_lib and bool(songs))
            self.append(b)

        if delete:
            if callable(delete):
                b = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE)
                b.connect('activate', lambda item: delete(songs))
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")
            else:
                b = TrashMenuItem()
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")

                def trash_cb(item):
                    parent = get_menu_item_top_parent(item)
                    trash_songs(parent, songs, librarian)

                b.connect('activate', trash_cb)
                b.set_sensitive(is_file and bool(songs))
            self.append(b)

        if edit:
            self.separate()
            b = qltk.MenuItem(_("Edit _Tags"), Icons.EDIT)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<alt>Return")

            def song_properties_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = SongProperties(librarian, songs, parent)
                window.show()

            b.connect('activate', song_properties_cb)
            self.append(b)

            b = qltk.MenuItem(_("_Information"), Icons.DIALOG_INFORMATION)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<Primary>I")

            def information_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = Information(librarian, songs, parent)
                window.show()

            b.connect('activate', information_cb)
            self.append(b)

        if show_files and any(is_a_file(s) for s in songs):

            def show_files_cb(menu_item):
                print_d("Trying to show files...")
                if not show_songs(songs):
                    parent = get_menu_item_top_parent(menu_item)
                    msg = ErrorMessage(
                        parent, _("Unable to show files"),
                        _("Error showing files, "
                          "or no program available to show them."))
                    msg.run()

            self.separate()
            total = len([s for s in songs if is_a_file(s)])
            text = ngettext("_Show in File Manager",
                            "_Show %(total)d Files in File Manager", total) % {
                                "total": total
                            }
            b = qltk.MenuItem(text, Icons.DOCUMENT_OPEN)
            b.set_sensitive(
                bool(songs) and len(songs) < MenuItemPlugin.MAX_INVOCATIONS)
            b.connect('activate', show_files_cb)
            self.append(b)

        def selection_done_cb(menu):
            menu.destroy()

        self.connect('selection-done', selection_done_cb)
Exemplo n.º 10
0
    def __init__(self, app, add_show_item=False):
        super().__init__()

        self._app = app
        player = app.player

        show_item_bottom = is_plasma()
        if add_show_item:
            show_item = Gtk.CheckMenuItem.new_with_mnemonic(
                _("_Show %(application-name)s") %
                {"application-name": app.name})

            def on_toggled(menuitem):
                if menuitem.get_active():
                    app.present()
                else:
                    app.hide()

            self._toggle_id = show_item.connect("toggled", on_toggled)

            def on_visible_changed(*args):
                with show_item.handler_block(self._toggle_id):
                    show_item.set_active(app.window.get_visible())

            connect_destroy(app.window, "notify::visible", on_visible_changed)
        else:
            show_item = None

        self._play_item = MenuItem(_("_Play"), Icons.MEDIA_PLAYBACK_START)
        self._play_item.connect("activate", self._on_play_pause, player)
        self._play_item.set_no_show_all(True)
        self._pause_item = MenuItem(_("P_ause"), Icons.MEDIA_PLAYBACK_PAUSE)
        self._pause_item.connect("activate", self._on_play_pause, player)
        self._pause_item.set_no_show_all(True)
        self._action_item = None

        previous = MenuItem(_("Pre_vious"), Icons.MEDIA_SKIP_BACKWARD)
        previous.connect('activate', lambda *args: player.previous(force=True))

        next = MenuItem(_("_Next"), Icons.MEDIA_SKIP_FORWARD)
        next.connect('activate', lambda *args: player.next())

        player_options = app.player_options

        shuffle = Gtk.CheckMenuItem(label=_("_Shuffle"), use_underline=True)
        player_options.bind_property("shuffle", shuffle, "active",
                                     GObject.BindingFlags.BIDIRECTIONAL)
        player_options.notify("shuffle")

        repeat = Gtk.CheckMenuItem(label=_("_Repeat"), use_underline=True)
        player_options.bind_property("repeat", repeat, "active",
                                     GObject.BindingFlags.BIDIRECTIONAL)
        player_options.notify("repeat")

        safter = Gtk.CheckMenuItem(label=_("Stop _After This Song"),
                                   use_underline=True)
        player_options.bind_property("stop-after", safter, "active",
                                     GObject.BindingFlags.BIDIRECTIONAL)
        player_options.notify("stop-after")

        browse = qltk.MenuItem(_("Open _Browser"), Icons.EDIT_FIND)
        browse_sub = Gtk.Menu()

        for Kind in browsers.browsers:
            i = Gtk.MenuItem(label=Kind.accelerated_name, use_underline=True)
            connect_obj(i, 'activate', LibraryBrowser.open, Kind, app.library,
                        app.player)
            browse_sub.append(i)

        browse.set_submenu(browse_sub)

        self._props = qltk.MenuItem(_("Edit _Tags"), Icons.EDIT)

        def on_properties(*args):
            song = player.song
            window = SongProperties(app.librarian, [song])
            window.show()

        self._props.connect('activate', on_properties)

        self._info = MenuItem(_("_Information"), Icons.DIALOG_INFORMATION)

        self._playlists_item = MenuItem(_("Play_lists"),
                                        Icons.FOLDER_DRAG_ACCEPT)
        self._new_playlist_submenu_for(player.song)

        def on_information(*args):
            song = player.song
            window = Information(app.librarian, [song])
            window.show()

        self._info.connect('activate', on_information)

        def set_rating(value):
            song = player.song
            song["~#rating"] = value
            app.librarian.changed([song])

        self._rating_item = rating = RatingsMenuItem([], app.library)

        quit = MenuItem(_("_Quit"), Icons.APPLICATION_EXIT)
        quit.connect('activate', lambda *x: app.quit())

        if not show_item_bottom and show_item:
            self.append(show_item)
            self.append(SeparatorMenuItem())

        self.append(self._play_item)
        self.append(self._pause_item)
        self.append(previous)
        self.append(next)
        self.append(SeparatorMenuItem())
        self.append(shuffle)
        self.append(repeat)
        self.append(safter)
        self.append(SeparatorMenuItem())
        self.append(rating)
        self.append(self._playlists_item)
        self.append(self._props)
        self.append(self._info)
        self.append(SeparatorMenuItem())
        self.append(browse)
        self.append(SeparatorMenuItem())
        self.append(quit)

        if show_item_bottom and show_item:
            self.append(SeparatorMenuItem())
            self.append(show_item)

        self.show_all()

        self.set_paused(True)
        self.set_song(None)
Exemplo n.º 11
0
    def __init__(self, library, songs, plugins=True, playlists=True,
                 queue=True, devices=True, remove=True, delete=False,
                 edit=True, ratings=True, items=None, accels=True):
        super(SongsMenu, self).__init__()

        # The library may actually be a librarian; if it is, use it,
        # otherwise find the real librarian.
        librarian = getattr(library, 'librarian', library)

        if ratings:
            ratings_item = RatingsMenuItem(songs, librarian)
            ratings_item.set_sensitive(bool(songs))
            self.append(ratings_item)
            self.separate()

        # external item groups
        for subitems in reversed(items or []):
            self.separate()
            for item in subitems:
                self.append(item)
            self.separate()

        if plugins:
            submenu = self.plugins.Menu(librarian, songs)
            if submenu is not None:
                b = qltk.MenuItem(_("_Plugins"), Icons.SYSTEM_RUN)
                b.set_sensitive(bool(songs))
                self.append(b)
                b.set_submenu(submenu)
                self.append(SeparatorMenuItem())

        in_lib = True
        can_add = True
        is_file = True
        for song in songs:
            if song not in library:
                in_lib = False
            if not song.can_add:
                can_add = False
            if not song.is_file:
                is_file = False

        if playlists:
            # Needed here to avoid a circular import; most browsers use
            # a SongsMenu, but SongsMenu needs access to the playlist
            # browser for this item.

            # FIXME: Two things are now importing browsers, so we need
            # some kind of inversion of control here.
            from quodlibet.browsers.playlists.menu import PlaylistMenu
            try:
                submenu = PlaylistMenu(songs)
            except AttributeError as e:
                print_w("Couldn't get Playlists menu: %s" % e)
            else:
                b = qltk.MenuItem(_("Play_lists"), Icons.LIST_ADD)
                b.set_sensitive(can_add and bool(songs))
                b.set_submenu(submenu)
                self.append(b)
        if queue:
            b = qltk.MenuItem(_("Add to _Queue"), Icons.LIST_ADD)

            def enqueue_cb(item, songs):
                songs = filter(lambda s: s.can_add, songs)
                if songs:
                    from quodlibet import app
                    app.window.playlist.enqueue(songs)

            b.connect('activate', enqueue_cb, songs)
            if accels:
                qltk.add_fake_accel(b, "<Primary>Return")
            self.append(b)
            b.set_sensitive(can_add and bool(songs))

        if devices:
            from quodlibet import browsers
            try:
                browsers.media
            except AttributeError:
                pass
            else:
                if browsers.media.MediaDevices in browsers.browsers:
                    submenu = browsers.media.Menu(songs, library)
                    b = qltk.MenuItem(_("_Copy to Device"), Icons.EDIT_COPY)
                    b.set_sensitive(
                        can_add and len(submenu) > 0 and bool(songs))
                    b.set_submenu(submenu)
                    self.append(b)

        if remove or delete:
            self.separate()

        if remove:
            b = qltk.MenuItem(_("_Remove from Library"), Icons.LIST_REMOVE)
            if callable(remove):
                b.connect('activate', lambda item: remove(songs))
            else:
                def remove_cb(item, songs, library):
                    library.remove(set(songs))

                b.connect('activate', remove_cb, songs, library)
                b.set_sensitive(in_lib and bool(songs))
            self.append(b)

        if delete:
            if callable(delete):
                b = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE)
                b.connect('activate', lambda item: delete(songs))
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")
            else:
                b = TrashMenuItem()
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")

                def trash_cb(item):
                    parent = get_menu_item_top_parent(item)
                    trash_songs(parent, songs, librarian)

                b.connect('activate', trash_cb)
                b.set_sensitive(is_file and bool(songs))
            self.append(b)

        if edit:
            self.separate()
            b = qltk.MenuItem(_("Edit _Tags"), Icons.DOCUMENT_PROPERTIES)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<alt>Return")

            def song_properties_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = SongProperties(librarian, songs, parent)
                window.show()

            b.connect('activate', song_properties_cb)
            self.append(b)

            b = qltk.MenuItem(_("_Information"), Icons.DIALOG_INFORMATION)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<Primary>I")

            def information_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = Information(librarian, songs, parent)
                window.show()
            b.connect('activate', information_cb)
            self.append(b)

        def selection_done_cb(menu):
            menu.destroy()

        self.connect('selection-done', selection_done_cb)
Exemplo n.º 12
0
    def __init__(self,
                 library,
                 songs,
                 plugins=True,
                 playlists=True,
                 queue=True,
                 devices=True,
                 remove=True,
                 delete=False,
                 edit=True,
                 ratings=True,
                 items=None,
                 accels=True):
        super(SongsMenu, self).__init__()

        # The library may actually be a librarian; if it is, use it,
        # otherwise find the real librarian.
        librarian = getattr(library, 'librarian', library)

        if ratings:
            ratings_item = RatingsMenuItem(songs, librarian)
            ratings_item.set_sensitive(bool(songs))
            self.append(ratings_item)
            self.separate()

        # external item groups
        for subitems in reversed(items or []):
            self.separate()
            for item in subitems:
                self.append(item)
            self.separate()

        if plugins:
            submenu = self.plugins.Menu(librarian, songs)
            if submenu is not None:
                b = qltk.MenuItem(_("_Plugins"), Icons.SYSTEM_RUN)
                b.set_sensitive(bool(songs))
                self.append(b)
                b.set_submenu(submenu)
                self.append(SeparatorMenuItem())

        in_lib = True
        can_add = True
        is_file = True
        for song in songs:
            if song not in library:
                in_lib = False
            if not song.can_add:
                can_add = False
            if not song.is_file:
                is_file = False

        if playlists:
            # Needed here to avoid a circular import; most browsers use
            # a SongsMenu, but SongsMenu needs access to the playlist
            # browser for this item.

            # FIXME: Two things are now importing browsers, so we need
            # some kind of inversion of control here.
            from quodlibet.browsers.playlists.menu import PlaylistMenu
            try:
                submenu = PlaylistMenu(songs)
            except AttributeError as e:
                print_w("Couldn't get Playlists menu: %s" % e)
            else:
                b = qltk.MenuItem(_("Play_lists"), Icons.LIST_ADD)
                b.set_sensitive(can_add and bool(songs))
                b.set_submenu(submenu)
                self.append(b)
        if queue:
            b = qltk.MenuItem(_("Add to _Queue"), Icons.LIST_ADD)

            def enqueue_cb(item, songs):
                songs = filter(lambda s: s.can_add, songs)
                if songs:
                    from quodlibet import app
                    app.window.playlist.enqueue(songs)

            b.connect('activate', enqueue_cb, songs)
            if accels:
                qltk.add_fake_accel(b, "<Primary>Return")
            self.append(b)
            b.set_sensitive(can_add and bool(songs))

        if devices:
            from quodlibet import browsers
            try:
                browsers.media
            except AttributeError:
                pass
            else:
                if browsers.media.MediaDevices in browsers.browsers:
                    submenu = browsers.media.Menu(songs, library)
                    b = qltk.MenuItem(_("_Copy to Device"), Icons.EDIT_COPY)
                    b.set_sensitive(can_add and len(submenu) > 0
                                    and bool(songs))
                    b.set_submenu(submenu)
                    self.append(b)

        if remove or delete:
            self.separate()

        if remove:
            b = qltk.MenuItem(_("_Remove from Library"), Icons.LIST_REMOVE)
            if callable(remove):
                b.connect('activate', lambda item: remove(songs))
            else:

                def remove_cb(item, songs, library):
                    library.remove(set(songs))

                b.connect('activate', remove_cb, songs, library)
                b.set_sensitive(in_lib and bool(songs))
            self.append(b)

        if delete:
            if callable(delete):
                b = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE)
                b.connect('activate', lambda item: delete(songs))
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")
            else:
                b = TrashMenuItem()
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")

                def trash_cb(item):
                    parent = get_menu_item_top_parent(item)
                    trash_songs(parent, songs, librarian)

                b.connect('activate', trash_cb)
                b.set_sensitive(is_file and bool(songs))
            self.append(b)

        if edit:
            self.separate()
            b = qltk.MenuItem(_("Edit _Tags"), Icons.DOCUMENT_PROPERTIES)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<alt>Return")

            def song_properties_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = SongProperties(librarian, songs, parent)
                window.show()

            b.connect('activate', song_properties_cb)
            self.append(b)

            b = qltk.MenuItem(_("_Information"), Icons.DIALOG_INFORMATION)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<Primary>I")

            def information_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = Information(librarian, songs, parent)
                window.show()

            b.connect('activate', information_cb)
            self.append(b)

        def selection_done_cb(menu):
            menu.destroy()

        self.connect('selection-done', selection_done_cb)
Exemplo n.º 13
0
    def __init__(self,
                 library,
                 songs,
                 plugins=True,
                 playlists=True,
                 queue=True,
                 remove=True,
                 delete=False,
                 edit=True,
                 ratings=True,
                 show_files=True,
                 download=False,
                 items=None,
                 accels=True,
                 removal_confirmer=None,
                 folder_chooser=None):
        super().__init__()
        # The library may actually be a librarian; if it is, use it,
        # otherwise find the real librarian.
        librarian = getattr(library, 'librarian', library)

        if ratings:
            ratings_item = RatingsMenuItem(songs, librarian)
            ratings_item.set_sensitive(bool(songs))
            self.append(ratings_item)
            self.separate()

        # external item groups
        for subitems in reversed(items or []):
            self.separate()
            for item in subitems:
                self.append(item)
            self.separate()

        if plugins:
            submenu = self.plugins.Menu(librarian, songs)
            if submenu is not None:
                b = qltk.MenuItem(_("_Plugins"), Icons.SYSTEM_RUN)
                b.set_sensitive(bool(songs))
                self.append(b)
                b.set_submenu(submenu)
                self.append(SeparatorMenuItem())

        in_lib = True
        can_add = True
        is_file = True
        for song in songs:
            if song not in library:
                in_lib = False
            if not song.can_add:
                can_add = False
            if not song.is_file:
                is_file = False

        if playlists:
            try:
                from quodlibet.browsers.playlists.menu import PlaylistMenu
                submenu = PlaylistMenu(songs, library.playlists)
            except AttributeError as e:
                print_w("Couldn't get Playlists menu: %s" % e)
            else:
                b = qltk.MenuItem(_("Play_lists"), Icons.FOLDER_DRAG_ACCEPT)
                b.set_sensitive(can_add and bool(songs))
                b.set_submenu(submenu)
                self.append(b)
        if queue:
            b = qltk.MenuItem(_("Add to _Queue"), Icons.LIST_ADD)

            def enqueue_cb(item, songs):
                songs = [s for s in songs if s.can_add]
                if songs:
                    from quodlibet import app
                    app.window.playlist.enqueue(songs)

            b.connect('activate', enqueue_cb, songs)
            if accels:
                qltk.add_fake_accel(b, "<Primary>Return")
            self.append(b)
            b.set_sensitive(can_add and bool(songs))

        if remove or delete:
            self.separate()

        if remove:
            self._confirm_song_removal = (removal_confirmer
                                          or confirm_song_removal_invoke)
            b = qltk.MenuItem(_("_Remove from Library…"), Icons.LIST_REMOVE)
            if callable(remove):
                b.connect('activate', lambda item: remove(songs))
            else:

                def remove_cb(item, songs, library):
                    parent = get_menu_item_top_parent(item)
                    if self._confirm_song_removal(parent, songs):
                        library.remove(songs)

                b.connect('activate', remove_cb, songs, library)
                b.set_sensitive(in_lib and bool(songs))
            self.append(b)

        if delete:
            if callable(delete):
                b = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE)
                b.connect('activate', lambda item: delete(songs))
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")
            else:
                b = TrashMenuItem()
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")

                def trash_cb(item):
                    parent = get_menu_item_top_parent(item)
                    trash_songs(parent, songs, librarian)

                b.connect('activate', trash_cb)
                b.set_sensitive(is_file and bool(songs))
            self.append(b)

        if edit:
            self.separate()
            b = qltk.MenuItem(_("Edit _Tags"), Icons.EDIT)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<alt>Return")

            def song_properties_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = SongProperties(librarian, songs, parent)
                window.show()

            b.connect('activate', song_properties_cb)
            self.append(b)

            b = qltk.MenuItem(_("_Information"), Icons.DIALOG_INFORMATION)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<Primary>I")

            def information_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = Information(librarian, songs, parent)
                window.show()

            b.connect('activate', information_cb)
            self.append(b)

        if show_files and any(is_a_file(s) for s in songs):

            def show_files_cb(menu_item):
                print_d("Trying to show files...")
                if not show_songs(songs):
                    parent = get_menu_item_top_parent(menu_item)
                    msg = ErrorMessage(
                        parent, _("Unable to show files"),
                        _("Error showing files, "
                          "or no program available to show them."))
                    msg.run()

            self.separate()
            total = len([s for s in songs if is_a_file(s)])
            text = ngettext("_Show in File Manager",
                            "_Show %(total)d Files in File Manager", total) % {
                                "total": total
                            }
            b = qltk.MenuItem(text, Icons.DOCUMENT_OPEN)
            b.set_sensitive(
                bool(songs) and len(songs) < MenuItemPlugin.MAX_INVOCATIONS)
            b.connect('activate', show_files_cb)
            self.append(b)

        if download:

            def is_downloadable(song: AudioFile):
                return bool(not song.is_file and song.get("~uri", False))

            self.separate()
            relevant = [s for s in songs if is_downloadable(s)]
            total = len(relevant)
            text = ngettext("_Download file…", "_Download %(total)d files…",
                            total) % {
                                "total": total
                            }
            b = qltk.MenuItem(text, Icons.EMBLEM_DOWNLOADS)
            b.set_sensitive(relevant
                            and len(relevant) < MenuItemPlugin.MAX_INVOCATIONS)

            def _finished(p, successes, failures):
                msg = (f"<b>{successes}</b> " + _("successful") +
                       f"\n<b>{failures}</b> " + _("failed"))
                print_d(msg.replace("\n", "; "))
                warning = Message(Gtk.MessageType.INFO,
                                  app.window,
                                  _("Downloads complete"),
                                  msg,
                                  escape_desc=False)
                warning.run()

            def download_cb(menu_item):
                songs = relevant
                total = len(songs)
                msg = ngettext("Download {name!r} to",
                               "Download {total} files to", total)
                msg = msg.format(
                    name=next(iter(songs))("title")[:99] if total else "?",
                    total=total)
                chooser = folder_chooser or choose_folders
                paths = chooser(None,
                                msg,
                                _("Download here"),
                                allow_multiple=False)
                if not paths:
                    print_d("Cancelling download")
                    return
                path = paths[0]
                progress = DownloadProgress(songs)

                progress.connect('finished', _finished)
                copool.add(progress.download_songs, path)

            b.connect('activate', download_cb)
            self.append(b)

        def selection_done_cb(menu):
            menu.destroy()

        self.connect('selection-done', selection_done_cb)
 def test_no_rating(self):
     af = AudioFile({"~filename": fsnative(u"/foobar"), 'artist': 'foo'})
     rmi = RatingsMenuItem([af], self.library)
     children = [mi for mi in rmi.get_submenu().get_children()
                 if isinstance(mi, Gtk.CheckMenuItem)]
     self.failIf(any([c.get_active() for c in children]))
Exemplo n.º 15
0
    def __init__(self, library, songs, plugins=True, playlists=True,
                 queue=True, remove=True, delete=False, edit=True,
                 ratings=True, show_files=True, items=None, accels=True,
                 removal_confirmer=None):
        super(SongsMenu, self).__init__()
        # The library may actually be a librarian; if it is, use it,
        # otherwise find the real librarian.
        librarian = getattr(library, 'librarian', library)

        if ratings:
            ratings_item = RatingsMenuItem(songs, librarian)
            ratings_item.set_sensitive(bool(songs))
            self.append(ratings_item)
            self.separate()

        # external item groups
        for subitems in reversed(items or []):
            self.separate()
            for item in subitems:
                self.append(item)
            self.separate()

        if plugins:
            submenu = self.plugins.Menu(librarian, songs)
            if submenu is not None:
                b = qltk.MenuItem(_("_Plugins"), Icons.SYSTEM_RUN)
                b.set_sensitive(bool(songs))
                self.append(b)
                b.set_submenu(submenu)
                self.append(SeparatorMenuItem())

        in_lib = True
        can_add = True
        is_file = True
        for song in songs:
            if song not in library:
                in_lib = False
            if not song.can_add:
                can_add = False
            if not song.is_file:
                is_file = False

        if playlists:
            # Needed here to avoid a circular import; most browsers use
            # a SongsMenu, but SongsMenu needs access to the playlist
            # browser for this item.

            # FIXME: Two things are now importing browsers, so we need
            # some kind of inversion of control here.
            from quodlibet.browsers.playlists.menu import PlaylistMenu
            from quodlibet.browsers.playlists import PlaylistsBrowser
            try:
                submenu = PlaylistMenu(songs, PlaylistsBrowser.playlists())

                def on_new(widget, playlist):
                    PlaylistsBrowser.changed(playlist)
                submenu.connect('new', on_new)
            except AttributeError as e:
                print_w("Couldn't get Playlists menu: %s" % e)
            else:
                b = qltk.MenuItem(_("Play_lists"), Icons.FOLDER_DRAG_ACCEPT)
                b.set_sensitive(can_add and bool(songs))
                b.set_submenu(submenu)
                self.append(b)
        if queue:
            b = qltk.MenuItem(_("Add to _Queue"), Icons.LIST_ADD)

            def enqueue_cb(item, songs):
                songs = [s for s in songs if s.can_add]
                if songs:
                    from quodlibet import app
                    app.window.playlist.enqueue(songs)

            b.connect('activate', enqueue_cb, songs)
            if accels:
                qltk.add_fake_accel(b, "<Primary>Return")
            self.append(b)
            b.set_sensitive(can_add and bool(songs))

        if remove or delete:
            self.separate()

        if remove:
            self._confirm_song_removal = (removal_confirmer or
                                          confirm_song_removal_invoke)
            b = qltk.MenuItem(_("_Remove from Library…"), Icons.LIST_REMOVE)
            if callable(remove):
                b.connect('activate', lambda item: remove(songs))
            else:
                def remove_cb(item, songs, library):
                    parent = get_menu_item_top_parent(item)
                    if self._confirm_song_removal(parent, songs):
                        library.remove(songs)

                b.connect('activate', remove_cb, songs, library)
                b.set_sensitive(in_lib and bool(songs))
            self.append(b)

        if delete:
            if callable(delete):
                b = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE)
                b.connect('activate', lambda item: delete(songs))
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")
            else:
                b = TrashMenuItem()
                if accels:
                    qltk.add_fake_accel(b, "<Primary>Delete")

                def trash_cb(item):
                    parent = get_menu_item_top_parent(item)
                    trash_songs(parent, songs, librarian)

                b.connect('activate', trash_cb)
                b.set_sensitive(is_file and bool(songs))
            self.append(b)

        if edit:
            self.separate()
            b = qltk.MenuItem(_("Edit _Tags"), Icons.EDIT)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<alt>Return")

            def song_properties_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = SongProperties(librarian, songs, parent)
                window.show()

            b.connect('activate', song_properties_cb)
            self.append(b)

            b = qltk.MenuItem(_("_Information"), Icons.DIALOG_INFORMATION)
            b.set_sensitive(bool(songs))
            if accels:
                qltk.add_fake_accel(b, "<Primary>I")

            def information_cb(menu_item):
                parent = get_menu_item_top_parent(menu_item)
                window = Information(librarian, songs, parent)
                window.show()
            b.connect('activate', information_cb)
            self.append(b)

        if show_files and any(is_a_file(s) for s in songs):
            def show_files_cb(menu_item):
                print_d("Trying to show files...")
                if not show_songs(songs):
                    msg = ErrorMessage(self.plugin_window,
                                 _("Unable to show files"),
                                 _("Error showing files, "
                                   "or no program available to show them."))
                    msg.run()

            self.separate()
            total = len([s for s in songs if is_a_file(s)])
            text = ngettext(
                "_Show in File Manager",
                "_Show %(total)d Files in File Manager", total) % {
                    "total": total}
            b = qltk.MenuItem(text, Icons.DOCUMENT_OPEN)
            b.set_sensitive(bool(songs)
                            and len(songs) < MenuItemPlugin.MAX_INVOCATIONS)
            b.connect('activate', show_files_cb)
            self.append(b)

        def selection_done_cb(menu):
            menu.destroy()

        self.connect('selection-done', selection_done_cb)