Example #1
0
 def action_callback(view_action, current_action):
     current = browsers.name(
         browsers.get(current_action.get_current_value()))
     self._select_browser(view_action, current, library, player)
Example #2
0
    def __init__(self, library, player, headless=False):
        super(QuodLibetWindow, self).__init__(dialog=False)
        self.last_dir = const.HOME

        self.__update_title(player)
        self.set_default_size(550, 450)

        main_box = Gtk.VBox()
        self.add(main_box)

        # create main menubar, load/restore accelerator groups
        self.__library = library
        ui = self.__create_menu(player, library)
        accel_group = ui.get_accel_group()
        self.add_accel_group(accel_group)

        # dbus app menu
        AppMenu(self, ui.get_action_groups()[0])

        accel_fn = os.path.join(const.USERDIR, "accels")
        Gtk.AccelMap.load(accel_fn)

        def accel_save_cb(*args):
            Gtk.AccelMap.save(accel_fn)
        accel_group.connect_object('accel-changed', accel_save_cb, None)
        main_box.pack_start(ui.get_widget("/Menu"), False, True, 0)

        # get the playlist up before other stuff
        self.songlist = MainSongList(library, player)
        self.songlist.show_all()
        self.songlist.connect_after(
            'drag-data-received', self.__songlist_drag_data_recv)
        self.song_scroller = SongListScroller(
            ui.get_widget("/Menu/View/SongList"))
        self.song_scroller.add(self.songlist)
        self.qexpander = QueueExpander(
            ui.get_widget("/Menu/View/Queue"), library, player)
        self.playlist = PlaylistMux(
            player, self.qexpander.model, self.songlist.model)

        top_bar = TopBar(self, player, library)
        main_box.pack_start(top_bar, False, True, 0)
        self.top_bar = top_bar

        self.__browserbox = Alignment(bottom=3)
        main_box.pack_start(self.__browserbox, True, True, 0)

        statusbox = StatusBarBox(self.songlist.model, player)
        self.order = statusbox.order
        self.repeat = statusbox.repeat
        self.statusbar = statusbox.statusbar

        main_box.pack_start(
            Alignment(statusbox, border=3, top=-3, right=3),
            False, True, 0)

        self.songpane = ConfigRVPaned("memory", "queue_position", 0.75)
        self.songpane.pack1(self.song_scroller, resize=True, shrink=False)
        self.songpane.pack2(self.qexpander, resize=True, shrink=False)
        self.__handle_position = self.songpane.get_property("position")

        def songpane_button_press_cb(pane, event):
            """If we start to drag the pane handle while the
            queue expander is unexpanded, expand it and move the handle
            to the bottom, so we can 'drag' the queue out
            """

            if event.window != pane.get_handle_window():
                return False

            if not self.qexpander.get_expanded():
                self.qexpander.set_expanded(True)
                pane.set_relative(1.0)
            return False

        self.songpane.connect("button-press-event", songpane_button_press_cb)

        self.song_scroller.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::expanded', self.__expand_or)
        self.qexpander.connect('draw', self.__qex_size_allocate)
        self.songpane.connect('notify', self.__moved_pane_handle)

        try:
            orders = []
            for e in config.getstringlist('memory', 'sortby', []):
                orders.append((e[1:], int(e[0])))
        except ValueError:
            pass
        else:
            self.songlist.set_sort_orders(orders)

        self.browser = None
        self.ui = ui

        main_box.show_all()

        try:
            self.select_browser(
                self, config.get("memory", "browser"), library, player, True)
        except:
            config.set("memory", "browser", browsers.name(0))
            config.save(const.CONFIG)
            raise

        # set at least the playlist before the mainloop starts..
        player.setup(self.playlist, None, 0)

        def delayed_song_set():
            self.__delayed_setup = None
            song = library.get(config.get("memory", "song"))
            seek_pos = config.getint("memory", "seek", 0)
            config.set("memory", "seek", 0)
            player.setup(self.playlist, song, seek_pos)
        self.__delayed_setup = GLib.idle_add(delayed_song_set)
        self.showhide_playlist(ui.get_widget("/Menu/View/SongList"))
        self.showhide_playqueue(ui.get_widget("/Menu/View/Queue"))

        self.songlist.connect('popup-menu', self.__songs_popup_menu)
        self.songlist.connect('columns-changed', self.__cols_changed)
        self.songlist.connect('columns-changed', self.__hide_headers)
        self.songlist.info.connect("changed", self.__set_time)

        lib = library.librarian
        gobject_weak(lib.connect_object, 'changed', self.__song_changed,
                     player, parent=self)

        self._playback_error_dialog = None
        player_sigs = [
            ('song-started', self.__song_started),
            ('paused', self.__update_paused, True),
            ('unpaused', self.__update_paused, False),
        ]
        for sig in player_sigs:
            gobject_weak(player.connect, *sig, **{"parent": self})

        # make sure we redraw all error indicators before opening
        # a dialog (blocking the main loop), so connect after default handlers
        gobject_weak(player.connect_after, 'error',
                     self.__player_error, **{"parent": self})

        # connect after to let SongTracker update stats
        player_sigs.append(
            gobject_weak(player.connect_after, "song-ended",
                         self.__song_ended, parent=self))

        targets = [("text/uri-list", Gtk.TargetFlags.OTHER_APP, DND_URI_LIST)]
        targets = [Gtk.TargetEntry.new(*t) for t in targets]

        self.drag_dest_set(
            Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY)
        self.connect('drag-data-received', self.__drag_data_received)

        if not headless:
            GLib.idle_add(self.__configure_scan_dirs, library)

        if config.getboolean('library', 'refresh_on_start'):
            self.__rebuild(None, False)

        self.connect_object("key-press-event", self.__key_pressed, player)

        self.connect("delete-event", self.__save_browser)
        self.connect("destroy", self.__destroy)

        self.enable_window_tracking("quodlibet")
Example #3
0
    def __init__(self, library, player):
        super(QuodLibetWindow, self).__init__()
        self.last_dir = const.HOME

        self.__update_title(player)
        self.set_default_size(550, 450)

        main_box = gtk.VBox()
        self.add(main_box)
        
        # create test instance of the MPD backend
        self._mpd = quodmpd.QuodMpd()

        # create main menubar, load/restore accelerator groups
        self.__library = library
        self.__create_menu(player, library)
        self.add_accel_group(self.ui.get_accel_group())

        accel_fn = os.path.join(const.USERDIR, "accels")
        gtk.accel_map_load(accel_fn)
        accelgroup = gtk.accel_groups_from_object(self)[0]
        accelgroup.connect('accel-changed',
                lambda *args: gtk.accel_map_save(accel_fn))
        main_box.pack_start(self.ui.get_widget("/Menu"), expand=False)

        # get the playlist up before other stuff
        self.songlist = MainSongList(library, player)
        self.songlist.show_all()
        self.add_accel_group(self.songlist.accelerators)
        self.songlist.connect_after(
            'drag-data-received', self.__songlist_drag_data_recv)
        self.song_scroller = SongListScroller(
            self.ui.get_widget("/Menu/View/SongList"))
        self.song_scroller.add(self.songlist)
        self.qexpander = QueueExpander(
            self.ui.get_widget("/Menu/View/Queue"), library, player)
        self.playlist = PlaylistMux(
            player, self.qexpander.model, self.songlist.model)

        top_bar = TopBar(self, player, library)
        top_align = Alignment(top_bar, border=3, bottom=-3)
        main_box.pack_start(top_align, expand=False)

        self.__browserbox = Alignment(top=3, bottom=3)
        main_box.pack_start(self.__browserbox)

        statusbox = StatusBarBox(self.songlist.model, player)
        self.order = statusbox.order
        self.repeat = statusbox.repeat
        self.statusbar = statusbox.statusbar

        main_box.pack_start(Alignment(statusbox, border=3, top=-3),
                            expand=False)

        self.songpane = gtk.VPaned()
        self.songpane.pack1(self.song_scroller, resize=True, shrink=False)
        self.songpane.pack2(self.qexpander, resize=True, shrink=False)
        self.__handle_position =  self.songpane.get_property("position")

        self.song_scroller.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::expanded', self.__expand_or)
        self.qexpander.connect('size-allocate', self.__qex_size_allocate)
        self.songpane.connect('notify', self.__moved_pane_handle)

        sort = config.get('memory', 'sortby')
        self.songlist.set_sort_by(None, sort[1:], order=int(sort[0]))

        self.browser = None

        main_box.show_all()

        try:
            self.select_browser(
                self, config.get("memory", "browser"), library, player, True)
        except:
            config.set("memory", "browser", browsers.name(0))
            config.save(const.CONFIG)
            raise

        # set at least the playlist before the mainloop starts..
        player.setup(self.playlist, None, 0)

        def delayed_song_set():
            song = library.get(config.get("memory", "song"))
            seek_pos = config.getint("memory", "seek")
            config.set("memory", "seek", 0)
            player.setup(self.playlist, song, seek_pos)
        gobject.idle_add(delayed_song_set)
        self.showhide_playlist(self.ui.get_widget("/Menu/View/SongList"))
        self.showhide_playqueue(self.ui.get_widget("/Menu/View/Queue"))

        self.songlist.connect('popup-menu', self.__songs_popup_menu)
        self.songlist.connect('columns-changed', self.__cols_changed)
        self.songlist.connect('columns-changed', self.__hide_headers)
        self.songlist.get_selection().connect(
                'changed', util.DeferredSignal(self.__set_time))

        lib = library.librarian
        gobject_weak(lib.connect, 'removed', self.__set_time, parent=self)
        gobject_weak(lib.connect, 'added', self.__set_time, parent=self)
        gobject_weak(lib.connect_object, 'changed', self.__song_changed,
                     player, parent=self)

        player_sigs = [
            ('song-ended', self.__song_ended),
            ('song-started', self.__song_started),
            ('paused', self.__update_paused, True),
            ('unpaused', self.__update_paused, False),
        ]
        for sig in player_sigs:
            gobject_weak(player.connect, *sig, **{"parent": self})

        targets = [("text/uri-list", 0, 1)]
        self.drag_dest_set(
            gtk.DEST_DEFAULT_ALL, targets, gtk.gdk.ACTION_DEFAULT)
        self.connect_object('drag-motion', QuodLibetWindow.__drag_motion, self)
        self.connect_object('drag-leave', QuodLibetWindow.__drag_leave, self)
        self.connect_object(
            'drag-data-received', QuodLibetWindow.__drag_data_received, self)

        if config.getboolean('library', 'refresh_on_start'):
            self.__rebuild(None, False)

        self.connect_object("key-press-event", self.__key_pressed, player)

        self.connect("delete-event", self.__save_browser)
        self.connect("destroy", self.__destroy)

        self.enable_window_tracking("quodlibet")
Example #4
0
 def test_name(self):
     self.assertEqual(browsers.name(browsers.empty.EmptyBar), "Disabled")
Example #5
0
def _dump_browsers(app):
    f = StringIO()
    for i, b in enumerate(browsers.browsers):
        if not b.is_empty:
            f.write("%d. %s\n" % (i, browsers.name(b)))
    return f.getvalue()
Example #6
0
    def __init__(self, library, player, headless=False, restore_cb=None):
        super(QuodLibetWindow, self).__init__(dialog=False)
        self.last_dir = get_home_dir()

        self.__destroyed = False
        self.__update_title(player)
        self.set_default_size(550, 450)

        main_box = Gtk.VBox()
        self.add(main_box)

        # create main menubar, load/restore accelerator groups
        self.__library = library
        ui = self.__create_menu(player, library)
        accel_group = ui.get_accel_group()
        self.add_accel_group(accel_group)

        def scroll_and_jump(*args):
            self.__jump_to_current(True, True)

        keyval, mod = Gtk.accelerator_parse("<control><shift>J")
        accel_group.connect(keyval, mod, 0, scroll_and_jump)

        # dbus app menu
        # Unity puts the app menu next to our menu bar. Since it only contains
        # menu items also available in the menu bar itself, don't add it.
        if not util.is_unity():
            AppMenu(self, ui.get_action_groups()[0])

        # custom accel map
        accel_fn = os.path.join(quodlibet.get_user_dir(), "accels")
        Gtk.AccelMap.load(accel_fn)
        # save right away so we fill the file with example comments of all
        # accels
        Gtk.AccelMap.save(accel_fn)

        menubar = ui.get_widget("/Menu")

        # Since https://git.gnome.org/browse/gtk+/commit/?id=b44df22895c79
        # toplevel menu items show an empty 16x16 image. While we don't
        # need image items there UIManager creates them by default.
        # Work around by removing the empty GtkImages
        for child in menubar.get_children():
            if isinstance(child, Gtk.ImageMenuItem):
                child.set_image(None)

        main_box.pack_start(menubar, False, True, 0)

        # get the playlist up before other stuff
        self.songlist = MainSongList(library, player)
        self.songlist.show_all()
        self.songlist.connect("key-press-event", self.__songlist_key_press)
        self.songlist.connect_after('drag-data-received',
                                    self.__songlist_drag_data_recv)
        self.song_scroller = SongListScroller(
            ui.get_widget("/Menu/View/SongList"))
        self.song_scroller.add(self.songlist)
        self.qexpander = QueueExpander(ui.get_widget("/Menu/View/Queue"),
                                       library, player)
        self.playlist = PlaylistMux(player, self.qexpander.model,
                                    self.songlist.model)

        top_bar = TopBar(self, player, library)
        main_box.pack_start(top_bar, False, True, 0)
        self.top_bar = top_bar

        self.__browserbox = Align(bottom=3)
        main_box.pack_start(self.__browserbox, True, True, 0)

        statusbox = StatusBarBox(self.songlist.model, player)
        self.order = statusbox.order
        self.repeat = statusbox.repeat
        self.statusbar = statusbox.statusbar

        main_box.pack_start(Align(statusbox, border=3, top=-3, right=3), False,
                            True, 0)

        self.songpane = ConfigRVPaned("memory", "queue_position", 0.75)
        self.songpane.pack1(self.song_scroller, resize=True, shrink=False)
        self.songpane.pack2(self.qexpander, resize=True, shrink=False)
        self.__handle_position = self.songpane.get_property("position")

        def songpane_button_press_cb(pane, event):
            """If we start to drag the pane handle while the
            queue expander is unexpanded, expand it and move the handle
            to the bottom, so we can 'drag' the queue out
            """

            if event.window != pane.get_handle_window():
                return False

            if not self.qexpander.get_expanded():
                self.qexpander.set_expanded(True)
                pane.set_relative(1.0)
            return False

        self.songpane.connect("button-press-event", songpane_button_press_cb)

        self.song_scroller.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::expanded', self.__expand_or)
        self.qexpander.connect('draw', self.__qex_size_allocate)
        self.songpane.connect('notify', self.__moved_pane_handle)

        try:
            orders = []
            for e in config.getstringlist('memory', 'sortby', []):
                orders.append((e[1:], int(e[0])))
        except ValueError:
            pass
        else:
            self.songlist.set_sort_orders(orders)

        self.browser = None
        self.ui = ui

        main_box.show_all()

        self._playback_error_dialog = None
        connect_destroy(player, 'song-started', self.__song_started)
        connect_destroy(player, 'paused', self.__update_paused, True)
        connect_destroy(player, 'unpaused', self.__update_paused, False)
        # make sure we redraw all error indicators before opening
        # a dialog (blocking the main loop), so connect after default handlers
        connect_after_destroy(player, 'error', self.__player_error)
        # connect after to let SongTracker update stats
        connect_after_destroy(player, "song-ended", self.__song_ended)

        # set at least the playlist. the song should be restored
        # after the browser emits the song list
        player.setup(self.playlist, None, 0)
        self.__restore_cb = restore_cb
        self.__first_browser_set = True

        restore_browser = not headless
        try:
            self.select_browser(self, config.get("memory", "browser"), library,
                                player, restore_browser)
        except:
            config.set("memory", "browser", browsers.name(0))
            config.save()
            raise

        self.showhide_playlist(ui.get_widget("/Menu/View/SongList"))
        self.showhide_playqueue(ui.get_widget("/Menu/View/Queue"))

        self.songlist.connect('popup-menu', self.__songs_popup_menu)
        self.songlist.connect('columns-changed', self.__cols_changed)
        self.songlist.connect('columns-changed', self.__hide_headers)
        self.songlist.info.connect("changed", self.__set_time)

        lib = library.librarian
        connect_destroy(lib, 'changed', self.__song_changed, player)

        targets = [("text/uri-list", Gtk.TargetFlags.OTHER_APP, DND_URI_LIST)]
        targets = [Gtk.TargetEntry.new(*t) for t in targets]

        self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY)
        self.connect('drag-data-received', self.__drag_data_received)

        if not headless:
            on_first_map(self, self.__configure_scan_dirs, library)

        if config.getboolean('library', 'refresh_on_start'):
            self.__rebuild(None, False)

        self.connect("key-press-event", self.__key_pressed, player)

        self.connect("destroy", self.__destroy)

        self.enable_window_tracking("quodlibet")
Example #7
0
def _dump_browsers(app):
    response = u""
    for i, b in enumerate(browsers.browsers):
        response += u"%d. %s\n" % (i, browsers.name(b))
    return text2fsn(response)
Example #8
0
    def __create_menu(self, player, library):
        ag = Gtk.ActionGroup.new("QuodLibetWindowActions")

        act = Action(name="Music", label=_("_Music"))
        ag.add_action(act)

        act = Action(name="AddFolders", label=_(u"_Add a Folder…"), icon_name=Icons.LIST_ADD)
        act.connect("activate", self.open_chooser)
        ag.add_action_with_accel(act, "<Primary>O")

        act = Action(name="AddFiles", label=_(u"_Add a File…"), icon_name=Icons.LIST_ADD)
        act.connect("activate", self.open_chooser)
        ag.add_action(act)

        act = Action(name="AddLocation", label=_(u"_Add a Location…"), icon_name=Icons.LIST_ADD)
        act.connect("activate", self.open_location)
        ag.add_action(act)

        act = Action(name="BrowseLibrary", label=_("Open _Browser"), icon_name=Icons.EDIT_FIND)
        ag.add_action(act)

        act = Action(name="Preferences", label=_("_Preferences"), icon_name=Icons.PREFERENCES_SYSTEM)
        act.connect("activate", self.__preferences)
        ag.add_action(act)

        act = Action(name="Plugins", label=_("_Plugins"), icon_name=Icons.SYSTEM_RUN)
        act.connect("activate", self.__plugins)
        ag.add_action(act)

        act = Action(name="Quit", label=_("_Quit"), icon_name=Icons.APPLICATION_EXIT)
        act.connect("activate", lambda *x: self.destroy())
        ag.add_action_with_accel(act, "<Primary>Q")

        act = Action(name="Control", label=_("_Control"))
        ag.add_action(act)

        act = Action(name="EditTags", label=_("Edit _Tags"), icon_name=Icons.DOCUMENT_PROPERTIES)
        act.connect("activate", self.__current_song_prop)
        ag.add_action(act)

        act = Action(name="Information", label=_("_Information"), icon_name=Icons.DIALOG_INFORMATION)
        act.connect("activate", self.__current_song_info)
        ag.add_action(act)

        act = Action(name="Jump", label=_("_Jump to Playing Song"), icon_name=Icons.GO_JUMP)
        act.connect("activate", self.__jump_to_current)
        ag.add_action_with_accel(act, "<Primary>J")

        act = Action(name="View", label=_("_View"))
        ag.add_action(act)

        act = Action(name="Help", label=_("_Help"))
        ag.add_action(act)

        act = Action(name="Previous", label=_("Pre_vious"), icon_name=Icons.MEDIA_SKIP_BACKWARD)
        act.connect("activate", self.__previous_song)
        ag.add_action_with_accel(act, "<Primary>comma")

        act = Action(name="PlayPause", label=_("_Play"), icon_name=Icons.MEDIA_PLAYBACK_START)
        act.connect("activate", self.__play_pause)
        ag.add_action_with_accel(act, "<Primary>space")

        act = Action(name="Next", label=_("_Next"), icon_name=Icons.MEDIA_SKIP_FORWARD)
        act.connect("activate", self.__next_song)
        ag.add_action_with_accel(act, "<Primary>period")

        act = ToggleAction(name="StopAfter", label=_("Stop After This Song"))
        ag.add_action_with_accel(act, "<shift>space")

        # access point for the tray icon
        self.stop_after = act

        act = Action(name="AddBookmark", label=_("Add Bookmark"), icon_name=Icons.LIST_ADD)
        connect_obj(act, "activate", self.__add_bookmark, library.librarian, player)
        ag.add_action_with_accel(act, "<Primary>D")

        act = Action(name="EditBookmarks", label=_(u"Edit Bookmarks…"))
        connect_obj(act, "activate", self.__edit_bookmarks, library.librarian, player)
        ag.add_action_with_accel(act, "<Primary>B")

        act = Action(name="About", label=_("_About"), icon_name=Icons.HELP_ABOUT)
        connect_obj(act, "activate", self.__show_about, player)
        ag.add_action_with_accel(act, None)

        act = Action(name="OnlineHelp", label=_("Online Help"), icon_name=Icons.HELP_BROWSER)

        def website_handler(*args):
            util.website(const.ONLINE_HELP)

        act.connect("activate", website_handler)
        ag.add_action_with_accel(act, "F1")

        act = Action(name="SearchHelp", label=_("Search Help"))

        def search_help_handler(*args):
            util.website(const.SEARCH_HELP)

        act.connect("activate", search_help_handler)
        ag.add_action_with_accel(act, None)

        act = Action(name="RefreshLibrary", label=_("Re_fresh Library"), icon_name=Icons.VIEW_REFRESH)
        act.connect("activate", self.__rebuild, False)
        ag.add_action(act)

        act = ToggleAction(name="SongList", label=_("Song _List"))
        act.set_active(config.getboolean("memory", "songlist"))
        act.connect("activate", self.showhide_playlist)
        ag.add_action(act)

        act = ToggleAction(name="Queue", label=_("_Queue"))
        act.set_active(config.getboolean("memory", "queue"))
        act.connect("activate", self.showhide_playqueue)
        ag.add_action(act)

        current = config.get("memory", "browser")
        try:
            browsers.get(current)
        except ValueError:
            current = browsers.name(browsers.default)

        first_action = None
        for Kind in browsers.browsers:
            name = browsers.name(Kind)
            index = browsers.index(name)
            action_name = "View" + Kind.__name__
            label = Kind.accelerated_name
            act = RadioAction(name=action_name, label=Kind.accelerated_name, value=index)
            act.join_group(first_action)
            first_action = first_action or act
            if name == current:
                act.set_active(True)
            ag.add_action(act)
        assert first_action

        def action_callback(view_action, current_action):
            current = browsers.name(browsers.get(current_action.get_current_value()))
            self.select_browser(view_action, current, library, player)

        first_action.connect("changed", action_callback)

        for Kind in browsers.browsers:
            if Kind.is_empty:
                continue
            action = "Browser" + Kind.__name__
            label = Kind.accelerated_name
            act = Action(name=action, label=label)

            def browser_activate(action, Kind):
                LibraryBrowser.open(Kind, library, player)

            act.connect("activate", browser_activate, Kind)
            ag.add_action_with_accel(act, None)

        ui = Gtk.UIManager()
        ui.insert_action_group(ag, -1)

        ui.add_ui_from_string(MAIN_MENU % {"browsers": BrowseLibrary()})
        self._filter_menu = FilterMenu(library, player, ui)

        menustr = MENU % {"views": ViewBrowser()}
        ui.add_ui_from_string(menustr)

        # Cute. So. UIManager lets you attach tooltips, but when they're
        # for menu items, they just get ignored. So here I get to actually
        # attach them.
        ui.get_widget("/Menu/Music/RefreshLibrary").set_tooltip_text(_("Check for changes in your library"))

        return ui
Example #9
0
 def action_callback(view_action, current_action):
     current = browsers.name(browsers.get(current_action.get_current_value()))
     self.select_browser(view_action, current, library, player)
    def __create_menu(self, player, library):
        ag = Gtk.ActionGroup.new('QuodLibetWindowActions')

        actions = [
            ('Music', None, _("_Music")),
            ('AddFolders', Gtk.STOCK_ADD, _(u'_Add a Folder…'),
             "<control>O", None, self.open_chooser),
            ('AddFiles', Gtk.STOCK_ADD, _(u'_Add a File…'),
             None, None, self.open_chooser),
            ('AddLocation', Gtk.STOCK_ADD, _(u'_Add a Location…'),
             None, None, self.open_location),
            ('BrowseLibrary', Gtk.STOCK_FIND, _('Open _Browser'), ""),
            ("Preferences", Gtk.STOCK_PREFERENCES, None, None, None,
             self.__preferences),
            ("Plugins", Gtk.STOCK_EXECUTE, _("_Plugins"), None, None,
             self.__plugins),
            ("Quit", Gtk.STOCK_QUIT, None, None, None,
             lambda *x: self.destroy()),
            ("Control", None, _("_Control")),
            ("EditTags", Gtk.STOCK_PROPERTIES, _("Edit _Tags"), "", None,
             self.__current_song_prop),
            ("Information", Gtk.STOCK_INFO, None, None, None,
             self.__current_song_info),

            ("Jump", Gtk.STOCK_JUMP_TO, _("_Jump to Playing Song"),
             "<control>J", None, self.__jump_to_current),

            ("View", None, _("_View")),
            ("Help", None, _("_Help")),
            ]

        actions.append(("Previous", Gtk.STOCK_MEDIA_PREVIOUS, None,
                        "<control>comma", None, self.__previous_song))

        actions.append(("PlayPause", Gtk.STOCK_MEDIA_PLAY, None,
                        "<control>space", None, self.__play_pause))

        actions.append(("Next", Gtk.STOCK_MEDIA_NEXT, None,
                        "<control>period", None, self.__next_song))

        ag.add_actions(actions)

        act = Gtk.ToggleAction.new("StopAfter",
                                   _("Stop After This Song"), None, "")
        ag.add_action_with_accel(act, "<shift>space")

        # access point for the tray icon
        self.stop_after = act

        act = Gtk.Action.new(
            "AddBookmark", _("Add Bookmark"), None, Gtk.STOCK_ADD)
        connect_obj(act, 'activate', self.__add_bookmark,
                           library.librarian, player)
        ag.add_action_with_accel(act, "<ctrl>D")

        act = Gtk.Action.new("EditBookmarks", _(u"Edit Bookmarks…"), None, "")
        connect_obj(act, 'activate', self.__edit_bookmarks,
                           library.librarian, player)
        ag.add_action_with_accel(act, "<ctrl>B")

        act = Gtk.Action.new("About", None, None, Gtk.STOCK_ABOUT)
        connect_obj(act, 'activate', self.__show_about, player)
        ag.add_action_with_accel(act, None)

        act = Gtk.Action.new(
            "OnlineHelp", _("Online Help"), None, Gtk.STOCK_HELP)

        def website_handler(*args):
            util.website(const.ONLINE_HELP)

        act.connect('activate', website_handler)
        ag.add_action_with_accel(act, "F1")

        act = Gtk.Action.new("SearchHelp", _("Search Help"), None, "")

        def search_help_handler(*args):
            util.website(const.SEARCH_HELP)

        act.connect('activate', search_help_handler)
        ag.add_action_with_accel(act, None)

        act = Gtk.Action.new(
            "RefreshLibrary", _("Re_fresh Library"), None, Gtk.STOCK_REFRESH)
        act.connect('activate', self.__rebuild, False)
        ag.add_action_with_accel(act, None)

        ag.add_toggle_actions([
            ("SongList", None, _("Song _List"), None, None,
             self.showhide_playlist,
             config.getboolean("memory", "songlist"))])

        ag.add_toggle_actions([
            ("Queue", None, _("_Queue"), None, None,
             self.showhide_playqueue,
             config.getboolean("memory", "queue"))])

        view_actions = []
        for i, Kind in enumerate(browsers.browsers):
            action = "View" + Kind.__name__
            label = Kind.accelerated_name
            view_actions.append((action, None, label, None, None, i))

        current = config.get("memory", "browser")
        try:
            browsers.get(current)
        except ValueError:
            current = browsers.name(browsers.default)

        def action_callback(view_action, current):
            self.select_browser(view_action, current, library, player)
        ag.add_radio_actions(
            view_actions, current, action_callback,
            None)

        for Kind in browsers.browsers:
            if Kind.is_empty:
                continue
            action = "Browser" + Kind.__name__
            label = Kind.accelerated_name
            act = Gtk.Action.new(action, label, None, None)

            def browser_activate(action, Kind):
                LibraryBrowser.open(Kind, library, player)

            act.connect('activate', browser_activate, Kind)
            ag.add_action_with_accel(act, None)

        ui = Gtk.UIManager()
        ui.insert_action_group(ag, -1)

        ui.add_ui_from_string(
            MAIN_MENU % {"browsers": BrowseLibrary()})
        self._filter_menu = FilterMenu(library, player, ui)

        menustr = MENU % {
            "views": ViewBrowser(),
        }
        ui.add_ui_from_string(menustr)

        # Cute. So. UIManager lets you attach tooltips, but when they're
        # for menu items, they just get ignored. So here I get to actually
        # attach them.
        ui.get_widget("/Menu/Music/RefreshLibrary").set_tooltip_text(
                _("Check for changes in your library"))

        return ui
 def test_name(self):
     self.assertEqual(browsers.name(browsers.tracks.TrackList), "SearchBar")
Example #12
0
 def test_name(self):
     self.assertEqual(browsers.name(browsers.search.SearchBar), "SearchBar")
Example #13
0
    def __create_menu(self, player, library):
        def add_view_items(ag):
            act = Action(name="Information", label=_('_Information'),
                         icon_name=Icons.DIALOG_INFORMATION)
            act.connect('activate', self.__current_song_info)
            ag.add_action(act)

            act = Action(name="Jump", label=_('_Jump to Playing Song'),
                         icon_name=Icons.GO_JUMP)
            self.__jump_to_current(True, None, True)
            act.connect('activate', self.__jump_to_current)
            ag.add_action_with_accel(act, "<Primary>J")

        def add_top_level_items(ag):
            ag.add_action(Action(name="File", label=_("_File")))
            ag.add_action(Action(name="Song", label=_("_Song")))
            ag.add_action(Action(name="View", label=_('_View')))
            ag.add_action(Action(name="Browse", label=_("_Browse")))
            ag.add_action(Action(name="Control", label=_('_Control')))
            ag.add_action(Action(name="Help", label=_('_Help')))

        ag = Gtk.ActionGroup.new('QuodLibetWindowActions')
        add_top_level_items(ag)
        add_view_items(ag)

        act = Action(name="AddFolders", label=_(u'_Add a Folder…'),
                     icon_name=Icons.LIST_ADD)
        act.connect('activate', self.open_chooser)
        ag.add_action_with_accel(act, "<Primary>O")

        act = Action(name="AddFiles", label=_(u'_Add a File…'),
                     icon_name=Icons.LIST_ADD)
        act.connect('activate', self.open_chooser)
        ag.add_action(act)

        act = Action(name="AddLocation", label=_(u'_Add a Location…'),
                     icon_name=Icons.LIST_ADD)
        act.connect('activate', self.open_location)
        ag.add_action(act)

        act = Action(name="BrowseLibrary", label=_('Open _Browser'),
                     icon_name=Icons.EDIT_FIND)
        ag.add_action(act)

        act = Action(name="Preferences", label=_('_Preferences'),
                     icon_name=Icons.PREFERENCES_SYSTEM)
        act.connect('activate', self.__preferences)
        ag.add_action(act)

        act = Action(name="Plugins", label=_('_Plugins'),
                     icon_name=Icons.SYSTEM_RUN)
        act.connect('activate', self.__plugins)
        ag.add_action(act)

        act = Action(name="Quit", label=_('_Quit'),
                     icon_name=Icons.APPLICATION_EXIT)
        act.connect('activate', lambda *x: self.destroy())
        ag.add_action_with_accel(act, "<Primary>Q")

        act = Action(name="EditTags", label=_('Edit _Tags'),
                     icon_name=Icons.DOCUMENT_PROPERTIES)
        act.connect('activate', self.__current_song_prop)
        ag.add_action(act)

        act = Action(name="EditBookmarks", label=_(u"Edit Bookmarks…"))
        connect_obj(act, 'activate', self.__edit_bookmarks,
                           library.librarian, player)
        ag.add_action_with_accel(act, "<Primary>B")

        act = Action(name="Previous", label=_('Pre_vious'),
                     icon_name=Icons.MEDIA_SKIP_BACKWARD)
        act.connect('activate', self.__previous_song)
        ag.add_action_with_accel(act, "<Primary>comma")

        act = Action(name="PlayPause", label=_('_Play'),
                     icon_name=Icons.MEDIA_PLAYBACK_START)
        act.connect('activate', self.__play_pause)
        ag.add_action_with_accel(act, "<Primary>space")

        act = Action(name="Next", label=_('_Next'),
                     icon_name=Icons.MEDIA_SKIP_FORWARD)
        act.connect('activate', self.__next_song)
        ag.add_action_with_accel(act, "<Primary>period")

        act = ToggleAction(name="StopAfter", label=_("Stop After This Song"))
        ag.add_action_with_accel(act, "<shift>space")

        # access point for the tray icon
        self.stop_after = act

        act = Action(name="Shortcuts", label=_("_Keyboard Shortcuts"))
        act.connect('activate', self.__keyboard_shortcuts)
        ag.add_action_with_accel(act, "<Primary>question")

        act = Action(name="About", label=_("_About"),
                     icon_name=Icons.HELP_ABOUT)
        act.connect('activate', self.__show_about)
        ag.add_action_with_accel(act, None)

        act = Action(name="OnlineHelp", label=_("Online Help"),
                     icon_name=Icons.HELP_BROWSER)

        def website_handler(*args):
            util.website(const.ONLINE_HELP)

        act.connect('activate', website_handler)
        ag.add_action_with_accel(act, "F1")

        act = Action(name="SearchHelp", label=_("Search Help"))

        def search_help_handler(*args):
            util.website(const.SEARCH_HELP)

        act.connect('activate', search_help_handler)
        ag.add_action_with_accel(act, None)

        act = Action(name="CheckUpdates", label=_("_Check for Updates…"),
                     icon_name=Icons.NETWORK_SERVER)

        def check_updates_handler(*args):
            d = UpdateDialog(self)
            d.run()
            d.destroy()

        act.connect('activate', check_updates_handler)
        ag.add_action_with_accel(act, None)

        act = Action(
            name="RefreshLibrary", label=_("_Scan Library"),
            icon_name=Icons.VIEW_REFRESH)
        act.connect('activate', self.__rebuild, False)
        ag.add_action(act)

        current = config.get("memory", "browser")
        try:
            browsers.get(current)
        except ValueError:
            current = browsers.name(browsers.default)

        first_action = None
        for Kind in browsers.browsers:
            name = browsers.name(Kind)
            index = browsers.index(name)
            action_name = "View" + Kind.__name__
            act = RadioAction(name=action_name, label=Kind.accelerated_name,
                              value=index)
            act.join_group(first_action)
            first_action = first_action or act
            if name == current:
                act.set_active(True)
            ag.add_action_with_accel(act, "<Primary>%d" % ((index + 1) % 10,))
        assert first_action
        self._browser_action = first_action

        def action_callback(view_action, current_action):
            current = browsers.name(
                browsers.get(current_action.get_current_value()))
            self._select_browser(view_action, current, library, player)

        first_action.connect("changed", action_callback)

        for Kind in browsers.browsers:
            action = "Browser" + Kind.__name__
            label = Kind.accelerated_name
            name = browsers.name(Kind)
            index = browsers.index(name)
            act = Action(name=action, label=label)

            def browser_activate(action, Kind):
                LibraryBrowser.open(Kind, library, player)

            act.connect('activate', browser_activate, Kind)
            ag.add_action_with_accel(act,
                                     "<Primary><alt>%d" % ((index + 1) % 10,))

        ui = Gtk.UIManager()
        ui.insert_action_group(ag, -1)

        menustr = MENU % {
            "views": browser_menu_items(),
            "browsers": secondary_browser_menu_items(),
            "filters_menu": FilterMenu.MENU
        }
        ui.add_ui_from_string(menustr)
        self._filter_menu = FilterMenu(library, player, ui)

        # Cute. So. UIManager lets you attach tooltips, but when they're
        # for menu items, they just get ignored. So here I get to actually
        # attach them.
        ui.get_widget("/Menu/File/RefreshLibrary").set_tooltip_text(
            _("Check for changes in your library"))

        return ui
Example #14
0
    def __init__(self, library, player, headless=False, restore_cb=None):
        super(QuodLibetWindow, self).__init__(dialog=False)

        self.__destroyed = False
        self.__update_title(player)
        self.set_default_size(600, 480)

        main_box = Gtk.VBox()
        self.add(main_box)
        self.side_book = qltk.Notebook()

        # get the playlist up before other stuff
        self.songlist = MainSongList(library, player)
        self.songlist.connect("key-press-event", self.__songlist_key_press)
        self.songlist.connect_after(
            'drag-data-received', self.__songlist_drag_data_recv)
        self.song_scroller = ScrolledWindow()
        self.song_scroller.set_policy(
            Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        self.song_scroller.set_shadow_type(Gtk.ShadowType.IN)
        self.song_scroller.add(self.songlist)

        self.qexpander = QueueExpander(library, player)
        self.qexpander.set_no_show_all(True)
        self.qexpander.set_visible(config.getboolean("memory", "queue"))

        def on_queue_visible(qex, param):
            config.set("memory", "queue", str(qex.get_visible()))

        self.qexpander.connect("notify::visible", on_queue_visible)

        self.playlist = PlaylistMux(
            player, self.qexpander.model, self.songlist.model)

        self.__player = player
        # create main menubar, load/restore accelerator groups
        self.__library = library
        ui = self.__create_menu(player, library)
        accel_group = ui.get_accel_group()
        self.add_accel_group(accel_group)

        def scroll_and_jump(*args):
            self.__jump_to_current(True, None, True)

        keyval, mod = Gtk.accelerator_parse("<Primary><shift>J")
        accel_group.connect(keyval, mod, 0, scroll_and_jump)

        # custom accel map
        accel_fn = os.path.join(quodlibet.get_user_dir(), "accels")
        Gtk.AccelMap.load(accel_fn)
        # save right away so we fill the file with example comments of all
        # accels
        Gtk.AccelMap.save(accel_fn)

        menubar = ui.get_widget("/Menu")

        # Since https://git.gnome.org/browse/gtk+/commit/?id=b44df22895c79
        # toplevel menu items show an empty 16x16 image. While we don't
        # need image items there UIManager creates them by default.
        # Work around by removing the empty GtkImages
        for child in menubar.get_children():
            if isinstance(child, Gtk.ImageMenuItem):
                child.set_image(None)

        main_box.pack_start(menubar, False, True, 0)

        top_bar = TopBar(self, player, library)
        main_box.pack_start(top_bar, False, True, 0)
        self.top_bar = top_bar

        self.__browserbox = Align(bottom=3)
        self.__paned = paned = ConfigRHPaned("memory", "sidebar_pos", 0.25)
        paned.pack1(self.__browserbox, resize=True)
        # We'll pack2 when necessary (when the first sidebar plugin is set up)

        main_box.pack_start(paned, True, True, 0)

        play_order = PlayOrderWidget(self.songlist.model, player)
        statusbox = StatusBarBox(play_order, self.qexpander)
        self.order = play_order
        self.statusbar = statusbox.statusbar

        main_box.pack_start(
            Align(statusbox, border=3, top=-3),
            False, True, 0)

        self.songpane = SongListPaned(self.song_scroller, self.qexpander)
        self.songpane.show_all()

        try:
            orders = []
            for e in config.getstringlist('memory', 'sortby', []):
                orders.append((e[1:], int(e[0])))
        except ValueError:
            pass
        else:
            self.songlist.set_sort_orders(orders)

        self.browser = None
        self.ui = ui

        main_box.show_all()

        self._playback_error_dialog = None
        connect_destroy(player, 'song-started', self.__song_started)
        connect_destroy(player, 'paused', self.__update_paused, True)
        connect_destroy(player, 'unpaused', self.__update_paused, False)
        # make sure we redraw all error indicators before opening
        # a dialog (blocking the main loop), so connect after default handlers
        connect_after_destroy(player, 'error', self.__player_error)
        # connect after to let SongTracker update stats
        connect_after_destroy(player, "song-ended", self.__song_ended)

        # set at least the playlist. the song should be restored
        # after the browser emits the song list
        player.setup(self.playlist, None, 0)
        self.__restore_cb = restore_cb
        self.__first_browser_set = True

        restore_browser = not headless
        try:
            self._select_browser(
                self, config.get("memory", "browser"), library, player,
                restore_browser)
        except:
            config.set("memory", "browser", browsers.name(browsers.default))
            config.save()
            raise

        self.songlist.connect('popup-menu', self.__songs_popup_menu)
        self.songlist.connect('columns-changed', self.__cols_changed)
        self.songlist.connect('columns-changed', self.__hide_headers)
        self.songlist.info.connect("changed", self.__set_totals)

        lib = library.librarian
        connect_destroy(lib, 'changed', self.__song_changed, player)

        targets = [("text/uri-list", Gtk.TargetFlags.OTHER_APP, DND_URI_LIST)]
        targets = [Gtk.TargetEntry.new(*t) for t in targets]

        self.drag_dest_set(
            Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY)
        self.connect('drag-data-received', self.__drag_data_received)

        if not headless:
            on_first_map(self, self.__configure_scan_dirs, library)

        if config.getboolean('library', 'refresh_on_start'):
            self.__rebuild(None, False)

        self.connect("key-press-event", self.__key_pressed, player)

        self.connect("destroy", self.__destroy)

        self.enable_window_tracking("quodlibet")
Example #15
0
    def __init__(self, library, player, headless=False, restore_cb=None):
        super().__init__(dialog=False)

        self.__destroyed = False
        self.__update_title(player)
        self.set_default_size(600, 480)

        main_box = Gtk.VBox()
        self.add(main_box)
        self.side_book = qltk.Notebook()

        # get the playlist up before other stuff
        self.songlist = MainSongList(library, player)
        self.songlist.connect("key-press-event", self.__songlist_key_press)
        self.songlist.connect_after('drag-data-received',
                                    self.__songlist_drag_data_recv)
        self.song_scroller = ScrolledWindow()
        self.song_scroller.set_policy(Gtk.PolicyType.AUTOMATIC,
                                      Gtk.PolicyType.AUTOMATIC)
        self.song_scroller.set_shadow_type(Gtk.ShadowType.IN)
        self.song_scroller.add(self.songlist)

        self.qexpander = QueueExpander(library, player)
        self.qexpander.set_no_show_all(True)
        self.qexpander.set_visible(config.getboolean("memory", "queue"))

        def on_queue_visible(qex, param):
            config.set("memory", "queue", str(qex.get_visible()))

        self.qexpander.connect("notify::visible", on_queue_visible)

        self.playlist = PlaylistMux(player, self.qexpander.model,
                                    self.songlist.model)

        self.__player = player
        # create main menubar, load/restore accelerator groups
        self.__library = library
        ui = self.__create_menu(player, library)
        accel_group = ui.get_accel_group()
        self.add_accel_group(accel_group)

        def scroll_and_jump(*args):
            self.__jump_to_current(True, None, True)

        keyval, mod = Gtk.accelerator_parse("<Primary><shift>J")
        accel_group.connect(keyval, mod, 0, scroll_and_jump)

        # custom accel map
        accel_fn = os.path.join(quodlibet.get_user_dir(), "accels")
        Gtk.AccelMap.load(accel_fn)
        # save right away so we fill the file with example comments of all
        # accels
        Gtk.AccelMap.save(accel_fn)

        menubar = ui.get_widget("/Menu")

        # Since https://git.gnome.org/browse/gtk+/commit/?id=b44df22895c79
        # toplevel menu items show an empty 16x16 image. While we don't
        # need image items there UIManager creates them by default.
        # Work around by removing the empty GtkImages
        for child in menubar.get_children():
            if isinstance(child, Gtk.ImageMenuItem):
                child.set_image(None)

        main_box.pack_start(menubar, False, True, 0)

        top_bar = TopBar(self, player, library)
        main_box.pack_start(top_bar, False, True, 0)
        self.top_bar = top_bar

        self.__browserbox = Align(bottom=3)
        self.__paned = paned = ConfigRHPaned("memory", "sidebar_pos", 0.25)
        paned.pack1(self.__browserbox, resize=True)
        # We'll pack2 when necessary (when the first sidebar plugin is set up)

        main_box.pack_start(paned, True, True, 0)

        play_order = PlayOrderWidget(self.songlist.model, player)
        statusbox = StatusBarBox(play_order, self.qexpander)
        self.order = play_order
        self.statusbar = statusbox.statusbar

        main_box.pack_start(Align(statusbox, border=3, top=-3), False, True, 0)

        self.songpane = SongListPaned(self.song_scroller, self.qexpander)
        self.songpane.show_all()

        try:
            orders = []
            for e in config.getstringlist('memory', 'sortby', []):
                orders.append((e[1:], int(e[0])))
        except ValueError:
            pass
        else:
            self.songlist.set_sort_orders(orders)

        self.browser = None
        self.ui = ui

        main_box.show_all()

        self._playback_error_dialog = None
        connect_destroy(player, 'song-started', self.__song_started)
        connect_destroy(player, 'paused', self.__update_paused, True)
        connect_destroy(player, 'unpaused', self.__update_paused, False)
        # make sure we redraw all error indicators before opening
        # a dialog (blocking the main loop), so connect after default handlers
        connect_after_destroy(player, 'error', self.__player_error)
        # connect after to let SongTracker update stats
        connect_after_destroy(player, "song-ended", self.__song_ended)

        # set at least the playlist. the song should be restored
        # after the browser emits the song list
        player.setup(self.playlist, None, 0)
        self.__restore_cb = restore_cb
        self.__first_browser_set = True

        restore_browser = not headless
        try:
            self._select_browser(self, config.get("memory", "browser"),
                                 library, player, restore_browser)
        except:
            config.set("memory", "browser", browsers.name(browsers.default))
            config.save()
            raise

        self.songlist.connect('popup-menu', self.__songs_popup_menu)
        self.songlist.connect('columns-changed', self.__cols_changed)
        self.songlist.connect('columns-changed', self.__hide_headers)
        self.songlist.info.connect("changed", self.__set_totals)

        lib = library.librarian
        connect_destroy(lib, 'changed', self.__song_changed, player)

        targets = [("text/uri-list", Gtk.TargetFlags.OTHER_APP, DND_URI_LIST)]
        targets = [Gtk.TargetEntry.new(*t) for t in targets]

        self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY)
        self.connect('drag-data-received', self.__drag_data_received)

        if not headless:
            on_first_map(self, self.__configure_scan_dirs, library)

        if config.getboolean('library', 'refresh_on_start'):
            self.__rebuild(None, False)

        self.connect("key-press-event", self.__key_pressed, player)

        self.connect("destroy", self.__destroy)

        self.enable_window_tracking("quodlibet")
Example #16
0
 def test_name(self):
     self.assertEqual(browsers.name(browsers.empty.EmptyBar), "Disabled")
Example #17
0
    def __create_menu(self, player, library):
        def add_view_items(ag):
            act = Action(name="Information",
                         label=_('_Information'),
                         icon_name=Icons.DIALOG_INFORMATION)
            act.connect('activate', self.__current_song_info)
            ag.add_action(act)

            act = Action(name="Jump",
                         label=_('_Jump to Playing Song'),
                         icon_name=Icons.GO_JUMP)
            self.__jump_to_current(True, None, True)
            act.connect('activate', self.__jump_to_current)
            ag.add_action_with_accel(act, "<Primary>J")

        def add_top_level_items(ag):
            ag.add_action(Action(name="File", label=_("_File")))
            ag.add_action(Action(name="Song", label=_("_Song")))
            ag.add_action(Action(name="View", label=_('_View')))
            ag.add_action(Action(name="Browse", label=_("_Browse")))
            ag.add_action(Action(name="Control", label=_('_Control')))
            ag.add_action(Action(name="Help", label=_('_Help')))

        ag = Gtk.ActionGroup.new('QuodLibetWindowActions')
        add_top_level_items(ag)
        add_view_items(ag)

        act = Action(name="AddFolders",
                     label=_(u'_Add a Folder…'),
                     icon_name=Icons.LIST_ADD)
        act.connect('activate', self.open_chooser)
        ag.add_action_with_accel(act, "<Primary>O")

        act = Action(name="AddFiles",
                     label=_(u'_Add a File…'),
                     icon_name=Icons.LIST_ADD)
        act.connect('activate', self.open_chooser)
        ag.add_action(act)

        act = Action(name="AddLocation",
                     label=_(u'_Add a Location…'),
                     icon_name=Icons.LIST_ADD)
        act.connect('activate', self.open_location)
        ag.add_action(act)

        act = Action(name="BrowseLibrary",
                     label=_('Open _Browser'),
                     icon_name=Icons.EDIT_FIND)
        ag.add_action(act)

        act = Action(name="Preferences",
                     label=_('_Preferences'),
                     icon_name=Icons.PREFERENCES_SYSTEM)
        act.connect('activate', self.__preferences)
        ag.add_action(act)

        act = Action(name="Plugins",
                     label=_('_Plugins'),
                     icon_name=Icons.SYSTEM_RUN)
        act.connect('activate', self.__plugins)
        ag.add_action(act)

        act = Action(name="Quit",
                     label=_('_Quit'),
                     icon_name=Icons.APPLICATION_EXIT)
        act.connect('activate', lambda *x: self.destroy())
        ag.add_action_with_accel(act, "<Primary>Q")

        act = Action(name="EditTags",
                     label=_('Edit _Tags'),
                     icon_name=Icons.DOCUMENT_PROPERTIES)
        act.connect('activate', self.__current_song_prop)
        ag.add_action(act)

        act = Action(name="EditBookmarks", label=_(u"Edit Bookmarks…"))
        connect_obj(act, 'activate', self.__edit_bookmarks, library.librarian,
                    player)
        ag.add_action_with_accel(act, "<Primary>B")

        act = Action(name="Previous",
                     label=_('Pre_vious'),
                     icon_name=Icons.MEDIA_SKIP_BACKWARD)
        act.connect('activate', self.__previous_song)
        ag.add_action_with_accel(act, "<Primary>comma")

        act = Action(name="PlayPause",
                     label=_('_Play'),
                     icon_name=Icons.MEDIA_PLAYBACK_START)
        act.connect('activate', self.__play_pause)
        ag.add_action_with_accel(act, "<Primary>space")

        act = Action(name="Next",
                     label=_('_Next'),
                     icon_name=Icons.MEDIA_SKIP_FORWARD)
        act.connect('activate', self.__next_song)
        ag.add_action_with_accel(act, "<Primary>period")

        act = ToggleAction(name="StopAfter", label=_("Stop After This Song"))
        ag.add_action_with_accel(act, "<shift>space")

        # access point for the tray icon
        self.stop_after = act

        act = Action(name="Shortcuts", label=_("_Keyboard Shortcuts"))
        act.connect('activate', self.__keyboard_shortcuts)
        ag.add_action_with_accel(act, "<Primary>question")

        act = Action(name="About",
                     label=_("_About"),
                     icon_name=Icons.HELP_ABOUT)
        act.connect('activate', self.__show_about)
        ag.add_action_with_accel(act, None)

        act = Action(name="OnlineHelp",
                     label=_("Online Help"),
                     icon_name=Icons.HELP_BROWSER)

        def website_handler(*args):
            util.website(const.ONLINE_HELP)

        act.connect('activate', website_handler)
        ag.add_action_with_accel(act, "F1")

        act = Action(name="SearchHelp", label=_("Search Help"))

        def search_help_handler(*args):
            util.website(const.SEARCH_HELP)

        act.connect('activate', search_help_handler)
        ag.add_action_with_accel(act, None)

        act = Action(name="CheckUpdates",
                     label=_("_Check for Updates…"),
                     icon_name=Icons.NETWORK_SERVER)

        def check_updates_handler(*args):
            d = UpdateDialog(self)
            d.run()
            d.destroy()

        act.connect('activate', check_updates_handler)
        ag.add_action_with_accel(act, None)

        act = Action(name="RefreshLibrary",
                     label=_("_Scan Library"),
                     icon_name=Icons.VIEW_REFRESH)
        act.connect('activate', self.__rebuild, False)
        ag.add_action(act)

        current = config.get("memory", "browser")
        try:
            browsers.get(current)
        except ValueError:
            current = browsers.name(browsers.default)

        first_action = None
        for Kind in browsers.browsers:
            name = browsers.name(Kind)
            index = browsers.index(name)
            action_name = "View" + Kind.__name__
            act = RadioAction(name=action_name,
                              label=Kind.accelerated_name,
                              value=index)
            act.join_group(first_action)
            first_action = first_action or act
            if name == current:
                act.set_active(True)
            ag.add_action_with_accel(act, "<Primary>%d" % ((index + 1) % 10, ))
        assert first_action
        self._browser_action = first_action

        def action_callback(view_action, current_action):
            current = browsers.name(
                browsers.get(current_action.get_current_value()))
            self._select_browser(view_action, current, library, player)

        first_action.connect("changed", action_callback)

        for Kind in browsers.browsers:
            action = "Browser" + Kind.__name__
            label = Kind.accelerated_name
            name = browsers.name(Kind)
            index = browsers.index(name)
            act = Action(name=action, label=label)

            def browser_activate(action, Kind):
                LibraryBrowser.open(Kind, library, player)

            act.connect('activate', browser_activate, Kind)
            ag.add_action_with_accel(act,
                                     "<Primary><alt>%d" % ((index + 1) % 10, ))

        ui = Gtk.UIManager()
        ui.insert_action_group(ag, -1)

        menustr = MENU % {
            "views": browser_menu_items(),
            "browsers": secondary_browser_menu_items(),
            "filters_menu": FilterMenu.MENU
        }
        ui.add_ui_from_string(menustr)
        self._filter_menu = FilterMenu(library, player, ui)

        # Cute. So. UIManager lets you attach tooltips, but when they're
        # for menu items, they just get ignored. So here I get to actually
        # attach them.
        ui.get_widget("/Menu/File/RefreshLibrary").set_tooltip_text(
            _("Check for changes in your library"))

        return ui
 def test_key(self):
     self.assertEqual(browsers.get(browsers.name(self.Kind)), self.Kind)
Example #19
0
 def test_key(self):
     self.assertEqual(browsers.get(browsers.name(self.Kind)), self.Kind)
Example #20
0
    def __init__(self, library, player, headless=False):
        super(QuodLibetWindow, self).__init__(dialog=False)
        self.last_dir = const.HOME

        self.__destroyed = False
        self.__update_title(player)
        self.set_default_size(550, 450)

        main_box = Gtk.VBox()
        self.add(main_box)

        # create main menubar, load/restore accelerator groups
        self.__library = library
        ui = self.__create_menu(player, library)
        accel_group = ui.get_accel_group()
        self.add_accel_group(accel_group)

        def scroll_and_jump(*args):
            self.__jump_to_current(True, True)

        keyval, mod = Gtk.accelerator_parse("<control><shift>J")
        accel_group.connect(keyval, mod, 0, scroll_and_jump)

        # dbus app menu
        AppMenu(self, ui.get_action_groups()[0])

        # custom accel map
        accel_fn = os.path.join(const.USERDIR, "accels")
        Gtk.AccelMap.load(accel_fn)
        # save right away so we fill the file with example comments of all
        # accels
        Gtk.AccelMap.save(accel_fn)

        menubar = ui.get_widget("/Menu")

        # Since https://git.gnome.org/browse/gtk+/commit/?id=b44df22895c79
        # toplevel menu items show an empty 16x16 image. While we don't
        # need image items there UIManager creates them by default.
        # Work around by removing the empty GtkImages
        for child in menubar.get_children():
            if isinstance(child, Gtk.ImageMenuItem):
                child.set_image(None)

        main_box.pack_start(menubar, False, True, 0)

        # get the playlist up before other stuff
        self.songlist = MainSongList(library, player)
        self.songlist.show_all()
        self.songlist.connect("key-press-event", self.__songlist_key_press)
        self.songlist.connect_after(
            'drag-data-received', self.__songlist_drag_data_recv)
        self.song_scroller = SongListScroller(
            ui.get_widget("/Menu/View/SongList"))
        self.song_scroller.add(self.songlist)
        self.qexpander = QueueExpander(
            ui.get_widget("/Menu/View/Queue"), library, player)
        self.playlist = PlaylistMux(
            player, self.qexpander.model, self.songlist.model)

        top_bar = TopBar(self, player, library)
        main_box.pack_start(top_bar, False, True, 0)
        self.top_bar = top_bar

        self.__browserbox = Alignment(bottom=3)
        main_box.pack_start(self.__browserbox, True, True, 0)

        statusbox = StatusBarBox(self.songlist.model, player)
        self.order = statusbox.order
        self.repeat = statusbox.repeat
        self.statusbar = statusbox.statusbar

        main_box.pack_start(
            Alignment(statusbox, border=3, top=-3, right=3),
            False, True, 0)

        self.songpane = ConfigRVPaned("memory", "queue_position", 0.75)
        self.songpane.pack1(self.song_scroller, resize=True, shrink=False)
        self.songpane.pack2(self.qexpander, resize=True, shrink=False)
        self.__handle_position = self.songpane.get_property("position")

        def songpane_button_press_cb(pane, event):
            """If we start to drag the pane handle while the
            queue expander is unexpanded, expand it and move the handle
            to the bottom, so we can 'drag' the queue out
            """

            if event.window != pane.get_handle_window():
                return False

            if not self.qexpander.get_expanded():
                self.qexpander.set_expanded(True)
                pane.set_relative(1.0)
            return False

        self.songpane.connect("button-press-event", songpane_button_press_cb)

        self.song_scroller.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::visible', self.__show_or)
        self.qexpander.connect('notify::expanded', self.__expand_or)
        self.qexpander.connect('draw', self.__qex_size_allocate)
        self.songpane.connect('notify', self.__moved_pane_handle)

        try:
            orders = []
            for e in config.getstringlist('memory', 'sortby', []):
                orders.append((e[1:], int(e[0])))
        except ValueError:
            pass
        else:
            self.songlist.set_sort_orders(orders)

        self.browser = None
        self.ui = ui

        main_box.show_all()

        # set at least the playlist. the song should be restored
        # after the browser emits the song list
        player.setup(self.playlist, None, 0)
        self.__first_browser_set = True

        restore_browser = not headless
        try:
            self.select_browser(
                self, config.get("memory", "browser"), library, player,
                restore_browser)
        except:
            config.set("memory", "browser", browsers.name(0))
            config.save(const.CONFIG)
            raise

        self.showhide_playlist(ui.get_widget("/Menu/View/SongList"))
        self.showhide_playqueue(ui.get_widget("/Menu/View/Queue"))

        self.songlist.connect('popup-menu', self.__songs_popup_menu)
        self.songlist.connect('columns-changed', self.__cols_changed)
        self.songlist.connect('columns-changed', self.__hide_headers)
        self.songlist.info.connect("changed", self.__set_time)

        lib = library.librarian
        connect_destroy(lib, 'changed', self.__song_changed, player)

        self._playback_error_dialog = None
        player_sigs = [
            ('song-started', self.__song_started),
            ('paused', self.__update_paused, True),
            ('unpaused', self.__update_paused, False),
        ]
        for sig in player_sigs:
            connect_destroy(player, *sig)

        # make sure we redraw all error indicators before opening
        # a dialog (blocking the main loop), so connect after default handlers
        connect_after_destroy(player, 'error', self.__player_error)

        # connect after to let SongTracker update stats
        connect_after_destroy(player, "song-ended", self.__song_ended)

        targets = [("text/uri-list", Gtk.TargetFlags.OTHER_APP, DND_URI_LIST)]
        targets = [Gtk.TargetEntry.new(*t) for t in targets]

        self.drag_dest_set(
            Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY)
        self.connect('drag-data-received', self.__drag_data_received)

        if not headless:
            GLib.idle_add(self.__configure_scan_dirs, library)

        if config.getboolean('library', 'refresh_on_start'):
            self.__rebuild(None, False)

        self.connect("key-press-event", self.__key_pressed, player)

        self.connect("destroy", self.__destroy)

        self.enable_window_tracking("quodlibet")
Example #21
0
def _dump_browsers(app):
    f = StringIO()
    for i, b in enumerate(browsers.browsers):
        f.write("%d. %s\n" % (i, browsers.name(b)))
    return f.getvalue()
 def test_name(self):
     self.assertEqual(browsers.name(browsers.search.SearchBar), "SearchBar")