[formatting] reformat using "black -t py34"
getting rid of thinking about consistent formatting...
This commit is contained in:
parent
fa98bcbdd1
commit
30c1f712a6
119 changed files with 3961 additions and 3495 deletions
|
@ -10,36 +10,40 @@ import core.widget
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.volume))
|
||||
|
||||
self.__level = 'n/a'
|
||||
self.__level = "n/a"
|
||||
self.__muted = True
|
||||
device = self.parameter('device', 'Master,0')
|
||||
self._cmdString = 'amixer get {}'.format(device)
|
||||
device = self.parameter("device", "Master,0")
|
||||
self._cmdString = "amixer get {}".format(device)
|
||||
|
||||
def volume(self, widget):
|
||||
if self.__level == 'n/a':
|
||||
if self.__level == "n/a":
|
||||
return self.__level
|
||||
m = re.search(r'([\d]+)\%', self.__level)
|
||||
m = re.search(r"([\d]+)\%", self.__level)
|
||||
self.__muted = True
|
||||
if m:
|
||||
if m.group(1) != '0' and '[on]' in self.__level:
|
||||
if m.group(1) != "0" and "[on]" in self.__level:
|
||||
self.__muted = False
|
||||
return '{}%'.format(m.group(1))
|
||||
return "{}%".format(m.group(1))
|
||||
else:
|
||||
return '0%'
|
||||
return "0%"
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
self.__level = util.cli.execute('amixer get {}'.format(self.parameter('device', 'Master,0')))
|
||||
self.__level = util.cli.execute(
|
||||
"amixer get {}".format(self.parameter("device", "Master,0"))
|
||||
)
|
||||
except Exception as e:
|
||||
self.__level = 'n/a'
|
||||
self.__level = "n/a"
|
||||
|
||||
def state(self, widget):
|
||||
if self.__muted:
|
||||
return ['warning', 'muted']
|
||||
return ['unmuted']
|
||||
return ["warning", "muted"]
|
||||
return ["unmuted"]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -15,34 +15,39 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
PATTERN = '{} packages upgraded, {} newly installed, {} to remove and {} not upgraded.'
|
||||
PATTERN = "{} packages upgraded, {} newly installed, {} to remove and {} not upgraded."
|
||||
|
||||
|
||||
def parse_result(to_parse):
|
||||
# We want to line with the iforamtion about package upgrade
|
||||
line_to_parse = to_parse.split('\n')[-4]
|
||||
result = re.search('(.+) packages upgraded, (.+) newly installed, (.+) to remove', line_to_parse)
|
||||
line_to_parse = to_parse.split("\n")[-4]
|
||||
result = re.search(
|
||||
"(.+) packages upgraded, (.+) newly installed, (.+) to remove", line_to_parse
|
||||
)
|
||||
|
||||
return int(result.group(1)), int(result.group(3))
|
||||
|
||||
|
||||
def get_apt_check_info(module):
|
||||
widget = module.widget()
|
||||
try:
|
||||
res = util.cli.execute('aptitude full-upgrade --simulate --assume-yes')
|
||||
widget.set('error', None)
|
||||
res = util.cli.execute("aptitude full-upgrade --simulate --assume-yes")
|
||||
widget.set("error", None)
|
||||
except (RuntimeError, FileNotFoundError) as e:
|
||||
widget.set('error', 'unable to query APT: {}'.format(e))
|
||||
widget.set("error", "unable to query APT: {}".format(e))
|
||||
return
|
||||
|
||||
to_upgrade = 0
|
||||
to_remove = 0
|
||||
try:
|
||||
to_upgrade, to_remove = parse_result(res)
|
||||
widget.set('to_upgrade', to_upgrade)
|
||||
widget.set('to_remove', to_remove)
|
||||
widget.set("to_upgrade", to_upgrade)
|
||||
widget.set("to_remove", to_remove)
|
||||
except Exception as e:
|
||||
widget.set('error', 'parse error: {}'.format(e))
|
||||
widget.set("error", "parse error: {}".format(e))
|
||||
|
||||
core.event.trigger("update", [module.id], redraw_only=True)
|
||||
|
||||
core.event.trigger('update', [ module.id ], redraw_only=True)
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=30)
|
||||
|
@ -51,30 +56,32 @@ class Module(core.module.Module):
|
|||
self.__thread = None
|
||||
|
||||
def updates(self, widget):
|
||||
if widget.get('error'):
|
||||
return widget.get('error')
|
||||
return '{} to upgrade, {} to remove'.format(
|
||||
widget.get('to_upgrade', 0), widget.get('to_remove', 0)
|
||||
if widget.get("error"):
|
||||
return widget.get("error")
|
||||
return "{} to upgrade, {} to remove".format(
|
||||
widget.get("to_upgrade", 0), widget.get("to_remove", 0)
|
||||
)
|
||||
|
||||
def update(self):
|
||||
if self.__thread and self.__thread.isAlive(): return
|
||||
if self.__thread and self.__thread.isAlive():
|
||||
return
|
||||
|
||||
self.__thread = threading.Thread(target=get_apt_check_info, args=(self,))
|
||||
self.__thread.start()
|
||||
|
||||
def state(self, widget):
|
||||
cnt = 0
|
||||
ret = 'good'
|
||||
for t in ['to_upgrade', 'to_remove']:
|
||||
ret = "good"
|
||||
for t in ["to_upgrade", "to_remove"]:
|
||||
cnt += widget.get(t, 0)
|
||||
if cnt > 50:
|
||||
ret = 'critical'
|
||||
ret = "critical"
|
||||
elif cnt > 0:
|
||||
ret = 'warning'
|
||||
if widget.get('error'):
|
||||
ret = 'critical'
|
||||
ret = "warning"
|
||||
if widget.get("error"):
|
||||
ret = "critical"
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -10,6 +10,7 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
|
@ -18,7 +19,7 @@ class Module(core.module.Module):
|
|||
|
||||
@property
|
||||
def __format(self):
|
||||
return self.parameter('format', 'Update Arch: {}')
|
||||
return self.parameter("format", "Update Arch: {}")
|
||||
|
||||
def utilization(self, widget):
|
||||
return self.__format.format(self.__packages)
|
||||
|
@ -27,10 +28,11 @@ class Module(core.module.Module):
|
|||
return self.__packages == 0
|
||||
|
||||
def update(self):
|
||||
result = util.cli.execute('checkupdates')
|
||||
self.__packages = len(result.split('\n')) - 1
|
||||
result = util.cli.execute("checkupdates")
|
||||
self.__packages = len(result.split("\n")) - 1
|
||||
|
||||
def state(self, widget):
|
||||
return self.threshold_state(self.__packages, 1, 100)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -23,30 +23,27 @@ import util.cli
|
|||
import util.format
|
||||
import util.popup
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.status))
|
||||
|
||||
device = self.parameter('device', 'hci0')
|
||||
self.manager = self.parameter('manager', 'blueman-manager')
|
||||
self._path = '/sys/class/bluetooth/{}'.format(device)
|
||||
self._status = 'Off'
|
||||
device = self.parameter("device", "hci0")
|
||||
self.manager = self.parameter("manager", "blueman-manager")
|
||||
self._path = "/sys/class/bluetooth/{}".format(device)
|
||||
self._status = "Off"
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.manager)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.manager)
|
||||
|
||||
# determine whether to use pop-up menu or simply toggle the device on/off
|
||||
right_click_popup = util.format.asbool(
|
||||
self.parameter('right_click_popup', True))
|
||||
self.parameter("right_click_popup", True)
|
||||
)
|
||||
|
||||
if right_click_popup:
|
||||
core.input.register(self,
|
||||
button=core.input.RIGHT_MOUSE,
|
||||
cmd=self.popup)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.popup)
|
||||
else:
|
||||
core.input.register(self,
|
||||
button=core.input.RIGHT_MOUSE,
|
||||
cmd=self._toggle)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self._toggle)
|
||||
|
||||
def status(self, widget):
|
||||
"""Get status."""
|
||||
|
@ -55,35 +52,33 @@ class Module(core.module.Module):
|
|||
def update(self):
|
||||
"""Update current state."""
|
||||
if not os.path.exists(self._path):
|
||||
self._status = '?'
|
||||
self._status = "?"
|
||||
return
|
||||
|
||||
# search for whichever rfkill directory available
|
||||
try:
|
||||
dirnames = next(os.walk(self._path))[1]
|
||||
for dirname in dirnames:
|
||||
m = re.match(r'rfkill[0-9]+', dirname)
|
||||
m = re.match(r"rfkill[0-9]+", dirname)
|
||||
if m is not None:
|
||||
with open(os.path.join(self._path,
|
||||
dirname,
|
||||
'state'), 'r') as f:
|
||||
with open(os.path.join(self._path, dirname, "state"), "r") as f:
|
||||
state = int(f.read())
|
||||
if state == 1:
|
||||
self._status = 'On'
|
||||
self._status = "On"
|
||||
else:
|
||||
self._status = 'Off'
|
||||
self._status = "Off"
|
||||
return
|
||||
|
||||
except IOError:
|
||||
self._status = '?'
|
||||
self._status = "?"
|
||||
|
||||
def popup(self, widget):
|
||||
"""Show a popup menu."""
|
||||
menu = util.popup.PopupMenu()
|
||||
if self._status == 'On':
|
||||
menu.add_menuitem('Disable Bluetooth')
|
||||
elif self._status == 'Off':
|
||||
menu.add_menuitem('Enable Bluetooth')
|
||||
if self._status == "On":
|
||||
menu.add_menuitem("Disable Bluetooth")
|
||||
elif self._status == "Off":
|
||||
menu.add_menuitem("Enable Bluetooth")
|
||||
else:
|
||||
return
|
||||
|
||||
|
@ -95,32 +90,35 @@ class Module(core.module.Module):
|
|||
|
||||
def _toggle(self, widget=None):
|
||||
"""Toggle bluetooth state."""
|
||||
if self._status == 'On':
|
||||
state = 'false'
|
||||
if self._status == "On":
|
||||
state = "false"
|
||||
else:
|
||||
state = 'true'
|
||||
state = "true"
|
||||
|
||||
dst = self.parameter('dbus_destination', 'org.blueman.Mechanism')
|
||||
dst_path = self.parameter('dbus_destination_path', '/')
|
||||
dst = self.parameter("dbus_destination", "org.blueman.Mechanism")
|
||||
dst_path = self.parameter("dbus_destination_path", "/")
|
||||
|
||||
cmd = 'dbus-send --system --print-reply --dest={}'\
|
||||
' {} org.blueman.Mechanism.SetRfkillState'\
|
||||
' boolean:{}'.format(dst, dst_path, state)
|
||||
cmd = (
|
||||
"dbus-send --system --print-reply --dest={}"
|
||||
" {} org.blueman.Mechanism.SetRfkillState"
|
||||
" boolean:{}".format(dst, dst_path, state)
|
||||
)
|
||||
|
||||
logging.debug('bt: toggling bluetooth')
|
||||
logging.debug("bt: toggling bluetooth")
|
||||
util.cli.execute(cmd)
|
||||
|
||||
def state(self, widget):
|
||||
"""Get current state."""
|
||||
state = []
|
||||
|
||||
if self._status == '?':
|
||||
state = ['unknown']
|
||||
elif self._status == 'On':
|
||||
state = ['ON']
|
||||
if self._status == "?":
|
||||
state = ["unknown"]
|
||||
elif self._status == "On":
|
||||
state = ["ON"]
|
||||
else:
|
||||
state = ['OFF']
|
||||
state = ["OFF"]
|
||||
|
||||
return state
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -20,19 +20,18 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.status))
|
||||
|
||||
self.manager = self.parameter('manager', 'blueman-manager')
|
||||
self._status = 'Off'
|
||||
self.manager = self.parameter("manager", "blueman-manager")
|
||||
self._status = "Off"
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
self._bus = dbus.SystemBus()
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.manager)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE,
|
||||
cmd=self._toggle)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.manager)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self._toggle)
|
||||
|
||||
def status(self, widget):
|
||||
"""Get status."""
|
||||
|
@ -40,58 +39,63 @@ class Module(core.module.Module):
|
|||
|
||||
def update(self):
|
||||
"""Update current state."""
|
||||
state = len(subprocess.run(['bluetoothctl', 'list'], stdout=subprocess.PIPE).stdout)
|
||||
state = len(
|
||||
subprocess.run(["bluetoothctl", "list"], stdout=subprocess.PIPE).stdout
|
||||
)
|
||||
if state > 0:
|
||||
connected_devices = self.get_connected_devices()
|
||||
self._status = 'On - {}'.format(connected_devices)
|
||||
self._status = "On - {}".format(connected_devices)
|
||||
else:
|
||||
self._status = 'Off'
|
||||
adapters_cmd = 'rfkill list | grep Bluetooth'
|
||||
if not len(subprocess.run(adapters_cmd, shell=True, stdout=subprocess.PIPE).stdout):
|
||||
self._status = 'No Adapter Found'
|
||||
self._status = "Off"
|
||||
adapters_cmd = "rfkill list | grep Bluetooth"
|
||||
if not len(
|
||||
subprocess.run(adapters_cmd, shell=True, stdout=subprocess.PIPE).stdout
|
||||
):
|
||||
self._status = "No Adapter Found"
|
||||
return
|
||||
|
||||
def _toggle(self, widget=None):
|
||||
"""Toggle bluetooth state."""
|
||||
if 'On' in self._status:
|
||||
state = 'false'
|
||||
if "On" in self._status:
|
||||
state = "false"
|
||||
else:
|
||||
state = 'true'
|
||||
state = "true"
|
||||
|
||||
cmd = 'dbus-send --system --print-reply --dest=org.blueman.Mechanism /org/blueman/mechanism org.blueman.Mechanism.SetRfkillState boolean:%s' % state
|
||||
cmd = (
|
||||
"dbus-send --system --print-reply --dest=org.blueman.Mechanism /org/blueman/mechanism org.blueman.Mechanism.SetRfkillState boolean:%s"
|
||||
% state
|
||||
)
|
||||
|
||||
logging.debug('bt: toggling bluetooth')
|
||||
logging.debug("bt: toggling bluetooth")
|
||||
core.util.execute(cmd)
|
||||
|
||||
def state(self, widget):
|
||||
"""Get current state."""
|
||||
state = []
|
||||
|
||||
if self._status == 'No Adapter Found':
|
||||
state.append('critical')
|
||||
elif self._status == 'On - 0':
|
||||
state.append('warning')
|
||||
elif 'On' in self._status and not(self._status == 'On - 0'):
|
||||
state.append('ON')
|
||||
if self._status == "No Adapter Found":
|
||||
state.append("critical")
|
||||
elif self._status == "On - 0":
|
||||
state.append("warning")
|
||||
elif "On" in self._status and not (self._status == "On - 0"):
|
||||
state.append("ON")
|
||||
else:
|
||||
state.append('critical')
|
||||
state.append("critical")
|
||||
return state
|
||||
|
||||
def get_connected_devices(self):
|
||||
devices = 0
|
||||
objects = dbus.Interface(
|
||||
self._bus.get_object('org.bluez', '/'),
|
||||
'org.freedesktop.DBus.ObjectManager'
|
||||
self._bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager"
|
||||
).GetManagedObjects()
|
||||
for path, interfaces in objects.items():
|
||||
if 'org.bluez.Device1' in interfaces:
|
||||
if "org.bluez.Device1" in interfaces:
|
||||
if dbus.Interface(
|
||||
self._bus.get_object('org.bluez', path),
|
||||
'org.freedesktop.DBus.Properties'
|
||||
).Get(
|
||||
'org.bluez.Device1', 'Connected'
|
||||
):
|
||||
self._bus.get_object("org.bluez", path),
|
||||
"org.freedesktop.DBus.Properties",
|
||||
).Get("org.bluez.Device1", "Connected"):
|
||||
devices += 1
|
||||
return devices
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pylint: disable=C0111,R0903,W0212
|
||||
# pylint: disable=C0111,R0903,W0212
|
||||
|
||||
"""Enable/disable automatic screen locking.
|
||||
|
||||
|
@ -21,10 +21,11 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=10)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(''))
|
||||
super().__init__(config, theme, core.widget.Widget(""))
|
||||
|
||||
self.__active = False
|
||||
self.__xid = None
|
||||
|
@ -32,7 +33,7 @@ class Module(core.module.Module):
|
|||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__toggle)
|
||||
|
||||
def __check_requirements(self):
|
||||
requirements = ['xdotool', 'xprop', 'xdg-screensaver']
|
||||
requirements = ["xdotool", "xprop", "xdg-screensaver"]
|
||||
missing = []
|
||||
for tool in requirements:
|
||||
if not shutil.which(tool):
|
||||
|
@ -40,20 +41,24 @@ class Module(core.module.Module):
|
|||
return missing
|
||||
|
||||
def __get_i3bar_xid(self):
|
||||
xid = util.cli.execute('xdotool search --class \'i3bar\'').partition('\n')[0].strip()
|
||||
xid = (
|
||||
util.cli.execute("xdotool search --class 'i3bar'")
|
||||
.partition("\n")[0]
|
||||
.strip()
|
||||
)
|
||||
if xid.isdigit():
|
||||
return xid
|
||||
logging.warning('Module caffeine: xdotool couldn\'t get X window ID of \'i3bar\'.')
|
||||
logging.warning("Module caffeine: xdotool couldn't get X window ID of 'i3bar'.")
|
||||
return None
|
||||
|
||||
def __notify(self):
|
||||
if not shutil.which('notify-send'):
|
||||
if not shutil.which("notify-send"):
|
||||
return
|
||||
|
||||
if self.__active:
|
||||
util.cli.execute('notify-send \'Consuming caffeine\'')
|
||||
util.cli.execute("notify-send 'Consuming caffeine'")
|
||||
else:
|
||||
util.cli.execute('notify-send \'Out of coffee\'')
|
||||
util.cli.execute("notify-send 'Out of coffee'")
|
||||
|
||||
def _suspend_screensaver(self):
|
||||
self.__xid = self.__get_i3bar_xid()
|
||||
|
@ -63,7 +68,7 @@ class Module(core.module.Module):
|
|||
pid = os.fork()
|
||||
if pid == 0:
|
||||
os.setsid()
|
||||
util.cli.execute('xdg-screensaver suspend {}'.format(self.__xid))
|
||||
util.cli.execute("xdg-screensaver suspend {}".format(self.__xid))
|
||||
os._exit(0)
|
||||
else:
|
||||
os.waitpid(pid, 0)
|
||||
|
@ -71,8 +76,12 @@ class Module(core.module.Module):
|
|||
|
||||
def __resume_screensaver(self):
|
||||
success = True
|
||||
xprop_path = shutil.which('xprop')
|
||||
pids = [ p.pid for p in psutil.process_iter() if p.cmdline() == [xprop_path, '-id', str(self.__xid), '-spy'] ]
|
||||
xprop_path = shutil.which("xprop")
|
||||
pids = [
|
||||
p.pid
|
||||
for p in psutil.process_iter()
|
||||
if p.cmdline() == [xprop_path, "-id", str(self.__xid), "-spy"]
|
||||
]
|
||||
for pid in pids:
|
||||
try:
|
||||
os.kill(pid, 9)
|
||||
|
@ -82,13 +91,13 @@ class Module(core.module.Module):
|
|||
|
||||
def state(self, _):
|
||||
if self.__active:
|
||||
return 'activated'
|
||||
return 'deactivated'
|
||||
return "activated"
|
||||
return "deactivated"
|
||||
|
||||
def __toggle(self, _):
|
||||
missing = self.__check_requirements()
|
||||
if missing:
|
||||
logging.warning('Could not run caffeine - missing %s!', ', '.join(missing))
|
||||
logging.warning("Could not run caffeine - missing %s!", ", ".join(missing))
|
||||
return
|
||||
|
||||
self.__active = not self.__active
|
||||
|
@ -102,4 +111,5 @@ class Module(core.module.Module):
|
|||
else:
|
||||
self.__active = not self.__active
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -42,90 +42,88 @@ import util.cli
|
|||
import util.graph
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
self.__layout = self.parameter('layout', 'cpu2.maxfreq cpu2.cpuload cpu2.coresload cpu2.temp cpu2.fanspeed')
|
||||
self.__layout = self.parameter(
|
||||
"layout", "cpu2.maxfreq cpu2.cpuload cpu2.coresload cpu2.temp cpu2.fanspeed"
|
||||
)
|
||||
self.__widget_names = self.__layout.split()
|
||||
self.__colored = util.format.asbool(self.parameter('colored', False))
|
||||
self.__colored = util.format.asbool(self.parameter("colored", False))
|
||||
widget_list = []
|
||||
for widget_name in self.__widget_names:
|
||||
if widget_name == 'cpu2.maxfreq':
|
||||
widget = core.widget.Widget(
|
||||
name=widget_name, full_text=self.maxfreq)
|
||||
widget.set('type', 'freq')
|
||||
elif widget_name == 'cpu2.cpuload':
|
||||
widget = core.widget.Widget(
|
||||
name=widget_name, full_text=self.cpuload)
|
||||
widget.set('type', 'load')
|
||||
elif widget_name == 'cpu2.coresload':
|
||||
widget = core.widget.Widget(
|
||||
name=widget_name, full_text=self.coresload)
|
||||
widget.set('type', 'loads')
|
||||
elif widget_name == 'cpu2.temp':
|
||||
widget = core.widget.Widget(
|
||||
name=widget_name, full_text=self.temp)
|
||||
widget.set('type', 'temp')
|
||||
elif widget_name == 'cpu2.fanspeed':
|
||||
widget = core.widget.Widget(
|
||||
name=widget_name, full_text=self.fanspeed)
|
||||
widget.set('type', 'fan')
|
||||
if widget_name == "cpu2.maxfreq":
|
||||
widget = core.widget.Widget(name=widget_name, full_text=self.maxfreq)
|
||||
widget.set("type", "freq")
|
||||
elif widget_name == "cpu2.cpuload":
|
||||
widget = core.widget.Widget(name=widget_name, full_text=self.cpuload)
|
||||
widget.set("type", "load")
|
||||
elif widget_name == "cpu2.coresload":
|
||||
widget = core.widget.Widget(name=widget_name, full_text=self.coresload)
|
||||
widget.set("type", "loads")
|
||||
elif widget_name == "cpu2.temp":
|
||||
widget = core.widget.Widget(name=widget_name, full_text=self.temp)
|
||||
widget.set("type", "temp")
|
||||
elif widget_name == "cpu2.fanspeed":
|
||||
widget = core.widget.Widget(name=widget_name, full_text=self.fanspeed)
|
||||
widget.set("type", "fan")
|
||||
if self.__colored:
|
||||
widget.set('pango', True)
|
||||
widget.set("pango", True)
|
||||
widget_list.append(widget)
|
||||
self.widgets(widget_list)
|
||||
self.__temp_pattern = self.parameter('temp_pattern')
|
||||
self.__temp_pattern = self.parameter("temp_pattern")
|
||||
if self.__temp_pattern is None:
|
||||
self.__temp = 'n/a'
|
||||
self.__fan_pattern = self.parameter('fan_pattern')
|
||||
self.__temp = "n/a"
|
||||
self.__fan_pattern = self.parameter("fan_pattern")
|
||||
if self.__fan_pattern is None:
|
||||
self.__fan = 'n/a'
|
||||
self.__fan = "n/a"
|
||||
# maxfreq is loaded only once at startup
|
||||
if 'cpu2.maxfreq' in self.__widget_names:
|
||||
if "cpu2.maxfreq" in self.__widget_names:
|
||||
self.__maxfreq = psutil.cpu_freq().max / 1000
|
||||
|
||||
def maxfreq(self, _):
|
||||
return '{:.2f}GHz'.format(self.__maxfreq)
|
||||
return "{:.2f}GHz".format(self.__maxfreq)
|
||||
|
||||
def cpuload(self, _):
|
||||
return '{:>3}%'.format(self.__cpuload)
|
||||
return "{:>3}%".format(self.__cpuload)
|
||||
|
||||
def add_color(self, bar):
|
||||
"""add color as pango markup to a bar"""
|
||||
if bar in ['▁', '▂']:
|
||||
color = self.theme.color('green', 'green')
|
||||
elif bar in ['▃', '▄']:
|
||||
color = self.theme.color('yellow', 'yellow')
|
||||
elif bar in ['▅', '▆']:
|
||||
color = self.theme.color('orange', 'orange')
|
||||
elif bar in ['▇', '█']:
|
||||
color = self.theme.color('red', 'red')
|
||||
if bar in ["▁", "▂"]:
|
||||
color = self.theme.color("green", "green")
|
||||
elif bar in ["▃", "▄"]:
|
||||
color = self.theme.color("yellow", "yellow")
|
||||
elif bar in ["▅", "▆"]:
|
||||
color = self.theme.color("orange", "orange")
|
||||
elif bar in ["▇", "█"]:
|
||||
color = self.theme.color("red", "red")
|
||||
colored_bar = '<span foreground="{}">{}</span>'.format(color, bar)
|
||||
return colored_bar
|
||||
|
||||
def coresload(self, _):
|
||||
mono_bars = [util.graph.hbar(x) for x in self.__coresload]
|
||||
if not self.__colored:
|
||||
return ''.join(mono_bars)
|
||||
return "".join(mono_bars)
|
||||
colored_bars = [self.add_color(x) for x in mono_bars]
|
||||
return ''.join(colored_bars)
|
||||
return "".join(colored_bars)
|
||||
|
||||
def temp(self, _):
|
||||
if self.__temp == 'n/a' or self.__temp == 0:
|
||||
return 'n/a'
|
||||
return '{}°C'.format(self.__temp)
|
||||
if self.__temp == "n/a" or self.__temp == 0:
|
||||
return "n/a"
|
||||
return "{}°C".format(self.__temp)
|
||||
|
||||
def fanspeed(self, _):
|
||||
if self.__fanspeed == 'n/a':
|
||||
return 'n/a'
|
||||
return '{}RPM'.format(self.__fanspeed)
|
||||
if self.__fanspeed == "n/a":
|
||||
return "n/a"
|
||||
return "{}RPM".format(self.__fanspeed)
|
||||
|
||||
def _parse_sensors_output(self):
|
||||
output = util.cli.execute('sensors -u')
|
||||
lines = output.split('\n')
|
||||
temp = 'n/a'
|
||||
fan = 'n/a'
|
||||
output = util.cli.execute("sensors -u")
|
||||
lines = output.split("\n")
|
||||
temp = "n/a"
|
||||
fan = "n/a"
|
||||
temp_line = None
|
||||
fan_line = None
|
||||
for line in lines:
|
||||
|
@ -136,23 +134,24 @@ class Module(core.module.Module):
|
|||
if temp_line is not None and fan_line is not None:
|
||||
break
|
||||
if temp_line is not None:
|
||||
temp = round(float(temp_line.split(':')[1].strip()))
|
||||
temp = round(float(temp_line.split(":")[1].strip()))
|
||||
if fan_line is not None:
|
||||
fan = int(fan_line.split(':')[1].strip()[:-4])
|
||||
fan = int(fan_line.split(":")[1].strip()[:-4])
|
||||
return temp, fan
|
||||
|
||||
def update(self):
|
||||
if 'cpu2.maxfreq' in self.__widget_names:
|
||||
if "cpu2.maxfreq" in self.__widget_names:
|
||||
self.__maxfreq = psutil.cpu_freq().max / 1000
|
||||
if 'cpu2.cpuload' in self.__widget_names:
|
||||
if "cpu2.cpuload" in self.__widget_names:
|
||||
self.__cpuload = round(psutil.cpu_percent(percpu=False))
|
||||
if 'cpu2.coresload' in self.__widget_names:
|
||||
if "cpu2.coresload" in self.__widget_names:
|
||||
self.__coresload = psutil.cpu_percent(percpu=True)
|
||||
if 'cpu2.temp' in self.__widget_names or 'cpu2.fanspeed' in self.__widget_names:
|
||||
if "cpu2.temp" in self.__widget_names or "cpu2.fanspeed" in self.__widget_names:
|
||||
self.__temp, self.__fanspeed = self._parse_sensors_output()
|
||||
|
||||
def state(self, widget):
|
||||
"""for having per-widget icons"""
|
||||
return [widget.get('type', '')]
|
||||
return [widget.get("type", "")]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,71 +27,82 @@ import core.input
|
|||
|
||||
import util.format
|
||||
|
||||
|
||||
def default_format(module):
|
||||
default = '%x %X %Z'
|
||||
if module == 'datetz':
|
||||
default = '%x %Z'
|
||||
if module == 'timetz':
|
||||
default = '%X %Z'
|
||||
default = "%x %X %Z"
|
||||
if module == "datetz":
|
||||
default = "%x %Z"
|
||||
if module == "timetz":
|
||||
default = "%X %Z"
|
||||
return default
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.get_time))
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.next_tz)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.prev_tz)
|
||||
self.__fmt = self.parameter('format', self.default_format())
|
||||
self.__fmt = self.parameter("format", self.default_format())
|
||||
|
||||
default_timezone = ''
|
||||
default_timezone = ""
|
||||
try:
|
||||
default_timezone = tzlocal.get_localzone().zone
|
||||
except Exception as e:
|
||||
logging.error('unable to get default timezone: {}'.format(str(e)))
|
||||
logging.error("unable to get default timezone: {}".format(str(e)))
|
||||
try:
|
||||
self._timezones = util.format.aslist(self.parameter('timezone', default_timezone))
|
||||
self._timezones = util.format.aslist(
|
||||
self.parameter("timezone", default_timezone)
|
||||
)
|
||||
except:
|
||||
self._timezones = [default_timezone]
|
||||
self._current_tz = 0
|
||||
|
||||
l = locale.getdefaultlocale()
|
||||
if not l or l == (None, None):
|
||||
l = ('en_US', 'UTF-8')
|
||||
lcl = self.parameter('locale', '.'.join(l))
|
||||
l = ("en_US", "UTF-8")
|
||||
lcl = self.parameter("locale", ".".join(l))
|
||||
try:
|
||||
locale.setlocale(locale.LC_TIME, lcl.split('.'))
|
||||
locale.setlocale(locale.LC_TIME, lcl.split("."))
|
||||
except Exception:
|
||||
locale.setlocale(locale.LC_TIME, ('en_US', 'UTF-8'))
|
||||
locale.setlocale(locale.LC_TIME, ("en_US", "UTF-8"))
|
||||
|
||||
def default_format(self):
|
||||
return '%x %X %Z'
|
||||
return "%x %X %Z"
|
||||
|
||||
def get_time(self, widget):
|
||||
try:
|
||||
try:
|
||||
tz = pytz.timezone(self._timezones[self._current_tz].strip())
|
||||
retval = datetime.datetime.now(tz=tzlocal.get_localzone()).astimezone(tz).strftime(self.__fmt)
|
||||
retval = (
|
||||
datetime.datetime.now(tz=tzlocal.get_localzone())
|
||||
.astimezone(tz)
|
||||
.strftime(self.__fmt)
|
||||
)
|
||||
except pytz.exceptions.UnknownTimeZoneError:
|
||||
retval = '[Unknown timezone: {}]'.format(self._timezones[self._current_tz].strip())
|
||||
retval = "[Unknown timezone: {}]".format(
|
||||
self._timezones[self._current_tz].strip()
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error('unable to get time: {}'.format(str(e)))
|
||||
retval = '[n/a]'
|
||||
logging.error("unable to get time: {}".format(str(e)))
|
||||
retval = "[n/a]"
|
||||
|
||||
enc = locale.getpreferredencoding()
|
||||
if hasattr(retval, 'decode'):
|
||||
if hasattr(retval, "decode"):
|
||||
return retval.decode(enc)
|
||||
return retval
|
||||
|
||||
def next_tz(self, event):
|
||||
next_timezone = self._current_tz + 1
|
||||
if next_timezone >= len(self._timezones):
|
||||
next_timezone = 0 # wraparound
|
||||
next_timezone = 0 # wraparound
|
||||
self._current_tz = next_timezone
|
||||
|
||||
def prev_tz(self, event):
|
||||
previous_timezone = self._current_tz - 1
|
||||
if previous_timezone < 0:
|
||||
previous_timezone = 0 # wraparound
|
||||
previous_timezone = 0 # wraparound
|
||||
self._current_tz = previous_timezone
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -10,12 +10,14 @@ Parameters:
|
|||
import core.decorators
|
||||
from .datetimetz import Module
|
||||
|
||||
|
||||
class Module(Module):
|
||||
@core.decorators.every(hours=1)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme)
|
||||
|
||||
def default_format(self):
|
||||
return '%x %Z'
|
||||
return "%x %Z"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -45,66 +45,71 @@ import core.decorators
|
|||
import util.cli
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.deadbeef))
|
||||
|
||||
buttons = {'LEFT_CLICK': core.input.LEFT_MOUSE,
|
||||
'RIGHT_CLICK': core.input.RIGHT_MOUSE,
|
||||
'MIDDLE_CLICK': core.input.MIDDLE_MOUSE,
|
||||
'SCROLL_UP': core.input.WHEEL_UP,
|
||||
'SCROLL_DOWN': core.input.WHEEL_DOWN,
|
||||
}
|
||||
|
||||
self._song = ''
|
||||
self._format = self.parameter('format', '{artist} - {title}')
|
||||
self._tf_format = self.parameter('tf_format', '')
|
||||
self._show_tf_when_stopped = util.format.asbool(self.parameter('tf_format_if_stopped', False))
|
||||
prev_button = self.parameter('previous', 'LEFT_CLICK')
|
||||
next_button = self.parameter('next', 'RIGHT_CLICK')
|
||||
pause_button = self.parameter('pause', 'MIDDLE_CLICK')
|
||||
buttons = {
|
||||
"LEFT_CLICK": core.input.LEFT_MOUSE,
|
||||
"RIGHT_CLICK": core.input.RIGHT_MOUSE,
|
||||
"MIDDLE_CLICK": core.input.MIDDLE_MOUSE,
|
||||
"SCROLL_UP": core.input.WHEEL_UP,
|
||||
"SCROLL_DOWN": core.input.WHEEL_DOWN,
|
||||
}
|
||||
|
||||
self.now_playing = 'deadbeef --nowplaying %a;%t;%b;%l;%n;%y;%c;%r;%e'
|
||||
self.now_playing_tf = 'deadbeef --nowplaying-tf '
|
||||
cmd = 'deadbeef '
|
||||
self._song = ""
|
||||
self._format = self.parameter("format", "{artist} - {title}")
|
||||
self._tf_format = self.parameter("tf_format", "")
|
||||
self._show_tf_when_stopped = util.format.asbool(
|
||||
self.parameter("tf_format_if_stopped", False)
|
||||
)
|
||||
prev_button = self.parameter("previous", "LEFT_CLICK")
|
||||
next_button = self.parameter("next", "RIGHT_CLICK")
|
||||
pause_button = self.parameter("pause", "MIDDLE_CLICK")
|
||||
|
||||
core.input.register(self, button=buttons[prev_button],
|
||||
cmd=cmd + '--prev')
|
||||
core.input.register(self, button=buttons[next_button],
|
||||
cmd=cmd + '--next')
|
||||
core.input.register(self, button=buttons[pause_button],
|
||||
cmd=cmd + '--play-pause')
|
||||
self.now_playing = "deadbeef --nowplaying %a;%t;%b;%l;%n;%y;%c;%r;%e"
|
||||
self.now_playing_tf = "deadbeef --nowplaying-tf "
|
||||
cmd = "deadbeef "
|
||||
|
||||
core.input.register(self, button=buttons[prev_button], cmd=cmd + "--prev")
|
||||
core.input.register(self, button=buttons[next_button], cmd=cmd + "--next")
|
||||
core.input.register(
|
||||
self, button=buttons[pause_button], cmd=cmd + "--play-pause"
|
||||
)
|
||||
|
||||
# modify the tf_format if we don't want it to show on stop
|
||||
# this adds conditions to the query itself, rather than
|
||||
# polling to see if deadbeef is running
|
||||
# doing this reduces the number of calls we have to make
|
||||
if self._tf_format and not self._show_tf_when_stopped:
|
||||
self._tf_format = '$if($or(%isplaying%,%ispaused%),{query})'.format(query=self._tf_format)
|
||||
self._tf_format = "$if($or(%isplaying%,%ispaused%),{query})".format(
|
||||
query=self._tf_format
|
||||
)
|
||||
|
||||
@core.decorators.scrollable
|
||||
def deadbeef(self, widget):
|
||||
return self.string_song
|
||||
|
||||
def hidden(self):
|
||||
return self.string_song == ''
|
||||
return self.string_song == ""
|
||||
|
||||
def update(self):
|
||||
widgets = self.widgets()
|
||||
try:
|
||||
if self._tf_format == '': # no tf format set, use the old style
|
||||
if self._tf_format == "": # no tf format set, use the old style
|
||||
return self.update_standard(widgets)
|
||||
return self.update_tf(widgets)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
self._song = 'error'
|
||||
self._song = "error"
|
||||
|
||||
def update_tf(self, widgets):
|
||||
## ensure that deadbeef is actually running
|
||||
## easiest way to do this is to check --nowplaying for
|
||||
## the string 'nothing'
|
||||
if util.cli.execute(self.now_playing) == 'nothing':
|
||||
self._song = ''
|
||||
if util.cli.execute(self.now_playing) == "nothing":
|
||||
self._song = ""
|
||||
return
|
||||
## perform the actual query -- these can be much more sophisticated
|
||||
data = util.cli.execute(self.now_playing_tf + self._tf_format)
|
||||
|
@ -112,19 +117,21 @@ class Module(core.module.Module):
|
|||
|
||||
def update_standard(self, widgets):
|
||||
data = util.cli.execute(self.now_playing)
|
||||
if data == 'nothing':
|
||||
self._song = ''
|
||||
if data == "nothing":
|
||||
self._song = ""
|
||||
else:
|
||||
data = data.split(';')
|
||||
self._song = self._format.format(artist=data[0],
|
||||
title=data[1],
|
||||
album=data[2],
|
||||
length=data[3],
|
||||
trackno=data[4],
|
||||
year=data[5],
|
||||
comment=data[6],
|
||||
copyright=data[7],
|
||||
time=data[8])
|
||||
data = data.split(";")
|
||||
self._song = self._format.format(
|
||||
artist=data[0],
|
||||
title=data[1],
|
||||
album=data[2],
|
||||
length=data[3],
|
||||
trackno=data[4],
|
||||
year=data[5],
|
||||
comment=data[6],
|
||||
copyright=data[7],
|
||||
time=data[8],
|
||||
)
|
||||
|
||||
@property
|
||||
def string_song(self):
|
||||
|
@ -136,4 +143,5 @@ Returns the current song as a string, either as a unicode() (Python <
|
|||
return unicode(self._song)
|
||||
return str(self._song)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -19,51 +19,61 @@ import core.module
|
|||
import core.widget
|
||||
import core.input
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.deezer))
|
||||
|
||||
buttons = {'LEFT_CLICK':core.input.LEFT_MOUSE,
|
||||
'RIGHT_CLICK':core.input.RIGHT_MOUSE,
|
||||
'MIDDLE_CLICK':core.input.MIDDLE_MOUSE,
|
||||
'SCROLL_UP':core.input.WHEEL_UP,
|
||||
'SCROLL_DOWN':core.input.WHEEL_DOWN,
|
||||
}
|
||||
|
||||
self._song = ''
|
||||
self._format = self.parameter('format', '{artist} - {title}')
|
||||
prev_button = self.parameter('previous', 'LEFT_CLICK')
|
||||
next_button = self.parameter('next', 'RIGHT_CLICK')
|
||||
pause_button = self.parameter('pause', 'MIDDLE_CLICK')
|
||||
buttons = {
|
||||
"LEFT_CLICK": core.input.LEFT_MOUSE,
|
||||
"RIGHT_CLICK": core.input.RIGHT_MOUSE,
|
||||
"MIDDLE_CLICK": core.input.MIDDLE_MOUSE,
|
||||
"SCROLL_UP": core.input.WHEEL_UP,
|
||||
"SCROLL_DOWN": core.input.WHEEL_DOWN,
|
||||
}
|
||||
|
||||
cmd = 'dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.deezer \
|
||||
/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.'
|
||||
core.input.register(self, button=buttons[prev_button],
|
||||
cmd=cmd + 'Previous')
|
||||
core.input.register(self, button=buttons[next_button],
|
||||
cmd=cmd + 'Next')
|
||||
core.input.register(self, button=buttons[pause_button],
|
||||
cmd=cmd + 'PlayPause')
|
||||
self._song = ""
|
||||
self._format = self.parameter("format", "{artist} - {title}")
|
||||
prev_button = self.parameter("previous", "LEFT_CLICK")
|
||||
next_button = self.parameter("next", "RIGHT_CLICK")
|
||||
pause_button = self.parameter("pause", "MIDDLE_CLICK")
|
||||
|
||||
cmd = "dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.deezer \
|
||||
/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player."
|
||||
core.input.register(self, button=buttons[prev_button], cmd=cmd + "Previous")
|
||||
core.input.register(self, button=buttons[next_button], cmd=cmd + "Next")
|
||||
core.input.register(self, button=buttons[pause_button], cmd=cmd + "PlayPause")
|
||||
|
||||
def deezer(self, widget):
|
||||
return str(self._song)
|
||||
|
||||
def hidden(self):
|
||||
return str(self._song) == ''
|
||||
return str(self._song) == ""
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
bus = dbus.SessionBus()
|
||||
deezer = bus.get_object('org.mpris.MediaPlayer2.deezer', '/org/mpris/MediaPlayer2')
|
||||
deezer_iface = dbus.Interface(deezer, 'org.freedesktop.DBus.Properties')
|
||||
props = deezer_iface.Get('org.mpris.MediaPlayer2.Player', 'Metadata')
|
||||
playback_status = str(deezer_iface.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus'))
|
||||
self._song = self._format.format(album=str(props.get('xesam:album')),
|
||||
title=str(props.get('xesam:title')),
|
||||
artist=','.join(props.get('xesam:artist')),
|
||||
trackNumber=str(props.get('xesam:trackNumber')),
|
||||
playbackStatus=u'\u25B6' if playback_status=='Playing' else u'\u258D\u258D' if playback_status=='Paused' else '',)
|
||||
deezer = bus.get_object(
|
||||
"org.mpris.MediaPlayer2.deezer", "/org/mpris/MediaPlayer2"
|
||||
)
|
||||
deezer_iface = dbus.Interface(deezer, "org.freedesktop.DBus.Properties")
|
||||
props = deezer_iface.Get("org.mpris.MediaPlayer2.Player", "Metadata")
|
||||
playback_status = str(
|
||||
deezer_iface.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus")
|
||||
)
|
||||
self._song = self._format.format(
|
||||
album=str(props.get("xesam:album")),
|
||||
title=str(props.get("xesam:title")),
|
||||
artist=",".join(props.get("xesam:artist")),
|
||||
trackNumber=str(props.get("xesam:trackNumber")),
|
||||
playbackStatus="\u25B6"
|
||||
if playback_status == "Playing"
|
||||
else "\u258D\u258D"
|
||||
if playback_status == "Paused"
|
||||
else "",
|
||||
)
|
||||
except Exception:
|
||||
self._song = ''
|
||||
self._song = ""
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -19,34 +19,41 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
def get_dnf_info(widget):
|
||||
res = util.cli.execute('dnf updateinfo', ignore_errors=True)
|
||||
res = util.cli.execute("dnf updateinfo", ignore_errors=True)
|
||||
|
||||
security = 0
|
||||
bugfixes = 0
|
||||
enhancements = 0
|
||||
other = 0
|
||||
for line in res.split('\n'):
|
||||
if not line.startswith(' '): continue
|
||||
elif 'ecurity' in line:
|
||||
for line in res.split("\n"):
|
||||
if not line.startswith(" "):
|
||||
continue
|
||||
elif "ecurity" in line:
|
||||
for s in line.split():
|
||||
if s.isdigit(): security += int(s)
|
||||
elif 'ugfix' in line:
|
||||
if s.isdigit():
|
||||
security += int(s)
|
||||
elif "ugfix" in line:
|
||||
for s in line.split():
|
||||
if s.isdigit(): bugfixes += int(s)
|
||||
elif 'hancement' in line:
|
||||
if s.isdigit():
|
||||
bugfixes += int(s)
|
||||
elif "hancement" in line:
|
||||
for s in line.split():
|
||||
if s.isdigit(): enhancements += int(s)
|
||||
if s.isdigit():
|
||||
enhancements += int(s)
|
||||
else:
|
||||
for s in line.split():
|
||||
if s.isdigit(): other += int(s)
|
||||
if s.isdigit():
|
||||
other += int(s)
|
||||
|
||||
widget.set('security', security)
|
||||
widget.set('bugfixes', bugfixes)
|
||||
widget.set('enhancements', enhancements)
|
||||
widget.set('other', other)
|
||||
widget.set("security", security)
|
||||
widget.set("bugfixes", bugfixes)
|
||||
widget.set("enhancements", enhancements)
|
||||
widget.set("other", other)
|
||||
|
||||
core.event.trigger("update", [widget.module.id], redraw_only=True)
|
||||
|
||||
core.event.trigger('update', [ widget.module.id ], redraw_only=True)
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=30)
|
||||
|
@ -55,9 +62,9 @@ class Module(core.module.Module):
|
|||
|
||||
def updates(self, widget):
|
||||
result = []
|
||||
for t in ['security', 'bugfixes', 'enhancements', 'other']:
|
||||
for t in ["security", "bugfixes", "enhancements", "other"]:
|
||||
result.append(str(widget.get(t, 0)))
|
||||
return '/'.join(result)
|
||||
return "/".join(result)
|
||||
|
||||
def update(self):
|
||||
thread = threading.Thread(target=get_dnf_info, args=(self.widget(),))
|
||||
|
@ -65,11 +72,12 @@ class Module(core.module.Module):
|
|||
|
||||
def state(self, widget):
|
||||
cnt = 0
|
||||
for t in ['security', 'bugfixes', 'enhancements', 'other']:
|
||||
for t in ["security", "bugfixes", "enhancements", "other"]:
|
||||
cnt += widget.get(t, 0)
|
||||
if cnt == 0:
|
||||
return 'good'
|
||||
if cnt > 50 or widget.get('security', 0) > 0:
|
||||
return 'critical'
|
||||
return "good"
|
||||
if cnt > 50 or widget.get("security", 0) > 0:
|
||||
return "critical"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -15,29 +15,33 @@ import core.module
|
|||
import core.widget
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(seconds=5)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.docker_info))
|
||||
self.__info = ''
|
||||
self.__info = ""
|
||||
|
||||
def state(self, widget):
|
||||
state = []
|
||||
if self.__info == 'OK - 0':
|
||||
state.append('warning')
|
||||
elif self.__info in ['n/a', 'daemon off']:
|
||||
state.append('critical')
|
||||
if self.__info == "OK - 0":
|
||||
state.append("warning")
|
||||
elif self.__info in ["n/a", "daemon off"]:
|
||||
state.append("critical")
|
||||
return state
|
||||
|
||||
def docker_info(self, widget):
|
||||
try:
|
||||
cli = docker.DockerClient(base_url='unix://var/run/docker.sock')
|
||||
cli = docker.DockerClient(base_url="unix://var/run/docker.sock")
|
||||
cli.ping()
|
||||
self.__info = 'OK - {}'.format(len(cli.containers.list(filters={'status': 'running'})))
|
||||
self.__info = "OK - {}".format(
|
||||
len(cli.containers.list(filters={"status": "running"}))
|
||||
)
|
||||
except ConnectionError:
|
||||
self.__info = 'daemon off'
|
||||
self.__info = "daemon off"
|
||||
except Exception:
|
||||
self.__info = 'n/a'
|
||||
self.__info = "n/a"
|
||||
return self.__info
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pylint: disable=C0111,R0903
|
||||
# pylint: disable=C0111,R0903
|
||||
|
||||
'''Toggle dunst notifications.'''
|
||||
"""Toggle dunst notifications."""
|
||||
|
||||
import core.module
|
||||
import core.widget
|
||||
|
@ -8,28 +8,27 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(''))
|
||||
super().__init__(config, theme, core.widget.Widget(""))
|
||||
self._paused = False
|
||||
# Make sure that dunst is currently not paused
|
||||
util.cli.execute('killall -s SIGUSR2 dunst', ignore_errors=True)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.toggle_status
|
||||
)
|
||||
util.cli.execute("killall -s SIGUSR2 dunst", ignore_errors=True)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.toggle_status)
|
||||
|
||||
def toggle_status(self, event):
|
||||
self._paused = not self._paused
|
||||
|
||||
|
||||
try:
|
||||
if self._paused:
|
||||
util.cli.execute('killall -s SIGUSR1 dunst')
|
||||
util.cli.execute("killall -s SIGUSR1 dunst")
|
||||
else:
|
||||
util.cli.execute('killall -s SIGUSR2 dunst')
|
||||
util.cli.execute("killall -s SIGUSR2 dunst")
|
||||
except:
|
||||
self._paused = not self._paused # toggling failed
|
||||
self._paused = not self._paused # toggling failed
|
||||
|
||||
def state(self, widget):
|
||||
if self._paused:
|
||||
return ['muted', 'warning']
|
||||
return ['unmuted']
|
||||
return ["muted", "warning"]
|
||||
return ["unmuted"]
|
||||
|
|
|
@ -24,51 +24,64 @@ import core.decorators
|
|||
|
||||
import util.format
|
||||
|
||||
|
||||
def getfromkrak(coin, currency):
|
||||
abbrev = {
|
||||
'Btc': ['xbt', 'XXBTZ'],
|
||||
'Eth': ['eth', 'XETHZ'],
|
||||
'Ltc': ['ltc', 'XLTCZ'],
|
||||
"Btc": ["xbt", "XXBTZ"],
|
||||
"Eth": ["eth", "XETHZ"],
|
||||
"Ltc": ["ltc", "XLTCZ"],
|
||||
}
|
||||
data = abbrev.get(coin, None)
|
||||
if not data: return
|
||||
epair = '{}{}'.format(data[0], currency)
|
||||
tickname = '{}{}'.format(data[1], currency.upper())
|
||||
if not data:
|
||||
return
|
||||
epair = "{}{}".format(data[0], currency)
|
||||
tickname = "{}{}".format(data[1], currency.upper())
|
||||
try:
|
||||
krakenget = requests.get('https://api.kraken.com/0/public/Ticker?pair='+epair).json()
|
||||
krakenget = requests.get(
|
||||
"https://api.kraken.com/0/public/Ticker?pair=" + epair
|
||||
).json()
|
||||
except (RequestException, Exception):
|
||||
return 'No connection'
|
||||
if not 'result' in krakenget:
|
||||
return 'No data'
|
||||
kethusdask = float(krakenget['result'][tickname]['a'][0])
|
||||
kethusdbid = float(krakenget['result'][tickname]['b'][0])
|
||||
return coin+': '+str((kethusdask+kethusdbid)/2)[0:6]
|
||||
return "No connection"
|
||||
if not "result" in krakenget:
|
||||
return "No data"
|
||||
kethusdask = float(krakenget["result"][tickname]["a"][0])
|
||||
kethusdbid = float(krakenget["result"][tickname]["b"][0])
|
||||
return coin + ": " + str((kethusdask + kethusdbid) / 2)[0:6]
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=30)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.curprice))
|
||||
|
||||
self.__curprice = ''
|
||||
self.__getbtc = util.format.asbool(self.parameter('getbtc', True))
|
||||
self.__geteth = util.format.asbool(self.parameter('geteth', True))
|
||||
self.__getltc = util.format.asbool(self.parameter('getltc', True))
|
||||
self.__getcur = self.parameter('getcur', 'usd')
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd='xdg-open https://cryptowat.ch/')
|
||||
self.__curprice = ""
|
||||
self.__getbtc = util.format.asbool(self.parameter("getbtc", True))
|
||||
self.__geteth = util.format.asbool(self.parameter("geteth", True))
|
||||
self.__getltc = util.format.asbool(self.parameter("getltc", True))
|
||||
self.__getcur = self.parameter("getcur", "usd")
|
||||
core.input.register(
|
||||
self, button=core.input.LEFT_MOUSE, cmd="xdg-open https://cryptowat.ch/"
|
||||
)
|
||||
|
||||
def curprice(self, widget):
|
||||
return self.__curprice
|
||||
|
||||
def update(self):
|
||||
currency = self.__getcur
|
||||
btcprice, ethprice, ltcprice = '', '', ''
|
||||
btcprice, ethprice, ltcprice = "", "", ""
|
||||
if self.__getbtc:
|
||||
btcprice = getfromkrak('Btc', currency)
|
||||
btcprice = getfromkrak("Btc", currency)
|
||||
if self.__geteth:
|
||||
ethprice = getfromkrak('Eth', currency)
|
||||
ethprice = getfromkrak("Eth", currency)
|
||||
if self.__getltc:
|
||||
ltcprice = getfromkrak('Ltc', currency)
|
||||
self.__curprice = btcprice+' '*(self.__getbtc*self.__geteth)+ethprice+' '*(self.__getltc*max(self.__getbtc, self.__geteth))+ltcprice
|
||||
ltcprice = getfromkrak("Ltc", currency)
|
||||
self.__curprice = (
|
||||
btcprice
|
||||
+ " " * (self.__getbtc * self.__geteth)
|
||||
+ ethprice
|
||||
+ " " * (self.__getltc * max(self.__getbtc, self.__geteth))
|
||||
+ ltcprice
|
||||
)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -18,6 +18,7 @@ import core.widget
|
|||
import core.decorators
|
||||
import core.input
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=5)
|
||||
def __init__(self, config, theme):
|
||||
|
@ -25,15 +26,19 @@ class Module(core.module.Module):
|
|||
|
||||
self.__count = 0
|
||||
self.__requests = requests.Session()
|
||||
self.__requests.headers.update({'Authorization':'token {}'.format(self.parameter('token', ''))})
|
||||
self.__requests.headers.update(
|
||||
{"Authorization": "token {}".format(self.parameter("token", ""))}
|
||||
)
|
||||
|
||||
cmd = 'xdg-open'
|
||||
cmd = "xdg-open"
|
||||
if not shutil.which(cmd):
|
||||
cmd = 'x-www-browser'
|
||||
cmd = "x-www-browser"
|
||||
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd='{} https://github.com/notifications'.format(cmd))
|
||||
core.input.register(
|
||||
self,
|
||||
button=core.input.LEFT_MOUSE,
|
||||
cmd="{} https://github.com/notifications".format(cmd),
|
||||
)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.update)
|
||||
|
||||
def github(self, _):
|
||||
|
@ -42,17 +47,25 @@ class Module(core.module.Module):
|
|||
def update(self):
|
||||
try:
|
||||
self.__count = 0
|
||||
url = 'https://api.github.com/notifications'
|
||||
url = "https://api.github.com/notifications"
|
||||
while True:
|
||||
notifications = self.__requests.get(url)
|
||||
self.__count += len(list(filter(lambda notification: notification['unread'], notifications.json())))
|
||||
next_link = notifications.links.get('next')
|
||||
self.__count += len(
|
||||
list(
|
||||
filter(
|
||||
lambda notification: notification["unread"],
|
||||
notifications.json(),
|
||||
)
|
||||
)
|
||||
)
|
||||
next_link = notifications.links.get("next")
|
||||
if next_link is not None:
|
||||
url = next_link.get('url')
|
||||
url = next_link.get("url")
|
||||
else:
|
||||
break
|
||||
|
||||
except Exception:
|
||||
self.__count = 'n/a'
|
||||
self.__count = "n/a"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -12,42 +12,47 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
widgets = [
|
||||
core.widget.Widget(name='gpmdp.prev'),
|
||||
core.widget.Widget(name='gpmdp.main', full_text=self.description),
|
||||
core.widget.Widget(name='gpmdp.next'),
|
||||
core.widget.Widget(name="gpmdp.prev"),
|
||||
core.widget.Widget(name="gpmdp.main", full_text=self.description),
|
||||
core.widget.Widget(name="gpmdp.next"),
|
||||
]
|
||||
super().__init__(config, theme, widgets)
|
||||
|
||||
core.input.register(widgets[0], button=core.input.LEFT_MOUSE,
|
||||
cmd='playerctl previous')
|
||||
core.input.register(widgets[1], button=core.input.LEFT_MOUSE,
|
||||
cmd='playerctl play-pause')
|
||||
core.input.register(widgets[2], button=core.input.LEFT_MOUSE,
|
||||
cmd='playerctl next')
|
||||
core.input.register(
|
||||
widgets[0], button=core.input.LEFT_MOUSE, cmd="playerctl previous"
|
||||
)
|
||||
core.input.register(
|
||||
widgets[1], button=core.input.LEFT_MOUSE, cmd="playerctl play-pause"
|
||||
)
|
||||
core.input.register(
|
||||
widgets[2], button=core.input.LEFT_MOUSE, cmd="playerctl next"
|
||||
)
|
||||
|
||||
self.__status = None
|
||||
self.__tags = None
|
||||
|
||||
def description(self, widget):
|
||||
return self.__tags if self.__tags else 'n/a'
|
||||
return self.__tags if self.__tags else "n/a"
|
||||
|
||||
def update(self):
|
||||
self.__load_song()
|
||||
|
||||
def state(self, widget):
|
||||
if widget.name == 'gpmdp.prev':
|
||||
return 'prev'
|
||||
if widget.name == 'gpmdp.next':
|
||||
return 'next'
|
||||
if widget.name == "gpmdp.prev":
|
||||
return "prev"
|
||||
if widget.name == "gpmdp.next":
|
||||
return "next"
|
||||
return self.__status
|
||||
|
||||
def __load_song(self):
|
||||
info = util.cli.execute('gpmdp-remote current', ignore_errors=True)
|
||||
status = util.cli.execute('gpmdp-remote status', ignore_errors=True)
|
||||
self.__status = status.split('\n')[0].lower()
|
||||
self.__tags = info.split('\n')[0]
|
||||
info = util.cli.execute("gpmdp-remote current", ignore_errors=True)
|
||||
status = util.cli.execute("gpmdp-remote status", ignore_errors=True)
|
||||
self.__status = status.split("\n")[0].lower()
|
||||
self.__tags = info.split("\n")[0]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -9,12 +9,13 @@ import socket
|
|||
import core.module
|
||||
import core.widget
|
||||
|
||||
HOST = 'localhost'
|
||||
HOST = "localhost"
|
||||
PORT = 7634
|
||||
|
||||
CHUNK_SIZE = 1024
|
||||
RECORD_SIZE = 5
|
||||
SEPARATOR = '|'
|
||||
SEPARATOR = "|"
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
|
@ -29,7 +30,7 @@ class Module(core.module.Module):
|
|||
try:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.connect((HOST, PORT))
|
||||
data = ''
|
||||
data = ""
|
||||
while True:
|
||||
chunk = sock.recv(CHUNK_SIZE)
|
||||
if chunk:
|
||||
|
@ -46,7 +47,7 @@ class Module(core.module.Module):
|
|||
split data using | separator and remove first item
|
||||
(because the first item is empty)
|
||||
"""
|
||||
parts = data.split('|')[1:]
|
||||
parts = data.split("|")[1:]
|
||||
return parts
|
||||
|
||||
@staticmethod
|
||||
|
@ -54,8 +55,9 @@ class Module(core.module.Module):
|
|||
"""
|
||||
partition parts: one device record is five (5) items
|
||||
"""
|
||||
per_disk = [parts[i:i+RECORD_SIZE]
|
||||
for i in range(len(parts))[::RECORD_SIZE]]
|
||||
per_disk = [
|
||||
parts[i : i + RECORD_SIZE] for i in range(len(parts))[::RECORD_SIZE]
|
||||
]
|
||||
return per_disk
|
||||
|
||||
@staticmethod
|
||||
|
@ -64,20 +66,20 @@ class Module(core.module.Module):
|
|||
get device name (without /dev part, to save space on bar)
|
||||
and temperature (in °C) as tuple
|
||||
"""
|
||||
device_name = device_record[0].split('/')[-1]
|
||||
device_name = device_record[0].split("/")[-1]
|
||||
device_temp = device_record[2]
|
||||
return (device_name, device_temp)
|
||||
|
||||
@staticmethod
|
||||
def __get_hddtemp(device_record):
|
||||
name, temp = device_record
|
||||
hddtemp = '{}+{}°C'.format(name, temp)
|
||||
hddtemp = "{}+{}°C".format(name, temp)
|
||||
return hddtemp
|
||||
|
||||
def __get_hddtemps(self):
|
||||
data = self.__fetch_data()
|
||||
if data is None:
|
||||
return 'n/a'
|
||||
return "n/a"
|
||||
parts = self.__get_parts(data)
|
||||
per_disk = self.__partition_parts(parts)
|
||||
names_and_temps = [self.__get_name_and_temp(x) for x in per_disk]
|
||||
|
@ -87,4 +89,5 @@ class Module(core.module.Module):
|
|||
def update(self):
|
||||
self.__hddtemps = self.__get_hddtemps()
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -8,16 +8,18 @@ import core.module
|
|||
import core.widget
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
self.__hname = ''
|
||||
self.__hname = ""
|
||||
|
||||
def output(self, _):
|
||||
return self.__hname + ' ' + u'\uf233'
|
||||
return self.__hname + " " + "\uf233"
|
||||
|
||||
def update(self):
|
||||
self.__hname = platform.node()
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -16,21 +16,22 @@ import core.module
|
|||
import core.widget
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
UNK = 'UNK'
|
||||
UNK = "UNK"
|
||||
|
||||
@core.decorators.every(seconds=30)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
|
||||
self.__label = self.parameter('label')
|
||||
self.__target = self.parameter('target')
|
||||
self.__expect = self.parameter('expect', '200')
|
||||
self.__label = self.parameter("label")
|
||||
self.__target = self.parameter("target")
|
||||
self.__expect = self.parameter("expect", "200")
|
||||
|
||||
def labelize(self, s):
|
||||
if self.__label is None:
|
||||
return s
|
||||
return '{}: {}'.format(self.__label, s)
|
||||
return "{}: {}".format(self.__label, s)
|
||||
|
||||
def getStatus(self):
|
||||
try:
|
||||
|
@ -46,8 +47,8 @@ class Module(core.module.Module):
|
|||
if self.__status == self.__expect:
|
||||
return self.labelize(self.__status)
|
||||
else:
|
||||
reason = ' != {}'.format(self.__expect)
|
||||
return self.labelize('{}{}'.format(self.__status, reason))
|
||||
reason = " != {}".format(self.__expect)
|
||||
return self.labelize("{}{}".format(self.__status, reason))
|
||||
|
||||
def output(self, widget):
|
||||
return self.__output
|
||||
|
@ -58,9 +59,10 @@ class Module(core.module.Module):
|
|||
|
||||
def state(self, widget):
|
||||
if self.__status == self.UNK:
|
||||
return 'warning'
|
||||
return "warning"
|
||||
if self.__status != self.__expect:
|
||||
return 'critical'
|
||||
return "critical"
|
||||
return self.__output
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pylint: disable=C0111,R0903
|
||||
# pylint: disable=C0111,R0903
|
||||
|
||||
"""Displays the indicator status, for numlock, scrolllock and capslock
|
||||
|
||||
|
@ -13,18 +13,29 @@ import core.widget
|
|||
import util.cli
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
self.__include = tuple(filter(len, util.format.aslist(self.parameter('include', 'NumLock,CapsLock'))))
|
||||
self.__signalType = self.parameter('signaltype') if not self.parameter('signaltype') is None else 'warning'
|
||||
self.__include = tuple(
|
||||
filter(
|
||||
len, util.format.aslist(self.parameter("include", "NumLock,CapsLock"))
|
||||
)
|
||||
)
|
||||
self.__signalType = (
|
||||
self.parameter("signaltype")
|
||||
if not self.parameter("signaltype") is None
|
||||
else "warning"
|
||||
)
|
||||
|
||||
def update(self):
|
||||
status_line = ''
|
||||
for line in util.cli.execute('xset q', ignore_errors=True).replace(' ', '').split('\n'):
|
||||
if 'capslock' in line.lower():
|
||||
status_line = line
|
||||
status_line = ""
|
||||
for line in (
|
||||
util.cli.execute("xset q", ignore_errors=True).replace(" ", "").split("\n")
|
||||
):
|
||||
if "capslock" in line.lower():
|
||||
status_line = line
|
||||
break
|
||||
for indicator in self.__include:
|
||||
widget = self.widget(indicator)
|
||||
|
@ -32,15 +43,21 @@ class Module(core.module.Module):
|
|||
widget = core.widget.Widget(name=indicator, module=self)
|
||||
self.widgets().append(widget)
|
||||
|
||||
widget.set('status', True if '{}:on'.format(indicator.lower()) in status_line.lower() else False)
|
||||
widget.set(
|
||||
"status",
|
||||
True
|
||||
if "{}:on".format(indicator.lower()) in status_line.lower()
|
||||
else False,
|
||||
)
|
||||
widget.full_text(indicator)
|
||||
|
||||
def state(self, widget):
|
||||
states = []
|
||||
if widget.get('status', False):
|
||||
if widget.get("status", False):
|
||||
states.append(self.__signalType)
|
||||
else:
|
||||
states.append('normal')
|
||||
states.append("normal")
|
||||
return states
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -11,31 +11,30 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(seconds=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.current_layout))
|
||||
|
||||
core.input.register(
|
||||
self,
|
||||
button=core.input.LEFT_MOUSE,
|
||||
cmd=self.__next_keymap)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_keymap)
|
||||
self.__current_layout = self.__get_current_layout()
|
||||
|
||||
def current_layout(self, _):
|
||||
return self.__current_layout
|
||||
|
||||
def __next_keymap(self, event):
|
||||
util.cli.execute('xkb-switch -n', ignore_errors=True)
|
||||
util.cli.execute("xkb-switch -n", ignore_errors=True)
|
||||
|
||||
def __get_current_layout(self):
|
||||
try:
|
||||
res = util.cli.execute('xkb-switch')
|
||||
return res.split('\n')[0]
|
||||
res = util.cli.execute("xkb-switch")
|
||||
return res.split("\n")[0]
|
||||
except RuntimeError:
|
||||
return ['n/a']
|
||||
return ["n/a"]
|
||||
|
||||
def update(self):
|
||||
self.__current_layout = self.__get_current_layout()
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -12,14 +12,13 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.current_layout))
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.__next_keymap)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE,
|
||||
cmd=self.__prev_keymap)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_keymap)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_keymap)
|
||||
|
||||
def __next_keymap(self, event):
|
||||
self._set_keymap(1)
|
||||
|
@ -29,41 +28,49 @@ class Module(core.module.Module):
|
|||
|
||||
def _set_keymap(self, rotation):
|
||||
layouts = self.get_layouts()
|
||||
if len(layouts) == 1: return # nothing to do
|
||||
if len(layouts) == 1:
|
||||
return # nothing to do
|
||||
layouts = layouts[rotation:] + layouts[:rotation]
|
||||
|
||||
layout_list = []
|
||||
variant_list = []
|
||||
for l in layouts:
|
||||
tmp = l.split(':')
|
||||
tmp = l.split(":")
|
||||
layout_list.append(tmp[0])
|
||||
variant_list.append(tmp[1] if len(tmp) > 1 else '')
|
||||
variant_list.append(tmp[1] if len(tmp) > 1 else "")
|
||||
|
||||
util.cli.execute('setxkbmap -layout {} -variant {}'.format(','.join(layout_list), ','.join(variant_list)), ignore_errors=True)
|
||||
util.cli.execute(
|
||||
"setxkbmap -layout {} -variant {}".format(
|
||||
",".join(layout_list), ",".join(variant_list)
|
||||
),
|
||||
ignore_errors=True,
|
||||
)
|
||||
|
||||
def get_layouts(self):
|
||||
try:
|
||||
res = util.cli.execute('setxkbmap -query')
|
||||
res = util.cli.execute("setxkbmap -query")
|
||||
except RuntimeError:
|
||||
return ['n/a']
|
||||
return ["n/a"]
|
||||
layouts = []
|
||||
variants = []
|
||||
for line in res.split('\n'):
|
||||
if not line: continue
|
||||
if 'layout' in line:
|
||||
layouts = line.split(':')[1].strip().split(',')
|
||||
if 'variant' in line:
|
||||
variants = line.split(':')[1].strip().split(',')
|
||||
for line in res.split("\n"):
|
||||
if not line:
|
||||
continue
|
||||
if "layout" in line:
|
||||
layouts = line.split(":")[1].strip().split(",")
|
||||
if "variant" in line:
|
||||
variants = line.split(":")[1].strip().split(",")
|
||||
|
||||
result = []
|
||||
for idx, layout in enumerate(layouts):
|
||||
if len(variants) > idx and variants[idx]:
|
||||
layout = '{}:{}'.format(layout, variants[idx])
|
||||
layout = "{}:{}".format(layout, variants[idx])
|
||||
result.append(layout)
|
||||
return result if len(result) > 0 else ['n/a']
|
||||
return result if len(result) > 0 else ["n/a"]
|
||||
|
||||
def current_layout(self, widget):
|
||||
layouts = self.get_layouts()
|
||||
return layouts[0]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -11,18 +11,19 @@ import core.widget
|
|||
import core.input
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(seconds=10)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.status))
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd='virt-manager')
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd="virt-manager")
|
||||
|
||||
def status(self, _):
|
||||
conn = libvirt.openReadOnly(None)
|
||||
if conn == None:
|
||||
return 'Failed to open connection to the hypervisor'
|
||||
return 'VMs %s' % (conn.numOfDomains())
|
||||
return "Failed to open connection to the hypervisor"
|
||||
return "VMs %s" % (conn.numOfDomains())
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -29,17 +29,18 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.description))
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd='mocp -G')
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd='mocp -t shuffle')
|
||||
self.__format = self.parameter('format', '%state %artist - %song | %ct/%tt')
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd="mocp -G")
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd="mocp -t shuffle")
|
||||
self.__format = self.parameter("format", "%state %artist - %song | %ct/%tt")
|
||||
self.__running = False
|
||||
|
||||
def description(self, widget):
|
||||
return self.__info if self.__running == True else 'Music On Console Player'
|
||||
return self.__info if self.__running == True else "Music On Console Player"
|
||||
|
||||
def update(self):
|
||||
self.__load_song()
|
||||
|
@ -51,4 +52,5 @@ class Module(core.module.Module):
|
|||
except RuntimeError:
|
||||
self.__running = False
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -52,22 +52,25 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
self._layout = self.parameter('layout', 'mpd.prev mpd.main mpd.next mpd.shuffle mpd.repeat')
|
||||
self._layout = self.parameter(
|
||||
"layout", "mpd.prev mpd.main mpd.next mpd.shuffle mpd.repeat"
|
||||
)
|
||||
|
||||
self._fmt = self.parameter('format', '{artist} - {title} {position}/{duration}')
|
||||
self._fmt = self.parameter("format", "{artist} - {title} {position}/{duration}")
|
||||
self._status = None
|
||||
self._shuffle = False
|
||||
self._repeat = False
|
||||
self._tags = defaultdict(lambda: '')
|
||||
self._tags = defaultdict(lambda: "")
|
||||
|
||||
if not self.parameter('host'):
|
||||
self._hostcmd = ''
|
||||
if not self.parameter("host"):
|
||||
self._hostcmd = ""
|
||||
else:
|
||||
self._hostcmd = ' -h ' + self.parameter('host')
|
||||
self._hostcmd = " -h " + self.parameter("host")
|
||||
|
||||
# Create widgets
|
||||
widget_list = []
|
||||
|
@ -76,19 +79,38 @@ class Module(core.module.Module):
|
|||
widget = core.widget.Widget(name=widget_name, module=self)
|
||||
widget_list.append(widget)
|
||||
|
||||
if widget_name == 'mpd.prev':
|
||||
widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc prev' + self._hostcmd}
|
||||
elif widget_name == 'mpd.main':
|
||||
widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc toggle' + self._hostcmd}
|
||||
if widget_name == "mpd.prev":
|
||||
widget_map[widget] = {
|
||||
"button": core.input.LEFT_MOUSE,
|
||||
"cmd": "mpc prev" + self._hostcmd,
|
||||
}
|
||||
elif widget_name == "mpd.main":
|
||||
widget_map[widget] = {
|
||||
"button": core.input.LEFT_MOUSE,
|
||||
"cmd": "mpc toggle" + self._hostcmd,
|
||||
}
|
||||
widget.full_text(self.description)
|
||||
elif widget_name == 'mpd.next':
|
||||
widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc next' + self._hostcmd}
|
||||
elif widget_name == 'mpd.shuffle':
|
||||
widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc random' + self._hostcmd}
|
||||
elif widget_name == 'mpd.repeat':
|
||||
widget_map[widget] = {'button': core.input.LEFT_MOUSE, 'cmd': 'mpc repeat' + self._hostcmd}
|
||||
elif widget_name == "mpd.next":
|
||||
widget_map[widget] = {
|
||||
"button": core.input.LEFT_MOUSE,
|
||||
"cmd": "mpc next" + self._hostcmd,
|
||||
}
|
||||
elif widget_name == "mpd.shuffle":
|
||||
widget_map[widget] = {
|
||||
"button": core.input.LEFT_MOUSE,
|
||||
"cmd": "mpc random" + self._hostcmd,
|
||||
}
|
||||
elif widget_name == "mpd.repeat":
|
||||
widget_map[widget] = {
|
||||
"button": core.input.LEFT_MOUSE,
|
||||
"cmd": "mpc repeat" + self._hostcmd,
|
||||
}
|
||||
else:
|
||||
raise KeyError('The mpd module does not support a {widget_name!r} widget'.format(widget_name=widget_name))
|
||||
raise KeyError(
|
||||
"The mpd module does not support a {widget_name!r} widget".format(
|
||||
widget_name=widget_name
|
||||
)
|
||||
)
|
||||
self.widgets(widget_list)
|
||||
|
||||
# Register input callbacks
|
||||
|
@ -106,74 +128,79 @@ class Module(core.module.Module):
|
|||
self._load_song()
|
||||
|
||||
def state(self, widget):
|
||||
if widget.name == 'mpd.shuffle':
|
||||
return 'shuffle-on' if self._shuffle else 'shuffle-off'
|
||||
if widget.name == 'mpd.repeat':
|
||||
return 'repeat-on' if self._repeat else 'repeat-off'
|
||||
if widget.name == 'mpd.prev':
|
||||
return 'prev'
|
||||
if widget.name == 'mpd.next':
|
||||
return 'next'
|
||||
if widget.name == "mpd.shuffle":
|
||||
return "shuffle-on" if self._shuffle else "shuffle-off"
|
||||
if widget.name == "mpd.repeat":
|
||||
return "repeat-on" if self._repeat else "repeat-off"
|
||||
if widget.name == "mpd.prev":
|
||||
return "prev"
|
||||
if widget.name == "mpd.next":
|
||||
return "next"
|
||||
return self._status
|
||||
|
||||
def _load_song(self):
|
||||
info = ''
|
||||
tags = ['name',
|
||||
'artist',
|
||||
'album',
|
||||
'albumartist',
|
||||
'comment',
|
||||
'composer',
|
||||
'date',
|
||||
'originaldate',
|
||||
'disc',
|
||||
'genre',
|
||||
'performer',
|
||||
'title',
|
||||
'track',
|
||||
'time',
|
||||
'file',
|
||||
'id',
|
||||
'prio',
|
||||
'mtime',
|
||||
'mdate']
|
||||
joinedtags = '\n'.join(['tag {0} %{0}%'.format(tag) for tag in tags])
|
||||
info = util.cli.execute('mpc -f "{}"{}'.format(joinedtags, self._hostcmd), ignore_errors=True)
|
||||
info = ""
|
||||
tags = [
|
||||
"name",
|
||||
"artist",
|
||||
"album",
|
||||
"albumartist",
|
||||
"comment",
|
||||
"composer",
|
||||
"date",
|
||||
"originaldate",
|
||||
"disc",
|
||||
"genre",
|
||||
"performer",
|
||||
"title",
|
||||
"track",
|
||||
"time",
|
||||
"file",
|
||||
"id",
|
||||
"prio",
|
||||
"mtime",
|
||||
"mdate",
|
||||
]
|
||||
joinedtags = "\n".join(["tag {0} %{0}%".format(tag) for tag in tags])
|
||||
info = util.cli.execute(
|
||||
'mpc -f "{}"{}'.format(joinedtags, self._hostcmd), ignore_errors=True
|
||||
)
|
||||
|
||||
self._tags = defaultdict(lambda: '')
|
||||
self._tags = defaultdict(lambda: "")
|
||||
self._status = None
|
||||
for line in info.split('\n'):
|
||||
if line.startswith('[playing]'):
|
||||
self._status = 'playing'
|
||||
elif line.startswith('[paused]'):
|
||||
self._status = 'paused'
|
||||
for line in info.split("\n"):
|
||||
if line.startswith("[playing]"):
|
||||
self._status = "playing"
|
||||
elif line.startswith("[paused]"):
|
||||
self._status = "paused"
|
||||
|
||||
if line.startswith('['):
|
||||
if line.startswith("["):
|
||||
timer = line.split()[2]
|
||||
position = timer.split('/')[0]
|
||||
dur = timer.split('/')[1]
|
||||
duration = dur.split(' ')[0]
|
||||
self._tags.update({'position': position})
|
||||
self._tags.update({'duration': duration})
|
||||
position = timer.split("/")[0]
|
||||
dur = timer.split("/")[1]
|
||||
duration = dur.split(" ")[0]
|
||||
self._tags.update({"position": position})
|
||||
self._tags.update({"duration": duration})
|
||||
|
||||
if line.startswith('volume'):
|
||||
value = line.split(' ', 2)[1:]
|
||||
if line.startswith("volume"):
|
||||
value = line.split(" ", 2)[1:]
|
||||
for option in value:
|
||||
if option.startswith('repeat: on'):
|
||||
if option.startswith("repeat: on"):
|
||||
self._repeat = True
|
||||
elif option.startswith('repeat: off'):
|
||||
elif option.startswith("repeat: off"):
|
||||
self._repeat = False
|
||||
elif option.startswith('random: on'):
|
||||
elif option.startswith("random: on"):
|
||||
self._shuffle = True
|
||||
elif option.startswith('random: off'):
|
||||
elif option.startswith("random: off"):
|
||||
self._shuffle = False
|
||||
if line.startswith('tag'):
|
||||
key, value = line.split(' ', 2)[1:]
|
||||
if line.startswith("tag"):
|
||||
key, value = line.split(" ", 2)[1:]
|
||||
self._tags.update({key: value})
|
||||
if key == 'file':
|
||||
self._tags.update({'file1': os.path.basename(value)})
|
||||
if key == "file":
|
||||
self._tags.update({"file1": os.path.basename(value)})
|
||||
self._tags.update(
|
||||
{'file2':
|
||||
os.path.splitext(os.path.basename(value))[0]})
|
||||
{"file2": os.path.splitext(os.path.basename(value))[0]}
|
||||
)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -13,24 +13,33 @@ import core.widget
|
|||
|
||||
import util.format
|
||||
|
||||
WIDGET_NAME = 'network_traffic'
|
||||
WIDGET_NAME = "network_traffic"
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
widgets = [
|
||||
core.widget.Widget(module=self, name='{0}.rx'.format(WIDGET_NAME), full_text=self.download_rate),
|
||||
core.widget.Widget(module=self, name='{0}.tx'.format(WIDGET_NAME), full_text=self.upload_rate)
|
||||
core.widget.Widget(
|
||||
module=self,
|
||||
name="{0}.rx".format(WIDGET_NAME),
|
||||
full_text=self.download_rate,
|
||||
),
|
||||
core.widget.Widget(
|
||||
module=self,
|
||||
name="{0}.tx".format(WIDGET_NAME),
|
||||
full_text=self.upload_rate,
|
||||
),
|
||||
]
|
||||
super().__init__(config, theme, widgets)
|
||||
|
||||
self.widgets()[0].set('theme.minwidth', '0000000KiB/s')
|
||||
self.widgets()[1].set('theme.minwidth', '0000000KiB/s')
|
||||
self.widgets()[0].set("theme.minwidth", "0000000KiB/s")
|
||||
self.widgets()[1].set("theme.minwidth", "0000000KiB/s")
|
||||
|
||||
try:
|
||||
self._bandwidth = BandwidthInfo()
|
||||
|
||||
self._rate_recv = '?'
|
||||
self._rate_sent = '?'
|
||||
self._rate_recv = "?"
|
||||
self._rate_sent = "?"
|
||||
self._bytes_recv = self._bandwidth.bytes_recv()
|
||||
self._bytes_sent = self._bandwidth.bytes_sent()
|
||||
except Exception:
|
||||
|
@ -40,10 +49,10 @@ class Module(core.module.Module):
|
|||
def state(self, widget):
|
||||
"""Return the widget state"""
|
||||
|
||||
if widget.name == '{}.rx'.format(WIDGET_NAME):
|
||||
return 'rx'
|
||||
elif widget.name == '{}.tx'.format(WIDGET_NAME):
|
||||
return 'tx'
|
||||
if widget.name == "{}.rx".format(WIDGET_NAME):
|
||||
return "rx"
|
||||
elif widget.name == "{}.tx".format(WIDGET_NAME):
|
||||
return "tx"
|
||||
|
||||
return None
|
||||
|
||||
|
@ -52,8 +61,8 @@ class Module(core.module.Module):
|
|||
bytes_recv = self._bandwidth.bytes_recv()
|
||||
bytes_sent = self._bandwidth.bytes_sent()
|
||||
|
||||
self._rate_recv = (bytes_recv - self._bytes_recv)
|
||||
self._rate_sent = (bytes_sent - self._bytes_sent)
|
||||
self._rate_recv = bytes_recv - self._bytes_recv
|
||||
self._rate_sent = bytes_sent - self._bytes_sent
|
||||
|
||||
self._bytes_recv, self._bytes_sent = bytes_recv, bytes_sent
|
||||
except Exception:
|
||||
|
@ -61,10 +70,11 @@ class Module(core.module.Module):
|
|||
pass
|
||||
|
||||
def download_rate(self, _):
|
||||
return '{}/s'.format(util.format.byte(self._rate_recv))
|
||||
return "{}/s".format(util.format.byte(self._rate_recv))
|
||||
|
||||
def upload_rate(self, _):
|
||||
return '{}/s'.format(util.format.byte(self._rate_sent))
|
||||
return "{}/s".format(util.format.byte(self._rate_sent))
|
||||
|
||||
|
||||
class BandwidthInfo(object):
|
||||
"""Get received/sent bytes from network adapter"""
|
||||
|
@ -85,10 +95,10 @@ class BandwidthInfo(object):
|
|||
@classmethod
|
||||
def default_network_adapter(cls):
|
||||
"""Return default active network adapter"""
|
||||
gateway = netifaces.gateways()['default']
|
||||
gateway = netifaces.gateways()["default"]
|
||||
|
||||
if not gateway:
|
||||
raise 'No default gateway found'
|
||||
raise "No default gateway found"
|
||||
|
||||
return gateway[netifaces.AF_INET][1]
|
||||
|
||||
|
@ -97,4 +107,5 @@ class BandwidthInfo(object):
|
|||
"""Return IO counters"""
|
||||
return psutil.net_io_counters(pernic=True)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -20,24 +20,30 @@ import core.widget
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
|
||||
self.__notmuch_count_query = self.parameter('query', 'tag:unread AND NOT path:/.*Trash.*/')
|
||||
self.__notmuch_count_query = self.parameter(
|
||||
"query", "tag:unread AND NOT path:/.*Trash.*/"
|
||||
)
|
||||
|
||||
def output(self, widget):
|
||||
return self.__notmuch_count
|
||||
return self.__notmuch_count
|
||||
|
||||
def state(self, widgets):
|
||||
if self.__notmuch_count == 0:
|
||||
return 'empty'
|
||||
return 'items'
|
||||
return "empty"
|
||||
return "items"
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
self.__notmuch_count = util.cli.execute('notmuch count {}'.format(self.__notmuch_count_query)).strip()
|
||||
self.__notmuch_count = util.cli.execute(
|
||||
"notmuch count {}".format(self.__notmuch_count_query)
|
||||
).strip()
|
||||
except Exception:
|
||||
self.__notmuch_count = 'n/a'
|
||||
self.__notmuch_count = "n/a"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -15,11 +15,12 @@ import core.widget
|
|||
import util.cli
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.utilization))
|
||||
|
||||
self.__utilization = 'Not found: 0 0/0'
|
||||
self.__utilization = "Not found: 0 0/0"
|
||||
|
||||
def utilization(self, widget):
|
||||
return self.__utilization
|
||||
|
@ -28,49 +29,52 @@ class Module(core.module.Module):
|
|||
return "not found" in self.__utilization
|
||||
|
||||
def update(self):
|
||||
sp = util.cli.execute('nvidia-smi -q', ignore_errors=True)
|
||||
sp = util.cli.execute("nvidia-smi -q", ignore_errors=True)
|
||||
|
||||
title = ''
|
||||
usedMem = ''
|
||||
totalMem = ''
|
||||
temp = ''
|
||||
name = 'not found'
|
||||
clockMem = ''
|
||||
clockGpu = ''
|
||||
fanspeed = ''
|
||||
for item in sp.split('\n'):
|
||||
title = ""
|
||||
usedMem = ""
|
||||
totalMem = ""
|
||||
temp = ""
|
||||
name = "not found"
|
||||
clockMem = ""
|
||||
clockGpu = ""
|
||||
fanspeed = ""
|
||||
for item in sp.split("\n"):
|
||||
try:
|
||||
key, val = item.split(':')
|
||||
key, val = item.split(":")
|
||||
key, val = key.strip(), val.strip()
|
||||
if title == 'Clocks':
|
||||
if key == 'Graphics':
|
||||
clockGpu = val.split(' ')[0]
|
||||
elif key == 'Memory':
|
||||
clockMem = val.split(' ')[0]
|
||||
if title == 'FB Memory Usage':
|
||||
if key == 'Total':
|
||||
totalMem = val.split(' ')[0]
|
||||
elif key == 'Used':
|
||||
usedMem = val.split(' ')[0]
|
||||
elif key == 'GPU Current Temp':
|
||||
temp = val.split(' ')[0]
|
||||
elif key == 'Product Name':
|
||||
if title == "Clocks":
|
||||
if key == "Graphics":
|
||||
clockGpu = val.split(" ")[0]
|
||||
elif key == "Memory":
|
||||
clockMem = val.split(" ")[0]
|
||||
if title == "FB Memory Usage":
|
||||
if key == "Total":
|
||||
totalMem = val.split(" ")[0]
|
||||
elif key == "Used":
|
||||
usedMem = val.split(" ")[0]
|
||||
elif key == "GPU Current Temp":
|
||||
temp = val.split(" ")[0]
|
||||
elif key == "Product Name":
|
||||
name = val
|
||||
elif key == 'Fan Speed':
|
||||
fanspeed = val.split(' ')[0]
|
||||
elif key == "Fan Speed":
|
||||
fanspeed = val.split(" ")[0]
|
||||
|
||||
except:
|
||||
title = item.strip()
|
||||
|
||||
str_format = self.parameter('format', '{name}: {temp}°C {mem_used}/{mem_total} MiB')
|
||||
str_format = self.parameter(
|
||||
"format", "{name}: {temp}°C {mem_used}/{mem_total} MiB"
|
||||
)
|
||||
self.__utilization = str_format.format(
|
||||
name = name,
|
||||
temp = temp,
|
||||
mem_used = usedMem,
|
||||
mem_total = totalMem,
|
||||
clock_gpu = clockGpu,
|
||||
clock_mem = clockMem,
|
||||
fanspeed = fanspeed,
|
||||
)
|
||||
name=name,
|
||||
temp=temp,
|
||||
mem_used=usedMem,
|
||||
mem_total=totalMem,
|
||||
clock_gpu=clockGpu,
|
||||
clock_mem=clockMem,
|
||||
fanspeed=fanspeed,
|
||||
)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -27,27 +27,30 @@ import core.module
|
|||
import core.widget
|
||||
import core.input
|
||||
|
||||
|
||||
def get_frame(url):
|
||||
img_bytes = b""
|
||||
stream = urllib.request.urlopen(url)
|
||||
img_bytes = b""
|
||||
stream = urllib.request.urlopen(url)
|
||||
while True:
|
||||
img_bytes += stream.read(1024)
|
||||
a = img_bytes.find(b'\xff\xd8')
|
||||
b = img_bytes.find(b'\xff\xd9')
|
||||
a = img_bytes.find(b"\xff\xd8")
|
||||
b = img_bytes.find(b"\xff\xd9")
|
||||
if a != -1 and b != -1:
|
||||
jpg = img_bytes[a:b+2]
|
||||
img_bytes = img_bytes[b+2:]
|
||||
jpg = img_bytes[a : b + 2]
|
||||
img_bytes = img_bytes[b + 2 :]
|
||||
img = Image.open(BytesIO(jpg))
|
||||
return img
|
||||
return None
|
||||
|
||||
|
||||
class WebcamImagesWorker(threading.Thread):
|
||||
def __init__(self, url, queue):
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
|
||||
self.__url = url
|
||||
self.__queue = queue
|
||||
self.__running = True
|
||||
|
||||
def run(self):
|
||||
while self.__running:
|
||||
img = get_frame(self.__url)
|
||||
|
@ -56,6 +59,7 @@ class WebcamImagesWorker(threading.Thread):
|
|||
def stop(self):
|
||||
self.__running = False
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(seconds=5)
|
||||
def __init__(self, config, theme):
|
||||
|
@ -69,34 +73,44 @@ class Module(core.module.Module):
|
|||
self.__webcam_images_worker = None
|
||||
self.__webcam_image_url = self.__octoprint_address + "/webcam/?action=stream"
|
||||
self.__webcam_images_queue = None
|
||||
|
||||
|
||||
self.__printer_bed_temperature = "-"
|
||||
self.__tool1_temperature = "-"
|
||||
|
||||
|
||||
self.update_status()
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.__show_popup)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__show_popup)
|
||||
|
||||
def octoprint_status(self, widget):
|
||||
if self.__octoprint_state == "Offline" or self.__octoprint_state == "Unknown":
|
||||
return self.__octoprint_state
|
||||
return self.__octoprint_state + " | B: " + str(self.__printer_bed_temperature) + "°C" + " | T1: " + str(self.__tool1_temperature) + "°C"
|
||||
return (
|
||||
self.__octoprint_state
|
||||
+ " | B: "
|
||||
+ str(self.__printer_bed_temperature)
|
||||
+ "°C"
|
||||
+ " | T1: "
|
||||
+ str(self.__tool1_temperature)
|
||||
+ "°C"
|
||||
)
|
||||
|
||||
def __get(self, endpoint):
|
||||
url = self.__octoprint_address + "/api/" + endpoint
|
||||
headers = {"X-Api-Key": self.__octoprint_api_token}
|
||||
resp = requests.get(url, headers=headers)
|
||||
|
||||
|
||||
try:
|
||||
return resp.json(), resp.status_code
|
||||
except simplejson.errors.JSONDecodeError:
|
||||
return None, resp.status_code
|
||||
|
||||
|
||||
def __get_printer_bed_temperature(self):
|
||||
printer_info, status_code = self.__get("printer")
|
||||
if status_code == 200:
|
||||
return printer_info["temperature"]["bed"]["actual"], printer_info["temperature"]["bed"]["target"]
|
||||
return (
|
||||
printer_info["temperature"]["bed"]["actual"],
|
||||
printer_info["temperature"]["bed"]["target"],
|
||||
)
|
||||
return None, None
|
||||
|
||||
def __get_octoprint_state(self):
|
||||
|
@ -109,7 +123,7 @@ class Module(core.module.Module):
|
|||
printer_info, status_code = self.__get("printer")
|
||||
if status_code == 200:
|
||||
temperatures = printer_info["temperature"]
|
||||
|
||||
|
||||
tool_id = 0
|
||||
while True:
|
||||
try:
|
||||
|
@ -122,9 +136,9 @@ class Module(core.module.Module):
|
|||
|
||||
def update_status(self):
|
||||
try:
|
||||
self.__octoprint_state = self.__get_octoprint_state()
|
||||
self.__octoprint_state = self.__get_octoprint_state()
|
||||
|
||||
actual_temp, _ = self.__get_printer_bed_temperature()
|
||||
actual_temp, _ = self.__get_printer_bed_temperature()
|
||||
if actual_temp is None:
|
||||
actual_temp = "-"
|
||||
self.__printer_bed_temperature = str(actual_temp)
|
||||
|
@ -149,17 +163,18 @@ class Module(core.module.Module):
|
|||
|
||||
root.after(5, self.__refresh_image, root, webcam_image, webcam_image_container)
|
||||
|
||||
def __refresh_temperatures(self, root, printer_bed_temperature_label, tools_temperature_label):
|
||||
def __refresh_temperatures(
|
||||
self, root, printer_bed_temperature_label, tools_temperature_label
|
||||
):
|
||||
actual_bed_temp, target_bed_temp = self.__get_printer_bed_temperature()
|
||||
if actual_bed_temp is None:
|
||||
actual_bed_temp = "-"
|
||||
if target_bed_temp is None:
|
||||
target_bed_temp = "-"
|
||||
|
||||
bed_temp = "Bed: " + str(actual_bed_temp) + "/" + str(target_bed_temp) + " °C"
|
||||
bed_temp = "Bed: " + str(actual_bed_temp) + "/" + str(target_bed_temp) + " °C"
|
||||
printer_bed_temperature_label.config(text=bed_temp)
|
||||
|
||||
|
||||
tool_temperatures = self.__get_tool_temperatures()
|
||||
tools_temp = "Tools: "
|
||||
|
||||
|
@ -167,48 +182,68 @@ class Module(core.module.Module):
|
|||
tools_temp += "-/- °C"
|
||||
else:
|
||||
for i, tool_temperature in enumerate(tool_temperatures):
|
||||
tools_temp += str(tool_temperature[0]) + "/" + str(tool_temperature[1]) + "°C"
|
||||
if i != len(tool_temperatures)-1:
|
||||
tools_temp += (
|
||||
str(tool_temperature[0]) + "/" + str(tool_temperature[1]) + "°C"
|
||||
)
|
||||
if i != len(tool_temperatures) - 1:
|
||||
tools_temp += "\t"
|
||||
tools_temperature_label.config(text=tools_temp)
|
||||
|
||||
root.after(500, self.__refresh_temperatures, root, printer_bed_temperature_label, tools_temperature_label)
|
||||
|
||||
root.after(
|
||||
500,
|
||||
self.__refresh_temperatures,
|
||||
root,
|
||||
printer_bed_temperature_label,
|
||||
tools_temperature_label,
|
||||
)
|
||||
|
||||
def __show_popup(self, widget):
|
||||
root = tk.Tk()
|
||||
root.attributes('-type', 'dialog')
|
||||
root.attributes("-type", "dialog")
|
||||
root.title("Octoprint")
|
||||
frame = tk.Frame(root)
|
||||
frame = tk.Frame(root)
|
||||
if self.__octoprint_webcam:
|
||||
|
||||
#load first image synchronous before popup is shown, otherwise tkinter isn't able to layout popup properly
|
||||
# load first image synchronous before popup is shown, otherwise tkinter isn't able to layout popup properly
|
||||
img = get_frame(self.__webcam_image_url)
|
||||
webcam_image = ImageTk.PhotoImage(img)
|
||||
webcam_image_container = tk.Button(frame, image=webcam_image)
|
||||
webcam_image_container = tk.Button(frame, image=webcam_image)
|
||||
webcam_image_container.pack()
|
||||
|
||||
self.__webcam_images_queue = queue.Queue()
|
||||
|
||||
self.__webcam_images_worker = WebcamImagesWorker(self.__webcam_image_url, self.__webcam_images_queue)
|
||||
self.__webcam_images_worker = WebcamImagesWorker(
|
||||
self.__webcam_image_url, self.__webcam_images_queue
|
||||
)
|
||||
self.__webcam_images_worker.start()
|
||||
else:
|
||||
logging.debug("Not using webcam, as webcam is disabled. Enable with --webcam.")
|
||||
logging.debug(
|
||||
"Not using webcam, as webcam is disabled. Enable with --webcam."
|
||||
)
|
||||
frame.pack()
|
||||
|
||||
temperatures_label = tk.Label(frame, text="Temperatures", font=('', 25))
|
||||
temperatures_label = tk.Label(frame, text="Temperatures", font=("", 25))
|
||||
temperatures_label.pack()
|
||||
|
||||
printer_bed_temperature_label = tk.Label(frame, text="Bed: -/- °C", font=('', 15))
|
||||
printer_bed_temperature_label.pack()
|
||||
|
||||
tools_temperature_label = tk.Label(frame, text="Tools: -/- °C", font=('', 15))
|
||||
tools_temperature_label.pack()
|
||||
|
||||
printer_bed_temperature_label = tk.Label(
|
||||
frame, text="Bed: -/- °C", font=("", 15)
|
||||
)
|
||||
printer_bed_temperature_label.pack()
|
||||
|
||||
tools_temperature_label = tk.Label(frame, text="Tools: -/- °C", font=("", 15))
|
||||
tools_temperature_label.pack()
|
||||
|
||||
root.after(10, self.__refresh_image, root, webcam_image, webcam_image_container)
|
||||
root.after(500, self.__refresh_temperatures, root, printer_bed_temperature_label, tools_temperature_label)
|
||||
root.after(
|
||||
500,
|
||||
self.__refresh_temperatures,
|
||||
root,
|
||||
printer_bed_temperature_label,
|
||||
tools_temperature_label,
|
||||
)
|
||||
root.bind("<Destroy>", self.__on_close_popup)
|
||||
|
||||
root.eval('tk::PlaceWindow . center')
|
||||
|
||||
root.eval("tk::PlaceWindow . center")
|
||||
root.mainloop()
|
||||
|
||||
def __on_close_popup(self, event):
|
||||
|
@ -219,6 +254,7 @@ class Module(core.module.Module):
|
|||
self.update_status()
|
||||
|
||||
def state(self, widget):
|
||||
return []
|
||||
return []
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -20,22 +20,23 @@ import core.decorators
|
|||
import util.cli
|
||||
import util.format
|
||||
|
||||
#list of repositories.
|
||||
#the last one should always be other
|
||||
repos = ['core', 'extra', 'community', 'multilib', 'testing', 'other']
|
||||
# list of repositories.
|
||||
# the last one should always be other
|
||||
repos = ["core", "extra", "community", "multilib", "testing", "other"]
|
||||
|
||||
|
||||
def get_pacman_info(widget, path):
|
||||
cmd = '{}/../../bin/pacman-updates'.format(path)
|
||||
cmd = "{}/../../bin/pacman-updates".format(path)
|
||||
if not os.path.exists(cmd):
|
||||
cmd = '/usr/share/bumblebee-status/bin/pacman-update'
|
||||
cmd = "/usr/share/bumblebee-status/bin/pacman-update"
|
||||
result = util.cli.execute(cmd, ignore_errors=True)
|
||||
|
||||
count = len(repos)*[0]
|
||||
count = len(repos) * [0]
|
||||
|
||||
for line in result.splitlines():
|
||||
if line.startswith(('http', 'rsync')):
|
||||
for i in range(len(repos)-1):
|
||||
if '/' + repos[i] + '/' in line:
|
||||
if line.startswith(("http", "rsync")):
|
||||
for i in range(len(repos) - 1):
|
||||
if "/" + repos[i] + "/" in line:
|
||||
count[i] += 1
|
||||
break
|
||||
else:
|
||||
|
@ -43,7 +44,8 @@ def get_pacman_info(widget, path):
|
|||
|
||||
for i in range(len(repos)):
|
||||
widget.set(repos[i], count[i])
|
||||
core.event.trigger('update', [ widget.module.id ], redraw_only=True)
|
||||
core.event.trigger("update", [widget.module.id], redraw_only=True)
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=30)
|
||||
|
@ -51,9 +53,9 @@ class Module(core.module.Module):
|
|||
super().__init__(config, theme, core.widget.Widget(self.updates))
|
||||
|
||||
def updates(self, widget):
|
||||
if util.format.asbool(self.parameter('sum')):
|
||||
if util.format.asbool(self.parameter("sum")):
|
||||
return str(sum(map(lambda x: widget.get(x, 0), repos)))
|
||||
return '/'.join(map(lambda x: str(widget.get(x, 0)), repos))
|
||||
return "/".join(map(lambda x: str(widget.get(x, 0)), repos))
|
||||
|
||||
def update(self):
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
|
@ -61,11 +63,14 @@ class Module(core.module.Module):
|
|||
thread.start()
|
||||
|
||||
def state(self, widget):
|
||||
weightedCount = sum(map(lambda x: (len(repos)-x[0]) * widget.get(x[1], 0), enumerate(repos)))
|
||||
weightedCount = sum(
|
||||
map(lambda x: (len(repos) - x[0]) * widget.get(x[1], 0), enumerate(repos))
|
||||
)
|
||||
|
||||
if weightedCount < 10:
|
||||
return 'good'
|
||||
return "good"
|
||||
|
||||
return self.threshold_state(weightedCount, 100, 150)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -12,30 +12,36 @@ import core.module
|
|||
import core.widget
|
||||
import core.input
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=1)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.pihole_status))
|
||||
|
||||
self._pihole_address = self.parameter('address', '')
|
||||
self._pihole_pw_hash = self.parameter('pwhash', '')
|
||||
self._pihole_address = self.parameter("address", "")
|
||||
self._pihole_pw_hash = self.parameter("pwhash", "")
|
||||
self._pihole_status = None
|
||||
self._ads_blocked_today = '-'
|
||||
self._ads_blocked_today = "-"
|
||||
self.update_pihole_status()
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.toggle_pihole_status)
|
||||
core.input.register(
|
||||
self, button=core.input.LEFT_MOUSE, cmd=self.toggle_pihole_status
|
||||
)
|
||||
|
||||
def pihole_status(self, widget):
|
||||
if self._pihole_status is None:
|
||||
return 'pi-hole unknown'
|
||||
return 'pi-hole {}'.format('up {} blocked'.format(self._ads_blocked_today) if self._pihole_status else 'down')
|
||||
return "pi-hole unknown"
|
||||
return "pi-hole {}".format(
|
||||
"up {} blocked".format(self._ads_blocked_today)
|
||||
if self._pihole_status
|
||||
else "down"
|
||||
)
|
||||
|
||||
def update_pihole_status(self):
|
||||
try:
|
||||
data = requests.get(self._pihole_address + '/admin/api.php?summary').json()
|
||||
self._pihole_status = True if data['status'] == 'enabled' else False
|
||||
self._ads_blocked_today = data['ads_blocked_today']
|
||||
data = requests.get(self._pihole_address + "/admin/api.php?summary").json()
|
||||
self._pihole_status = True if data["status"] == "enabled" else False
|
||||
self._ads_blocked_today = data["ads_blocked_today"]
|
||||
except Exception as e:
|
||||
self._pihole_status = None
|
||||
|
||||
|
@ -44,17 +50,24 @@ class Module(core.module.Module):
|
|||
try:
|
||||
req = None
|
||||
if self._pihole_status:
|
||||
req = requests.get(self._pihole_address + '/admin/api.php?disable&auth=' + self._pihole_pw_hash)
|
||||
req = requests.get(
|
||||
self._pihole_address
|
||||
+ "/admin/api.php?disable&auth="
|
||||
+ self._pihole_pw_hash
|
||||
)
|
||||
else:
|
||||
req = requests.get(self._pihole_address + '/admin/api.php?enable&auth=' + self._pihole_pw_hash)
|
||||
req = requests.get(
|
||||
self._pihole_address
|
||||
+ "/admin/api.php?enable&auth="
|
||||
+ self._pihole_pw_hash
|
||||
)
|
||||
if req is not None:
|
||||
if req.status_code == 200:
|
||||
status = req.json()['status']
|
||||
self._pihole_status = False if status == 'disabled' else True
|
||||
status = req.json()["status"]
|
||||
self._pihole_status = False if status == "disabled" else True
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def update(self):
|
||||
self.update_pihole_status()
|
||||
|
||||
|
@ -62,7 +75,8 @@ class Module(core.module.Module):
|
|||
if self._pihole_status is None:
|
||||
return []
|
||||
elif self._pihole_status:
|
||||
return ['enabled']
|
||||
return ['disabled', 'warning']
|
||||
return ["enabled"]
|
||||
return ["disabled", "warning"]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -26,97 +26,102 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.text))
|
||||
|
||||
# Parameters
|
||||
self.__work_period = int(self.parameter('work', 25))
|
||||
self.__break_period = int(self.parameter('break', 5))
|
||||
self.__time_format = self.parameter('format', '%m:%s')
|
||||
self.__notify_cmd = self.parameter('notify', '')
|
||||
self.__work_period = int(self.parameter("work", 25))
|
||||
self.__break_period = int(self.parameter("break", 5))
|
||||
self.__time_format = self.parameter("format", "%m:%s")
|
||||
self.__notify_cmd = self.parameter("notify", "")
|
||||
|
||||
# TODO: Handle time formats more gracefully. This is kludge.
|
||||
self.display_seconds_p = False
|
||||
self.display_minutes_p = False
|
||||
if '%s' in self.__time_format:
|
||||
if "%s" in self.__time_format:
|
||||
self.display_seconds_p = True
|
||||
if '%m' in self.__time_format:
|
||||
if "%m" in self.__time_format:
|
||||
self.display_minutes_p = True
|
||||
|
||||
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
|
||||
|
||||
self.time = None
|
||||
self.pomodoro = { 'state':'OFF', 'type': ''}
|
||||
self.__text = self.remaining_time_str() + self.pomodoro['type']
|
||||
self.pomodoro = {"state": "OFF", "type": ""}
|
||||
self.__text = self.remaining_time_str() + self.pomodoro["type"]
|
||||
|
||||
core.input.register(
|
||||
self, button=core.input.LEFT_MOUSE, cmd=self.timer_play_pause
|
||||
)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.timer_reset)
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.timer_play_pause)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE,
|
||||
cmd=self.timer_reset)
|
||||
|
||||
def remaining_time_str(self):
|
||||
if self.display_seconds_p and self.display_minutes_p:
|
||||
minutes, seconds = divmod(self.remaining_time.seconds, 60)
|
||||
if not self.display_seconds_p:
|
||||
minutes = ceil(self.remaining_time.seconds / 60)
|
||||
seconds = 0
|
||||
seconds = 0
|
||||
if not self.display_minutes_p:
|
||||
minutes = 0
|
||||
seconds = self.remaining_time.seconds
|
||||
|
||||
minutes = '{:2d}'.format(minutes)
|
||||
seconds = '{:02d}'.format(seconds)
|
||||
return self.__time_format.replace('%m',minutes).replace('%s',seconds)+' '
|
||||
minutes = "{:2d}".format(minutes)
|
||||
seconds = "{:02d}".format(seconds)
|
||||
return self.__time_format.replace("%m", minutes).replace("%s", seconds) + " "
|
||||
|
||||
def text(self, widget):
|
||||
return '{}'.format(self.__text)
|
||||
|
||||
return "{}".format(self.__text)
|
||||
|
||||
def update(self):
|
||||
if self.pomodoro['state'] == 'ON':
|
||||
timediff = (datetime.datetime.now() - self.time)
|
||||
if self.pomodoro["state"] == "ON":
|
||||
timediff = datetime.datetime.now() - self.time
|
||||
if timediff.seconds >= 0:
|
||||
self.remaining_time -= timediff
|
||||
self.time = datetime.datetime.now()
|
||||
|
||||
if self.remaining_time.total_seconds() <= 0:
|
||||
self.notify()
|
||||
if self.pomodoro['type'] == 'Work':
|
||||
self.pomodoro['type'] = 'Break'
|
||||
self.remaining_time = datetime.timedelta(minutes=self.__break_period)
|
||||
elif self.pomodoro['type'] == 'Break':
|
||||
self.pomodoro['type'] = 'Work'
|
||||
if self.pomodoro["type"] == "Work":
|
||||
self.pomodoro["type"] = "Break"
|
||||
self.remaining_time = datetime.timedelta(
|
||||
minutes=self.__break_period
|
||||
)
|
||||
elif self.pomodoro["type"] == "Break":
|
||||
self.pomodoro["type"] = "Work"
|
||||
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
|
||||
|
||||
self.__text = self.remaining_time_str() + self.pomodoro['type']
|
||||
|
||||
self.__text = self.remaining_time_str() + self.pomodoro["type"]
|
||||
|
||||
def notify(self):
|
||||
if self.__notify_cmd:
|
||||
util.cli.execute(self.__notify_cmd)
|
||||
|
||||
def timer_play_pause(self, widget):
|
||||
if self.pomodoro['state'] == 'OFF':
|
||||
self.pomodoro = {'state': 'ON', 'type': 'Work'}
|
||||
if self.pomodoro["state"] == "OFF":
|
||||
self.pomodoro = {"state": "ON", "type": "Work"}
|
||||
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
|
||||
self.time = datetime.datetime.now()
|
||||
elif self.pomodoro['state'] == 'ON':
|
||||
self.pomodoro['state'] = 'PAUSED'
|
||||
self.remaining_time -= (datetime.datetime.now() - self.time)
|
||||
elif self.pomodoro["state"] == "ON":
|
||||
self.pomodoro["state"] = "PAUSED"
|
||||
self.remaining_time -= datetime.datetime.now() - self.time
|
||||
self.time = datetime.datetime.now()
|
||||
elif self.pomodoro['state'] == 'PAUSED':
|
||||
self.pomodoro['state'] = 'ON'
|
||||
elif self.pomodoro["state"] == "PAUSED":
|
||||
self.pomodoro["state"] = "ON"
|
||||
self.time = datetime.datetime.now()
|
||||
|
||||
def timer_reset(self, widget):
|
||||
if self.pomodoro['state'] == 'ON' or self.pomodoro['state'] == 'PAUSED':
|
||||
self.pomodoro = {'state':'OFF', 'type': '' }
|
||||
if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "PAUSED":
|
||||
self.pomodoro = {"state": "OFF", "type": ""}
|
||||
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
|
||||
|
||||
def state(self, widget):
|
||||
state = [];
|
||||
state.append(self.pomodoro['state'].lower())
|
||||
if self.pomodoro['state'] == 'ON' or self.pomodoro['state'] == 'OFF':
|
||||
state.append(self.pomodoro['type'].lower())
|
||||
state = []
|
||||
state.append(self.pomodoro["state"].lower())
|
||||
if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "OFF":
|
||||
state.append(self.pomodoro["type"].lower())
|
||||
|
||||
return state
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -31,36 +31,37 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.query))
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.__chooseNvidia)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE,
|
||||
cmd=self.__chooseIntel)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__chooseNvidia)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__chooseIntel)
|
||||
|
||||
self.nvidiastring = self.parameter('nvidiastring', 'nv')
|
||||
self.intelstring = self.parameter('intelstring', 'it')
|
||||
self.nvidiastring = self.parameter("nvidiastring", "nv")
|
||||
self.intelstring = self.parameter("intelstring", "it")
|
||||
|
||||
def __chooseNvidia(self, event):
|
||||
util.cli.execute('sudo prime-select nvidia')
|
||||
util.cli.execute("sudo prime-select nvidia")
|
||||
|
||||
def __chooseIntel(self, event):
|
||||
util.cli.execute('sudo prime-select intel')
|
||||
util.cli.execute("sudo prime-select intel")
|
||||
|
||||
def query(self, widget):
|
||||
try:
|
||||
res = util.cli.execute('prime-select query')
|
||||
res = util.cli.execute("prime-select query")
|
||||
except RuntimeError:
|
||||
return 'n/a'
|
||||
return "n/a"
|
||||
|
||||
for line in res.split('\n'):
|
||||
if not line: continue
|
||||
if 'nvidia' in line:
|
||||
for line in res.split("\n"):
|
||||
if not line:
|
||||
continue
|
||||
if "nvidia" in line:
|
||||
return self.nvidiastring
|
||||
if 'intel' in line:
|
||||
if "intel" in line:
|
||||
return self.intelstring
|
||||
return 'n/a'
|
||||
return "n/a"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -21,6 +21,7 @@ import util.format
|
|||
|
||||
import re
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.get_progress_text))
|
||||
|
@ -28,33 +29,31 @@ class Module(core.module.Module):
|
|||
|
||||
def get_progress_text(self, widget):
|
||||
if self.update_progress_info(widget):
|
||||
width = util.format.asint(self.parameter('barwidth', 8))
|
||||
count = round((width * widget.get('per')) / 100)
|
||||
filledchar = self.parameter('barfilledchar', '#')
|
||||
emptychar = self.parameter('baremptychar', '-')
|
||||
width = util.format.asint(self.parameter("barwidth", 8))
|
||||
count = round((width * widget.get("per")) / 100)
|
||||
filledchar = self.parameter("barfilledchar", "#")
|
||||
emptychar = self.parameter("baremptychar", "-")
|
||||
|
||||
bar = '[{}{}]'.format(
|
||||
filledchar * count,
|
||||
emptychar * (width - count)
|
||||
)
|
||||
bar = "[{}{}]".format(filledchar * count, emptychar * (width - count))
|
||||
|
||||
str_format = self.parameter('format', '{bar} {cmd} {arg}')
|
||||
str_format = self.parameter("format", "{bar} {cmd} {arg}")
|
||||
return str_format.format(
|
||||
bar = bar,
|
||||
pid = widget.get('pid'),
|
||||
cmd = widget.get('cmd'),
|
||||
arg = widget.get('arg'),
|
||||
percentage = widget.get('per'),
|
||||
quantity = widget.get('qty'),
|
||||
speed = widget.get('spd'),
|
||||
time = widget.get('tim')
|
||||
bar=bar,
|
||||
pid=widget.get("pid"),
|
||||
cmd=widget.get("cmd"),
|
||||
arg=widget.get("arg"),
|
||||
percentage=widget.get("per"),
|
||||
quantity=widget.get("qty"),
|
||||
speed=widget.get("spd"),
|
||||
time=widget.get("tim"),
|
||||
)
|
||||
else:
|
||||
return self.parameter('placeholder', 'n/a')
|
||||
return self.parameter("placeholder", "n/a")
|
||||
|
||||
def update_progress_info(self, widget):
|
||||
"""Update widget's informations about the copy"""
|
||||
if not self.__active: return
|
||||
if not self.__active:
|
||||
return
|
||||
|
||||
# These regex extracts following groups:
|
||||
# 1. pid
|
||||
|
@ -64,39 +63,44 @@ class Module(core.module.Module):
|
|||
# 5. quantity (.. unit / .. unit formated)
|
||||
# 6. speed
|
||||
# 7. time remaining
|
||||
extract_nospeed = re.compile('\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\)\n.*')
|
||||
extract_wtspeed = re.compile('\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\) (\d*\.\d .*) remaining (\d*:\d*:\d*)\n.*')
|
||||
extract_nospeed = re.compile(
|
||||
"\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\)\n.*"
|
||||
)
|
||||
extract_wtspeed = re.compile(
|
||||
"\[ *(\d*)\] ([a-zA-Z]*) (.*)\n\t(\d*\.*\d*)% \((.*)\) (\d*\.\d .*) remaining (\d*:\d*:\d*)\n.*"
|
||||
)
|
||||
|
||||
try:
|
||||
raw = util.cli.execute('progress -qW 0.1')
|
||||
raw = util.cli.execute("progress -qW 0.1")
|
||||
result = extract_wtspeed.match(raw)
|
||||
|
||||
if not result:
|
||||
# Abord speed measures
|
||||
raw = util.cli.execute('progress -q')
|
||||
raw = util.cli.execute("progress -q")
|
||||
result = extract_nospeed.match(raw)
|
||||
|
||||
widget.set('spd', '???.? B/s')
|
||||
widget.set('tim', '??:??:??')
|
||||
widget.set("spd", "???.? B/s")
|
||||
widget.set("tim", "??:??:??")
|
||||
else:
|
||||
widget.set('spd', result.group(6))
|
||||
widget.set('tim', result.group(7))
|
||||
widget.set("spd", result.group(6))
|
||||
widget.set("tim", result.group(7))
|
||||
|
||||
widget.set('pid', int(result.group(1)))
|
||||
widget.set('cmd', result.group(2))
|
||||
widget.set('arg', result.group(3))
|
||||
widget.set('per', float(result.group(4)))
|
||||
widget.set('qty', result.group(5))
|
||||
widget.set("pid", int(result.group(1)))
|
||||
widget.set("cmd", result.group(2))
|
||||
widget.set("arg", result.group(3))
|
||||
widget.set("per", float(result.group(4)))
|
||||
widget.set("qty", result.group(5))
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def update(self):
|
||||
self.__active = bool(util.cli.execute('progress -q'))
|
||||
self.__active = bool(util.cli.execute("progress -q"))
|
||||
|
||||
def state(self, widget):
|
||||
if self.__active:
|
||||
return 'copying'
|
||||
return 'pending'
|
||||
return "copying"
|
||||
return "pending"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -7,13 +7,13 @@ import core.decorators
|
|||
|
||||
import util.location
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.public_ip))
|
||||
|
||||
self.__ip = ''
|
||||
|
||||
self.__ip = ""
|
||||
|
||||
def public_ip(self, widget):
|
||||
return self.__ip
|
||||
|
@ -22,6 +22,7 @@ class Module(core.module.Module):
|
|||
try:
|
||||
self.__ip = util.location.public_ip()
|
||||
except Exception:
|
||||
self.__ip = 'n/a'
|
||||
self.__ip = "n/a"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -12,7 +12,8 @@ import core.input
|
|||
|
||||
import util.cli
|
||||
|
||||
possible_orientations = ['normal', 'left', 'inverted', 'right']
|
||||
possible_orientations = ["normal", "left", "inverted", "right"]
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
|
@ -20,37 +21,42 @@ class Module(core.module.Module):
|
|||
|
||||
def update(self):
|
||||
widgets = self.widgets()
|
||||
for line in util.cli.execute('xrandr -q').split('\n'):
|
||||
if not ' connected' in line:
|
||||
for line in util.cli.execute("xrandr -q").split("\n"):
|
||||
if not " connected" in line:
|
||||
continue
|
||||
display = line.split(' ', 2)[0]
|
||||
display = line.split(" ", 2)[0]
|
||||
|
||||
orientation = 'normal'
|
||||
orientation = "normal"
|
||||
for curr_orient in possible_orientations:
|
||||
if((line.split(' ')).count(curr_orient) > 1):
|
||||
if (line.split(" ")).count(curr_orient) > 1:
|
||||
orientation = curr_orient
|
||||
break
|
||||
|
||||
widget = self.widget(display)
|
||||
if not widget:
|
||||
widget = core.widget.Widget(full_text=display, name=display)
|
||||
core.input.register(widget, button=core.input.LEFT_MOUSE, cmd=self.__toggle)
|
||||
widget.set('orientation', orientation)
|
||||
core.input.register(
|
||||
widget, button=core.input.LEFT_MOUSE, cmd=self.__toggle
|
||||
)
|
||||
widget.set("orientation", orientation)
|
||||
widgets.append(widget)
|
||||
|
||||
def state(self, widget):
|
||||
return widget.get('orientation', 'normal')
|
||||
return widget.get("orientation", "normal")
|
||||
|
||||
def __toggle(self, event):
|
||||
widget = self.widget_by_id(event['instance'])
|
||||
widget = self.widget_by_id(event["instance"])
|
||||
|
||||
# compute new orientation based on current orientation
|
||||
idx = possible_orientations.index(widget.get('orientation'))
|
||||
idx = possible_orientations.index(widget.get("orientation"))
|
||||
idx = (idx + 1) % len(possible_orientations)
|
||||
new_orientation = possible_orientations[idx]
|
||||
|
||||
widget.set('orientation', new_orientation)
|
||||
widget.set("orientation", new_orientation)
|
||||
|
||||
util.cli.execute(
|
||||
"xrandr --output {} --rotation {}".format(widget.name, new_orientation)
|
||||
)
|
||||
|
||||
util.cli.execute('xrandr --output {} --rotation {}'.format(widget.name, new_orientation))
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -30,17 +30,19 @@ import core.input
|
|||
class Module(core.module.Module):
|
||||
REFRESH_DELAY = 600
|
||||
SCROLL_SPEED = 3
|
||||
LAYOUT_STYLES_ITEMS = [[1,1,1],[3,3,2],[2,3,3],[3,2,3]]
|
||||
HISTORY_FILENAME = '.config/i3/rss.hist'
|
||||
LAYOUT_STYLES_ITEMS = [[1, 1, 1], [3, 3, 2], [2, 3, 3], [3, 2, 3]]
|
||||
HISTORY_FILENAME = ".config/i3/rss.hist"
|
||||
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.ticker_update))
|
||||
|
||||
self._feeds = self.parameter('feeds', 'https://www.espn.com/espn/rss/news').split(' ')
|
||||
self._feeds = self.parameter(
|
||||
"feeds", "https://www.espn.com/espn/rss/news"
|
||||
).split(" ")
|
||||
self._feeds_to_update = []
|
||||
self._response = ''
|
||||
self._response = ""
|
||||
|
||||
self._max_title_length = int(self.parameter('length', 60))
|
||||
self._max_title_length = int(self.parameter("length", 60))
|
||||
|
||||
self._items = []
|
||||
self._current_item = None
|
||||
|
@ -51,76 +53,103 @@ class Module(core.module.Module):
|
|||
|
||||
self._state = []
|
||||
|
||||
self._newspaper_filename = tempfile.mktemp('.html')
|
||||
self._newspaper_filename = tempfile.mktemp(".html")
|
||||
|
||||
self._last_refresh = 0
|
||||
self._last_update = 0
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self._open)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self._create_newspaper)
|
||||
core.input.register(
|
||||
self, button=core.input.RIGHT_MOUSE, cmd=self._create_newspaper
|
||||
)
|
||||
|
||||
self._history = {'ticker': {}, 'newspaper': {}}
|
||||
self._history = {"ticker": {}, "newspaper": {}}
|
||||
self._load_history()
|
||||
|
||||
def _load_history(self):
|
||||
if os.path.isfile(self.HISTORY_FILENAME):
|
||||
self._history = json.loads(open(self.HISTORY_FILENAME, 'r').read())
|
||||
self._history = json.loads(open(self.HISTORY_FILENAME, "r").read())
|
||||
|
||||
def _update_history(self, group):
|
||||
sources = set([i['source'] for i in self._items])
|
||||
self._history[group] = dict([[s, [i['title'] for i in self._items if i['source'] == s]] for s in sources])
|
||||
sources = set([i["source"] for i in self._items])
|
||||
self._history[group] = dict(
|
||||
[
|
||||
[s, [i["title"] for i in self._items if i["source"] == s]]
|
||||
for s in sources
|
||||
]
|
||||
)
|
||||
|
||||
def _save_history(self):
|
||||
if not os.path.exists(os.path.dirname(self.HISTORY_FILENAME)):
|
||||
os.makedirs(os.path.dirname(self.HISTORY_FILENAME))
|
||||
open(self.HISTORY_FILENAME, 'w').write(json.dumps(self._history))
|
||||
open(self.HISTORY_FILENAME, "w").write(json.dumps(self._history))
|
||||
|
||||
def _check_history(self, items, group):
|
||||
for i in items:
|
||||
i['new'] = not (i['source'] in self._history[group] and i['title'] in self._history[group][i['source']])
|
||||
i["new"] = not (
|
||||
i["source"] in self._history[group]
|
||||
and i["title"] in self._history[group][i["source"]]
|
||||
)
|
||||
|
||||
def _open(self, _):
|
||||
if self._current_item:
|
||||
webbrowser.open(self._current_item['link'])
|
||||
webbrowser.open(self._current_item["link"])
|
||||
|
||||
def _check_for_image(self, entry):
|
||||
image = next(iter([l['href'] for l in entry['links'] if l['rel'] == 'enclosure']), None)
|
||||
if not image and 'media_content' in entry:
|
||||
image = next(
|
||||
iter([l["href"] for l in entry["links"] if l["rel"] == "enclosure"]), None
|
||||
)
|
||||
if not image and "media_content" in entry:
|
||||
try:
|
||||
media = sorted(entry['media_content'], key=lambda i: i['height'] if 'height' in i else 0, reverse=True)
|
||||
image = next(iter([i['url'] for i in media if i['medium'] == 'image']), None)
|
||||
media = sorted(
|
||||
entry["media_content"],
|
||||
key=lambda i: i["height"] if "height" in i else 0,
|
||||
reverse=True,
|
||||
)
|
||||
image = next(
|
||||
iter([i["url"] for i in media if i["medium"] == "image"]), None
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
if not image:
|
||||
match = re.search(r"<img[^>]*src\s*=['\']*([^\s^>^'^\']*)['\']*", entry['summary'])
|
||||
match = re.search(
|
||||
r"<img[^>]*src\s*=['\']*([^\s^>^'^\']*)['\']*", entry["summary"]
|
||||
)
|
||||
if match:
|
||||
image = match.group(1)
|
||||
return image if image else ''
|
||||
return image if image else ""
|
||||
|
||||
def _remove_tags(self, txt):
|
||||
return re.sub('<[^>]*>', '', txt)
|
||||
return re.sub("<[^>]*>", "", txt)
|
||||
|
||||
def _create_item(self, entry, url, feed):
|
||||
return {'title': self._remove_tags(entry['title'].replace('\n', ' ')),
|
||||
'link': entry['link'],
|
||||
'new': True,
|
||||
'source': url,
|
||||
'summary': self._remove_tags(entry['summary']),
|
||||
'feed': feed,
|
||||
'image': self._check_for_image(entry),
|
||||
'published': time.mktime(entry.published_parsed) if hasattr(entry, 'published_parsed') else 0}
|
||||
return {
|
||||
"title": self._remove_tags(entry["title"].replace("\n", " ")),
|
||||
"link": entry["link"],
|
||||
"new": True,
|
||||
"source": url,
|
||||
"summary": self._remove_tags(entry["summary"]),
|
||||
"feed": feed,
|
||||
"image": self._check_for_image(entry),
|
||||
"published": time.mktime(entry.published_parsed)
|
||||
if hasattr(entry, "published_parsed")
|
||||
else 0,
|
||||
}
|
||||
|
||||
def _update_items_from_feed(self, url):
|
||||
parser = feedparser.parse(url)
|
||||
new_items = [self._create_item(entry, url, parser['feed']['title']) for entry in parser['entries']]
|
||||
new_items = [
|
||||
self._create_item(entry, url, parser["feed"]["title"])
|
||||
for entry in parser["entries"]
|
||||
]
|
||||
# Check history
|
||||
self._check_history(new_items, 'ticker')
|
||||
self._check_history(new_items, "ticker")
|
||||
# Remove the previous items
|
||||
self._items = [i for i in self._items if i['source'] != url]
|
||||
self._items = [i for i in self._items if i["source"] != url]
|
||||
# Add the new items
|
||||
self._items.extend(new_items)
|
||||
# Sort the items on publish date
|
||||
self._items.sort(key=lambda i: i['published'], reverse=True)
|
||||
self._items.sort(key=lambda i: i["published"], reverse=True)
|
||||
|
||||
def _check_for_refresh(self):
|
||||
if self._feeds_to_update:
|
||||
|
@ -129,12 +158,12 @@ class Module(core.module.Module):
|
|||
self._update_items_from_feed(url)
|
||||
|
||||
if not self._feeds_to_update:
|
||||
self._update_history('ticker')
|
||||
self._update_history("ticker")
|
||||
self._save_history()
|
||||
|
||||
if not self._current_item:
|
||||
self._next_item()
|
||||
elif time.time()-self._last_refresh >= self.REFRESH_DELAY:
|
||||
elif time.time() - self._last_refresh >= self.REFRESH_DELAY:
|
||||
# Populate the list with feeds to update
|
||||
self._feeds_to_update = self._feeds[:]
|
||||
# Update the refresh time
|
||||
|
@ -149,19 +178,27 @@ class Module(core.module.Module):
|
|||
return
|
||||
|
||||
# Index of the current element
|
||||
idx = self._items.index(self._current_item) if self._current_item in self._items else - 1
|
||||
idx = (
|
||||
self._items.index(self._current_item)
|
||||
if self._current_item in self._items
|
||||
else -1
|
||||
)
|
||||
|
||||
# First show new items, else show next
|
||||
new_items = [i for i in self._items if i['new']]
|
||||
self._current_item = next(iter(new_items), self._items[(idx+1) % len(self._items)])
|
||||
new_items = [i for i in self._items if i["new"]]
|
||||
self._current_item = next(
|
||||
iter(new_items), self._items[(idx + 1) % len(self._items)]
|
||||
)
|
||||
|
||||
def _check_scroll_done(self):
|
||||
# Check if the complete title has been shown
|
||||
if self._ticker_offset + self._max_title_length > len(self._current_item['title']):
|
||||
if self._ticker_offset + self._max_title_length > len(
|
||||
self._current_item["title"]
|
||||
):
|
||||
# Do not immediately show next item after scroll
|
||||
self._post_delay -= 1
|
||||
if self._post_delay == 0:
|
||||
self._current_item['new'] = False
|
||||
self._current_item["new"] = False
|
||||
# Mark the previous item as 'old'
|
||||
self._next_item()
|
||||
else:
|
||||
|
@ -171,7 +208,7 @@ class Module(core.module.Module):
|
|||
def ticker_update(self, _):
|
||||
# Only update the ticker once a second
|
||||
now = time.time()
|
||||
if now-self._last_update < 1:
|
||||
if now - self._last_update < 1:
|
||||
return self._response
|
||||
|
||||
self._last_update = now
|
||||
|
@ -180,18 +217,20 @@ class Module(core.module.Module):
|
|||
|
||||
# If no items were retrieved, return an empty string
|
||||
if not self._current_item:
|
||||
return ' '*self._max_title_length
|
||||
return " " * self._max_title_length
|
||||
|
||||
# Prepare a substring of the item title
|
||||
self._response = self._current_item['title'][self._ticker_offset:self._ticker_offset+self._max_title_length]
|
||||
self._response = self._current_item["title"][
|
||||
self._ticker_offset : self._ticker_offset + self._max_title_length
|
||||
]
|
||||
# Add spaces if too short
|
||||
self._response = self._response.ljust(self._max_title_length)
|
||||
|
||||
# Do not immediately scroll
|
||||
if self._pre_delay > 0:
|
||||
# Change state during pre_delay for new items
|
||||
if self._current_item['new']:
|
||||
self._state = ['warning']
|
||||
if self._current_item["new"]:
|
||||
self._state = ["warning"]
|
||||
self._pre_delay -= 1
|
||||
return self._response
|
||||
|
||||
|
@ -205,48 +244,76 @@ class Module(core.module.Module):
|
|||
|
||||
def _create_news_element(self, item, overlay_title):
|
||||
try:
|
||||
timestr = '' if item['published'] == 0 else str(time.ctime(item['published']))
|
||||
timestr = (
|
||||
"" if item["published"] == 0 else str(time.ctime(item["published"]))
|
||||
)
|
||||
except Exception as exc:
|
||||
logging.error(str(exc))
|
||||
raise e
|
||||
element = "<div class='item' onclick=window.open('"+item['link']+"')>"
|
||||
element = "<div class='item' onclick=window.open('" + item["link"] + "')>"
|
||||
element += "<div class='titlecontainer'>"
|
||||
element += " <img "+("" if item['image'] else "class='noimg' ")+"src='"+item['image']+"'>"
|
||||
element += " <div class='title"+(" overlay" if overlay_title else "")+"'>"+("<span class='star'>★</span>" if item['new'] else "")+item['title']+"</div>"
|
||||
element += (
|
||||
" <img "
|
||||
+ ("" if item["image"] else "class='noimg' ")
|
||||
+ "src='"
|
||||
+ item["image"]
|
||||
+ "'>"
|
||||
)
|
||||
element += (
|
||||
" <div class='title"
|
||||
+ (" overlay" if overlay_title else "")
|
||||
+ "'>"
|
||||
+ ("<span class='star'>★</span>" if item["new"] else "")
|
||||
+ item["title"]
|
||||
+ "</div>"
|
||||
)
|
||||
element += "</div>"
|
||||
element += "<div class='summary'>"+item['summary']+"</div>"
|
||||
element += "<div class='info'><span class='author'>"+item['feed']+"</span><span class='published'>"+timestr+"</span></div>"
|
||||
element += "<div class='summary'>" + item["summary"] + "</div>"
|
||||
element += (
|
||||
"<div class='info'><span class='author'>"
|
||||
+ item["feed"]
|
||||
+ "</span><span class='published'>"
|
||||
+ timestr
|
||||
+ "</span></div>"
|
||||
)
|
||||
element += "</div>"
|
||||
return element
|
||||
|
||||
def _create_news_section(self, newspaper_items):
|
||||
style = random.randint(0, 3)
|
||||
section = "<table><tr class='style"+str(style)+"'>"
|
||||
section = "<table><tr class='style" + str(style) + "'>"
|
||||
for i in range(0, 3):
|
||||
section += "<td><div class='itemcontainer'>"
|
||||
for _ in range(0, self.LAYOUT_STYLES_ITEMS[style][i]):
|
||||
if newspaper_items:
|
||||
section += self._create_news_element(newspaper_items[0], self.LAYOUT_STYLES_ITEMS[style][i] != 3)
|
||||
section += self._create_news_element(
|
||||
newspaper_items[0], self.LAYOUT_STYLES_ITEMS[style][i] != 3
|
||||
)
|
||||
del newspaper_items[0]
|
||||
section += "</div></td>"
|
||||
section += "</tr></table>"
|
||||
return section
|
||||
|
||||
def _create_newspaper(self, _):
|
||||
content = ''
|
||||
content = ""
|
||||
newspaper_items = self._items[:]
|
||||
self._check_history(newspaper_items, 'newspaper')
|
||||
self._check_history(newspaper_items, "newspaper")
|
||||
|
||||
# Make sure new items are always listed first, independent of publish date
|
||||
newspaper_items.sort(key=lambda i: i['published']+(10000000 if i['new'] else 0), reverse=True)
|
||||
newspaper_items.sort(
|
||||
key=lambda i: i["published"] + (10000000 if i["new"] else 0), reverse=True
|
||||
)
|
||||
|
||||
while newspaper_items:
|
||||
content += self._create_news_section(newspaper_items)
|
||||
open(self._newspaper_filename, 'w').write(HTML_TEMPLATE.replace('[[CONTENT]]', content))
|
||||
webbrowser.open('file://'+self._newspaper_filename)
|
||||
self._update_history('newspaper')
|
||||
open(self._newspaper_filename, "w").write(
|
||||
HTML_TEMPLATE.replace("[[CONTENT]]", content)
|
||||
)
|
||||
webbrowser.open("file://" + self._newspaper_filename)
|
||||
self._update_history("newspaper")
|
||||
self._save_history()
|
||||
|
||||
|
||||
HTML_TEMPLATE = """<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
|
|
@ -27,105 +27,119 @@ import core.input
|
|||
import util.cli
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.temperature))
|
||||
|
||||
self._temperature = 'unknown'
|
||||
self._mhz = 'n/a'
|
||||
self._match_number = int(self.parameter('match_number', '-1'))
|
||||
self._match_pattern = self.parameter('match_pattern', None)
|
||||
self._pattern = re.compile(r'^\s*{}:\s*([\d.]+)$'.format(self.parameter('match', 'temp1_input')), re.MULTILINE)
|
||||
self._json = util.format.asbool(self.parameter('json', False))
|
||||
self._freq = util.format.asbool(self.parameter('show_freq', True))
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd='xsensors')
|
||||
self._temperature = "unknown"
|
||||
self._mhz = "n/a"
|
||||
self._match_number = int(self.parameter("match_number", "-1"))
|
||||
self._match_pattern = self.parameter("match_pattern", None)
|
||||
self._pattern = re.compile(
|
||||
r"^\s*{}:\s*([\d.]+)$".format(self.parameter("match", "temp1_input")),
|
||||
re.MULTILINE,
|
||||
)
|
||||
self._json = util.format.asbool(self.parameter("json", False))
|
||||
self._freq = util.format.asbool(self.parameter("show_freq", True))
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd="xsensors")
|
||||
self.determine_method()
|
||||
|
||||
def determine_method(self):
|
||||
if self.parameter('path') != None and self._json == False:
|
||||
self.use_sensors = False # use thermal zone
|
||||
if self.parameter("path") != None and self._json == False:
|
||||
self.use_sensors = False # use thermal zone
|
||||
else:
|
||||
# try to use output of sensors -u
|
||||
try:
|
||||
output = util.cli.execute('sensors -u')
|
||||
output = util.cli.execute("sensors -u")
|
||||
self.use_sensors = True
|
||||
log.debug('Sensors command available')
|
||||
log.debug("Sensors command available")
|
||||
except FileNotFoundError as e:
|
||||
log.info('Sensors command not available, using /sys/class/thermal/thermal_zone*/')
|
||||
log.info(
|
||||
"Sensors command not available, using /sys/class/thermal/thermal_zone*/"
|
||||
)
|
||||
self.use_sensors = False
|
||||
|
||||
def _get_temp_from_sensors(self):
|
||||
if self._json == True:
|
||||
try:
|
||||
output = json.loads(util.cli.execute('sensors -j'))
|
||||
for key in self.parameter('path').split('/'):
|
||||
output = json.loads(util.cli.execute("sensors -j"))
|
||||
for key in self.parameter("path").split("/"):
|
||||
output = output[key]
|
||||
return int(float(output))
|
||||
except Exception as e:
|
||||
logging.error('unable to read sensors: {}'.format(str(e)))
|
||||
return 'unknown'
|
||||
logging.error("unable to read sensors: {}".format(str(e)))
|
||||
return "unknown"
|
||||
else:
|
||||
output = util.cli.execute('sensors -u')
|
||||
output = util.cli.execute("sensors -u")
|
||||
if self._match_pattern:
|
||||
temp_pattern = self.parameter('match', 'temp1_input')
|
||||
match = re.search(r'{}.+{}:\s*([\d.]+)$'.format(self._match_pattern, temp_pattern), output.replace('\n', ''))
|
||||
temp_pattern = self.parameter("match", "temp1_input")
|
||||
match = re.search(
|
||||
r"{}.+{}:\s*([\d.]+)$".format(self._match_pattern, temp_pattern),
|
||||
output.replace("\n", ""),
|
||||
)
|
||||
if match:
|
||||
return int(float(match.group(1)))
|
||||
else:
|
||||
return 'unknown'
|
||||
return "unknown"
|
||||
match = self._pattern.findall(output)
|
||||
if match:
|
||||
return int(float(match[self._match_number]))
|
||||
return 'unknown'
|
||||
return "unknown"
|
||||
|
||||
def get_temp(self):
|
||||
if self.use_sensors:
|
||||
temperature = self._get_temp_from_sensors()
|
||||
log.debug('Retrieve temperature from sensors -u')
|
||||
log.debug("Retrieve temperature from sensors -u")
|
||||
else:
|
||||
try:
|
||||
temperature = open(self.parameter('path', '/sys/class/thermal/thermal_zone0/temp')).read()[:2]
|
||||
log.debug('retrieved temperature from /sys/class/')
|
||||
temperature = open(
|
||||
self.parameter("path", "/sys/class/thermal/thermal_zone0/temp")
|
||||
).read()[:2]
|
||||
log.debug("retrieved temperature from /sys/class/")
|
||||
# TODO: Iterate through all thermal zones to determine the correct one and use its value
|
||||
# https://unix.stackexchange.com/questions/304845/discrepancy-between-number-of-cores-and-thermal-zones-in-sys-class-thermal
|
||||
|
||||
except IOError:
|
||||
temperature = 'unknown'
|
||||
log.info('Can not determine temperature, please install lm-sensors')
|
||||
temperature = "unknown"
|
||||
log.info("Can not determine temperature, please install lm-sensors")
|
||||
|
||||
return temperature
|
||||
|
||||
def get_mhz(self):
|
||||
mhz = None
|
||||
try:
|
||||
output = open('/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq').read()
|
||||
mhz = int(float(output)/1000.0)
|
||||
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)
|
||||
output = open("/proc/cpuinfo").read()
|
||||
m = re.search(r"cpu MHz\s+:\s+(\d+)", output)
|
||||
if m:
|
||||
mhz = int(m.group(1))
|
||||
else:
|
||||
m = re.search(r'BogoMIPS\s+:\s+(\d+)', output)
|
||||
m = re.search(r"BogoMIPS\s+:\s+(\d+)", output)
|
||||
if m:
|
||||
return '{} BogoMIPS'.format(int(m.group(1)))
|
||||
return "{} BogoMIPS".format(int(m.group(1)))
|
||||
if not mhz:
|
||||
return 'n/a'
|
||||
return "n/a"
|
||||
|
||||
if mhz < 1000:
|
||||
return '{} MHz'.format(mhz)
|
||||
return "{} MHz".format(mhz)
|
||||
else:
|
||||
return '{:0.01f} GHz'.format(float(mhz)/1000.0)
|
||||
return "{:0.01f} GHz".format(float(mhz) / 1000.0)
|
||||
|
||||
def temperature(self, _):
|
||||
if self._freq:
|
||||
return u'{}°c @ {}'.format(self._temperature, self._mhz)
|
||||
return "{}°c @ {}".format(self._temperature, self._mhz)
|
||||
else:
|
||||
return u'{}°c'.format(self._temperature)
|
||||
return "{}°c".format(self._temperature)
|
||||
|
||||
def update(self):
|
||||
self._temperature = self.get_temp()
|
||||
if self._freq:
|
||||
self._mhz = self.get_mhz()
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -33,15 +33,16 @@ import core.input
|
|||
import util.format
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.get_output))
|
||||
|
||||
self.__command = self.parameter('command', 'echo "no command configured"')
|
||||
self.__async = util.format.asbool(self.parameter('async'))
|
||||
self.__command = self.parameter("command", 'echo "no command configured"')
|
||||
self.__async = util.format.asbool(self.parameter("async"))
|
||||
|
||||
if self.__async:
|
||||
self.__output = 'please wait...'
|
||||
self.__output = "please wait..."
|
||||
self.__current_thread = threading.Thread()
|
||||
|
||||
# LMB and RMB will update output regardless of timer
|
||||
|
@ -66,13 +67,16 @@ class Module(core.module.Module):
|
|||
|
||||
# spawn new thread to execute command and pass callback method to get output from it
|
||||
self.__current_thread = threading.Thread(
|
||||
target=lambda obj, cmd: obj.set_output(util.cli.execute(cmd, ignore_errors=True)),
|
||||
args=(self, self.__command)
|
||||
target=lambda obj, cmd: obj.set_output(
|
||||
util.cli.execute(cmd, ignore_errors=True)
|
||||
),
|
||||
args=(self, self.__command),
|
||||
)
|
||||
self.__current_thread.start()
|
||||
|
||||
def state(self, _):
|
||||
if self.__output == 'no command configured':
|
||||
return 'warning'
|
||||
if self.__output == "no command configured":
|
||||
return "warning"
|
||||
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -19,22 +19,23 @@ Parameters:
|
|||
|
||||
import logging
|
||||
|
||||
LINK = 'https://github.com/tobi-wan-kenobi/bumblebee-status/wiki'
|
||||
LABEL = 'Click me'
|
||||
LINK = "https://github.com/tobi-wan-kenobi/bumblebee-status/wiki"
|
||||
LABEL = "Click me"
|
||||
|
||||
import core.module
|
||||
import core.widget
|
||||
import core.input
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
self.__labels = self.parameter('labels', '{}'.format(LABEL))
|
||||
self.__cmds = self.parameter('cmds', 'firefox {}'.format(LINK))
|
||||
self.__delim = self.parameter('delim', ';')
|
||||
self.__labels = self.parameter("labels", "{}".format(LABEL))
|
||||
self.__cmds = self.parameter("cmds", "firefox {}".format(LINK))
|
||||
self.__delim = self.parameter("delim", ";")
|
||||
|
||||
self.update_widgets()
|
||||
|
||||
|
@ -51,9 +52,11 @@ class Module(core.module.Module):
|
|||
|
||||
# report possible problem as a warning
|
||||
if len(cmds) is not len(labels):
|
||||
logging.warning('shortcut: the number of commands does not match '\
|
||||
'the number of provided labels.')
|
||||
logging.warning('cmds : %s, labels : %s', cmds, labels)
|
||||
logging.warning(
|
||||
"shortcut: the number of commands does not match "
|
||||
"the number of provided labels."
|
||||
)
|
||||
logging.warning("cmds : %s, labels : %s", cmds, labels)
|
||||
|
||||
for idx in range(0, num_shortcuts):
|
||||
cmd = cmds[idx]
|
||||
|
@ -64,4 +67,5 @@ class Module(core.module.Module):
|
|||
|
||||
widgets.append(widget)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -20,99 +20,107 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=5)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
self.devices = self.list_devices()
|
||||
self.display = self.parameter('display', 'combined')
|
||||
self.drives = self.parameter('drives', 'sda')
|
||||
self.display = self.parameter("display", "combined")
|
||||
self.drives = self.parameter("drives", "sda")
|
||||
self.widgets(self.create_widgets())
|
||||
|
||||
def create_widgets(self):
|
||||
widgets = []
|
||||
if self.display == 'combined':
|
||||
if self.display == "combined":
|
||||
widget = core.widget.Widget(module=self)
|
||||
widget.set('device', 'combined')
|
||||
widget.set('assessment', self.combined())
|
||||
widget.set("device", "combined")
|
||||
widget.set("assessment", self.combined())
|
||||
self.output(widget)
|
||||
widgets.append(widget)
|
||||
else:
|
||||
for device in self.devices:
|
||||
if self.display == 'singles' and device not in self.drives:
|
||||
if self.display == "singles" and device not in self.drives:
|
||||
continue
|
||||
widget = core.widget.Widget(module=self)
|
||||
widget.set('device', device)
|
||||
widget.set('assessment', self.smart(device))
|
||||
widget.set("device", device)
|
||||
widget.set("assessment", self.smart(device))
|
||||
self.output(widget)
|
||||
widgets.append(widget)
|
||||
return widgets
|
||||
|
||||
def update(self):
|
||||
for widget in self.widgets():
|
||||
device = widget.get('device')
|
||||
if device == 'combined':
|
||||
widget.set('assessment', self.combined())
|
||||
device = widget.get("device")
|
||||
if device == "combined":
|
||||
widget.set("assessment", self.combined())
|
||||
self.output(widget)
|
||||
else:
|
||||
widget.set('assessment', self.smart(device))
|
||||
widget.set("assessment", self.smart(device))
|
||||
self.output(widget)
|
||||
|
||||
def output(self, widget):
|
||||
device = widget.get('device')
|
||||
assessment = widget.get('assessment')
|
||||
widget.full_text('{}: {}'.format(device, assessment))
|
||||
device = widget.get("device")
|
||||
assessment = widget.get("assessment")
|
||||
widget.full_text("{}: {}".format(device, assessment))
|
||||
|
||||
def state(self, widget):
|
||||
states = []
|
||||
assessment = widget.get('assessment')
|
||||
if assessment == 'Pre-fail':
|
||||
states.append('warning')
|
||||
if assessment == 'Fail':
|
||||
states.append('critical')
|
||||
assessment = widget.get("assessment")
|
||||
if assessment == "Pre-fail":
|
||||
states.append("warning")
|
||||
if assessment == "Fail":
|
||||
states.append("critical")
|
||||
return states
|
||||
|
||||
def combined(self):
|
||||
for device in self.devices:
|
||||
result = self.smart(device)
|
||||
if result == 'Fail':
|
||||
return 'Fail'
|
||||
if result == 'Pre-fail':
|
||||
return 'Pre-fail'
|
||||
return 'OK'
|
||||
if result == "Fail":
|
||||
return "Fail"
|
||||
if result == "Pre-fail":
|
||||
return "Pre-fail"
|
||||
return "OK"
|
||||
|
||||
def list_devices(self):
|
||||
for (root, folders, files) in os.walk('/dev'):
|
||||
if root == '/dev':
|
||||
devices = {''.join(filter(lambda i: i.isdigit() == False, file)) for file in files if 'sd' in file}
|
||||
nvme = {file for file in files if('nvme0n' in file and 'p' not in file)}
|
||||
for (root, folders, files) in os.walk("/dev"):
|
||||
if root == "/dev":
|
||||
devices = {
|
||||
"".join(filter(lambda i: i.isdigit() == False, file))
|
||||
for file in files
|
||||
if "sd" in file
|
||||
}
|
||||
nvme = {
|
||||
file for file in files if ("nvme0n" in file and "p" not in file)
|
||||
}
|
||||
devices.update(nvme)
|
||||
return devices
|
||||
|
||||
def smart(self, disk_name):
|
||||
smartctl = shutil.which('smartctl')
|
||||
smartctl = shutil.which("smartctl")
|
||||
assessment = None
|
||||
|
||||
output = util.cli.execute('sudo {} --health {}'.format(
|
||||
smartctl, os.path.join('/dev/', disk_name)
|
||||
))
|
||||
output = output.split('\n')
|
||||
output = util.cli.execute(
|
||||
"sudo {} --health {}".format(smartctl, os.path.join("/dev/", disk_name))
|
||||
)
|
||||
output = output.split("\n")
|
||||
line = output[4]
|
||||
if 'SMART' in line:
|
||||
if any([i in line for i in ['PASSED', 'OK']]):
|
||||
assessment = 'OK'
|
||||
if "SMART" in line:
|
||||
if any([i in line for i in ["PASSED", "OK"]]):
|
||||
assessment = "OK"
|
||||
else:
|
||||
assessment = 'Fail'
|
||||
assessment = "Fail"
|
||||
|
||||
if assessment == 'OK':
|
||||
output = util.cli.execute('sudo {} -A {}'.format(
|
||||
smartctl, os.path.join('/dev/', disk_name)
|
||||
))
|
||||
output = output.split('\n')
|
||||
if assessment == "OK":
|
||||
output = util.cli.execute(
|
||||
"sudo {} -A {}".format(smartctl, os.path.join("/dev/", disk_name))
|
||||
)
|
||||
output = output.split("\n")
|
||||
for line in output:
|
||||
if 'Pre-fail' in line:
|
||||
assessment = 'Pre-fail'
|
||||
if "Pre-fail" in line:
|
||||
assessment = "Pre-fail"
|
||||
return assessment
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -36,6 +36,7 @@ import core.widget
|
|||
import core.input
|
||||
import core.decorators
|
||||
|
||||
|
||||
def formatStringBuilder(s, json):
|
||||
"""
|
||||
Parses Format Strings
|
||||
|
@ -43,14 +44,14 @@ def formatStringBuilder(s, json):
|
|||
s -> format string
|
||||
json -> the spaceapi response object
|
||||
"""
|
||||
identifiers = re.findall('%%.*?%%', s)
|
||||
identifiers = re.findall("%%.*?%%", s)
|
||||
for i in identifiers:
|
||||
ic = i[2:-2] # Discard %%
|
||||
j = ic.split('%')
|
||||
j = ic.split("%")
|
||||
|
||||
# Only neither of, or both true AND false may be overwritten
|
||||
if len(j) != 3 and len(j) != 1:
|
||||
return 'INVALID FORMAT STRING'
|
||||
return "INVALID FORMAT STRING"
|
||||
|
||||
if len(j) == 1: # no overwrite
|
||||
s = s.replace(i, json[j[0]])
|
||||
|
@ -66,30 +67,28 @@ class Module(core.module.Module):
|
|||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.getState))
|
||||
|
||||
core.input.register(
|
||||
self, button=core.input.LEFT_MOUSE, cmd=self.__forceReload
|
||||
)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__forceReload)
|
||||
|
||||
self.__data = {}
|
||||
self.__error = None
|
||||
self.__thread = None
|
||||
|
||||
# The URL representing the api endpoint
|
||||
self.__url = self.parameter('url', default='http://club.entropia.de/spaceapi')
|
||||
self.__url = self.parameter("url", default="http://club.entropia.de/spaceapi")
|
||||
self._format = self.parameter(
|
||||
'format', default=u' %%space%%: %%state.open%Open%Closed%%'
|
||||
"format", default=" %%space%%: %%state.open%Open%Closed%%"
|
||||
)
|
||||
|
||||
def state(self, widget):
|
||||
try:
|
||||
if self.__error is not None:
|
||||
return ['critical']
|
||||
elif self.__data['state.open']:
|
||||
return ['warning']
|
||||
return ["critical"]
|
||||
elif self.__data["state.open"]:
|
||||
return ["warning"]
|
||||
else:
|
||||
return []
|
||||
except KeyError:
|
||||
return ['critical']
|
||||
return ["critical"]
|
||||
|
||||
def update(self):
|
||||
if not self.__thread or self.__thread.is_alive() == False:
|
||||
|
@ -104,7 +103,7 @@ class Module(core.module.Module):
|
|||
try:
|
||||
text = formatStringBuilder(self._format, self.__data)
|
||||
except KeyError:
|
||||
text = 'KeyError'
|
||||
text = "KeyError"
|
||||
return text
|
||||
|
||||
def get_api_async(self):
|
||||
|
@ -115,19 +114,19 @@ class Module(core.module.Module):
|
|||
self.__data = self.__flatten(json.loads(request.text))
|
||||
self.__error = None
|
||||
except requests.exceptions.Timeout:
|
||||
self.__error = 'Timeout'
|
||||
self.__error = "Timeout"
|
||||
except requests.exceptions.HTTPError:
|
||||
self.__error = 'HTTP Error'
|
||||
self.__error = "HTTP Error"
|
||||
except ValueError:
|
||||
self.__error = 'Not a JSON response'
|
||||
core.event.trigger('update', [ self.id ], redraw_only=True)
|
||||
self.__error = "Not a JSON response"
|
||||
core.event.trigger("update", [self.id], redraw_only=True)
|
||||
|
||||
# left_mouse_button handler
|
||||
def __forceReload(self, event):
|
||||
if self.__thread:
|
||||
self.__thread.raise_exception()
|
||||
self.__error = 'RELOADING'
|
||||
core.event.trigger('update', [ self.id ], redraw_only=True)
|
||||
self.__error = "RELOADING"
|
||||
core.event.trigger("update", [self.id], redraw_only=True)
|
||||
|
||||
# Flattens the JSON structure recursively, e.g. ['space']['open']
|
||||
# becomes ['space.open']
|
||||
|
@ -138,7 +137,7 @@ class Module(core.module.Module):
|
|||
if type(value) is dict:
|
||||
flattened_key = self.__flatten(value)
|
||||
for fk in flattened_key:
|
||||
out[key + '.' + fk] = flattened_key[fk]
|
||||
out[key + "." + fk] = flattened_key[fk]
|
||||
else:
|
||||
out[key] = value
|
||||
return out
|
||||
|
|
|
@ -21,59 +21,69 @@ import core.widget
|
|||
import core.input
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.spotify))
|
||||
|
||||
buttons = {'LEFT_CLICK':core.input.LEFT_MOUSE,
|
||||
'RIGHT_CLICK':core.input.RIGHT_MOUSE,
|
||||
'MIDDLE_CLICK':core.input.MIDDLE_MOUSE,
|
||||
'SCROLL_UP':core.input.WHEEL_UP,
|
||||
'SCROLL_DOWN':core.input.WHEEL_DOWN,
|
||||
}
|
||||
|
||||
self.__song = ''
|
||||
self.__format = self.parameter('format', '{artist} - {title}')
|
||||
prev_button = self.parameter('previous', 'LEFT_CLICK')
|
||||
next_button = self.parameter('next', 'RIGHT_CLICK')
|
||||
pause_button = self.parameter('pause', 'MIDDLE_CLICK')
|
||||
buttons = {
|
||||
"LEFT_CLICK": core.input.LEFT_MOUSE,
|
||||
"RIGHT_CLICK": core.input.RIGHT_MOUSE,
|
||||
"MIDDLE_CLICK": core.input.MIDDLE_MOUSE,
|
||||
"SCROLL_UP": core.input.WHEEL_UP,
|
||||
"SCROLL_DOWN": core.input.WHEEL_DOWN,
|
||||
}
|
||||
|
||||
cmd = 'dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.spotify \
|
||||
/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.'
|
||||
core.input.register(self, button=buttons[prev_button],
|
||||
cmd=cmd + 'Previous')
|
||||
core.input.register(self, button=buttons[next_button],
|
||||
cmd=cmd + 'Next')
|
||||
core.input.register(self, button=buttons[pause_button],
|
||||
cmd=cmd + 'PlayPause')
|
||||
self.__song = ""
|
||||
self.__format = self.parameter("format", "{artist} - {title}")
|
||||
prev_button = self.parameter("previous", "LEFT_CLICK")
|
||||
next_button = self.parameter("next", "RIGHT_CLICK")
|
||||
pause_button = self.parameter("pause", "MIDDLE_CLICK")
|
||||
|
||||
cmd = "dbus-send --session --type=method_call --dest=org.mpris.MediaPlayer2.spotify \
|
||||
/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player."
|
||||
core.input.register(self, button=buttons[prev_button], cmd=cmd + "Previous")
|
||||
core.input.register(self, button=buttons[next_button], cmd=cmd + "Next")
|
||||
core.input.register(self, button=buttons[pause_button], cmd=cmd + "PlayPause")
|
||||
|
||||
@core.decorators.scrollable
|
||||
def spotify(self, widget):
|
||||
return self.string_song
|
||||
|
||||
def hidden(self):
|
||||
return self.string_song == ''
|
||||
return self.string_song == ""
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
bus = dbus.SessionBus()
|
||||
spotify = bus.get_object('org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2')
|
||||
spotify_iface = dbus.Interface(spotify, 'org.freedesktop.DBus.Properties')
|
||||
props = spotify_iface.Get('org.mpris.MediaPlayer2.Player', 'Metadata')
|
||||
playback_status = str(spotify_iface.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus'))
|
||||
self.__song = self.__format.format(album=str(props.get('xesam:album')),
|
||||
title=str(props.get('xesam:title')),
|
||||
artist=','.join(props.get('xesam:artist')),
|
||||
trackNumber=str(props.get('xesam:trackNumber')),
|
||||
playbackStatus=u'\u25B6' if playback_status=='Playing' else u'\u258D\u258D' if playback_status=='Paused' else '',)
|
||||
|
||||
spotify = bus.get_object(
|
||||
"org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2"
|
||||
)
|
||||
spotify_iface = dbus.Interface(spotify, "org.freedesktop.DBus.Properties")
|
||||
props = spotify_iface.Get("org.mpris.MediaPlayer2.Player", "Metadata")
|
||||
playback_status = str(
|
||||
spotify_iface.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus")
|
||||
)
|
||||
self.__song = self.__format.format(
|
||||
album=str(props.get("xesam:album")),
|
||||
title=str(props.get("xesam:title")),
|
||||
artist=",".join(props.get("xesam:artist")),
|
||||
trackNumber=str(props.get("xesam:trackNumber")),
|
||||
playbackStatus="\u25B6"
|
||||
if playback_status == "Playing"
|
||||
else "\u258D\u258D"
|
||||
if playback_status == "Paused"
|
||||
else "",
|
||||
)
|
||||
|
||||
except Exception:
|
||||
self.__song = ''
|
||||
self.__song = ""
|
||||
|
||||
@property
|
||||
def string_song(self):
|
||||
if sys.version_info.major < 3:
|
||||
return unicode(self.__song)
|
||||
return str(self.__song)
|
||||
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -22,39 +22,44 @@ import core.decorators
|
|||
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(hours=1)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.value))
|
||||
|
||||
self.__symbols = self.parameter('symbols', '')
|
||||
self.__change = util.format.asbool(self.parameter('change', True))
|
||||
self.__symbols = self.parameter("symbols", "")
|
||||
self.__change = util.format.asbool(self.parameter("change", True))
|
||||
self.__value = None
|
||||
|
||||
def value(self, widget):
|
||||
results = []
|
||||
if not self.__value:
|
||||
return 'n/a'
|
||||
return "n/a"
|
||||
data = json.loads(self.__value)
|
||||
|
||||
for symbol in data['quoteResponse']['result']:
|
||||
valkey = 'regularMarketChange' if self.__change else 'regularMarketPrice'
|
||||
sym = symbol.get('symbol', 'n/a')
|
||||
currency = symbol.get('currency', 'USD')
|
||||
val = 'n/a' if not valkey in symbol else '{:.2f}'.format(symbol[valkey])
|
||||
results.append('{} {} {}'.format(sym, val, currency))
|
||||
return u' '.join(results)
|
||||
for symbol in data["quoteResponse"]["result"]:
|
||||
valkey = "regularMarketChange" if self.__change else "regularMarketPrice"
|
||||
sym = symbol.get("symbol", "n/a")
|
||||
currency = symbol.get("currency", "USD")
|
||||
val = "n/a" if not valkey in symbol else "{:.2f}".format(symbol[valkey])
|
||||
results.append("{} {} {}".format(sym, val, currency))
|
||||
return " ".join(results)
|
||||
|
||||
def fetch(self):
|
||||
if self.__symbols:
|
||||
url = 'https://query1.finance.yahoo.com/v7/finance/quote?symbols='
|
||||
url += self.__symbols + '&fields=regularMarketPrice,currency,regularMarketChange'
|
||||
url = "https://query1.finance.yahoo.com/v7/finance/quote?symbols="
|
||||
url += (
|
||||
self.__symbols
|
||||
+ "&fields=regularMarketPrice,currency,regularMarketChange"
|
||||
)
|
||||
return urllib.request.urlopen(url).read().strip()
|
||||
else:
|
||||
logging.error('unable to retrieve stock exchange rate')
|
||||
logging.error("unable to retrieve stock exchange rate")
|
||||
return None
|
||||
|
||||
def update(self):
|
||||
self.__value = self.fetch()
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -23,13 +23,14 @@ import core.decorators
|
|||
|
||||
import util.location
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(hours=1)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.suntimes))
|
||||
|
||||
lat = self.parameter('lat', None)
|
||||
lon = self.parameter('lon', None)
|
||||
lat = self.parameter("lat", None)
|
||||
lon = self.parameter("lon", None)
|
||||
self.__sun = None
|
||||
|
||||
if not lat or not lon:
|
||||
|
@ -40,12 +41,13 @@ class Module(core.module.Module):
|
|||
def suntimes(self, _):
|
||||
if self.__sunset and self.__sunrise:
|
||||
if self.__isup:
|
||||
return u'\u21A7{} \u21A5{}'.format(
|
||||
self.__sunset.strftime('%H:%M'),
|
||||
self.__sunrise.strftime('%H:%M'))
|
||||
return u'\u21A5{} \u21A7{}'.format(self.__sunrise.strftime('%H:%M'),
|
||||
self.__sunset.strftime('%H:%M'))
|
||||
return 'n/a'
|
||||
return "\u21A7{} \u21A5{}".format(
|
||||
self.__sunset.strftime("%H:%M"), self.__sunrise.strftime("%H:%M")
|
||||
)
|
||||
return "\u21A5{} \u21A7{}".format(
|
||||
self.__sunrise.strftime("%H:%M"), self.__sunset.strftime("%H:%M")
|
||||
)
|
||||
return "n/a"
|
||||
|
||||
def __calculate_times(self):
|
||||
self.__isup = False
|
||||
|
@ -55,13 +57,13 @@ class Module(core.module.Module):
|
|||
try:
|
||||
self.__sunrise = self.__sun.get_local_sunrise_time()
|
||||
except SunTimeException:
|
||||
self.__sunrise = 'no sunrise'
|
||||
self.__sunrise = "no sunrise"
|
||||
order_matters = False
|
||||
|
||||
try:
|
||||
self.__sunset = self.__sun.get_local_sunset_time()
|
||||
except SunTimeException:
|
||||
self.__sunset = 'no sunset'
|
||||
self.__sunset = "no sunset"
|
||||
order_matters = False
|
||||
|
||||
if not order_matters:
|
||||
|
@ -74,19 +76,20 @@ class Module(core.module.Module):
|
|||
self.__sunrise = self.__sun.get_local_sunrise_time(tomorrow)
|
||||
self.__sunset = self.__sun.get_local_sunset_time(tomorrow)
|
||||
except SunTimeException:
|
||||
self.__sunrise = 'no sunrise'
|
||||
self.__sunset = 'no sunset'
|
||||
self.__sunrise = "no sunrise"
|
||||
self.__sunset = "no sunset"
|
||||
|
||||
elif now > self.__sunrise:
|
||||
tomorrow = (now + datetime.timedelta(days=1)).date()
|
||||
try:
|
||||
self.__sunrise = self.__sun.get_local_sunrise_time(tomorrow)
|
||||
except SunTimeException:
|
||||
self.__sunrise = 'no sunrise'
|
||||
self.__sunrise = "no sunrise"
|
||||
return
|
||||
self.__isup = True
|
||||
|
||||
def update(self):
|
||||
self.__calculate_times()
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=C0111,R0903
|
||||
|
||||
""" system module
|
||||
|
@ -28,7 +28,7 @@ try:
|
|||
import tkinter as tk
|
||||
from tkinter import messagebox as tkmessagebox
|
||||
except ImportError:
|
||||
logging.warning('failed to import tkinter - bumblebee popups won\'t work!')
|
||||
logging.warning("failed to import tkinter - bumblebee popups won't work!")
|
||||
|
||||
import core.module
|
||||
import core.widget
|
||||
|
@ -39,18 +39,18 @@ import util.cli
|
|||
import util.popup
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.text))
|
||||
|
||||
self.__confirm = util.format.asbool(self.parameter('confirm', True))
|
||||
self.__confirm = util.format.asbool(self.parameter("confirm", True))
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.popup)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.popup)
|
||||
|
||||
def text(self, widget):
|
||||
return ''
|
||||
return ""
|
||||
|
||||
def __on_command(self, header, text, command):
|
||||
do_it = True
|
||||
|
@ -58,33 +58,56 @@ class Module(core.module.Module):
|
|||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
root.focus_set()
|
||||
|
||||
|
||||
do_it = tkmessagebox.askyesno(header, text)
|
||||
root.destroy()
|
||||
|
||||
if do_it:
|
||||
util.cli.execute(command)
|
||||
|
||||
if do_it:
|
||||
util.cli.execute(command)
|
||||
|
||||
def popup(self, widget):
|
||||
menu = util.popup.menu()
|
||||
reboot_cmd = self.parameter('reboot', 'reboot')
|
||||
shutdown_cmd = self.parameter('shutdown', 'shutdown -h now')
|
||||
logout_cmd = self.parameter('logout', 'i3exit logout')
|
||||
switch_user_cmd = self.parameter('switch_user', 'i3exit switch_user')
|
||||
lock_cmd = self.parameter('lock', 'i3exit lock')
|
||||
suspend_cmd = self.parameter('suspend', 'i3exit suspend')
|
||||
hibernate_cmd = self.parameter('hibernate', 'i3exit hibernate')
|
||||
reboot_cmd = self.parameter("reboot", "reboot")
|
||||
shutdown_cmd = self.parameter("shutdown", "shutdown -h now")
|
||||
logout_cmd = self.parameter("logout", "i3exit logout")
|
||||
switch_user_cmd = self.parameter("switch_user", "i3exit switch_user")
|
||||
lock_cmd = self.parameter("lock", "i3exit lock")
|
||||
suspend_cmd = self.parameter("suspend", "i3exit suspend")
|
||||
hibernate_cmd = self.parameter("hibernate", "i3exit hibernate")
|
||||
|
||||
menu.add_menuitem('shutdown', callback=functools.partial(self.__on_command, 'Shutdown', 'Shutdown?', shutdown_cmd))
|
||||
menu.add_menuitem('reboot', callback=functools.partial(self.__on_command, 'Reboot', 'Reboot?', reboot_cmd))
|
||||
menu.add_menuitem('log out', callback=functools.partial(self.__on_command, 'Log out', 'Log out?', 'i3exit logout'))
|
||||
menu.add_menuitem(
|
||||
"shutdown",
|
||||
callback=functools.partial(
|
||||
self.__on_command, "Shutdown", "Shutdown?", shutdown_cmd
|
||||
),
|
||||
)
|
||||
menu.add_menuitem(
|
||||
"reboot",
|
||||
callback=functools.partial(
|
||||
self.__on_command, "Reboot", "Reboot?", reboot_cmd
|
||||
),
|
||||
)
|
||||
menu.add_menuitem(
|
||||
"log out",
|
||||
callback=functools.partial(
|
||||
self.__on_command, "Log out", "Log out?", "i3exit logout"
|
||||
),
|
||||
)
|
||||
# don't ask for these
|
||||
menu.add_menuitem('switch user', callback=functools.partial(util.cli.execute, switch_user_cmd))
|
||||
menu.add_menuitem('lock', callback=functools.partial(util.cli.execute, lock_cmd))
|
||||
menu.add_menuitem('suspend', callback=functools.partial(util.cli.execute, suspend_cmd))
|
||||
menu.add_menuitem('hibernate', callback=functools.partial(util.cli.execute, hibernate_cmd))
|
||||
menu.add_menuitem(
|
||||
"switch user", callback=functools.partial(util.cli.execute, switch_user_cmd)
|
||||
)
|
||||
menu.add_menuitem(
|
||||
"lock", callback=functools.partial(util.cli.execute, lock_cmd)
|
||||
)
|
||||
menu.add_menuitem(
|
||||
"suspend", callback=functools.partial(util.cli.execute, suspend_cmd)
|
||||
)
|
||||
menu.add_menuitem(
|
||||
"hibernate", callback=functools.partial(util.cli.execute, hibernate_cmd)
|
||||
)
|
||||
|
||||
menu.show(widget, 0, 0)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -13,24 +13,26 @@ import core.module
|
|||
import core.widget
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
|
||||
self.__pending_tasks = '0'
|
||||
self.__pending_tasks = "0"
|
||||
|
||||
def update(self):
|
||||
"""Return a string with the number of pending tasks from TaskWarrior."""
|
||||
try:
|
||||
taskrc = self.parameter('taskrc', '~/.taskrc')
|
||||
taskrc = self.parameter("taskrc", "~/.taskrc")
|
||||
w = TaskWarrior(config_filename=taskrc)
|
||||
pending_tasks = w.filter_tasks({'status': 'pending'})
|
||||
pending_tasks = w.filter_tasks({"status": "pending"})
|
||||
self.__pending_tasks = str(len(pending_tasks))
|
||||
except:
|
||||
self.__pending_tasks = 'n/a'
|
||||
self.__pending_tasks = "n/a"
|
||||
|
||||
def output(self, _):
|
||||
"""Format the task counter to output in bumblebee."""
|
||||
return '{}'.format(self.__pending_tasks)
|
||||
return "{}".format(self.__pending_tasks)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -10,12 +10,14 @@ Parameters:
|
|||
import core.decorators
|
||||
from .datetimetz import Module
|
||||
|
||||
|
||||
class Module(Module):
|
||||
@core.decorators.every(seconds=59) # ensures one update per minute
|
||||
@core.decorators.every(seconds=59) # ensures one update per minute
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme)
|
||||
|
||||
def default_format(self):
|
||||
return '%X %Z'
|
||||
return "%X %Z"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -18,7 +18,7 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
no_title = 'n/a'
|
||||
no_title = "n/a"
|
||||
|
||||
import core.module
|
||||
import core.widget
|
||||
|
@ -26,24 +26,32 @@ import core.decorators
|
|||
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
# parsing of parameters
|
||||
self.__scroll = util.format.asbool(self.parameter('scroll', False))
|
||||
self.__max = int(self.parameter('max', 64))
|
||||
self.__placeholder = self.parameter('placeholder', '...')
|
||||
self.__title = ''
|
||||
self.__scroll = util.format.asbool(self.parameter("scroll", False))
|
||||
self.__max = int(self.parameter("max", 64))
|
||||
self.__placeholder = self.parameter("placeholder", "...")
|
||||
self.__title = ""
|
||||
|
||||
# set output of the module
|
||||
self.widgets([core.widget.Widget(full_text=
|
||||
self.__scrolling_focused_title if self.__scroll else self.__focused_title)])
|
||||
self.widgets(
|
||||
[
|
||||
core.widget.Widget(
|
||||
full_text=self.__scrolling_focused_title
|
||||
if self.__scroll
|
||||
else self.__focused_title
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# create a connection with i3ipc
|
||||
self.__i3 = i3ipc.Connection()
|
||||
# event is called both on focus change and title change
|
||||
self.__i3.on('window', lambda __p_i3, __p_e: self.__pollTitle())
|
||||
self.__i3.on("window", lambda __p_i3, __p_e: self.__pollTitle())
|
||||
# begin listening for events
|
||||
threading.Thread(target=self.__i3.main).start()
|
||||
|
||||
|
@ -69,9 +77,12 @@ class Module(core.module.Module):
|
|||
if not self.__scroll:
|
||||
# cut the text if it is too long
|
||||
if len(self.__full_title) > self.__max:
|
||||
self.__title = self.__full_title[0:self.__max - len(self.__placeholder)]
|
||||
self.__title = '{}{}'.format(self.__title, self.__placeholder)
|
||||
self.__title = self.__full_title[
|
||||
0 : self.__max - len(self.__placeholder)
|
||||
]
|
||||
self.__title = "{}{}".format(self.__title, self.__placeholder)
|
||||
else:
|
||||
self.__title = self.__full_title
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -12,24 +12,27 @@ import core.module
|
|||
import core.widget
|
||||
import core.input
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
|
||||
self.__doc = os.path.expanduser(self.parameter('file', '~/Documents/todo.txt'))
|
||||
self.__doc = os.path.expanduser(self.parameter("file", "~/Documents/todo.txt"))
|
||||
self.__todos = self.count_items()
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd='xdg-open {}'.format(self.__doc))
|
||||
core.input.register(
|
||||
self, button=core.input.LEFT_MOUSE, cmd="xdg-open {}".format(self.__doc)
|
||||
)
|
||||
|
||||
def output(self, widget):
|
||||
return str(self.__todos)
|
||||
return str(self.__todos)
|
||||
|
||||
def update(self):
|
||||
self.__todos = self.count_items()
|
||||
self.__todos = self.count_items()
|
||||
|
||||
def state(self, widgets):
|
||||
if self.__todos == 0:
|
||||
return 'empty'
|
||||
return 'items'
|
||||
return "empty"
|
||||
return "items"
|
||||
|
||||
def count_items(self):
|
||||
try:
|
||||
|
@ -37,8 +40,9 @@ class Module(core.module.Module):
|
|||
with open(self.__doc) as f:
|
||||
for i, l in enumerate(f):
|
||||
pass
|
||||
return i+1
|
||||
return i + 1
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -24,37 +24,47 @@ import core.widget
|
|||
import util.format
|
||||
import util.graph
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
widgets = []
|
||||
super().__init__(config, theme, widgets)
|
||||
|
||||
self._exclude = tuple(filter(len, util.format.aslist(self.parameter('exclude', 'lo,virbr,docker,vboxnet,veth'))))
|
||||
self._status = ''
|
||||
self._exclude = tuple(
|
||||
filter(
|
||||
len,
|
||||
util.format.aslist(
|
||||
self.parameter("exclude", "lo,virbr,docker,vboxnet,veth")
|
||||
),
|
||||
)
|
||||
)
|
||||
self._status = ""
|
||||
|
||||
self._showname = util.format.asbool(self.parameter('showname', True))
|
||||
self._format = self.parameter('format', '{:.2f}')
|
||||
self._showname = util.format.asbool(self.parameter("showname", True))
|
||||
self._format = self.parameter("format", "{:.2f}")
|
||||
self._prev = {}
|
||||
self._states = {}
|
||||
self._lastcheck = 0
|
||||
self._states['include'] = []
|
||||
self._states['exclude'] = []
|
||||
for state in tuple(filter(len, util.format.aslist(self.parameter('states', '')))):
|
||||
if state[0] == '^':
|
||||
self._states['exclude'].append(state[1:])
|
||||
self._states["include"] = []
|
||||
self._states["exclude"] = []
|
||||
for state in tuple(
|
||||
filter(len, util.format.aslist(self.parameter("states", "")))
|
||||
):
|
||||
if state[0] == "^":
|
||||
self._states["exclude"].append(state[1:])
|
||||
else:
|
||||
self._states['include'].append(state)
|
||||
self._graphlen = int(self.parameter('graphlen', 0))
|
||||
self._states["include"].append(state)
|
||||
self._graphlen = int(self.parameter("graphlen", 0))
|
||||
if self._graphlen > 0:
|
||||
self._graphdata = {}
|
||||
self._first_run = True
|
||||
self._update_widgets(widgets)
|
||||
|
||||
def state(self, widget):
|
||||
if 'traffic.rx' in widget.name:
|
||||
return 'rx'
|
||||
if 'traffic.tx' in widget.name:
|
||||
return 'tx'
|
||||
if "traffic.rx" in widget.name:
|
||||
return "rx"
|
||||
if "traffic.tx" in widget.name:
|
||||
return "tx"
|
||||
return self._status
|
||||
|
||||
def update(self):
|
||||
|
@ -74,8 +84,8 @@ class Module(core.module.Module):
|
|||
retval = []
|
||||
try:
|
||||
for ip in netifaces.ifaddresses(intf).get(netifaces.AF_INET, []):
|
||||
if ip.get('addr', '') != '':
|
||||
retval.append(ip.get('addr'))
|
||||
if ip.get("addr", "") != "":
|
||||
retval.append(ip.get("addr"))
|
||||
except Exception:
|
||||
return []
|
||||
return retval
|
||||
|
@ -85,66 +95,80 @@ class Module(core.module.Module):
|
|||
computes theme.minwidth string
|
||||
based on traffic.format and traffic.graphlen parameters
|
||||
"""
|
||||
minwidth_str = ''
|
||||
minwidth_str = ""
|
||||
if self._graphlen > 0:
|
||||
graph_len = int(self._graphlen / 2)
|
||||
graph_prefix = '0' * graph_len
|
||||
graph_prefix = "0" * graph_len
|
||||
minwidth_str += graph_prefix
|
||||
minwidth_str += '1000'
|
||||
minwidth_str += "1000"
|
||||
try:
|
||||
length = int(re.match('{:\.(\d+)f}', self._format).group(1))
|
||||
length = int(re.match("{:\.(\d+)f}", self._format).group(1))
|
||||
if length > 0:
|
||||
minwidth_str += '.' + '0' * length
|
||||
minwidth_str += "." + "0" * length
|
||||
except AttributeError:
|
||||
# return default value
|
||||
return '1000.00KiB/s'
|
||||
return "1000.00KiB/s"
|
||||
finally:
|
||||
minwidth_str += 'KiB/s'
|
||||
minwidth_str += "KiB/s"
|
||||
return minwidth_str
|
||||
|
||||
def _update_widgets(self, widgets):
|
||||
interfaces = [i for i in netifaces.interfaces() if not i.startswith(self._exclude)]
|
||||
interfaces = [
|
||||
i for i in netifaces.interfaces() if not i.startswith(self._exclude)
|
||||
]
|
||||
|
||||
del widgets[:]
|
||||
|
||||
counters = psutil.net_io_counters(pernic=True)
|
||||
now = time.time()
|
||||
timediff = now - (self._lastcheck if self._lastcheck else now)
|
||||
if timediff <= 0: timediff = 1
|
||||
if timediff <= 0:
|
||||
timediff = 1
|
||||
self._lastcheck = now
|
||||
for interface in interfaces:
|
||||
if self._graphlen > 0:
|
||||
if interface not in self._graphdata:
|
||||
self._graphdata[interface] = {
|
||||
'rx': [0] * self._graphlen,
|
||||
'tx': [0] * self._graphlen}
|
||||
if not interface: interface = 'lo'
|
||||
state = 'down'
|
||||
"rx": [0] * self._graphlen,
|
||||
"tx": [0] * self._graphlen,
|
||||
}
|
||||
if not interface:
|
||||
interface = "lo"
|
||||
state = "down"
|
||||
if len(self.get_addresses(interface)) > 0:
|
||||
state = 'up'
|
||||
elif util.format.asbool(self.parameter('hide_down', True)):
|
||||
state = "up"
|
||||
elif util.format.asbool(self.parameter("hide_down", True)):
|
||||
continue
|
||||
|
||||
if len(self._states['exclude']) > 0 and state in self._states['exclude']: continue
|
||||
if len(self._states['include']) > 0 and state not in self._states['include']: continue
|
||||
if len(self._states["exclude"]) > 0 and state in self._states["exclude"]:
|
||||
continue
|
||||
if (
|
||||
len(self._states["include"]) > 0
|
||||
and state not in self._states["include"]
|
||||
):
|
||||
continue
|
||||
|
||||
data = {
|
||||
'rx': counters[interface].bytes_recv,
|
||||
'tx': counters[interface].bytes_sent,
|
||||
"rx": counters[interface].bytes_recv,
|
||||
"tx": counters[interface].bytes_sent,
|
||||
}
|
||||
|
||||
name = 'traffic-{}'.format(interface)
|
||||
name = "traffic-{}".format(interface)
|
||||
|
||||
if self._showname:
|
||||
self.create_widget(widgets, name, interface)
|
||||
self.create_widget(widgets, name, interface)
|
||||
|
||||
for direction in ['rx', 'tx']:
|
||||
name = 'traffic.{}-{}'.format(direction, interface)
|
||||
widget = self.create_widget(widgets, name, attributes={'theme.minwidth': self.get_minwidth_str()})
|
||||
for direction in ["rx", "tx"]:
|
||||
name = "traffic.{}-{}".format(direction, interface)
|
||||
widget = self.create_widget(
|
||||
widgets,
|
||||
name,
|
||||
attributes={"theme.minwidth": self.get_minwidth_str()},
|
||||
)
|
||||
prev = self._prev.get(name, 0)
|
||||
bspeed = (int(data[direction]) - int(prev))/timediff
|
||||
bspeed = (int(data[direction]) - int(prev)) / timediff
|
||||
speed = util.format.byte(bspeed, self._format)
|
||||
txtspeed = '{0}/s'.format(speed)
|
||||
txtspeed = "{0}/s".format(speed)
|
||||
if self._graphlen > 0:
|
||||
# skip first value returned by psutil, because it is
|
||||
# giant and ruins the grapth ratio until it gets pushed
|
||||
|
@ -152,10 +176,16 @@ class Module(core.module.Module):
|
|||
if self._first_run is True:
|
||||
self._first_run = False
|
||||
else:
|
||||
self._graphdata[interface][direction] = self._graphdata[interface][direction][1:]
|
||||
self._graphdata[interface][direction] = self._graphdata[
|
||||
interface
|
||||
][direction][1:]
|
||||
self._graphdata[interface][direction].append(bspeed)
|
||||
txtspeed = '{}{}'.format(util.graph.braille(self._graphdata[interface][direction]), txtspeed)
|
||||
widget.full_text(txtspeed)
|
||||
txtspeed = "{}{}".format(
|
||||
util.graph.braille(self._graphdata[interface][direction]),
|
||||
txtspeed,
|
||||
)
|
||||
widget.full_text(txtspeed)
|
||||
self._prev[name] = data[direction]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pylint: disable=C0111,R0903
|
||||
# pylint: disable=C0111,R0903
|
||||
|
||||
"""Toggle twmn notifications."""
|
||||
|
||||
|
@ -9,14 +9,15 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(''))
|
||||
super().__init__(config, theme, core.widget.Widget(""))
|
||||
|
||||
self.__paused = False
|
||||
# Make sure that twmn is currently not paused
|
||||
util.cli.execute('killall -SIGUSR2 twmnd', ignore_errors=True)
|
||||
util.cli.execute("killall -SIGUSR2 twmnd", ignore_errors=True)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.toggle_status)
|
||||
|
||||
def toggle_status(self, event):
|
||||
|
@ -24,15 +25,16 @@ class Module(core.module.Module):
|
|||
|
||||
try:
|
||||
if self.__paused:
|
||||
util.cli.execute('systemctl --user start twmnd')
|
||||
util.cli.execute("systemctl --user start twmnd")
|
||||
else:
|
||||
util.cli.execute('systemctl --user stop twmnd')
|
||||
util.cli.execute("systemctl --user stop twmnd")
|
||||
except:
|
||||
self.__paused = not self.__paused # toggling failed
|
||||
self.__paused = not self.__paused # toggling failed
|
||||
|
||||
def state(self, widget):
|
||||
if self.__paused:
|
||||
return ['muted']
|
||||
return ['unmuted']
|
||||
return ["muted"]
|
||||
return ["unmuted"]
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -7,17 +7,19 @@ from datetime import timedelta
|
|||
import core.module
|
||||
import core.widget
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
self.__uptime = ''
|
||||
self.__uptime = ""
|
||||
|
||||
def output(self, _):
|
||||
return '{}'.format(self.__uptime)
|
||||
return "{}".format(self.__uptime)
|
||||
|
||||
def update(self):
|
||||
with open('/proc/uptime', 'r') as f:
|
||||
with open("/proc/uptime", "r") as f:
|
||||
uptime_seconds = int(float(f.readline().split()[0]))
|
||||
self.__uptime = timedelta(seconds = uptime_seconds)
|
||||
self.__uptime = timedelta(seconds=uptime_seconds)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -25,6 +25,7 @@ import core.input
|
|||
import util.cli
|
||||
import util.popup
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.vpn_status))
|
||||
|
@ -32,74 +33,82 @@ class Module(core.module.Module):
|
|||
self.__connected_vpn_profile = None
|
||||
self.__selected_vpn_profile = None
|
||||
|
||||
res = util.cli.execute('nmcli -g NAME,TYPE c')
|
||||
res = util.cli.execute("nmcli -g NAME,TYPE c")
|
||||
lines = res.splitlines()
|
||||
|
||||
self.__vpn_profiles = []
|
||||
for line in lines:
|
||||
info = line.split(':')
|
||||
info = line.split(":")
|
||||
try:
|
||||
if self.__isvpn(info[1]):
|
||||
self.__vpn_profiles.append(info[0])
|
||||
except:
|
||||
pass
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd=self.popup)
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.popup)
|
||||
|
||||
def __isvpn(self, connection_type):
|
||||
return connection_type in ['vpn', 'wireguard']
|
||||
return connection_type in ["vpn", "wireguard"]
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
res = util.cli.execute('nmcli -g NAME,TYPE,DEVICE con')
|
||||
res = util.cli.execute("nmcli -g NAME,TYPE,DEVICE con")
|
||||
lines = res.splitlines()
|
||||
self.__connected_vpn_profile = None
|
||||
for line in lines:
|
||||
info = line.split(':')
|
||||
if self.__isvpn(info[1]) and info[2] != '':
|
||||
info = line.split(":")
|
||||
if self.__isvpn(info[1]) and info[2] != "":
|
||||
self.__connected_vpn_profile = info[0]
|
||||
|
||||
except Exception as e:
|
||||
logging.exception('Could not get VPN status')
|
||||
logging.exception("Could not get VPN status")
|
||||
self.__connected_vpn_profile = None
|
||||
|
||||
def vpn_status(self, widget):
|
||||
if self.__connected_vpn_profile is None:
|
||||
return 'off'
|
||||
return "off"
|
||||
return self.__connected_vpn_profile
|
||||
|
||||
def __on_vpndisconnect(self):
|
||||
try:
|
||||
util.cli.execute('nmcli c down \'{vpn}\''
|
||||
.format(vpn=self.__connected_vpn_profile))
|
||||
util.cli.execute(
|
||||
"nmcli c down '{vpn}'".format(vpn=self.__connected_vpn_profile)
|
||||
)
|
||||
self.__connected_vpn_profile = None
|
||||
except Exception as e:
|
||||
logging.exception('Could not disconnect VPN connection')
|
||||
logging.exception("Could not disconnect VPN connection")
|
||||
|
||||
def __on_vpnconnect(self, name):
|
||||
self.__selected_vpn_profile = name
|
||||
|
||||
try:
|
||||
util.cli.execute('nmcli c up \'{vpn}\''
|
||||
.format(vpn=self.__selected_vpn_profile))
|
||||
util.cli.execute(
|
||||
"nmcli c up '{vpn}'".format(vpn=self.__selected_vpn_profile)
|
||||
)
|
||||
self.__connected_vpn_profile = name
|
||||
except Exception as e:
|
||||
logging.exception('Could not establish VPN connection')
|
||||
logging.exception("Could not establish VPN connection")
|
||||
self.__connected_vpn_profile = None
|
||||
|
||||
def popup(self, widget):
|
||||
menu = util.popup.menu()
|
||||
|
||||
if self.__connected_vpn_profile is not None:
|
||||
menu.add_menuitem('Disconnect', callback=self.__on_vpndisconnect)
|
||||
menu.add_menuitem("Disconnect", callback=self.__on_vpndisconnect)
|
||||
for vpn_profile in self.__vpn_profiles:
|
||||
if self.__connected_vpn_profile is not None and self.__connected_vpn_profile == vpn_profile:
|
||||
if (
|
||||
self.__connected_vpn_profile is not None
|
||||
and self.__connected_vpn_profile == vpn_profile
|
||||
):
|
||||
continue
|
||||
menu.add_menuitem(vpn_profile, callback=functools.partial(self.__on_vpnconnect, vpn_profile))
|
||||
menu.add_menuitem(
|
||||
vpn_profile,
|
||||
callback=functools.partial(self.__on_vpnconnect, vpn_profile),
|
||||
)
|
||||
menu.show(widget)
|
||||
|
||||
def state(self, widget):
|
||||
return []
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -17,40 +17,42 @@ import core.decorators
|
|||
|
||||
import util.cli
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.text))
|
||||
|
||||
self.__tracking = False
|
||||
self.__project = ''
|
||||
self.__project = ""
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.toggle)
|
||||
|
||||
def toggle(self, widget):
|
||||
self.__project = 'hit'
|
||||
self.__project = "hit"
|
||||
if self.__tracking:
|
||||
util.cli.execute('watson stop')
|
||||
util.cli.execute("watson stop")
|
||||
else:
|
||||
util.cli.execute('watson restart')
|
||||
util.cli.execute("watson restart")
|
||||
self.__tracking = not self.__tracking
|
||||
|
||||
def text(self, widget):
|
||||
if self.__tracking:
|
||||
return self.__project
|
||||
else:
|
||||
return 'Paused'
|
||||
return "Paused"
|
||||
|
||||
def update(self):
|
||||
output = util.cli.execute('watson status')
|
||||
if re.match('No project started', output):
|
||||
output = util.cli.execute("watson status")
|
||||
if re.match("No project started", output):
|
||||
self.__tracking = False
|
||||
return
|
||||
|
||||
self.__tracking = True
|
||||
m = re.search(r'Project (.+) started', output)
|
||||
m = re.search(r"Project (.+) started", output)
|
||||
self.__project = m.group(1)
|
||||
|
||||
def state(self, widget):
|
||||
return 'on' if self.__tracking else 'off'
|
||||
return "on" if self.__tracking else "off"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -28,30 +28,37 @@ import re
|
|||
import requests
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=15)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.output))
|
||||
|
||||
self.__temperature = 0
|
||||
self.__apikey = self.parameter('apikey', 'af7bfe22287c652d032a3064ffa44088')
|
||||
self.__location = util.format.aslist(self.parameter('location', 'auto'))
|
||||
self.__apikey = self.parameter("apikey", "af7bfe22287c652d032a3064ffa44088")
|
||||
self.__location = util.format.aslist(self.parameter("location", "auto"))
|
||||
|
||||
self.__index = 0
|
||||
self.__showcity = util.format.asbool(self.parameter('showcity', True))
|
||||
self.__showminmax = util.format.asbool(self.parameter('showminmax', False))
|
||||
self.__unit = self.parameter('unit', 'metric')
|
||||
self.__showcity = util.format.asbool(self.parameter("showcity", True))
|
||||
self.__showminmax = util.format.asbool(self.parameter("showminmax", False))
|
||||
self.__unit = self.parameter("unit", "metric")
|
||||
self.__valid = False
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__next_location)
|
||||
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_location)
|
||||
core.input.register(
|
||||
self, button=core.input.LEFT_MOUSE, cmd=self.__next_location
|
||||
)
|
||||
core.input.register(
|
||||
self, button=core.input.RIGHT_MOUSE, cmd=self.__prev_location
|
||||
)
|
||||
|
||||
def __next_location(self, event):
|
||||
self.__index = (self.__index + 1) % len(self.__location)
|
||||
self.update()
|
||||
|
||||
def __prev_location(self, event):
|
||||
self.__index = len(self.__location) - 1 if self.__index <= 0 else self.__index - 1
|
||||
self.__index = (
|
||||
len(self.__location) - 1 if self.__index <= 0 else self.__index - 1
|
||||
)
|
||||
self.update()
|
||||
|
||||
def temperature(self):
|
||||
|
@ -64,15 +71,22 @@ class Module(core.module.Module):
|
|||
return util.format.astemperature(self.__tempmax, self.__unit)
|
||||
|
||||
def city(self):
|
||||
city = re.sub('[_-]', ' ', self.__city)
|
||||
return u'{} '.format(city)
|
||||
city = re.sub("[_-]", " ", self.__city)
|
||||
return "{} ".format(city)
|
||||
|
||||
def output(self, widget):
|
||||
if not self.__valid:
|
||||
return u'?'
|
||||
return "?"
|
||||
if self.__showminmax:
|
||||
self.__showcity=False
|
||||
return self.city() + self.temperature() + ' Hi:' + self.tempmax() + ' Lo:' + self.tempmin()
|
||||
self.__showcity = False
|
||||
return (
|
||||
self.city()
|
||||
+ self.temperature()
|
||||
+ " Hi:"
|
||||
+ self.tempmax()
|
||||
+ " Lo:"
|
||||
+ self.tempmin()
|
||||
)
|
||||
elif self.__showcity:
|
||||
return self.city() + self.temperature()
|
||||
else:
|
||||
|
@ -80,42 +94,51 @@ class Module(core.module.Module):
|
|||
|
||||
def state(self, widget):
|
||||
if self.__valid:
|
||||
if 'thunderstorm' in self.__weather:
|
||||
return ['thunder']
|
||||
elif 'drizzle' in self.__weather:
|
||||
return ['rain']
|
||||
elif 'rain' in self.__weather:
|
||||
return ['rain']
|
||||
elif 'snow' in self.__weather:
|
||||
return ['snow']
|
||||
elif 'sleet' in self.__weather:
|
||||
return ['sleet']
|
||||
elif 'clear' in self.__weather:
|
||||
return ['clear']
|
||||
elif 'cloud' in self.__weather:
|
||||
return ['clouds']
|
||||
if "thunderstorm" in self.__weather:
|
||||
return ["thunder"]
|
||||
elif "drizzle" in self.__weather:
|
||||
return ["rain"]
|
||||
elif "rain" in self.__weather:
|
||||
return ["rain"]
|
||||
elif "snow" in self.__weather:
|
||||
return ["snow"]
|
||||
elif "sleet" in self.__weather:
|
||||
return ["sleet"]
|
||||
elif "clear" in self.__weather:
|
||||
return ["clear"]
|
||||
elif "cloud" in self.__weather:
|
||||
return ["clouds"]
|
||||
|
||||
return []
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
weather_url = 'http://api.openweathermap.org/data/2.5/weather?appid={}'.format(self.__apikey)
|
||||
weather_url = '{}&units={}'.format(weather_url, self.__unit)
|
||||
if self.__location[self.__index] == 'auto':
|
||||
weather_url = "http://api.openweathermap.org/data/2.5/weather?appid={}".format(
|
||||
self.__apikey
|
||||
)
|
||||
weather_url = "{}&units={}".format(weather_url, self.__unit)
|
||||
if self.__location[self.__index] == "auto":
|
||||
coord = util.location.coordinates()
|
||||
weather_url = '{url}&lat={lat}&lon={lon}'.format(url=weather_url, lat=coord[0], lon=coord[1])
|
||||
weather_url = "{url}&lat={lat}&lon={lon}".format(
|
||||
url=weather_url, lat=coord[0], lon=coord[1]
|
||||
)
|
||||
elif self.__location[self.__index].isdigit():
|
||||
weather_url = '{url}&id={id}'.format(url=weather_url, id=self.__location[self.__index])
|
||||
weather_url = "{url}&id={id}".format(
|
||||
url=weather_url, id=self.__location[self.__index]
|
||||
)
|
||||
else:
|
||||
weather_url = '{url}&q={city}'.format(url=weather_url, city=self.__location[self.__index])
|
||||
weather_url = "{url}&q={city}".format(
|
||||
url=weather_url, city=self.__location[self.__index]
|
||||
)
|
||||
weather = requests.get(weather_url).json()
|
||||
self.__city = weather['name']
|
||||
self.__temperature = int(weather['main']['temp'])
|
||||
self.__tempmin = int(weather['main']['temp_min'])
|
||||
self.__tempmax = int(weather['main']['temp_max'])
|
||||
self.__weather = weather['weather'][0]['main'].lower()
|
||||
self.__city = weather["name"]
|
||||
self.__temperature = int(weather["main"]["temp"])
|
||||
self.__tempmin = int(weather["main"]["temp_min"])
|
||||
self.__tempmax = int(weather["main"]["temp_max"])
|
||||
self.__weather = weather["weather"][0]["main"].lower()
|
||||
self.__valid = True
|
||||
except Exception:
|
||||
self.__valid = False
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pylint: disable=C0111,R0903
|
||||
# pylint: disable=C0111,R0903
|
||||
|
||||
"""Opens a random xkcd comic in the browser."""
|
||||
|
||||
|
@ -7,12 +7,16 @@ import core.widget
|
|||
import core.input
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.never
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget('xkcd'))
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE,
|
||||
cmd="xdg-open https://c.xkcd.com/random/comic/"
|
||||
super().__init__(config, theme, core.widget.Widget("xkcd"))
|
||||
core.input.register(
|
||||
self,
|
||||
button=core.input.LEFT_MOUSE,
|
||||
cmd="xdg-open https://c.xkcd.com/random/comic/",
|
||||
)
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -15,21 +15,25 @@ import core.module
|
|||
import core.widget
|
||||
import core.decorators
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(seconds=5)
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.keystate))
|
||||
self.__keystate = 'No YubiKey'
|
||||
self.__keystate = "No YubiKey"
|
||||
|
||||
def keystate(self, widget):
|
||||
return self.__keystate
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
self.__keystate = "YubiKey: " + str(yubico.find_yubikey(debug=False).serial())
|
||||
self.__keystate = "YubiKey: " + str(
|
||||
yubico.find_yubikey(debug=False).serial()
|
||||
)
|
||||
except yubico.yubico_exception.YubicoError:
|
||||
self.__keystate = "No YubiKey"
|
||||
except Exception:
|
||||
self.__keystate = 'n/a'
|
||||
self.__keystate = "n/a"
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -36,46 +36,81 @@ import core.widget
|
|||
import util.cli
|
||||
import util.format
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, [])
|
||||
|
||||
self._includelist = set(filter(lambda x: len(x) > 0,
|
||||
util.format.aslist(self.parameter('list', default=''))))
|
||||
self._format = self.parameter('format', default='{name} {shortstatus} {used}/{size} ' +
|
||||
'({percentfree}%)')
|
||||
self._usesudo = util.format.asbool(self.parameter('sudo', default=False))
|
||||
self._showio = util.format.asbool(self.parameter('showio', default=True))
|
||||
self._ioformat = self.parameter('ioformat', default='{band}')
|
||||
self._warnfree = int(self.parameter('warnfree', default=10))
|
||||
self._includelist = set(
|
||||
filter(
|
||||
lambda x: len(x) > 0,
|
||||
util.format.aslist(self.parameter("list", default="")),
|
||||
)
|
||||
)
|
||||
self._format = self.parameter(
|
||||
"format", default="{name} {shortstatus} {used}/{size} " + "({percentfree}%)"
|
||||
)
|
||||
self._usesudo = util.format.asbool(self.parameter("sudo", default=False))
|
||||
self._showio = util.format.asbool(self.parameter("showio", default=True))
|
||||
self._ioformat = self.parameter("ioformat", default="{band}")
|
||||
self._warnfree = int(self.parameter("warnfree", default=10))
|
||||
|
||||
def update(self):
|
||||
widgets = self.widgets()
|
||||
zfs_version_path = '/sys/module/zfs/version'
|
||||
zfs_version_path = "/sys/module/zfs/version"
|
||||
# zpool list -H: List all zpools, use script mode (no headers and tabs as separators).
|
||||
try:
|
||||
with open(zfs_version_path, 'r') as zfs_mod_version:
|
||||
zfs_version = zfs_mod_version.readline().rstrip().split('-')[0]
|
||||
with open(zfs_version_path, "r") as zfs_mod_version:
|
||||
zfs_version = zfs_mod_version.readline().rstrip().split("-")[0]
|
||||
except IOError:
|
||||
# ZFS isn't installed or the module isn't loaded, stub the version
|
||||
zfs_version = '0.0.0'
|
||||
logging.error('ZFS version information not found at {}, check the module is loaded.'.format(zfs_version_path))
|
||||
zfs_version = "0.0.0"
|
||||
logging.error(
|
||||
"ZFS version information not found at {}, check the module is loaded.".format(
|
||||
zfs_version_path
|
||||
)
|
||||
)
|
||||
|
||||
raw_zpools = util.cli.execute(('sudo ' if self._usesudo else '') + 'zpool list -H').split('\n')
|
||||
raw_zpools = util.cli.execute(
|
||||
("sudo " if self._usesudo else "") + "zpool list -H"
|
||||
).split("\n")
|
||||
|
||||
for widget in widgets:
|
||||
widget.set('visited', False)
|
||||
widget.set("visited", False)
|
||||
|
||||
for raw_zpool in raw_zpools:
|
||||
try:
|
||||
# Ignored fields (assigned to _) are 'expandsz' and 'altroot', also 'ckpoint' in ZFS 0.8.0+
|
||||
if parse_version(zfs_version) < parse_version('0.8.0'):
|
||||
name, size, alloc, free, _, frag, cap, dedup, health, _ = raw_zpool.split('\t')
|
||||
if parse_version(zfs_version) < parse_version("0.8.0"):
|
||||
(
|
||||
name,
|
||||
size,
|
||||
alloc,
|
||||
free,
|
||||
_,
|
||||
frag,
|
||||
cap,
|
||||
dedup,
|
||||
health,
|
||||
_,
|
||||
) = raw_zpool.split("\t")
|
||||
else:
|
||||
name, size, alloc, free, _, _, frag, cap, dedup, health, _ = raw_zpool.split('\t')
|
||||
cap = cap.rstrip('%')
|
||||
percentuse=int(cap)
|
||||
percentfree=100-percentuse
|
||||
(
|
||||
name,
|
||||
size,
|
||||
alloc,
|
||||
free,
|
||||
_,
|
||||
_,
|
||||
frag,
|
||||
cap,
|
||||
dedup,
|
||||
health,
|
||||
_,
|
||||
) = raw_zpool.split("\t")
|
||||
cap = cap.rstrip("%")
|
||||
percentuse = int(cap)
|
||||
percentfree = 100 - percentuse
|
||||
# There is a command, zpool iostat, which is however blocking and was therefore
|
||||
# causing issues.
|
||||
# Instead, we read file `/proc/spl/kstat/zfs/<poolname>/io` which contains
|
||||
|
@ -83,7 +118,7 @@ class Module(core.module.Module):
|
|||
# (and timestamp) during each widget update, and during the next widget update we
|
||||
# use them to compute delta of transferred bytes, and using the last and current
|
||||
# timestamp the rate at which they have been transferred.
|
||||
with open('/proc/spl/kstat/zfs/{}/io'.format(name), 'r') as f:
|
||||
with open("/proc/spl/kstat/zfs/{}/io".format(name), "r") as f:
|
||||
# Third row provides data we need, we are interested in the first 4 values.
|
||||
# More info about this file can be found here:
|
||||
# https://github.com/zfsonlinux/zfs/blob/master/lib/libspl/include/sys/kstat.h#L580
|
||||
|
@ -100,12 +135,12 @@ class Module(core.module.Module):
|
|||
widget = self.widget(name)
|
||||
if not widget:
|
||||
widget = core.widget.Widget(name=name)
|
||||
widget.set('last_iostat', [0, 0, 0, 0])
|
||||
widget.set('last_timestamp', 0)
|
||||
widget.set("last_iostat", [0, 0, 0, 0])
|
||||
widget.set("last_timestamp", 0)
|
||||
widgets.append(widget)
|
||||
|
||||
delta_iostat = [b - a for a, b in zip(iostat, widget.get('last_iostat'))]
|
||||
widget.set('last_iostat', iostat)
|
||||
delta_iostat = [b - a for a, b in zip(iostat, widget.get("last_iostat"))]
|
||||
widget.set("last_iostat", iostat)
|
||||
|
||||
# From docs:
|
||||
# > Note that even though the time is always returned as a floating point number, not
|
||||
|
@ -114,8 +149,8 @@ class Module(core.module.Module):
|
|||
# Also, during one update cycle the reported I/O may be garbage if the system time
|
||||
# was changed.
|
||||
timestamp = time.time()
|
||||
delta_timestamp = widget.get('last_timestamp') - timestamp
|
||||
widget.set('last_timestamp', time.time())
|
||||
delta_timestamp = widget.get("last_timestamp") - timestamp
|
||||
widget.set("last_timestamp", time.time())
|
||||
|
||||
# abs is there because sometimes the result is -0
|
||||
rate_iostat = [abs(x / delta_timestamp) for x in delta_iostat]
|
||||
|
@ -123,17 +158,26 @@ class Module(core.module.Module):
|
|||
|
||||
# theme.minwidth is not set since these values are not expected to change
|
||||
# rapidly
|
||||
widget.full_text(self._format.format(name=name, used=alloc, left=free, size=size,
|
||||
percentfree=percentfree, percentuse=percentuse,
|
||||
status=health,
|
||||
shortstatus=self._shortstatus(health),
|
||||
fragpercent=frag, deduppercent=dedup))
|
||||
widget.set('state', health)
|
||||
widget.set('percentfree', percentfree)
|
||||
widget.set('visited', True)
|
||||
widget.full_text(
|
||||
self._format.format(
|
||||
name=name,
|
||||
used=alloc,
|
||||
left=free,
|
||||
size=size,
|
||||
percentfree=percentfree,
|
||||
percentuse=percentuse,
|
||||
status=health,
|
||||
shortstatus=self._shortstatus(health),
|
||||
fragpercent=frag,
|
||||
deduppercent=dedup,
|
||||
)
|
||||
)
|
||||
widget.set("state", health)
|
||||
widget.set("percentfree", percentfree)
|
||||
widget.set("visited", True)
|
||||
|
||||
if self._showio:
|
||||
wname, rname = [name + x for x in ['__write', '__read']]
|
||||
wname, rname = [name + x for x in ["__write", "__read"]]
|
||||
widget_w = self.widget(wname)
|
||||
widget_r = self.widget(rname)
|
||||
if not widget_w or not widget_r:
|
||||
|
@ -141,30 +185,40 @@ class Module(core.module.Module):
|
|||
widget_w = core.widget.Widget(name=wname)
|
||||
widgets.extend([widget_r, widget_w])
|
||||
for w in [widget_r, widget_w]:
|
||||
w.set('theme.minwidth', self._ioformat.format(ops=9999,
|
||||
band=util.format.bytefmt(999.99*(1024**2))))
|
||||
w.set('visited', True)
|
||||
widget_w.full_text(self._ioformat.format(ops=round(writes),
|
||||
band=util.format.bytefmt(nwritten)))
|
||||
widget_r.full_text(self._ioformat.format(ops=round(reads),
|
||||
band=util.format.bytefmt(nread)))
|
||||
w.set(
|
||||
"theme.minwidth",
|
||||
self._ioformat.format(
|
||||
ops=9999, band=util.format.bytefmt(999.99 * (1024 ** 2))
|
||||
),
|
||||
)
|
||||
w.set("visited", True)
|
||||
widget_w.full_text(
|
||||
self._ioformat.format(
|
||||
ops=round(writes), band=util.format.bytefmt(nwritten)
|
||||
)
|
||||
)
|
||||
widget_r.full_text(
|
||||
self._ioformat.format(
|
||||
ops=round(reads), band=util.format.bytefmt(nread)
|
||||
)
|
||||
)
|
||||
|
||||
for widget in widgets:
|
||||
if widget.get('visited') is False:
|
||||
if widget.get("visited") is False:
|
||||
widgets.remove(widget)
|
||||
self.widgets(widgets)
|
||||
|
||||
def state(self, widget):
|
||||
if widget.name.endswith('__read'):
|
||||
return 'poolread'
|
||||
elif widget.name.endswith('__write'):
|
||||
return 'poolwrite'
|
||||
if widget.name.endswith("__read"):
|
||||
return "poolread"
|
||||
elif widget.name.endswith("__write"):
|
||||
return "poolwrite"
|
||||
|
||||
state = widget.get('state')
|
||||
if state == 'FAULTED':
|
||||
return [state, 'critical']
|
||||
elif state == 'DEGRADED' or widget.get('percentfree') < self._warnfree:
|
||||
return [state, 'warning']
|
||||
state = widget.get("state")
|
||||
if state == "FAULTED":
|
||||
return [state, "critical"]
|
||||
elif state == "DEGRADED" or widget.get("percentfree") < self._warnfree:
|
||||
return [state, "warning"]
|
||||
|
||||
return state
|
||||
|
||||
|
@ -177,13 +231,14 @@ class Module(core.module.Module):
|
|||
# configuration. A faulted pool has corrupted metadata, or one or more faulted devices, and
|
||||
# insufficient replicas to continue functioning.
|
||||
shortstate = {
|
||||
'DEGRADED': 'DEG',
|
||||
'FAULTED': 'FLT',
|
||||
'ONLINE': 'ONL',
|
||||
"DEGRADED": "DEG",
|
||||
"FAULTED": "FLT",
|
||||
"ONLINE": "ONL",
|
||||
}
|
||||
try:
|
||||
return shortstate[status]
|
||||
except KeyError:
|
||||
return ''
|
||||
return ""
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue