Exemplo n.º 1
0
    def init(self):
        """
            Init main application
        """
        cssProviderFile = Gio.File.new_for_uri(
            'resource:///org/gnome/Lollypop/application.css')
        cssProvider = Gtk.CssProvider()
        cssProvider.load_from_file(cssProviderFile)
        screen = Gdk.Screen.get_default()
        styleContext = Gtk.StyleContext()
        styleContext.add_provider_for_screen(screen, cssProvider,
                                             Gtk.STYLE_PROVIDER_PRIORITY_USER)
        self.settings = Settings.new()
        ArtSize.BIG = self.settings.get_value('cover-size').get_int32()
        if LastFM is not None:
            self.lastfm = LastFM()
        self.db = Database()
        self.playlists = Playlists()
        # We store cursors for main thread
        SqlCursor.add(self.db)
        SqlCursor.add(self.playlists)
        self.albums = AlbumsDatabase()
        self.artists = ArtistsDatabase()
        self.genres = GenresDatabase()
        self.tracks = TracksDatabase()
        self.player = Player()
        self.scanner = CollectionScanner()
        self.art = Art()
        if not self.settings.get_value('disable-mpris'):
            MPRIS(self)
        if not self.settings.get_value('disable-mpd'):
            self.mpd = MpdServerDaemon(
                self.settings.get_value('mpd-eth').get_string(),
                self.settings.get_value('mpd-port').get_int32())
        if not self.settings.get_value('disable-notifications'):
            self.notify = NotificationManager()

        settings = Gtk.Settings.get_default()
        dark = self.settings.get_value('dark-ui')
        settings.set_property('gtk-application-prefer-dark-theme', dark)

        self._parser = TotemPlParser.Parser.new()
        self._parser.connect('entry-parsed', self._on_entry_parsed)

        self.add_action(self.settings.create_action('shuffle'))

        self._is_fs = False
Exemplo n.º 2
0
 def _update_mpd_setting(self, widget, state):
     """
         Update mpd setting
         @param widget as unused, state as widget state
     """
     Lp().settings.set_value('disable-mpd', GLib.Variant('b', not state))
     if Lp().mpd is None:
         Lp().mpd = MpdServerDaemon(
             Lp().settings.get_value('mpd-eth').get_string(),
             Lp().settings.get_value('mpd-port').get_int32())
     else:
         Lp().mpd.quit()
         Lp().mpd = None
Exemplo n.º 3
0
    def init(self):
        """
            Init main application
        """
        cssProviderFile = Gio.File.new_for_uri(
            'resource:///org/gnome/Lollypop/application.css')
        cssProvider = Gtk.CssProvider()
        cssProvider.load_from_file(cssProviderFile)
        screen = Gdk.Screen.get_default()
        styleContext = Gtk.StyleContext()
        styleContext.add_provider_for_screen(screen, cssProvider,
                                             Gtk.STYLE_PROVIDER_PRIORITY_USER)
        self.settings = Settings.new()
        ArtSize.BIG = self.settings.get_value('cover-size').get_int32()
        if LastFM is not None:
            self.lastfm = LastFM()
        self.db = Database()
        self.playlists = Playlists()
        # We store cursors for main thread
        SqlCursor.add(self.db)
        SqlCursor.add(self.playlists)
        self.albums = AlbumsDatabase()
        self.artists = ArtistsDatabase()
        self.genres = GenresDatabase()
        self.tracks = TracksDatabase()
        self.player = Player()
        self.scanner = CollectionScanner()
        self.art = Art()
        if not self.settings.get_value('disable-mpris'):
            MPRIS(self)
        if not self.settings.get_value('disable-mpd'):
            self.mpd = MpdServerDaemon(
                               self.settings.get_value('mpd-eth').get_string(),
                               self.settings.get_value('mpd-port').get_int32())
        if not self.settings.get_value('disable-notifications'):
            self.notify = NotificationManager()

        settings = Gtk.Settings.get_default()
        dark = self.settings.get_value('dark-ui')
        settings.set_property('gtk-application-prefer-dark-theme', dark)

        self._parser = TotemPlParser.Parser.new()
        self._parser.connect('entry-parsed', self._on_entry_parsed)

        self.add_action(self.settings.create_action('shuffle'))

        self._is_fs = False
Exemplo n.º 4
0
class Application(Gtk.Application):
    """
        Lollypop application:
            - Handle appmenu
            - Handle command line
            - Create main window
    """
    def __init__(self):
        """
            Create application
        """
        Gtk.Application.__init__(
            self,
            application_id='org.gnome.Lollypop',
            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
        self.cursors = {}
        self.window = None
        self.notify = None
        self.mpd = None
        self.lastfm = None
        self.debug = False
        self._externals_count = 0
        self._init_proxy()
        GLib.set_application_name('lollypop')
        GLib.set_prgname('lollypop')
        # TODO: Remove this test later
        if Gtk.get_minor_version() > 12:
            self.add_main_option("debug", b'd', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Debug lollypop", None)
            self.add_main_option("set-rating", b'r', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.INT, "Rate the current track",
                                 None)
            self.add_main_option("play-pause", b't', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Toggle playback", None)
            self.add_main_option("next", b'n', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Go to next track", None)
            self.add_main_option("prev", b'p', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Go to prev track", None)
        self.connect('command-line', self._on_command_line)
        self.register(None)
        if self.get_is_remote():
            Gdk.notify_startup_complete()

    def init(self):
        """
            Init main application
        """
        cssProviderFile = Gio.File.new_for_uri(
            'resource:///org/gnome/Lollypop/application.css')
        cssProvider = Gtk.CssProvider()
        cssProvider.load_from_file(cssProviderFile)
        screen = Gdk.Screen.get_default()
        styleContext = Gtk.StyleContext()
        styleContext.add_provider_for_screen(screen, cssProvider,
                                             Gtk.STYLE_PROVIDER_PRIORITY_USER)
        self.settings = Settings.new()
        ArtSize.BIG = self.settings.get_value('cover-size').get_int32()
        if LastFM is not None:
            self.lastfm = LastFM()
        self.db = Database()
        self.playlists = Playlists()
        # We store cursors for main thread
        SqlCursor.add(self.db)
        SqlCursor.add(self.playlists)
        self.albums = AlbumsDatabase()
        self.artists = ArtistsDatabase()
        self.genres = GenresDatabase()
        self.tracks = TracksDatabase()
        self.player = Player()
        self.scanner = CollectionScanner()
        self.art = Art()
        if not self.settings.get_value('disable-mpris'):
            MPRIS(self)
        if not self.settings.get_value('disable-mpd'):
            self.mpd = MpdServerDaemon(
                self.settings.get_value('mpd-eth').get_string(),
                self.settings.get_value('mpd-port').get_int32())
        if not self.settings.get_value('disable-notifications'):
            self.notify = NotificationManager()

        settings = Gtk.Settings.get_default()
        dark = self.settings.get_value('dark-ui')
        settings.set_property('gtk-application-prefer-dark-theme', dark)

        self._parser = TotemPlParser.Parser.new()
        self._parser.connect('entry-parsed', self._on_entry_parsed)

        self.add_action(self.settings.create_action('shuffle'))

        self._is_fs = False

    def do_startup(self):
        """
            Add startup notification and
            build gnome-shell menu after Gtk.Application startup
        """
        Gtk.Application.do_startup(self)
        Notify.init("Lollypop")

        # Check locale, we want unicode!
        (code, encoding) = getlocale()
        if encoding is None or encoding != "UTF-8":
            builder = Gtk.Builder()
            builder.add_from_resource('/org/gnome/Lollypop/Unicode.ui')
            self.window = builder.get_object('unicode')
            self.window.set_application(self)
            self.window.show()
        elif not self.window:
            self.init()
            menu = self._setup_app_menu()
            # If GNOME/Unity, add appmenu
            if is_gnome() or is_unity():
                self.set_app_menu(menu)
            self.window = Window(self)
            # If not GNOME add menu to toolbar
            if not is_gnome() and not is_unity():
                self.window.setup_menu(menu)
            self.window.connect('delete-event', self._hide_on_delete)
            self.window.init_list_one()
            self.window.show()
            self.player.restore_state()

    def prepare_to_exit(self, action=None, param=None):
        """
            Save window position and view
        """
        if self.settings.get_value('save-state'):
            self.window.save_view_state()
            if self.player.current_track.id is None:
                track_id = -1
            else:
                track_id = self.player.current_track.id
            self.settings.set_value('track-id', GLib.Variant('i', track_id))
        self.player.stop()
        if self.window:
            self.window.stop_all()
        self.quit()

    def quit(self):
        """
            Quit lollypop
        """
        if self.mpd is not None:
            self.mpd.quit()
        if self.scanner.is_locked():
            self.scanner.stop()
            GLib.idle_add(self.quit)
            return
        try:
            with SqlCursor(self.db) as sql:
                sql.execute('VACUUM')
            with SqlCursor(self.playlists) as sql:
                sql.execute('VACUUM')
            with SqlCursor(Radios()) as sql:
                sql.execute('VACUUM')
        except Exception as e:
            print("Application::quit(): ", e)
        self.window.destroy()
        Gst.deinit()

    def is_fullscreen(self):
        """
            Return True if application is fullscreen
        """
        return self._is_fs

#######################
# PRIVATE             #
#######################

    def _init_proxy(self):
        """
            Init proxy setting env
        """
        try:
            settings = Gio.Settings.new('org.gnome.system.proxy.http')
            h = settings.get_value('host').get_string()
            p = settings.get_value('port').get_int32()
            if h != '' and p != 0:
                os.environ['HTTP_PROXY'] = "%s:%s" % (h, p)
        except:
            pass

    def _on_command_line(self, app, app_cmd_line):
        """
            Handle command line
            @param app as Gio.Application
            @param options as Gio.ApplicationCommandLine
        """
        self._externals_count = 0
        options = app_cmd_line.get_options_dict()
        if options.contains('debug'):
            self.debug = True
        if options.contains('set-rating'):
            value = options.lookup_value('set-rating').get_int32()
            if value > 0 and value < 6 and\
                    self.player.current_track.id is not None:
                self.player.current_track.set_popularity(value)
        if options.contains('play-pause'):
            self.player.play_pause()
        elif options.contains('next'):
            self.player.next()
        elif options.contains('prev'):
            self.player.prev()
        args = app_cmd_line.get_arguments()
        if len(args) > 1:
            self.player.clear_externals()
            for f in args[1:]:
                try:
                    f = GLib.filename_to_uri(f)
                except:
                    pass
                self._parser.parse_async(f, True, None, None)
        if self.window is not None and not self.window.is_visible():
            self.window.setup_window()
            self.window.present()
        return 0

    def _on_entry_parsed(self, parser, uri, metadata):
        """
            Add playlist entry to external files
            @param parser as TotemPlParser.Parser
            @param track uri as str
            @param metadata as GLib.HastTable
        """
        self.player.load_external(uri)
        if self._externals_count == 0:
            self.player.set_party(False)
            self.player.play_first_external()
        self._externals_count += 1

    def _hide_on_delete(self, widget, event):
        """
            Hide window
            @param widget as Gtk.Widget
            @param event as Gdk.Event
        """
        if not self.settings.get_value('background-mode'):
            GLib.timeout_add(500, self.prepare_to_exit)
            self.scanner.stop()
        return widget.hide_on_delete()

    def _update_db(self, action=None, param=None):
        """
            Search for new music
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        if self.window:
            t = Thread(target=self.art.clean_all_cache)
            t.daemon = True
            t.start()
            self.window.update_db()

    def _fullscreen(self, action=None, param=None):
        """
            Show a fullscreen window with cover and artist informations
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        if self.window and not self._is_fs:
            fs = FullScreen(self, self.window)
            fs.connect("destroy", self._on_fs_destroyed)
            self._is_fs = True
            fs.show()

    def _on_fs_destroyed(self, widget):
        """
            Mark fullscreen as False
            @param widget as Fullscreen
        """
        self._is_fs = False

    def _settings_dialog(self, action=None, param=None):
        """
            Show settings dialog
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        dialog = SettingsDialog()
        dialog.show()

    def _about(self, action, param):
        """
            Setup about dialog
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/AboutDialog.ui')
        builder.get_object('artists').set_text(
            _("%s artist(s)") % self.artists.count())
        builder.get_object('albums').set_text(
            _("%s album(s)") % self.albums.count())
        builder.get_object('tracks').set_text(
            _("%s track(s)") % self.tracks.count())
        about = builder.get_object('about_dialog')
        about.set_transient_for(self.window)
        about.connect("response", self._about_response)
        about.show()

    def _help(self, action, param):
        """
            Show help in yelp
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        try:
            Gtk.show_uri(None, "help:lollypop", Gtk.get_current_event_time())
        except:
            print(_("Lollypop: You need to install yelp."))

    def _about_response(self, dialog, response_id):
        """
            Destroy about dialog when closed
            @param dialog as Gtk.Dialog
            @param response id as int
        """
        dialog.destroy()

    def _setup_app_menu(self):
        """
            Setup application menu
            @return menu as Gio.Menu
        """
        builder = Gtk.Builder()

        builder.add_from_resource('/org/gnome/Lollypop/Appmenu.ui')

        menu = builder.get_object('app-menu')

        # TODO: Remove this test later
        if Gtk.get_minor_version() > 12:
            settingsAction = Gio.SimpleAction.new('settings', None)
            settingsAction.connect('activate', self._settings_dialog)
            self.set_accels_for_action('app.settings', ["<Control>s"])
            self.add_action(settingsAction)

        updateAction = Gio.SimpleAction.new('update_db', None)
        updateAction.connect('activate', self._update_db)
        self.set_accels_for_action('app.update_db', ["<Control>u"])
        self.add_action(updateAction)

        fsAction = Gio.SimpleAction.new('fullscreen', None)
        fsAction.connect('activate', self._fullscreen)
        self.set_accels_for_action('app.fullscreen', ["F11", "<Control>m"])
        self.add_action(fsAction)

        aboutAction = Gio.SimpleAction.new('about', None)
        aboutAction.connect('activate', self._about)
        self.set_accels_for_action('app.about', ["F2"])
        self.add_action(aboutAction)

        helpAction = Gio.SimpleAction.new('help', None)
        helpAction.connect('activate', self._help)
        self.set_accels_for_action('app.help', ["F1"])
        self.add_action(helpAction)

        quitAction = Gio.SimpleAction.new('quit', None)
        quitAction.connect('activate', self.prepare_to_exit)
        self.set_accels_for_action('app.quit', ["<Control>q"])
        self.add_action(quitAction)

        return menu
Exemplo n.º 5
0
class Application(Gtk.Application):
    """
        Lollypop application:
            - Handle appmenu
            - Handle command line
            - Create main window
    """

    def __init__(self):
        """
            Create application
        """
        Gtk.Application.__init__(
                            self,
                            application_id='org.gnome.Lollypop',
                            flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
        self.cursors = {}
        self.window = None
        self.notify = None
        self.mpd = None
        self.lastfm = None
        self.debug = False
        self._externals_count = 0
        self._init_proxy()
        GLib.set_application_name('lollypop')
        GLib.set_prgname('lollypop')
        # TODO: Remove this test later
        if Gtk.get_minor_version() > 12:
            self.add_main_option("debug", b'd', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Debug lollypop", None)
            self.add_main_option("set-rating", b'r', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.INT, "Rate the current track",
                                 None)
            self.add_main_option("play-pause", b't', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Toggle playback",
                                 None)
            self.add_main_option("next", b'n', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Go to next track",
                                 None)
            self.add_main_option("prev", b'p', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE, "Go to prev track",
                                 None)
            self.add_main_option("emulate-phone", b'e', GLib.OptionFlags.NONE,
                                 GLib.OptionArg.NONE,
                                 "Emulate an Android Phone",
                                 None)
        self.connect('command-line', self._on_command_line)
        self.register(None)
        if self.get_is_remote():
            Gdk.notify_startup_complete()

    def init(self):
        """
            Init main application
        """
        cssProviderFile = Gio.File.new_for_uri(
            'resource:///org/gnome/Lollypop/application.css')
        cssProvider = Gtk.CssProvider()
        cssProvider.load_from_file(cssProviderFile)
        screen = Gdk.Screen.get_default()
        styleContext = Gtk.StyleContext()
        styleContext.add_provider_for_screen(screen, cssProvider,
                                             Gtk.STYLE_PROVIDER_PRIORITY_USER)
        self.settings = Settings.new()
        ArtSize.BIG = self.settings.get_value('cover-size').get_int32()
        if LastFM is not None:
            self.lastfm = LastFM()
        self.db = Database()
        self.playlists = Playlists()
        # We store cursors for main thread
        SqlCursor.add(self.db)
        SqlCursor.add(self.playlists)
        self.albums = AlbumsDatabase()
        self.artists = ArtistsDatabase()
        self.genres = GenresDatabase()
        self.tracks = TracksDatabase()
        self.player = Player()
        self.scanner = CollectionScanner()
        self.art = Art()
        if not self.settings.get_value('disable-mpris'):
            MPRIS(self)
        if not self.settings.get_value('disable-mpd'):
            self.mpd = MpdServerDaemon(
                               self.settings.get_value('mpd-eth').get_string(),
                               self.settings.get_value('mpd-port').get_int32())
        if not self.settings.get_value('disable-notifications'):
            self.notify = NotificationManager()

        settings = Gtk.Settings.get_default()
        dark = self.settings.get_value('dark-ui')
        settings.set_property('gtk-application-prefer-dark-theme', dark)

        self._parser = TotemPlParser.Parser.new()
        self._parser.connect('entry-parsed', self._on_entry_parsed)

        self.add_action(self.settings.create_action('shuffle'))

        self._is_fs = False

    def do_startup(self):
        """
            Add startup notification and
            build gnome-shell menu after Gtk.Application startup
        """
        Gtk.Application.do_startup(self)
        Notify.init("Lollypop")

        # Check locale, we want unicode!
        (code, encoding) = getlocale()
        if encoding is None or encoding != "UTF-8":
            builder = Gtk.Builder()
            builder.add_from_resource('/org/gnome/Lollypop/Unicode.ui')
            self.window = builder.get_object('unicode')
            self.window.set_application(self)
            self.window.show()
        elif not self.window:
            self.init()
            menu = self._setup_app_menu()
            # If GNOME/Unity, add appmenu
            if is_gnome() or is_unity():
                self.set_app_menu(menu)
            self.window = Window(self)
            # If not GNOME add menu to toolbar
            if not is_gnome() and not is_unity():
                self.window.setup_menu(menu)
            self.window.connect('delete-event', self._hide_on_delete)
            self.window.init_list_one()
            self.window.show()
            self.player.restore_state()

    def prepare_to_exit(self, action=None, param=None):
        """
            Save window position and view
        """
        if self.settings.get_value('save-state'):
            self.window.save_view_state()
            if self.player.current_track.id is None:
                track_id = -1
            else:
                track_id = self.player.current_track.id
            self.settings.set_value('track-id', GLib.Variant('i',
                                                             track_id))
        self.player.stop_all()
        if self.window:
            self.window.stop_all()
        self.quit()

    def quit(self):
        """
            Quit lollypop
        """
        if self.mpd is not None:
            self.mpd.quit()
        if self.scanner.is_locked():
            self.scanner.stop()
            GLib.idle_add(self.quit)
            return
        try:
            with SqlCursor(self.db) as sql:
                sql.execute('VACUUM')
            with SqlCursor(self.playlists) as sql:
                sql.execute('VACUUM')
            with SqlCursor(Radios()) as sql:
                sql.execute('VACUUM')
        except Exception as e:
            print("Application::quit(): ", e)
        self.window.destroy()
        Gst.deinit()

    def is_fullscreen(self):
        """
            Return True if application is fullscreen
        """
        return self._is_fs

#######################
# PRIVATE             #
#######################
    def _init_proxy(self):
        """
            Init proxy setting env
        """
        try:
            settings = Gio.Settings.new('org.gnome.system.proxy.http')
            h = settings.get_value('host').get_string()
            p = settings.get_value('port').get_int32()
            if h != '' and p != 0:
                os.environ['HTTP_PROXY'] = "%s:%s" % (h, p)
        except:
            pass

    def _on_command_line(self, app, app_cmd_line):
        """
            Handle command line
            @param app as Gio.Application
            @param options as Gio.ApplicationCommandLine
        """
        self._externals_count = 0
        options = app_cmd_line.get_options_dict()
        if options.contains('debug'):
            self.debug = True
        if options.contains('set-rating'):
            value = options.lookup_value('set-rating').get_int32()
            if value > 0 and value < 6 and\
                    self.player.current_track.id is not None:
                self.player.current_track.set_popularity(value)
        if options.contains('play-pause'):
            self.player.play_pause()
        elif options.contains('next'):
            self.player.next()
        elif options.contains('prev'):
            self.player.prev()
        elif options.contains('emulate-phone'):
            self.window.add_fake_phone()
        args = app_cmd_line.get_arguments()
        if len(args) > 1:
            self.player.clear_externals()
            for f in args[1:]:
                try:
                    f = GLib.filename_to_uri(f)
                except:
                    pass
                self._parser.parse_async(f, True,
                                         None, None)
        if self.window is not None and not self.window.is_visible():
            self.window.setup_window()
            self.window.present()
        return 0

    def _on_entry_parsed(self, parser, uri, metadata):
        """
            Add playlist entry to external files
            @param parser as TotemPlParser.Parser
            @param track uri as str
            @param metadata as GLib.HastTable
        """
        self.player.load_external(uri)
        if self._externals_count == 0:
            self.player.set_party(False)
            self.player.play_first_external()
        self._externals_count += 1

    def _hide_on_delete(self, widget, event):
        """
            Hide window
            @param widget as Gtk.Widget
            @param event as Gdk.Event
        """
        if not self.settings.get_value('background-mode'):
            GLib.timeout_add(500, self.prepare_to_exit)
            self.scanner.stop()
        return widget.hide_on_delete()

    def _update_db(self, action=None, param=None):
        """
            Search for new music
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        if self.window:
            t = Thread(target=self.art.clean_all_cache)
            t.daemon = True
            t.start()
            self.window.update_db()

    def _fullscreen(self, action=None, param=None):
        """
            Show a fullscreen window with cover and artist informations
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        if self.window and not self._is_fs:
            fs = FullScreen(self, self.window)
            fs.connect("destroy", self._on_fs_destroyed)
            self._is_fs = True
            fs.show()

    def _on_fs_destroyed(self, widget):
        """
            Mark fullscreen as False
            @param widget as Fullscreen
        """
        self._is_fs = False

    def _settings_dialog(self, action=None, param=None):
        """
            Show settings dialog
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        dialog = SettingsDialog()
        dialog.show()

    def _about(self, action, param):
        """
            Setup about dialog
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/AboutDialog.ui')
        artists = self.artists.count()
        albums = self.albums.count()
        tracks = self.tracks.count()
        builder.get_object('artists').set_text(
                        ngettext("%d artist", "%d artists", artists) % artists)
        builder.get_object('albums').set_text(
                            ngettext("%d album", "%d albums", albums) % albums)
        builder.get_object('tracks').set_text(
                            ngettext("%d track", "%d tracks", tracks) % tracks)
        about = builder.get_object('about_dialog')
        about.set_transient_for(self.window)
        about.connect("response", self._about_response)
        about.show()

    def _help(self, action, param):
        """
            Show help in yelp
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        try:
            Gtk.show_uri(None, "help:lollypop", Gtk.get_current_event_time())
        except:
            print(_("Lollypop: You need to install yelp."))

    def _about_response(self, dialog, response_id):
        """
            Destroy about dialog when closed
            @param dialog as Gtk.Dialog
            @param response id as int
        """
        dialog.destroy()

    def _setup_app_menu(self):
        """
            Setup application menu
            @return menu as Gio.Menu
        """
        builder = Gtk.Builder()

        builder.add_from_resource('/org/gnome/Lollypop/Appmenu.ui')

        menu = builder.get_object('app-menu')

        # TODO: Remove this test later
        if Gtk.get_minor_version() > 12:
            settingsAction = Gio.SimpleAction.new('settings', None)
            settingsAction.connect('activate', self._settings_dialog)
            self.set_accels_for_action('app.settings', ["<Control>s"])
            self.add_action(settingsAction)

        updateAction = Gio.SimpleAction.new('update_db', None)
        updateAction.connect('activate', self._update_db)
        self.set_accels_for_action('app.update_db', ["<Control>u"])
        self.add_action(updateAction)

        fsAction = Gio.SimpleAction.new('fullscreen', None)
        fsAction.connect('activate', self._fullscreen)
        self.set_accels_for_action('app.fullscreen', ["F11", "<Control>m"])
        self.add_action(fsAction)

        aboutAction = Gio.SimpleAction.new('about', None)
        aboutAction.connect('activate', self._about)
        self.set_accels_for_action('app.about', ["F2"])
        self.add_action(aboutAction)

        helpAction = Gio.SimpleAction.new('help', None)
        helpAction.connect('activate', self._help)
        self.set_accels_for_action('app.help', ["F1"])
        self.add_action(helpAction)

        quitAction = Gio.SimpleAction.new('quit', None)
        quitAction.connect('activate', self.prepare_to_exit)
        self.set_accels_for_action('app.quit', ["<Control>q"])
        self.add_action(quitAction)

        return menu