Пример #1
0
    def __init__(self):
        Screen.__init__(self, 'Weather')

        # Screen Title
        self.add(Label(0.13, "screentitle", 0, 0.87, _("Weather")))

        self.weather = Weather(self.config.weather_location)

        location = Label(0.04167, "text", 0.50, 0.13, self.weather.location,
            font_weight="bold")
        location.set_anchor_point_from_gravity(clutter.GRAVITY_CENTER)
        self.add(location)

        # Show today's weather
        self.create_day(self.weather.forecasts[0], 0.1, 0.15)

        # Show tomorrow's weather
        self.create_day(self.weather.forecasts[1], 0.1, 0.5)

        # Show day 3
        self.create_day(self.weather.forecasts[2], 0.4, 0.5)

        # Show day 4
        self.create_day(self.weather.forecasts[3], 0.7, 0.5)
Пример #2
0
class WeatherTest(EntertainerTest):
    """
    WeatherTest class
    Tests for the weather module.
    """
    def setUp(self):
        """Sets up everything for the test"""
        EntertainerTest.setUp(self)

        self.weather = Weather("Bath,England")

    def tearDown(self):
        """Clean up after the test"""
        EntertainerTest.tearDown(self)

    def testWeatherFindRemote(self):
        """Tests the weather code using a call to the outside world"""
        class EnglandTimeZone(tzinfo):
            '''An implementation of tzinfo specific to England.'''
            def __init__(self):
                tzinfo.__init__(self)
                self.stdoffset = timedelta(hours=0)
                self.reprname = 'England'
                self.stdname = 'WET' # Western Europe Time
                self.dstname = 'BST' # British Summer Time

            def __repr__(self):
                return self.reprname

            def _first_sunday_on_or_after(self, dt):
                '''Figure out the DST date.'''
                days_to_go = 6 - dt.weekday()
                if days_to_go:
                    dt += timedelta(days_to_go)
                return dt

            def tzname(self, dt):
                '''See `tzinfo.tzname`.'''
                if self.dst(dt):
                    return self.dstname
                else:
                    return self.stdname

            def utcoffset(self, dt):
                '''See `tzinfo.utcoffset`.'''
                return self.stdoffset + self.dst(dt)

            def dst(self, dt):
                '''See `tzinfo.dst`.'''
                DSTSTART = datetime(1, 4, 1, 2)
                DSTEND = datetime(1, 10, 25, 1)
                ZERO = timedelta(0)
                HOUR = timedelta(hours=1)
                if dt is None or dt.tzinfo is None:
                    return ZERO
                assert dt.tzinfo is self

                start = self._first_sunday_on_or_after(
                    DSTSTART.replace(year=dt.year))
                end = self._first_sunday_on_or_after(
                    DSTEND.replace(year=dt.year))

                if start <= dt.replace(tzinfo=None) < end:
                    return HOUR
                else:
                    return ZERO
        england = EnglandTimeZone()

        self.weather.location = 'Bath,England'
        self.weather.refresh()

        today = self.weather.forecasts[0]
        day = datetime.now(england).strftime('%a')
        self.assertEqual(str(today["Day"]), day)

    def testWeatherLocationLatinEncoding(self):
        """Tests whether code can handle Latin-1 encoding back from google"""
        #Check for Montreal which gets info back from google in Latin-1
        self.weather.location = "Montreal"
        self.weather.refresh()
        results = self.weather.forecasts
        #if there are results then it's working
        self.assertTrue(len(results) > 0)

    def test_yuma_conditions(self):
        """Tests that there's no 'weather-na' in Yuma."""
        # Here we expect sun http://en.wikipedia.org/wiki/Yuma,_Arizona.
        # `Yuma is the sunniest place on earth` (90% of the time)
        self.weather.location = "Yuma"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == 'weather-na')

    def test_london_conditions(self):
        """Tests that there's no 'weather-na' in London."""
        self.weather.location = "London"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == 'weather-na')

    def test_perth_conditions(self):
        """Tests that there's no 'weather-na' in Perth."""
        self.weather.location = "Perth"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == 'weather-na')

    def test_nyc_conditions(self):
        """Tests that there's no 'weather-na' in New York."""
        self.weather.location = "New York"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == 'weather-na')

    def test_north_pole_conditions(self):
        """Tests that there's no 'weather-na' in North Pole."""
        self.weather.location = "North Pole"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == 'weather-na')

    def test_no_location(self):
        """Tests the output if there's no location specified."""
        self.weather.location = ""
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Day"] == _("NA"))
            self.assertFalse(day["Low"] == _("NA"))
            self.assertFalse(day["High"] == _("NA"))
            self.assertFalse(day["Condition"] == _("NA"))
            self.assertFalse(day["Image"] == 'weather-na')
Пример #3
0
    def setUp(self):
        """Sets up everything for the test"""
        EntertainerTest.setUp(self)

        self.weather = Weather("Bath,England")
Пример #4
0
class WeatherTest(EntertainerTest):
    """
    WeatherTest class
    Tests for the weather module.
    """

    def setUp(self):
        """Sets up everything for the test"""
        EntertainerTest.setUp(self)

        self.weather = Weather("Bath,England")

    def tearDown(self):
        """Clean up after the test"""
        EntertainerTest.tearDown(self)

    def testWeatherFindRemote(self):
        """Tests the weather code using a call to the outside world"""

        class EnglandTimeZone(tzinfo):
            """An implementation of tzinfo specific to England."""

            def __init__(self):
                tzinfo.__init__(self)
                self.stdoffset = timedelta(hours=0)
                self.reprname = "England"
                self.stdname = "WET"  # Western Europe Time
                self.dstname = "BST"  # British Summer Time

            def __repr__(self):
                return self.reprname

            def _first_sunday_on_or_after(self, dt):
                """Figure out the DST date."""
                days_to_go = 6 - dt.weekday()
                if days_to_go:
                    dt += timedelta(days_to_go)
                return dt

            def tzname(self, dt):
                """See `tzinfo.tzname`."""
                if self.dst(dt):
                    return self.dstname
                else:
                    return self.stdname

            def utcoffset(self, dt):
                """See `tzinfo.utcoffset`."""
                return self.stdoffset + self.dst(dt)

            def dst(self, dt):
                """See `tzinfo.dst`."""
                DSTSTART = datetime(1, 4, 1, 2)
                DSTEND = datetime(1, 10, 25, 1)
                ZERO = timedelta(0)
                HOUR = timedelta(hours=1)
                if dt is None or dt.tzinfo is None:
                    return ZERO
                assert dt.tzinfo is self

                start = self._first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
                end = self._first_sunday_on_or_after(DSTEND.replace(year=dt.year))

                if start <= dt.replace(tzinfo=None) < end:
                    return HOUR
                else:
                    return ZERO

        england = EnglandTimeZone()

        self.weather.location = "Bath,England"
        self.weather.refresh()

        today = self.weather.forecasts[0]
        day = datetime.now(england).strftime("%a")
        self.assertEqual(str(today["Day"]), day)

    def testWeatherLocationLatinEncoding(self):
        """Tests whether code can handle Latin-1 encoding back from google"""
        # Check for Montreal which gets info back from google in Latin-1
        self.weather.location = "Montreal"
        self.weather.refresh()
        results = self.weather.forecasts
        # if there are results then it's working
        self.assertTrue(len(results) > 0)

    def test_yuma_conditions(self):
        """Tests that there's no 'weather-na' in Yuma."""
        # Here we expect sun http://en.wikipedia.org/wiki/Yuma,_Arizona.
        # `Yuma is the sunniest place on earth` (90% of the time)
        self.weather.location = "Yuma"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == "weather-na")

    def test_london_conditions(self):
        """Tests that there's no 'weather-na' in London."""
        self.weather.location = "London"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == "weather-na")

    def test_perth_conditions(self):
        """Tests that there's no 'weather-na' in Perth."""
        self.weather.location = "Perth"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == "weather-na")

    def test_nyc_conditions(self):
        """Tests that there's no 'weather-na' in New York."""
        self.weather.location = "New York"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == "weather-na")

    def test_north_pole_conditions(self):
        """Tests that there's no 'weather-na' in North Pole."""
        self.weather.location = "North Pole"
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Image"] == "weather-na")

    def test_no_location(self):
        """Tests the output if there's no location specified."""
        self.weather.location = ""
        self.weather.refresh()
        forecasts = self.weather.forecasts
        for day in forecasts:
            self.assertFalse(day["Day"] == _("NA"))
            self.assertFalse(day["Low"] == _("NA"))
            self.assertFalse(day["High"] == _("NA"))
            self.assertFalse(day["Condition"] == _("NA"))
            self.assertFalse(day["Image"] == "weather-na")
Пример #5
0
    def setUp(self):
        """Sets up everything for the test"""
        EntertainerTest.setUp(self)

        self.weather = Weather("Bath,England")
Пример #6
0
    def __init__(self, stand_alone):
        """
        Initialize content management dialog
        @param stand_alone: Boolean, Is this dialog running as a stand alone
            process
        """
        self.stand_alone = stand_alone
        self.config = Configuration()
        self.themes = []
        self.weather = Weather()

        # Load UI with gtk.Builder
        uifile = os.path.join(self.UI_DIR, 'manager.ui')
        self.builder = gtk.Builder()
        self.builder.set_translation_domain('entertainer')
        self.builder.add_from_file(uifile)

        # Get content management dialog and bind signal callbacks
        self.dialog = self.builder.get_object("ManagerDialog")
        if (self.dialog):
            callback_dic = {
                # Dialog-wide callbacks
                "on_close_button_clicked" : self.on_close_button_clicked,
                "on_ManagerDialog_destroy" : self.on_dialog_closed,

                # Media tab
                "on_button_remove_media_clicked" :
                    self.on_button_remove_media_clicked,
                "on_button_add_media_clicked" :
                    self.on_button_add_media_clicked,
                "on_button_edit_media_clicked" :
                    self.on_button_edit_media_clicked,
                "on_checkbutton_video_metadata_toggled" :
                    self.on_checkbutton_video_metadata_toggled,
                "on_lyrics_checkbox_toggled" : self.on_lyrics_checkbox_toggled,
                "on_art_checkbox_toggled" : self.on_art_checkbox_toggled,
                "on_button_media_rebuild_clicked" :
                    self.on_button_media_rebuild_clicked,

                # Weather tab
                "on_button_add_weather_clicked" :
                    self.on_button_add_weather_clicked,
                "on_button_remove_weather_clicked" :
                    self.on_button_remove_weather_clicked,
                "on_weather_display_checkbox_toggled" :
                    self.on_weather_display_checkbox_toggled,
                "on_location_find_button_clicked" :
                    self.on_location_find_button_clicked,
                "on_location_cancel_button_clicked" :
                    self.on_location_cancel_button_clicked,
                "on_location_add_button_clicked" :
                    self.on_location_add_button_clicked,
                "on_location_entry_activate" : self.on_location_entry_activate,

                # User Interface tab
                "on_theme_list_cursor_changed" :
                    self.on_theme_list_cursor_changed,
                "on_theme_add_button_clicked" :
                    self.on_theme_add_button_clicked,
                "on_theme_remove_button_clicked" :
                    self.on_theme_remove_button_clicked,
                "on_checkbutton_effects_toggled" :
                    self.on_checkbutton_effects_toggled,
                "on_combobox_effects_changed" :
                    self.on_combobox_effects_changed,

                # General tab
                "on_checkbutton_fullscreen_toggled" :
                    self.on_checkbutton_fullscreen_toggled,
                "on_checkbutton_autostart_toggled" :
                    self.on_checkbutton_autostart_toggled,
                "on_checkbutton_systray_icon_toggled" :
                    self.on_checkbutton_systray_icon_toggled,
                "on_spinbutton_slideshow_step_value_changed":
                    self.on_spinbutton_slideshow_step_value_changed
                }

        self.builder.connect_signals(callback_dic)

        # Initialize dialog widgets with correct values and show dialog
        self.init_dialog_values_from_configure_file()
        self.dialog.resize(500, 300)
        self.dialog.show()

        # Initialize location list in search dialog
        result_list = self.builder.get_object("location_results_treeview")
        store = gtk.ListStore(str)
        result_list.set_model(store)
        cell_renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn(_("Location"), cell_renderer, text=0)
        result_list.append_column(column)
Пример #7
0
class ManagerDialog:
    """
    This is a content management tool for Entertainer media center application.
    """

    # Temporary storage for entered URL
    url = ""
    UI_DIR = os.path.join(os.path.dirname(__file__), "uis")

    def __init__(self, stand_alone):
        """
        Initialize content management dialog
        @param stand_alone: Boolean, Is this dialog running as a stand alone
            process
        """
        self.stand_alone = stand_alone
        self.config = Configuration()
        self.themes = []
        self.weather = Weather()

        # Load UI with gtk.Builder
        uifile = os.path.join(self.UI_DIR, 'manager.ui')
        self.builder = gtk.Builder()
        self.builder.set_translation_domain('entertainer')
        self.builder.add_from_file(uifile)

        # Get content management dialog and bind signal callbacks
        self.dialog = self.builder.get_object("ManagerDialog")
        if (self.dialog):
            callback_dic = {
                # Dialog-wide callbacks
                "on_close_button_clicked" : self.on_close_button_clicked,
                "on_ManagerDialog_destroy" : self.on_dialog_closed,

                # Media tab
                "on_button_remove_media_clicked" :
                    self.on_button_remove_media_clicked,
                "on_button_add_media_clicked" :
                    self.on_button_add_media_clicked,
                "on_button_edit_media_clicked" :
                    self.on_button_edit_media_clicked,
                "on_checkbutton_video_metadata_toggled" :
                    self.on_checkbutton_video_metadata_toggled,
                "on_lyrics_checkbox_toggled" : self.on_lyrics_checkbox_toggled,
                "on_art_checkbox_toggled" : self.on_art_checkbox_toggled,
                "on_button_media_rebuild_clicked" :
                    self.on_button_media_rebuild_clicked,

                # Weather tab
                "on_button_add_weather_clicked" :
                    self.on_button_add_weather_clicked,
                "on_button_remove_weather_clicked" :
                    self.on_button_remove_weather_clicked,
                "on_weather_display_checkbox_toggled" :
                    self.on_weather_display_checkbox_toggled,
                "on_location_find_button_clicked" :
                    self.on_location_find_button_clicked,
                "on_location_cancel_button_clicked" :
                    self.on_location_cancel_button_clicked,
                "on_location_add_button_clicked" :
                    self.on_location_add_button_clicked,
                "on_location_entry_activate" : self.on_location_entry_activate,

                # User Interface tab
                "on_theme_list_cursor_changed" :
                    self.on_theme_list_cursor_changed,
                "on_theme_add_button_clicked" :
                    self.on_theme_add_button_clicked,
                "on_theme_remove_button_clicked" :
                    self.on_theme_remove_button_clicked,
                "on_checkbutton_effects_toggled" :
                    self.on_checkbutton_effects_toggled,
                "on_combobox_effects_changed" :
                    self.on_combobox_effects_changed,

                # General tab
                "on_checkbutton_fullscreen_toggled" :
                    self.on_checkbutton_fullscreen_toggled,
                "on_checkbutton_autostart_toggled" :
                    self.on_checkbutton_autostart_toggled,
                "on_checkbutton_systray_icon_toggled" :
                    self.on_checkbutton_systray_icon_toggled,
                "on_spinbutton_slideshow_step_value_changed":
                    self.on_spinbutton_slideshow_step_value_changed
                }

        self.builder.connect_signals(callback_dic)

        # Initialize dialog widgets with correct values and show dialog
        self.init_dialog_values_from_configure_file()
        self.dialog.resize(500, 300)
        self.dialog.show()

        # Initialize location list in search dialog
        result_list = self.builder.get_object("location_results_treeview")
        store = gtk.ListStore(str)
        result_list.set_model(store)
        cell_renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn(_("Location"), cell_renderer, text=0)
        result_list.append_column(column)

    def on_dialog_closed(self, widget):
        """Callback function for dialog's close button"""
        try:
            proxy = MessageBusProxy(client_name = "Manager GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.CONTENT_CONF_UPDATED))
            proxy.disconnectFromMessageBus()
        except socket.error:
            error = gtk.MessageDialog(
                    None, gtk.DIALOG_MODAL,
                    gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _(
                        "Entertainer backend is not running. "
                        "Cache cannot be rebuilt."
                    ))
            error.run()
            error.destroy()

        if(self.stand_alone):
            self.dialog.hide()
            self.dialog.destroy()
            gtk.main_quit()
        else:
            self.dialog.hide()
            self.dialog.destroy()

    def on_close_button_clicked(self, widget):
        """Callback function for dialog's close button"""
        if(self.stand_alone):
            self.dialog.hide()
            self.dialog.destroy()
            gtk.main_quit()
        else:
            self.dialog.hide()
            self.dialog.destroy()

    def on_button_add_media_clicked(self, widget):
        """Opens add URL dialog. """
        widget = self.builder.get_object("treeview_media")
        model = widget.get_model()
        # Open "Select folder" dialog
        dialog =  gtk.FileChooserDialog(_("Select folder"), None,
            gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
            (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
                gtk.STOCK_OPEN,gtk.RESPONSE_OK),
            None)
        status = dialog.run()
        # If folder was selected we add it to model and update config file
        if(status == gtk.RESPONSE_OK):
            self.add_to_model_and_config(dialog.get_current_folder(), model,
                self.media_folders, "Media")
        dialog.destroy()

    def on_button_remove_media_clicked(self, widget):
        """Remove currently selected folder from media folders"""
        widget = self.builder.get_object("treeview_media")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        if selection[1] == None:
            return
        rm_folder = model.get_value(selection[1], 0)
        self.media_folders.remove(rm_folder)
        str_folders = ";".join(self.media_folders)
        self.config.write_content_value("Media", "folders", str_folders)
        model.remove(selection[1])

    def on_button_edit_media_clicked(self, widget):
        """Edit currently selected folder"""
        widget = self.builder.get_object("treeview_media")
        url_dialog = self.builder.get_object("url_dialog")
        url_entry = self.builder.get_object("url_entry")
        model = widget.get_model()
        selection = widget.get_selection().get_selected()
        if selection[1] == None:
            return
        folder = model.get_value(selection[1], 0)
        url_entry.set_text(folder)
        url_dialog.set_title(_("Edit URL"))
        status = url_dialog.run()
        if status == gtk.RESPONSE_OK and os.path.exists(self.url):
            # Update list model
            model.set_value(selection[1], 0, self.url)
            # Update configure file
            pos = self.media_folders.index(folder)
            self.media_folders.remove(folder)
            self.media_folders.insert(pos, self.url)
            str_folders = ";".join(self.media_folders)
            self.config.write_content_value("Media", "folders",
                str_folders)

    def on_checkbutton_autostart_toggled(self, widget):
        '''Server autostart checkbox toggled.'''
        self.config.write_content_value("General", "start_server_auto",
            widget.get_active())

    def on_checkbutton_fullscreen_toggled(self, widget):
        '''Start in fullscreen checkbox toggled.'''
        self.config.write_content_value("General", "start_in_fullscreen",
            widget.get_active())

    def on_checkbutton_systray_icon_toggled(self, widget):
        """System Tray Icon checkbox toggled"""
        self.config.write_content_value("General", "display_icon",
            widget.get_active())

    def on_checkbutton_video_metadata_toggled(self, widget):
        """
        Download video file metadata from internet
        @param widget: GTK-Widget
        """
        self.config.write_content_value("Media", "download_metadata",
            widget.get_active())

    def on_spinbutton_slideshow_step_value_changed(self, widget):
        """Activation of slideshow effects"""
        self.config.write_content_value("Photographs", "slideshow_step",
            int(widget.get_value()))

    def on_lyrics_checkbox_toggled(self, widget):
        self.config.write_content_value("Media", "download_lyrics",
            widget.get_active())

    def on_art_checkbox_toggled(self, widget):
        self.config.write_content_value("Media", "download_album_art",
            widget.get_active())

    def on_button_add_weather_clicked(self, widget):
        """
        Open location search dialog
        @param widget: GTK-Widget
        """
        location_dialog = self.builder.get_object("weather_search_dialog")
        location_dialog.set_title(_("Add location"))

        # Clear results
        result_list = self.builder.get_object("location_results_treeview")
        model = result_list.get_model()
        model.clear()

        status = location_dialog.run()
        if(status == gtk.RESPONSE_OK):
            print "Added"

    def on_button_remove_weather_clicked(self, widget):
        """
        Remove currently selected weather location from the location list
        @param widget: GTK-Widget
        """
        widget = self.builder.get_object("treeview_locations")
        model = widget.get_model()
        self.weather_locations = []
        str_folders = ""
        self.config.write_content_value("Weather", "location", str_folders)
        model.clear()

    def on_weather_display_checkbox_toggled(self, widget):
        """
        Checkbox that defines should we use weather conditions
        @param widget: GTK-Widget
        """
        self.config.write_content_value("Weather", "display_in_menu",
            widget.get_active())
        if widget.get_active():
            self.builder.get_object("button_add_weather").set_sensitive(True)
            self.builder.get_object(
                "button_remove_weather").set_sensitive(True)
            self.builder.get_object("treeview_locations").set_sensitive(True)
        else:
            self.builder.get_object("button_add_weather").set_sensitive(False)
            self.builder.get_object(
                "button_remove_weather").set_sensitive(False)
            self.builder.get_object("treeview_locations").set_sensitive(False)

    def on_location_find_button_clicked(self, widget):
        """
        Find location by search string
        @param widget: GTK-Widget
        """
        add_button = self.builder.get_object("location_add_button")
        search_term = self.builder.get_object("location_entry").get_text()
        result_list = self.builder.get_object("location_results_treeview")
        model = result_list.get_model()
        model.clear()
        if search_term != "":
            self.weather.location = search_term
            self.weather.refresh()
            results = self.weather.forecasts
            if len(results) > 0:
                add_button.set_sensitive(True)
                model.append([search_term])
                result_list.set_cursor(0)
            else:
                model.clear()
                model.append([_("Location Not Found!")])
                add_button.set_sensitive(False)

    def on_location_cancel_button_clicked(self, widget):
        """
        Close location search dialog without taking any actions.0
        @param widget: GTK-Widget
        """
        location_dialog = self.builder.get_object("weather_search_dialog")
        location_entry = self.builder.get_object("location_entry")
        location_dialog.hide()
        location_entry.set_text("")
        location_dialog.response(gtk.RESPONSE_CANCEL)

    def on_location_add_button_clicked(self, widget):
        """
        Add selected location to location list and close search dialog
        @param widget: GTK-Widget
        """
        self.weather_locations = []
        result_list = self.builder.get_object("location_results_treeview")
        model = result_list.get_model()
        selection = result_list.get_selection().get_selected()
        if selection[1] == None:
            return
        location_string = model.get_value(selection[1], 0)

        location_list = self.builder.get_object("treeview_locations")
        loc_model = location_list.get_model()
        loc_model.clear()
        loc_model.append([location_string])

        self.weather_locations.append(location_string)
        str_locations = ";".join(self.weather_locations)
        self.config.write_content_value("Weather", "location", str_locations)

        location_dialog = self.builder.get_object("weather_search_dialog")
        location_entry = self.builder.get_object("location_entry")
        location_dialog.hide()
        location_entry.set_text("")
        location_dialog.response(gtk.RESPONSE_CANCEL)

    def on_location_entry_activate(self, widget):
        """
        User hit enter on location entry to start search
        @param widget: GTK-Widget
        """
        self.on_location_find_button_clicked(widget)

    def on_button_media_rebuild_clicked(self, widget):
        '''Rebuild media cache requested.'''
        try:
            proxy = MessageBusProxy(client_name = "Manager GUI")
            proxy.connectToMessageBus()
            proxy.sendMessage(Message(MessageType.REBUILD_IMAGE_CACHE))
            proxy.sendMessage(Message(MessageType.REBUILD_MUSIC_CACHE))
            proxy.sendMessage(Message(MessageType.REBUILD_VIDEO_CACHE))
            proxy.disconnectFromMessageBus()
        except socket.error:
            error = gtk.MessageDialog(
                None, gtk.DIALOG_MODAL,
                gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _(
                    "Entertainer backend is not running. "
                    "Cache cannot be rebuilt."
                ))
            error.run()
            error.destroy()

    def on_theme_add_button_clicked(self, widget):
        """Add theme button clicked"""
        themelist = self.builder.get_object("theme_list")
        model = themelist.get_model()
        # Open "Select folder" dialog
        dialog = gtk.FileChooserDialog(_("Select theme package file"),
            None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL,
            gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK), None)
        file_filter = gtk.FileFilter()
        file_filter.set_name(_("Theme package (tar.gz)"))
        file_filter.add_pattern("*.tar.gz")
        dialog.add_filter(file_filter)
        status = dialog.run()

        # If theme was selected with file chooser
        if(status == gtk.RESPONSE_OK):
            package = dialog.get_filename()
            tar = tarfile.open(package, 'r:gz') # Open tar.gz package

            # Make sure that package contains configuration file (is theme)
            content = tar.getnames()
            theme_name = None
            is_theme = False
            for element in content:
                if element[-10:] == "theme.conf":
                    theme_name = element[:-11]
                    is_theme = True

            # Install them
            if is_theme:
                tar.extractall(os.path.join(self.config.data_dir, 'themes'))
                model.insert(len(model), [theme_name])
            else:
                error = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
                    gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _("Invalid theme file!"))
                error.run()
                error.destroy()

        dialog.destroy()

    def on_theme_list_cursor_changed(self, widget):
        """Executed when theme is changed in theme list. Update preview."""
        # Get currently selected theme
        themelist = self.builder.get_object("theme_list")
        model = themelist.get_model()
        selection = themelist.get_selection().get_selected()
        name = model.get_value(selection[1], 0)
        themedir = os.path.join(self.config.data_dir, 'themes', name)
        theme = Theme(theme_path=themedir)

        # Update preview
        image = self.builder.get_object("theme_image")
        image.set_from_file(os.path.join(themedir, "thumbnail.png"))
        name = self.builder.get_object("name_label")
        name.set_text(theme.getName())
        author = self.builder.get_object("author_label")
        author.set_text(theme.getAuthor())
        license_label = self.builder.get_object("license_label")
        license_label.set_text(theme.getLicence())
        copyright_label = self.builder.get_object("copyright_label")
        copyright_label.set_text(theme.getCopyright())
        comment = self.builder.get_object("comment_label")
        comment.set_text(theme.getComment())

        self.config.write_content_value("General", "theme", name.get_text())

    def on_theme_remove_button_clicked(self, widget):
        """Remove theme button clicked"""
        # Get currently selected theme
        themelist = self.builder.get_object("theme_list")
        model = themelist.get_model()
        selection = themelist.get_selection().get_selected()
        name = model.get_value(selection[1], 0)

        confirm = gtk.MessageDialog(None,
            gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
                _("Are you sure you want to delete\ntheme: %(name)s") % \
                {'name': name})
        status = confirm.run()
        confirm.destroy()
        if(status == gtk.RESPONSE_YES):
            themedir = os.path.join(self.config.data_dir, 'themes', name)
            shutil.rmtree(themedir)
            model.remove(selection[1])
            themelist.set_cursor(0)
            self.themes.remove(name)

    def on_checkbutton_effects_toggled(self, widget):
        """Effect checkbox toggled"""
        combobox = self.builder.get_object("combobox_effects")
        combobox.set_sensitive(widget.get_active())
        self.config.write_content_value("General", "show_effects",
            widget.get_active())

    def on_combobox_effects_changed(self, widget):
        """User changed effect for screen transitions"""
        text = widget.get_active_text()
        if text == _("No effect"):
            english_text = "No effect"
        if text == _("Crossfade"):
            english_text = "Crossfade"
        if text == _("Zoom and fade"):
            english_text = "Zoom and fade"
        if text == _("Slide"):
            english_text = "Slide"
        self.config.write_content_value("General", "transition_effect",
            english_text)

    def init_dialog_values_from_configure_file(self):
        """Read configuration and set dialog widget values with read values.
        """
        # == Videos ==
        medialist_widget = self.builder.get_object("treeview_media")
        mediastore = gtk.ListStore(str)

        cell_renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn(_("Folders"), cell_renderer, text=0)
        medialist_widget.append_column(column)

        self.media_folders = self.config.media_folders

        # Fill model with folders read from config file
        self.init_model(mediastore, self.media_folders)

        medialist_widget.set_model(mediastore)

        # Checkboxes
        metadata_checkbox = self.builder.get_object("video_metadata_checkbox")
        metadata_checkbox.set_active(self.config.download_metadata)

        art_checkbox = self.builder.get_object("art_checkbox")
        art_checkbox.set_active(self.config.download_album_art)

        lyrics_checkbox = self.builder.get_object("lyrics_checkbox")
        lyrics_checkbox.set_active(self.config.download_lyrics)

        # == Weather ==
        locationlist_widget = self.builder.get_object("treeview_locations")
        location_model = gtk.ListStore(str)

        loc_cell = gtk.CellRendererText()
        location_column = gtk.TreeViewColumn(_("Location"), loc_cell, text=0)
        locationlist_widget.append_column(location_column)

        self.weather_location = self.config.weather_location

        # Fill model with location read from config file
        location_model.insert(0, [self.weather_location])
        locationlist_widget.set_model(location_model)

        weather_display_checkbox = self.builder.get_object(
            "weather_display_checkbox")
        display_val = self.config.display_weather_in_client
        weather_display_checkbox.set_active(display_val)
        if not display_val:
            self.builder.get_object("button_add_weather").set_sensitive(False)
            self.builder.get_object("button_remove_weather").set_sensitive(
                False)
            self.builder.get_object("treeview_locations").set_sensitive(False)

        # == User Interface ==
        self.load_themes()
        current_theme = self.config.theme_name

        themelist_widget = self.builder.get_object("theme_list")
        model = gtk.ListStore(str)

        cell_renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Themes", cell_renderer, text=0)
        themelist_widget.append_column(column)

        # Fill model with installed themes
        for i in range(len(self.themes)):
            model.insert(i, [self.themes[i]])

        themelist_widget.set_model(model)

        # Set current theme selected in theme list
        index = model.get_iter_first()
        unselected = True
        index_counter = 0
        while(unselected):
            name = model.get_value(index, 0)
            if name == current_theme:
                unselected = False
                themelist_widget.set_cursor(index_counter)
            index = model.iter_next(index)
            index_counter += 1

        effect_checkbox = self.builder.get_object("checkbutton_effects")
        effect_combobox = self.builder.get_object("combobox_effects")
        if self.config.show_effects:
            effect_checkbox.set_active(True)
            effect_combobox.set_sensitive(True)
        else:
            effect_checkbox.set_active(False)
            effect_combobox.set_sensitive(False)

        # Set Effect Combobox value (Text values are set in ui file)
        effect = self.config.transition_effect
        if effect == "No effect":
            effect_combobox.set_active(0)
        if effect == "Crossfade":
            effect_combobox.set_active(1)
        if effect == "Zoom and fade":
            effect_combobox.set_active(2)
        if effect == "Slide":
            effect_combobox.set_active(3)

        # == General ==
        checkbutton_fullscreen = self.builder.get_object(
            "checkbutton_fullscreen")
        if self.config.start_in_fullscreen:
            checkbutton_fullscreen.set_active(True)
        else:
            checkbutton_fullscreen.set_active(False)

        checkbutton_autostart = self.builder.get_object("checkbutton_autostart")
        if self.config.start_auto_server:
            checkbutton_autostart.set_active(True)
        else:
            checkbutton_autostart.set_active(False)

        checkbutton_systray_icon = self.builder.get_object(
            "checkbutton_systray_icon")
        if self.config.tray_icon_enabled:
            checkbutton_systray_icon.set_active(True)
        else:
            checkbutton_systray_icon.set_active(False)

        spinbutton_slideshow_step = self.builder.get_object(
            "spinbutton_slideshow_step")
        spinbutton_slideshow_step.set_value(self.config.slideshow_step)

    def add_to_model_and_config(self, selected_folder, model, folders, kind):
        """
        Add selected_folder to the model and the folders list while updating
        the configuration item section specified by type
        """
        if not selected_folder in folders:
            model.append([selected_folder])

            if(folders == None):
                folders = [selected_folder]
            else:
                folders.append(selected_folder)

            if "" in folders:
                folders.remove("")
            str_folders = ";".join(folders)
            self.config.write_content_value(kind, "folders", str_folders)

    def init_model(self, model, items):
        """Fill model with items from supplied list"""
        for i in range(len(items)):
            if not str(items[i]).strip() == "":
                model.insert(i, [items[i]])

    def load_themes(self):
        """Load themes"""
        themes = os.listdir(os.path.join(self.config.data_dir, 'themes'))
        for element in themes:
            theme = os.path.join(self.config.data_dir, 'themes', element)
            if os.path.isdir(theme):
                self.themes.append(element)