Merge branch 'master' of github.com:tobi-wan-kenobi/bumblebee-status

Pulling
This commit is contained in:
batman-nair 2017-10-13 11:54:52 +05:30
commit 5b53ed5cf3
9 changed files with 221 additions and 10 deletions

View file

@ -13,3 +13,4 @@ ratings:
- "**.py"
exclude_paths:
- tests/
- thirdparty/

View file

@ -0,0 +1,64 @@
# pylint: disable=C0111,R0903
"""Displays the current keyboard layout using libX11
Requires the following library:
* libX11.so.6
Parameters:
* layout-xkb.showname: Boolean that indicate whether the full name should be displayed. Defaults to false (only the symbol will be displayed)
"""
import bumblebee.input
import bumblebee.output
import bumblebee.engine
has_xkb = True
try:
from xkbgroup import *
except ImportError:
has_xkb = False
import logging
log = logging.getLogger(__name__)
class Module(bumblebee.engine.Module):
def __init__(self, engine, config):
super(Module, self).__init__(engine, config,
bumblebee.output.Widget(full_text=self.current_layout)
)
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
cmd=self._next_keymap)
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE,
cmd=self._prev_keymap)
def _next_keymap(self, event):
self._set_keymap(1)
def _prev_keymap(self, event):
self._set_keymap(-1)
def _set_keymap(self, rotation):
if not has_xkb: return
xkb = XKeyboard()
if xkb.groups_count < 2: return # nothing to doA
layouts = xkb.groups_symbols[rotation:] + xkb.groups_symbols[:rotation]
variants = xkb.groups_variants[rotation:] + xkb.groups_variants[:rotation]
try:
bumblebee.util.execute("setxkbmap -layout {} -variant {}".format(",".join(layouts), ",".join(variants)))
except RuntimeError:
pass
def current_layout(self, widget):
try:
xkb = XKeyboard()
log.debug("group num: {}".format(xkb.group_num))
name = xkb.group_name if bumblebee.util.asbool(self.parameter("showname")) else xkb.group_symbol
return "{} ({})".format(name, xkb.group_variant) if xkb.group_variant else name
except Exception:
return "n/a"
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -1,4 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Displays GPU name, temperature and memory usage.

View file

@ -0,0 +1,70 @@
# pylint: disable=C0111,R0903
"""Shows a widget for each connected screen and allows the user to loop through different orientations.
Requires the following executable:
* xrandr
"""
import os
import re
import sys
import bumblebee.util
import bumblebee.input
import bumblebee.output
import bumblebee.engine
possible_orientations = ["normal", "left", "inverted", "right"]
class Module(bumblebee.engine.Module):
def __init__(self, engine, config):
widgets = []
self._engine = engine
super(Module, self).__init__(engine, config, widgets)
self.update_widgets(widgets)
def update_widgets(self, widgets):
new_widgets = []
for line in bumblebee.util.execute("xrandr -q").split("\n"):
if not " connected" in line:
continue
display = line.split(" ", 2)[0]
orientation = "normal"
for curr_orient in possible_orientations:
if((line.split(" ")).count(curr_orient) > 1):
orientation = curr_orient
break
widget = self.widget(display)
if not widget:
widget = bumblebee.output.Widget(full_text=display, name=display)
self._engine.input.register_callback(widget, button=bumblebee.input.LEFT_MOUSE, cmd=self._toggle)
new_widgets.append(widget)
widget.set("orientation", orientation)
while len(widgets) > 0:
del widgets[0]
for widget in new_widgets:
widgets.append(widget)
def update(self, widgets):
self.update_widgets(widgets)
def state(self, widget):
return widget.get("orientation", "normal")
def _toggle(self, event):
widget = self.widget_by_id(event["instance"])
# compute new orientation based on current orientation
idx = possible_orientations.index(widget.get("orientation"))
idx = (idx + 1) % len(possible_orientations)
new_orientation = possible_orientations[idx]
widget.set("orientation", new_orientation)
bumblebee.util.execute("xrandr --output {} --rotation {}".format(widget.name, new_orientation))
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -47,9 +47,13 @@ class Module(bumblebee.engine.Module):
return temperature
def get_mhz( self ):
output = open("/proc/cpuinfo").read()
m = re.search(r"cpu MHz\s+:\s+(\d+)", output)
mhz = int(m.group(1))
try:
output = open("/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq").read()
mhz = int(float(output)/1000.0)
except:
output = open("/proc/cpuinfo").read()
m = re.search(r"cpu MHz\s+:\s+(\d+)", output)
mhz = int(m.group(1))
if mhz < 1000:
return "{} MHz".format(mhz)

View file

@ -16,6 +16,7 @@ Parameters:
import bumblebee.input
import bumblebee.output
import bumblebee.engine
import re
import json
import time
try:
@ -27,11 +28,12 @@ except ImportError:
class Module(bumblebee.engine.Module):
def __init__(self, engine, config):
super(Module, self).__init__(engine, config,
bumblebee.output.Widget(full_text=self.temperature)
bumblebee.output.Widget(full_text=self.output)
)
self._temperature = 0
self._apikey = self.parameter("apikey", "af7bfe22287c652d032a3064ffa44088")
self._location = self.parameter("location", "auto")
self._city = self.parameter("location", "")
self._interval = int(self.parameter("interval", "15"))
self._unit = self.parameter("unit", "metric")
self._nextcheck = 0
@ -46,10 +48,17 @@ class Module(bumblebee.engine.Module):
return "F"
return ""
def temperature(self, widget):
def temperature(self):
return u"{}°{}".format(self._temperature, self._unit_suffix())
def city(self):
self._city = re.sub('[_-]', ' ', self._city)
return u"{} ".format(self._city)
def output(self, widget):
if not self._valid:
return u"?"
return u"{}°{}".format(self._temperature, self._unit_suffix())
return self.city() + self.temperature()
def state( self, widget ):
if self._valid:
@ -83,6 +92,7 @@ class Module(bumblebee.engine.Module):
location_url = "http://ipinfo.io/json"
location = json.loads(requests.get(location_url).text)
coord = location["loc"].split(",")
self._city = location["city"]
weather_url = "{url}&lat={lat}&lon={lon}".format(url=weather_url, lat=coord[0], lon=coord[1])
else:
weather_url = "{url}&q={city}".format(url=weather_url, city=self._location)

View file

@ -25,17 +25,20 @@ def themes():
class Theme(object):
"""Represents a collection of icons and colors"""
def __init__(self, name):
self._init(self.load(name))
self._widget = None
self._cycle_idx = 0
self._cycle = {}
self._prevbg = None
self._colorset = {}
self._init(self.load(name))
def _init(self, data):
"""Initialize theme from data structure"""
self._theme = data
for iconset in data.get("icons", []):
self._merge(data, self._load_icons(iconset))
for colorset in data.get("colors", []):
self._merge(self._colorset, self._load_colors(colorset))
self._defaults = data.get("defaults", {})
self._cycles = self._theme.get("cycle", [])
self.reset()
@ -99,6 +102,21 @@ class Theme(object):
"""Return the SBW"""
return self._get(widget, "separator-block-width", None)
def _load_wal_colors(self):
walfile = os.path.expanduser("~/.cache/wal/colors.json")
result = {}
with io.open(walfile) as data:
colors = json.load(data)
for field in ["special", "colors"]:
for key in colors[field]:
result[key] = colors[field][key]
return result
def _load_colors(self, name):
"""Load colors for a theme"""
if name == "wal":
return self._load_wal_colors()
def _load_icons(self, name):
"""Load icons for a theme"""
path = "{}/icons/".format(theme_path())
@ -110,7 +128,7 @@ class Theme(object):
if os.path.isfile(themefile):
try:
with io.open(themefile,encoding="utf-8") as data:
with io.open(themefile, encoding="utf-8") as data:
return json.load(data)
except ValueError as exception:
raise bumblebee.error.ThemeLoadError("JSON error: {}".format(exception))
@ -155,7 +173,9 @@ class Theme(object):
widget.set(key, (idx + 1) % len(value))
value = value[idx]
return value
if isinstance(value, list) or isinstance(value, dict):
return value
return self._colorset.get(value, value)
# algorithm copied from
# http://blog.impressiver.com/post/31434674390/deep-merge-multiple-python-dicts

View file

@ -14,6 +14,7 @@
"brightness": { "prefix": "" },
"load": { "prefix": "" },
"layout": { "prefix": "" },
"layout-xkb": { "prefix": "" },
"todo": { "empty": {"prefix": "" },
"items": {"prefix": "" }
},

42
themes/wal-powerline.json Normal file
View file

@ -0,0 +1,42 @@
{
"icons": [ "awesome-fonts" ],
"colors": [ "wal" ],
"defaults": {
"separator-block-width": 0,
"critical": {
"fg": "cursor",
"bg": "color5"
},
"warning": {
"fg": "cursor",
"bg": "color6"
},
"default_separators": false
},
"cycle": [
{
"fg": "foreground",
"bg": "background"
},
{
"fg": "background",
"bg": "foreground"
}
],
"dnf": {
"good": {
"fg": "background",
"bg": "color3"
}
},
"battery": {
"charged": {
"fg": "background",
"bg": "color3"
},
"AC": {
"fg": "background",
"bg": "color3"
}
}
}