Beispiel #1
0
class She(base._TextBox):
    ''' Widget to display the Super Hybrid Engine status.
    can display either the mode or CPU speed on eeepc computers.'''

    defaults = manager.Defaults(
        ('font', 'Arial', 'Text Font'),
        ('fontsize', None, 'Calculated if None.'),
        ('padding', None, 'Padding Left and Right. Calculated in None.'),
        ('background', '000000', 'Background Colour'),
        ('foreground', 'ffffff', 'Foreground Colour'),
        ('device', '/sys/devices/platform/eeepc/cpufv', 'sys path to cpufv'),
        ('format', 'speed', 'Type of info to display "speed" or "name"'),
        ('update_delay', 0.5, 'Update Time in seconds.'),
    )

    def __init__(self, width=bar.CALCULATED, **config):
        base._TextBox.__init__(self, 'CPU', **config)
        self.modes = {
            '0x300': {'name': 'Performance', 'speed': '1.6GHz'},
            '0x301': {'name': 'Normal', 'speed': '1.2GHz'},
            '0x302': {'name': 'PoswerSave', 'speed': '800MHz'}
        }
        self.modes_index = self.modes.keys().sort()
        self.mode = None

    def _configure(self, qtile, bar):
        base._TextBox._configure(self, qtile, bar)
        self.timeout_add(self.update_delay, self.update)

    def _get_mode(self):
        with open(self.device) as f:
            mode = f.read().strip()
        return mode

    def update(self):
        mode = self._get_mode()
        if mode != self.mode:
            self.mode = mode
            self.draw()
        return True

    def draw(self):
        if self.mode in self.modes.keys():
            self.text = self.modes[self.mode][self.format]
        else:
            self.text = self.mode
        base._TextBox.draw(self)
Beispiel #2
0
class NetworkStatus(base._TextBox):
    '''Widget that displays network status
       if theme_path is set it draws the
       widget as an icon'''

    defaults = manager.Defaults(
        ("font", "Arial", "Text font"),
        ("fontsize", None, "Font pixel size. Calculated if None."),
        ("padding", 3, "Padding left and right. Calculated if None."),
        ("background", None, "Background colour."),
        ("foreground", "#ffffff", "Foreground colour."),
        ("theme_path", None, "Path of the icons"),
        ("update_interval", 0.2, "Update time in seconds."),
    )

    def __init__(self, **config):
        base._TextBox.__init__(self, 'NET', width=bar.CALCULATED, **config)
        if self.theme_path:
            self.width_type = bar.STATIC
            self.width = 0
        self.surfaces = {}
        self.netstate = "disconnected"

    def _configure(self, qtile, bar):
        base._TextBox._configure(self, qtile, bar)
        if self.theme_path:
            self.setup_images()
        self.timeout_add(self.update_interval, self.update)

    def update(self):
        networkprocess = subprocess.Popen(['nmcli', '-f', 'state', '-t', 'nm'],
                                          stdout=subprocess.PIPE)
        state = networkprocess.communicate()

        if state[0] != self.netstate:
            self.netstate = state[0]
            self.draw()
        return True

    def setup_images(self):
        for img_name in ('network-online', 'network-acquiring',
                         'network-offline'):
            try:
                img = cairo.ImageSurface.create_from_png(
                    os.path.join(self.theme_path, '%s.png' % img_name))
            except cairo.Error, error:
                self.theme_path = None
                self.width_type = bar.CALCULATED
                self.qtile.log.add(error)
                self.qtile.log.add('Switching to text mode')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / float(self.bar.height - 1)

            width = input_width / sp
            if width > self.width:
                self.width = int(width) + self.actual_padding * 2

            imgpat = cairo.SurfacePattern(img)

            scaler = cairo.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairo.FILTER_BEST)
            self.surfaces[img_name] = imgpat
Beispiel #3
0
class Backlight(base._TextBox):
    """
        A simple widget to show the current brightness of a monitor.
    """

    filenames = {}

    defaults = manager.Defaults(
        ('font', 'Arial', 'Text font'),
        ('fontsize', None, 'Font pixel size. Calculated if None.'),
        ('padding', 3, 'Padding left and right. Calculated if None.'),
        ('background', None, 'Background colour.'),
        ('foreground', '#ffffff', 'Foreground colour.'),
        ('backlight_name', 'acpi_video0', 'ACPI name of a backlight device'),
        ('brightness_file', 'brightness', 'Name of file with the '
         'current brightness in /sys/class/backlight/backlight_name'),
        ('max_brightness_file', 'max_brightness', 'Name of file with the '
         'maximum brightness in /sys/class/backlight/backlight_name'),
        ('update_delay', .2, 'The delay in seconds between updates'),
    )

    def __init__(self, **config):
        base._TextBox.__init__(self, "LIGHT", bar.CALCULATED, **config)

    def _configure(self, qtile, bar):
        base._TextBox._configure(self, qtile, bar)
        self.timeout_add(self.update_delay, self.update)

    def _load_file(self, name):
        try:
            path = os.path.join(BACKLIGHT_DIR, self.backlight_name, name)
            with open(path, 'r') as f:
                return f.read().strip()
        except IOError:
            return False
        except Exception:
            self.log.exception("Failed to get %s" % name)

    def _get_info(self):
        try:
            info = {
                'brightness': float(self._load_file(self.brightness_file)),
                'max': float(self._load_file(self.max_brightness_file)),
            }
        except TypeError:
            return False
        return info

    def _get_text(self):
        info = self._get_info()
        if info == False:
            return 'Error'

        percent = info['brightness'] / info['max']
        return FORMAT.format(percent=percent)

    def update(self):
        ntext = self._get_text()
        if ntext != self.text:
            self.text = ntext
            self.bar.draw()
        return True
Beispiel #4
0
class Battery(_Battery):
    """
        A simple but flexible text-based battery widget.
    """
    defaults = manager.Defaults(
        ('low_foreground', 'FF0000', 'font color when battery is low'),
        ('format', '{char} {percent:2.0%} {hour:d}:{min:02d}',
         'Display format'),
        ('charge_char', '^', 'Character to indicate the battery is charging'),
        ('discharge_char', 'V', 'Character to indicate the battery'
         ' is discharging'), *_Battery.defaults.defaults)

    def __init__(self, low_percentage=0.10, **config):
        base._TextBox.__init__(self, "BAT", bar.CALCULATED, **config)
        self.low_percentage = low_percentage

    def _configure(self, qtile, bar):
        base._TextBox._configure(self, qtile, bar)
        self.timeout_add(self.update_delay, self.update)

    def _get_text(self):
        info = self._get_info()
        if info == False:
            return 'Error'

        ## Set the charging character
        try:
            if info['stat'] == DISCHARGING:
                char = self.discharge_char
                time = info['now'] / info['power']
            elif info['stat'] == CHARGING:
                char = self.charge_char
                time = (info['full'] - info['now']) / info['power']
            else:
                return 'Full'
        except ZeroDivisionError:
            time = -1

        ## Calculate the battery percentage and time left
        if time >= 0:
            hour = int(time)
            min = int(time * 60) % 60
        else:
            hour = -1
            min = -1
        percent = info['now'] / info['full']
        if info['stat'] == DISCHARGING and percent < self.low_percentage:
            self.layout.colour = self.low_foreground
        else:
            self.layout.colour = self.foreground

        return self.format.format(char=char,
                                  percent=percent,
                                  hour=hour,
                                  min=min)

    def update(self):
        ntext = self._get_text()
        if ntext != self.text:
            self.text = ntext
            self.bar.draw()
        return True
Beispiel #5
0
class _Battery(base._TextBox):
    ''' Base battery class '''

    filenames = {}

    defaults = manager.Defaults(
        ('font', 'Arial', 'Text font'),
        ('fontsize', None, 'Font pixel size. Calculated if None.'),
        ('padding', 3, 'Padding left and right. Calculated if None.'),
        ('background', None, 'Background colour.'),
        ('foreground', '#ffffff', 'Foreground colour.'),
        ('battery_name', 'BAT0', 'ACPI name of a battery, usually BAT0'),
        ('status_file', 'status', 'Name of status file in'
         ' /sys/class/power_supply/battery_name'),
        ('energy_now_file', None, 'Name of file with the '
         'current energy in /sys/class/power_supply/battery_name'),
        ('energy_full_file', None, 'Name of file with the maximum'
         ' energy in /sys/class/power_supply/battery_name'),
        ('power_now_file', None, 'Name of file with the current'
         ' power draw in /sys/class/power_supply/battery_name'),
        ('update_delay', 1, 'The delay in seconds between updates'),
    )

    def _load_file(self, name):
        try:
            path = os.path.join(BAT_DIR, self.battery_name, name)
            with open(path, 'r') as f:
                return f.read().strip()
        except IOError:
            if name == 'current_now':
                return 0
            return False
        except Exception:
            self.log.exception("Failed to get %s" % name)

    def _get_param(self, name):
        if name in self.filenames:
            return self._load_file(self.filenames[name])
        else:
            ## Don't have the file name cached, figure it out
            file_list = BATTERY_INFO_FILES.get(name, [])
            if getattr(self, name, None):
                ## If a file is manually specified, check it first
                file_list.insert(0, getattr(self, name))

            ## Iterate over the possibilities, and return the first valid value
            for file in file_list:
                value = self._load_file(file)
                if not (value in (False, None)):
                    self.filenames[name] = file
                    return value

        ## If we made it this far, we don't have a valid file. Just return 0.
        return 0

    def _get_info(self):
        try:
            info = {
                'stat': self._get_param('status_file'),
                'now': float(self._get_param('energy_now_file')),
                'full': float(self._get_param('energy_full_file')),
                'power': float(self._get_param('power_now_file')),
            }
        except TypeError:
            return False
        return info
Beispiel #6
0
class BatteryIcon(_Battery):
    ''' Battery life indicator widget '''

    defaults = manager.Defaults(
        ('theme_path', default_icon_path(), 'Path of the icons'),
        ('custom_icons', {}, 'dict containing key->filename icon map'),
        *_Battery.defaults.defaults)

    def __init__(self, **config):
        base._TextBox.__init__(self, '0', width=bar.CALCULATED, **config)
        if self.theme_path:
            self.width_type = bar.STATIC
            self.width = 0
        self.surfaces = {}
        self.current_icon = 'battery-missing'
        self.icons = dict([(x, '{0}.png'.format(x)) for x in (
            'battery-missing',
            'battery-caution',
            'battery-low',
            'battery-good',
            'battery-full',
            'battery-caution-charging',
            'battery-low-charging',
            'battery-good-charging',
            'battery-full-charging',
            'battery-full-charged',
        )])
        self.icons.update(self.custom_icons)

    def _configure(self, qtile, bar):
        base._TextBox._configure(self, qtile, bar)
        self.setup_images()
        self.timeout_add(self.update_delay, self.update)

    def _get_icon_key(self):
        key = 'battery'
        info = self._get_info()
        if info == False or not info.get('full'):
            key += '-missing'
        else:
            percent = info['now'] / info['full']
            if percent < .2:
                key += '-caution'
            elif percent < .4:
                key += '-low'
            elif percent < .8:
                key += '-good'
            else:
                key += '-full'

            if info['stat'] == CHARGING:
                key += '-charging'
            elif info['stat'] == CHARGED:
                key += '-charged'
        return key

    def update(self):
        icon = self._get_icon_key()
        if icon != self.current_icon:
            self.current_icon = icon
            self.draw()
        return True

    def draw(self):
        if self.theme_path:
            self.drawer.clear(self.bar.background)
            self.drawer.ctx.set_source(self.surfaces[self.current_icon])
            self.drawer.ctx.paint()
            self.drawer.draw(self.offset, self.width)
        else:
            self.text = self.current_icon[8:]
            base._TextBox.draw(self)

    def setup_images(self):
        for key, name in self.icons.iteritems():
            try:
                path = os.path.join(self.theme_path, name)
                img = cairo.ImageSurface.create_from_png(path)
            except cairo.Error:
                self.theme_path = None
                self.qtile.log.add('Battery Icon switching to text mode')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / float(self.bar.height - 1)

            width = input_width / sp
            if width > self.width:
                self.width = int(width) + self.actual_padding * 2

            imgpat = cairo.SurfacePattern(img)

            scaler = cairo.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairo.FILTER_BEST)
            self.surfaces[key] = imgpat
Beispiel #7
0
class Metrics(base._TextBox):

    defaults = manager.Defaults(
        ("font", "Arial", "Metrics font"),
        ("fontsize", None, "Metrics pixel size. Calculated if None."),
        ("padding", None, "Metrics padding. Calculated if None."),
        ("background", "000000", "Background colour"),
        ("foreground", "ffffff", "Foreground colour")
    )

    def __init__(self, **kwargs):
        base._TextBox.__init__(self, **kwargs)
        self.cpu_usage, self.cpu_total = self.get_cpu_stat()
        self.interfaces = {}
        self.idle_ifaces = {}

    def _configure(self, qtile, bar):
        base._TextBox._configure(self, qtile, bar)
        self.timeout_add(0, self._update)

    def get_cpu_stat(self):
        stat = [int(i) for i in open('/proc/stat').readline().split()[1:]]
        return sum(stat[:3]), sum(stat)

    def get_cpu_usage(self):
        new_cpu_usage, new_cpu_total = self.get_cpu_stat()
        cpu_usage = new_cpu_usage - self.cpu_usage
        cpu_total = new_cpu_total - self.cpu_total
        self.cpu_usage = new_cpu_usage
        self.cpu_total = new_cpu_total
        return 'Cpu: %d%%' % (float(cpu_usage) / float(cpu_total) * 100.)

    def get_mem_usage(self):
        info = {}
        for line in open('/proc/meminfo'):
            key, val = line.split(':')
            info[key] = int(val.split()[0])
        mem = info['MemTotal']
        mem -= info['MemFree']
        mem -= info['Buffers']
        mem -= info['Cached']
        return 'Mem: %d%%' % (float(mem) / float(info['MemTotal']) * 100)

    def get_net_usage(self):
        interfaces = []
        basedir = '/sys/class/net'
        for iface in os.listdir(basedir):
            j = os.path.join
            ifacedir = j(basedir, iface)
            statdir = j(ifacedir, 'statistics')
            idle = iface in self.idle_ifaces
            try:
                if int(open(j(ifacedir, 'carrier')).read()):
                    rx = int(open(j(statdir, 'rx_bytes')).read())
                    tx = int(open(j(statdir, 'tx_bytes')).read())
                    if iface not in self.interfaces:
                        self.interfaces[iface] = (rx, tx)
                    old_rx, old_tx = self.interfaces[iface]
                    self.interfaces[iface] = (rx, tx)
                    rx = rx - old_rx
                    tx = tx - old_tx
                    if rx or tx:
                        idle = False
                        self.idle_ifaces[iface] = 0
                        rx = humanize_bytes(rx)
                        tx = humanize_bytes(tx)
                        interfaces.append('%s: %s / %s' % (iface, rx, tx))
            except:
                pass
            if idle:
                interfaces.append(
                    '%s: %-11s' % (iface, ("%ds idle" % self.idle_ifaces[iface]))
                )
                self.idle_ifaces[iface] += 1
                if self.idle_ifaces[iface] > 30:
                    del self.idle_ifaces[iface]
        return " | ".join(interfaces)

    def _update(self):
        self.update()
        self.timeout_add(1, self.update)
        return False

    def update(self):
        stat = [self.get_cpu_usage(), self.get_mem_usage()]
        net = self.get_net_usage()
        if net:
            stat.append(net)
        self.text = " | ".join(stat)
        self.bar.draw()
        return True