Пример #1
0
class BatteryStatusApplet:
    """An applet which displays battery information.

    """

    # State of the icon (a tuple containing the icon path and size)
    __previous_state = None

    def __init__(self, applet):
        self.applet = applet

        applet.tooltip.disable_toggle_on_click()

        self.backend = None
        for b in backends:
            if b.backend_useable():
                self.backend = b()
                break

        self.setup_context_menu()

        if self.backend is not None:
            self.__message_handler = MessageHandler(self)

            applet.timing.register(self.check_status_cb, check_status_interval)
            self.check_status_cb()
        else:
            self.set_battery_missing()

        applet.connect_size_changed(self.size_changed_cb)

    def size_changed_cb(self):
        if self.backend is not None:
            self.check_status_cb()
        else:
            self.set_battery_missing()

    def set_battery_missing(self):
        self.applet.tooltip.set(_("No batteries"))

        icon = os.path.join(themes_dir, self.applet.settings["theme"],
                            "battery-missing.svg")
        self.applet.icon.file(icon, size=awnlib.Icon.APPLET_SIZE)

    def setup_context_menu(self):
        prefs = gtk.Builder()
        prefs.add_from_file(ui_file)
        prefs.get_object("vbox-preferences").reparent(
            self.applet.dialog.new("preferences").vbox)
        """ Battery """
        if self.backend is not None:
            batteries = self.backend.get_batteries()

            self.combobox_battery = prefs.get_object("combobox-battery")
            awnlib.add_cell_renderer_text(self.combobox_battery)
            for model in batteries.values():
                self.combobox_battery.append_text(model)

            if self.applet.settings["battery-udi"] not in batteries:
                self.applet.settings["battery-udi"] = batteries.keys()[0]

            if len(self.applet.settings["low-level-unit"]) == 0:
                self.applet.settings["low-level-unit"] = _("Percent")

            battery_getter = lambda key_value: batteries[key_value]
            battery_setter = lambda widget_value: batteries.keys()[
                batteries.values().index(widget_value)]
        else:
            frame = prefs.get_object("frame-battery")
            frame.hide_all()
            frame.set_no_show_all(True)

            battery_getter = lambda v: v
            battery_setter = lambda v: v
        """ Display """
        # Only use themes that are likely to provide all the files
        self.themes = os.listdir(themes_dir)
        self.themes.sort()

        combobox_theme = prefs.get_object("combobox-theme")
        awnlib.add_cell_renderer_text(combobox_theme)
        for i in self.themes:
            combobox_theme.append_text(i)

        self.theme = self.applet.settings["theme"]
        if self.theme not in self.themes:
            self.applet.settings["theme"] = self.theme = default_theme
        """ Notifications """
        if self.backend is not None:
            self.hbox_low_level = prefs.get_object("hbox-low-level")
            self.hbox_low_level.set_sensitive(
                self.applet.settings["warn-low-level"])

            self.hbox_high_level = prefs.get_object("hbox-high-level")
            self.hbox_high_level.set_sensitive(
                self.applet.settings["notify-high-level"])
        else:
            frame = prefs.get_object("frame-notifications")
            frame.hide_all()
            frame.set_no_show_all(True)

        refresh_message = lambda v: self.__message_handler.evaluate()

        binder = self.applet.settings.get_binder(prefs)
        binder.bind("theme",
                    "combobox-theme",
                    key_callback=self.combobox_theme_changed_cb)
        binder.bind("battery-udi",
                    "combobox-battery",
                    getter_transform=battery_getter,
                    setter_transform=battery_setter,
                    key_callback=self.combobox_battery_changed_cb)
        binder.bind("warn-low-level",
                    "checkbutton-warn-low-level",
                    key_callback=self.toggled_warn_low_level_cb)
        binder.bind("notify-high-level",
                    "checkbutton-notify-high-level",
                    key_callback=self.toggled_notify_high_level_cb)
        binder.bind("level-warn-low",
                    "spinbutton-low-level",
                    key_callback=refresh_message)
        binder.bind("level-notify-high",
                    "spinbutton-high-level",
                    key_callback=refresh_message)
        binder.bind("low-level-unit",
                    "combobox-low-level",
                    key_callback=self.combobox_low_level_unit_changed_cb)
        self.applet.settings.load_bindings(binder)

    def toggled_warn_low_level_cb(self, active):
        self.hbox_low_level.set_sensitive(active)

        self.__message_handler.evaluate()

    def toggled_notify_high_level_cb(self, active):
        self.hbox_high_level.set_sensitive(active)

        self.__message_handler.evaluate()

    def combobox_low_level_unit_changed_cb(self, value):
        self.__message_handler.evaluate()

    def combobox_battery_changed_cb(self, udi):
        batteries = self.backend.get_batteries()

        try:
            self.backend.set_active_udi(udi)

            self.check_status_cb()
        except ValueError:
            pass
            # TODO restore combobox


#            udi = self.backend.get_active_udi()
#            self.combobox_battery.set_active(batteries.values().index(batteries[udi]))

    def combobox_theme_changed_cb(self, value):
        if self.backend is not None:
            self.check_status_cb()
        else:
            self.set_battery_missing()

    def check_status_cb(self):
        if not self.backend.is_present():
            self.set_battery_missing()
            return

        charge_percentage = self.backend.get_capacity_percentage()
        power_type = _("AC") if self.backend.is_on_ac_power() else _("battery")
        charge_message = _("Computer running on %s power") % power_type

        if self.backend.is_charged():
            charge_message += "\n" + _("Battery charged")
            icon = os.path.join(themes_dir, self.applet.settings["theme"],
                                "battery-charged.svg")
        else:
            is_charging = self.backend.is_charging()

            if is_charging:
                actoggle = "charging"
                time = self.backend.get_charge_time()
                title_message_suffix = _("until charged")
            else:
                actoggle = "discharging"
                time = self.backend.get_remaining_time()
                title_message_suffix = _("remaining")

            # May be None because charge rate is not always known (when switching between charging and discharging)
            if time is not None:
                charge_message += "\n" + self.format_time(
                    time, suffix=title_message_suffix)

            level = [
                key for key, value in charge_ranges.iteritems() if
                charge_percentage <= value[0] and charge_percentage >= value[1]
            ][0]
            icon = os.path.join(themes_dir, self.applet.settings["theme"],
                                "battery-" + actoggle + "-" + level + ".svg")

        self.applet.tooltip.set(" ".join(
            [charge_message, "(" + str(charge_percentage) + "%)"]))

        self.draw_icon(icon)
        self.__message_handler.evaluate()

    def draw_icon(self, icon):
        new_state = (icon, self.applet.get_size())
        if self.__previous_state == new_state:
            return

        self.__previous_state = new_state

        self.applet.icon.file(icon, size=awnlib.Icon.APPLET_SIZE)

    def is_battery_low(self):
        if not self.backend.is_discharging():
            return False

        unit = self.applet.settings["low-level-unit"]

        if unit == _("Percent") and self.backend.get_capacity_percentage(
        ) <= self.applet.settings["level-warn-low"]:
            return True

        time = self.backend.get_remaining_time()

        if time is None:
            return None

        hours, minutes = time
        return unit == _(
            "Time Remaining"
        ) and hours == 0 and minutes <= self.applet.settings["level-warn-low"]

    def is_battery_high(self):
        if self.backend.is_discharging():
            return False

        return self.backend.get_capacity_percentage(
        ) >= self.applet.settings["level-notify-high"]

    def format_time(self, time, suffix=""):
        hours, minutes = time

        message = []
        time = []

        if hours > 0:
            if hours > 1:
                message.append(_("%d hours"))
            else:
                message.append(_("%d hour"))
            time.append(hours)
        if minutes > 0:
            if minutes > 1:
                message.append(_("%d minutes"))
            else:
                message.append(_("%d minute"))
            time.append(minutes)

        message = " ".join(message) % tuple(time)
        return " ".join([message, suffix]).strip() if len(message) > 0 else ""
Пример #2
0
class BatteryStatusApplet:

    """An applet which displays battery information.

    """

    # State of the icon (a tuple containing the icon path and size)
    __previous_state = None

    def __init__(self, applet):
        self.applet = applet

        applet.tooltip.disable_toggle_on_click()

        self.backend = None
        for b in backends:
            if b.backend_useable():
                self.backend = b()
                break

        self.setup_context_menu()

        if self.backend is not None:
            self.__message_handler = MessageHandler(self)

            applet.timing.register(self.check_status_cb, check_status_interval)
            self.check_status_cb()
        else:
            self.set_battery_missing()

        applet.connect_size_changed(self.size_changed_cb)

    def size_changed_cb(self):
        if self.backend is not None:
            self.check_status_cb()
        else:
            self.set_battery_missing()

    def set_battery_missing(self):
        self.applet.tooltip.set(_("No batteries"))

        icon = os.path.join(themes_dir, self.applet.settings["theme"], "battery-missing.svg")
        self.applet.icon.file(icon, size=awnlib.Icon.APPLET_SIZE)

    def setup_context_menu(self):
        prefs = gtk.Builder()
        prefs.add_from_file(ui_file)
        prefs.get_object("vbox-preferences").reparent(self.applet.dialog.new("preferences").vbox)

        """ Battery """
        if self.backend is not None:
            batteries = self.backend.get_batteries()

            self.combobox_battery = prefs.get_object("combobox-battery")
            awnlib.add_cell_renderer_text(self.combobox_battery)
            for model in batteries.values():
                self.combobox_battery.append_text(model)

            if self.applet.settings["battery-udi"] not in batteries:
                self.applet.settings["battery-udi"] = batteries.keys()[0]

            if len(self.applet.settings["low-level-unit"]) == 0:
                self.applet.settings["low-level-unit"] = _("Percent")

            battery_getter = lambda key_value: batteries[key_value]
            battery_setter = lambda widget_value: batteries.keys()[batteries.values().index(widget_value)]
        else:
            frame = prefs.get_object("frame-battery")
            frame.hide_all()
            frame.set_no_show_all(True)

            battery_getter = lambda v: v
            battery_setter = lambda v: v

        """ Display """
        # Only use themes that are likely to provide all the files
        self.themes = os.listdir(themes_dir)
        self.themes.sort()

        combobox_theme = prefs.get_object("combobox-theme")
        awnlib.add_cell_renderer_text(combobox_theme)
        for i in self.themes:
            combobox_theme.append_text(i)

        self.theme = self.applet.settings["theme"]
        if self.theme not in self.themes:
            self.applet.settings["theme"] = self.theme = default_theme

        """ Notifications """
        if self.backend is not None:
            self.hbox_low_level = prefs.get_object("hbox-low-level")
            self.hbox_low_level.set_sensitive(self.applet.settings["warn-low-level"])

            self.hbox_high_level = prefs.get_object("hbox-high-level")
            self.hbox_high_level.set_sensitive(self.applet.settings["notify-high-level"])
        else:
            frame = prefs.get_object("frame-notifications")
            frame.hide_all()
            frame.set_no_show_all(True)

        refresh_message = lambda v: self.__message_handler.evaluate()

        binder = self.applet.settings.get_binder(prefs)
        binder.bind("theme", "combobox-theme", key_callback=self.combobox_theme_changed_cb)
        binder.bind("battery-udi", "combobox-battery", getter_transform=battery_getter, setter_transform=battery_setter, key_callback=self.combobox_battery_changed_cb)
        binder.bind("warn-low-level", "checkbutton-warn-low-level", key_callback=self.toggled_warn_low_level_cb)
        binder.bind("notify-high-level", "checkbutton-notify-high-level", key_callback=self.toggled_notify_high_level_cb)
        binder.bind("level-warn-low", "spinbutton-low-level", key_callback=refresh_message)
        binder.bind("level-notify-high", "spinbutton-high-level", key_callback=refresh_message)
        binder.bind("low-level-unit", "combobox-low-level", key_callback=self.combobox_low_level_unit_changed_cb)
        self.applet.settings.load_bindings(binder)

    def toggled_warn_low_level_cb(self, active):
        self.hbox_low_level.set_sensitive(active)

        self.__message_handler.evaluate()

    def toggled_notify_high_level_cb(self, active):
        self.hbox_high_level.set_sensitive(active)

        self.__message_handler.evaluate()

    def combobox_low_level_unit_changed_cb(self, value):
        self.__message_handler.evaluate()

    def combobox_battery_changed_cb(self, udi):
        batteries = self.backend.get_batteries()

        try:
            self.backend.set_active_udi(udi)

            self.check_status_cb()
        except ValueError:
            pass
            # TODO restore combobox
#            udi = self.backend.get_active_udi()
#            self.combobox_battery.set_active(batteries.values().index(batteries[udi]))

    def combobox_theme_changed_cb(self, value):
        if self.backend is not None:
            self.check_status_cb()
        else:
            self.set_battery_missing()

    def check_status_cb(self):
        if not self.backend.is_present():
            self.set_battery_missing()
            return

        charge_percentage = self.backend.get_capacity_percentage()
        power_type = _("AC") if self.backend.is_on_ac_power() else _("battery")
        charge_message = _("Computer running on %s power") % power_type

        if self.backend.is_charged():
            charge_message += "\n" + _("Battery charged")
            icon = os.path.join(themes_dir, self.applet.settings["theme"], "battery-charged.svg")
        else:
            is_charging = self.backend.is_charging()

            if is_charging:
                actoggle = "charging"
                time = self.backend.get_charge_time()
                title_message_suffix = _("until charged")
            else:
                actoggle = "discharging"
                time = self.backend.get_remaining_time()
                title_message_suffix = _("remaining")

            # May be None because charge rate is not always known (when switching between charging and discharging)
            if time is not None:
                charge_message += "\n" + self.format_time(time, suffix=title_message_suffix)

            level = [key for key, value in charge_ranges.iteritems() if charge_percentage <= value[0] and charge_percentage >= value[1]][0]
            icon = os.path.join(themes_dir, self.applet.settings["theme"], "battery-" + actoggle + "-" + level + ".svg")

        self.applet.tooltip.set(" ".join([charge_message, "(" + str(charge_percentage) + "%)"]))

        self.draw_icon(icon)
        self.__message_handler.evaluate()

    def draw_icon(self, icon):
        new_state = (icon, self.applet.get_size())
        if self.__previous_state == new_state:
            return

        self.__previous_state = new_state

        self.applet.icon.file(icon, size=awnlib.Icon.APPLET_SIZE)

    def is_battery_low(self):
        if not self.backend.is_discharging():
            return False

        unit = self.applet.settings["low-level-unit"]

        if unit == _("Percent") and self.backend.get_capacity_percentage() <= self.applet.settings["level-warn-low"]:
            return True

        time = self.backend.get_remaining_time()

        if time is None:
            return None

        hours, minutes = time
        return unit == _("Time Remaining") and hours == 0 and minutes <= self.applet.settings["level-warn-low"]

    def is_battery_high(self):
        if self.backend.is_discharging():
            return False

        return self.backend.get_capacity_percentage() >= self.applet.settings["level-notify-high"]

    def format_time(self, time, suffix=""):
        hours, minutes = time

        message = []
        time = []

        if hours > 0:
            if hours > 1:
                message.append(_("%d hours"))
            else:
                message.append(_("%d hour"))
            time.append(hours)
        if minutes > 0:
            if minutes > 1:
                message.append(_("%d minutes"))
            else:
                message.append(_("%d minute"))
            time.append(minutes)

        message = " ".join(message) % tuple(time)
        return " ".join([message, suffix]).strip() if len(message) > 0 else ""