Using remote
This commit is contained in:
commit
0b86b3df8c
16 changed files with 257 additions and 144 deletions
|
@ -6,6 +6,7 @@ python:
|
||||||
- "3.5"
|
- "3.5"
|
||||||
- "3.6"
|
- "3.6"
|
||||||
install:
|
install:
|
||||||
|
- pip install i3ipc
|
||||||
- pip install psutil
|
- pip install psutil
|
||||||
- pip install netifaces
|
- pip install netifaces
|
||||||
- pip install -U coverage==4.3
|
- pip install -U coverage==4.3
|
||||||
|
|
37
PKGBUILD
Normal file
37
PKGBUILD
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# Maintainer: Tobias Witek <tobi@tobi-wan-kenobi.at>
|
||||||
|
# Contributor: Daniel M. Capella <polycitizen@gmail.com>
|
||||||
|
|
||||||
|
pkgname=bumblebee-status
|
||||||
|
pkgver=1.4.2
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc='Modular, theme-able status line generator for the i3 window manager'
|
||||||
|
arch=('any')
|
||||||
|
url=https://github.com/tobi-wan-kenobi/bumblebee-status
|
||||||
|
license=('MIT')
|
||||||
|
depends=('python' 'python-netifaces' 'python-psutil' 'python-requests')
|
||||||
|
optdepends=('xorg-xbacklight: to display a displays brightness'
|
||||||
|
'xorg-xset: enable/disable automatic screen locking'
|
||||||
|
'libnotify: enable/disable automatic screen locking'
|
||||||
|
'dnf: display DNF package update information'
|
||||||
|
'xorg-setxkbmap: display/change the current keyboard layout'
|
||||||
|
'redshift: display the redshifts current color'
|
||||||
|
'pulseaudio: control pulseaudio sink/sources'
|
||||||
|
'xorg-xrandr: enable/disable screen outputs'
|
||||||
|
'pacman: display current status of pacman'
|
||||||
|
'iputils: display a ping'
|
||||||
|
'i3ipc-python: display titlebar'
|
||||||
|
'fakeroot: dependency of the pacman module')
|
||||||
|
source=("$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz")
|
||||||
|
sha512sums=('3a66fc469dd3b081337c9e213a1b2262f25f30977ee6ef65b9fa5a8b6aa341637832d1a5dbb74e30d68e2824e0d19d7a911eb3390dc6062707a552f429b483e8')
|
||||||
|
|
||||||
|
package() {
|
||||||
|
install -d "$pkgdir"/usr/bin \
|
||||||
|
"$pkgdir"/usr/share/$pkgname/{bumblebee/modules,themes/icons}
|
||||||
|
ln -s /usr/share/$pkgname/$pkgname "$pkgdir"/usr/bin/$pkgname
|
||||||
|
|
||||||
|
cd $pkgname-$pkgver
|
||||||
|
cp -a --parents $pkgname bumblebee/{,modules/}*.py themes/{,icons/}*.json \
|
||||||
|
"$pkgdir"/usr/share/$pkgname
|
||||||
|
|
||||||
|
install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
[![Test Coverage](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/coverage.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/coverage)
|
[![Test Coverage](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/coverage.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/coverage)
|
||||||
[![Issue Count](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/issue_count.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status)
|
[![Issue Count](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/issue_count.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status)
|
||||||
|
|
||||||
**Many, many thanks to all contributors! As of now, 21 of the modules are from various contributors (!), and only 16 from myself.**
|
**Many, many thanks to all contributors! As of now, 22 of the modules are from various contributors (!), and only 16 from myself.**
|
||||||
|
|
||||||
bumblebee-status is a modular, theme-able status line generator for the [i3 window manager](https://i3wm.org/).
|
bumblebee-status is a modular, theme-able status line generator for the [i3 window manager](https://i3wm.org/).
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ I hope you like it and appreciate any kind of feedback: Bug reports, Feature req
|
||||||
|
|
||||||
Thanks a lot!
|
Thanks a lot!
|
||||||
|
|
||||||
|
Required i3wm version: 4.12+ (in earlier versions, blocks won't have background colors)
|
||||||
|
|
||||||
Supported Python versions: 2.7, 3.3, 3.4, 3.5, 3.6
|
Supported Python versions: 2.7, 3.3, 3.4, 3.5, 3.6
|
||||||
|
|
||||||
Explicitly unsupported Python versions: 3.2 (missing unicode literals)
|
Explicitly unsupported Python versions: 3.2 (missing unicode literals)
|
||||||
|
@ -108,6 +110,7 @@ Modules and commandline utilities are only required for modules, the core itself
|
||||||
* requests (for the modules 'weather', 'github', 'getcrypto', 'stock')
|
* requests (for the modules 'weather', 'github', 'getcrypto', 'stock')
|
||||||
* power (for the module 'battery')
|
* power (for the module 'battery')
|
||||||
* dbus (for the module 'spotify')
|
* dbus (for the module 'spotify')
|
||||||
|
* i3rpc (for the module 'title')
|
||||||
|
|
||||||
# Required commandline utilities
|
# Required commandline utilities
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,13 @@ import bumblebee.output
|
||||||
import bumblebee.input
|
import bumblebee.input
|
||||||
import bumblebee.modules.error
|
import bumblebee.modules.error
|
||||||
|
|
||||||
|
try:
|
||||||
|
reload(sys)
|
||||||
|
sys.setdefaultencoding('UTF8')
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
config = bumblebee.config.Config(sys.argv[1:])
|
config = bumblebee.config.Config(sys.argv[1:])
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
# pylint: disable=C0111,R0903
|
# pylint: disable=C0111,R0903
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""Displays information about the current song in cmus.
|
"""Displays information about the current song in cmus.
|
||||||
|
|
||||||
|
@ -69,10 +68,6 @@ class Module(bumblebee.engine.Module):
|
||||||
return returns.get(widget.name, self._status)
|
return returns.get(widget.name, self._status)
|
||||||
|
|
||||||
def _eval_line(self, line):
|
def _eval_line(self, line):
|
||||||
# not a typo, use decode detection to see whether we are
|
|
||||||
# dealing with Python2 or Python3
|
|
||||||
if hasattr(line, "decode"):
|
|
||||||
line = line.encode("utf-8", "replace")
|
|
||||||
name, key, value = (line.split(" ", 2) + [None, None])[:3]
|
name, key, value = (line.split(" ", 2) + [None, None])[:3]
|
||||||
|
|
||||||
if name == "status":
|
if name == "status":
|
||||||
|
|
|
@ -8,6 +8,13 @@ Requires the following python packages:
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
* currency.interval: Interval in minutes between updates, default is 1.
|
* currency.interval: Interval in minutes between updates, default is 1.
|
||||||
|
* currency.source: Source currency (defaults to "GBP")
|
||||||
|
* currency.destination: Comma-separated list of destination currencies (defaults to "USD,EUR")
|
||||||
|
* currency.sourceformat: String format for source formatting; Defaults to "{}: {}" and has two variables,
|
||||||
|
the base symbol and the rate list
|
||||||
|
* currency.destinationdelimiter: Delimiter used for separating individual rates (defaults to "|")
|
||||||
|
|
||||||
|
Note: source and destination names right now must correspond to the names used by the API of http://fixer.io
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import bumblebee.input
|
import bumblebee.input
|
||||||
|
@ -21,40 +28,43 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
SYMBOL = {
|
||||||
|
"GBP": u"£", "EUR": u"€", "USD": u"$"
|
||||||
|
}
|
||||||
|
|
||||||
class Module(bumblebee.engine.Module):
|
class Module(bumblebee.engine.Module):
|
||||||
def __init__(self, engine, config):
|
def __init__(self, engine, config):
|
||||||
super(Module, self).__init__(engine, config,
|
super(Module, self).__init__(engine, config,
|
||||||
bumblebee.output.Widget(full_text=self.price)
|
bumblebee.output.Widget(full_text=self.price)
|
||||||
)
|
)
|
||||||
self._price = "-"
|
self._data = {}
|
||||||
self._interval = int(self.parameter("interval", "1"))
|
self._interval = int(self.parameter("interval", 1))
|
||||||
|
self._base = self.parameter("source", "GBP")
|
||||||
|
self._symbols = self.parameter("destination", "USD,EUR")
|
||||||
self._nextcheck = 0
|
self._nextcheck = 0
|
||||||
self._valid = False
|
|
||||||
|
|
||||||
def price(self, widget):
|
def price(self, widget):
|
||||||
if not self._valid:
|
if self._data == {}:
|
||||||
return u"?"
|
return "?"
|
||||||
return self._price
|
|
||||||
|
rates = []
|
||||||
|
for sym in self._data["rates"]:
|
||||||
|
rates.append(u"{}{}".format(self._data["rates"][sym], SYMBOL[sym] if sym in SYMBOL else sym))
|
||||||
|
|
||||||
|
basefmt = u"{}".format(self.parameter("sourceformat", "{}: {}"))
|
||||||
|
ratefmt = u"{}".format(self.parameter("destinationdelimiter", "|"))
|
||||||
|
|
||||||
|
return basefmt.format(SYMBOL[self._base] if self._base in SYMBOL else self._base, ratefmt.join(rates))
|
||||||
|
|
||||||
def update(self, widgets):
|
def update(self, widgets):
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
if self._nextcheck < int(time.time()):
|
if self._nextcheck < int(time.time()):
|
||||||
|
self._data = {}
|
||||||
|
self._nextcheck = int(time.time()) + self._interval*60
|
||||||
|
url = "http://api.fixer.io/latest?symbols={}&base={}".format(self._symbols, self._base)
|
||||||
try:
|
try:
|
||||||
self._nextcheck = int(time.time()) + self._interval*60
|
self._data = json.loads(requests.get(url).text)
|
||||||
price_url = "http://api.fixer.io/latest?symbols=USD,EUR&base=GBP"
|
except Exception:
|
||||||
try:
|
pass
|
||||||
price_json = json.loads( requests.get(price_url).text )
|
|
||||||
gbpeur = str(price_json['rates']['EUR'])
|
|
||||||
gbpusd = str(price_json['rates']['USD'])
|
|
||||||
except ValueError:
|
|
||||||
gbpeur = "-"
|
|
||||||
gbpusd = "-"
|
|
||||||
|
|
||||||
self._price = u"£/€ " + gbpeur + u" | £/$ " + gbpusd
|
|
||||||
self._valid = True
|
|
||||||
except RequestException:
|
|
||||||
self._price = u"£/€ - | £/$ -"
|
|
||||||
self._valid = True
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Module(bumblebee.engine.Module):
|
||||||
url = "https://api.github.com/notifications"
|
url = "https://api.github.com/notifications"
|
||||||
while True:
|
while True:
|
||||||
notifications = self._requests.get(url)
|
notifications = self._requests.get(url)
|
||||||
self._count += len(filter(lambda notification: notification.get("unread", False), notifications.json()))
|
self._count += len(list(filter(lambda notification: notification['unread'], notifications.json())))
|
||||||
next_link = notifications.links.get('next')
|
next_link = notifications.links.get('next')
|
||||||
if next_link is not None:
|
if next_link is not None:
|
||||||
url = next_link.get('url')
|
url = next_link.get('url')
|
||||||
|
|
|
@ -4,9 +4,6 @@
|
||||||
|
|
||||||
Requires the following executable:
|
Requires the following executable:
|
||||||
* setxkbmap
|
* setxkbmap
|
||||||
|
|
||||||
Parameters:
|
|
||||||
* layout.lang: pipe-separated list of languages to cycle through (e.g. us|rs|de). Default: en
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import bumblebee.util
|
import bumblebee.util
|
||||||
|
@ -17,58 +14,59 @@ import bumblebee.engine
|
||||||
class Module(bumblebee.engine.Module):
|
class Module(bumblebee.engine.Module):
|
||||||
def __init__(self, engine, config):
|
def __init__(self, engine, config):
|
||||||
super(Module, self).__init__(engine, config,
|
super(Module, self).__init__(engine, config,
|
||||||
bumblebee.output.Widget(full_text=self.layout)
|
bumblebee.output.Widget(full_text=self.current_layout)
|
||||||
)
|
)
|
||||||
self._languages = self.parameter("lang", "us").split("|")
|
|
||||||
self._idx = 0
|
|
||||||
|
|
||||||
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
cmd=self._next_keymap)
|
cmd=self._next_keymap)
|
||||||
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE,
|
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE,
|
||||||
cmd=self._prev_keymap)
|
cmd=self._prev_keymap)
|
||||||
|
|
||||||
def _next_keymap(self, event):
|
def _next_keymap(self, event):
|
||||||
self._idx = (self._idx + 1) % len(self._languages)
|
self._set_keymap(1)
|
||||||
self._set_keymap()
|
|
||||||
|
|
||||||
def _prev_keymap(self, event):
|
def _prev_keymap(self, event):
|
||||||
self._idx = self._idx - 1 if self._idx > 0 else len(self._languages) - 1
|
self._set_keymap(-1)
|
||||||
self._set_keymap()
|
|
||||||
|
def _set_keymap(self, rotation):
|
||||||
|
layouts = self.get_layouts()
|
||||||
|
if len(layouts) == 1: return # nothing to do
|
||||||
|
layouts = layouts[rotation:] + layouts[:rotation]
|
||||||
|
|
||||||
|
layout_list = []
|
||||||
|
variant_list = []
|
||||||
|
for l in layouts:
|
||||||
|
tmp = l.split(":")
|
||||||
|
layout_list.append(tmp[0])
|
||||||
|
variant_list.append(tmp[1] if len(tmp) > 1 else "")
|
||||||
|
|
||||||
def _set_keymap(self):
|
|
||||||
tmp = self._languages[self._idx].split(":")
|
|
||||||
layout = tmp[0]
|
|
||||||
variant = ""
|
|
||||||
if len(tmp) > 1:
|
|
||||||
variant = "-variant {}".format(tmp[1])
|
|
||||||
try:
|
try:
|
||||||
bumblebee.util.execute("setxkbmap -layout {} {}".format(layout, variant))
|
bumblebee.util.execute("setxkbmap -layout {} -variant {}".format(",".join(layout_list), ",".join(variant_list)))
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def layout(self, widget):
|
def get_layouts(self):
|
||||||
try:
|
try:
|
||||||
res = bumblebee.util.execute("setxkbmap -query")
|
res = bumblebee.util.execute("setxkbmap -query")
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
return "n/a"
|
return ["n/a"]
|
||||||
layout = ""
|
layouts = []
|
||||||
variant = None
|
variants = []
|
||||||
for line in res.split("\n"):
|
for line in res.split("\n"):
|
||||||
if not line:
|
if not line: continue
|
||||||
continue
|
|
||||||
if "layout" in line:
|
if "layout" in line:
|
||||||
layout = line.split(":")[1].strip()
|
layouts = line.split(":")[1].strip().split(",")
|
||||||
if "variant" in line:
|
if "variant" in line:
|
||||||
variant = line.split(":")[1].strip()
|
variants = line.split(":")[1].strip().split(",")
|
||||||
if variant:
|
|
||||||
layout += ":" + variant
|
|
||||||
|
|
||||||
if layout in self._languages:
|
result = []
|
||||||
self._idx = self._languages.index(layout)
|
for idx, layout in enumerate(layouts):
|
||||||
else:
|
if len(variants) > idx and variants[idx]:
|
||||||
self._languages.append(layout)
|
layout = "{}:{}".format(layout, variants[idx])
|
||||||
self._idx = len(self._languages) - 1
|
result.append(layout)
|
||||||
|
return result if len(result) > 0 else ["n/a"]
|
||||||
|
|
||||||
return layout
|
def current_layout(self, widget):
|
||||||
|
layouts = self.get_layouts()
|
||||||
|
return layouts[0]
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
|
|
|
@ -9,22 +9,24 @@ Parameters:
|
||||||
* memory.usedonly: Only show the amount of RAM in use (defaults to False). Same as memory.format="{used}"
|
* memory.usedonly: Only show the amount of RAM in use (defaults to False). Same as memory.format="{used}"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
import re
|
||||||
import psutil
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
import bumblebee.util
|
import bumblebee.util
|
||||||
import bumblebee.input
|
import bumblebee.input
|
||||||
import bumblebee.output
|
import bumblebee.output
|
||||||
import bumblebee.engine
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Container(object):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.__dict__.update(kwargs)
|
||||||
|
|
||||||
class Module(bumblebee.engine.Module):
|
class Module(bumblebee.engine.Module):
|
||||||
def __init__(self, engine, config):
|
def __init__(self, engine, config):
|
||||||
super(Module, self).__init__(engine, config,
|
super(Module, self).__init__(engine, config,
|
||||||
bumblebee.output.Widget(full_text=self.memory_usage)
|
bumblebee.output.Widget(full_text=self.memory_usage)
|
||||||
)
|
)
|
||||||
self._mem = psutil.virtual_memory()
|
self.update(None)
|
||||||
|
|
||||||
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
cmd="gnome-system-monitor")
|
cmd="gnome-system-monitor")
|
||||||
|
|
||||||
|
@ -36,18 +38,30 @@ class Module(bumblebee.engine.Module):
|
||||||
return self.parameter("format", "{used}/{total} ({percent:05.02f}%)")
|
return self.parameter("format", "{used}/{total} ({percent:05.02f}%)")
|
||||||
|
|
||||||
def memory_usage(self, widget):
|
def memory_usage(self, widget):
|
||||||
used = bumblebee.util.bytefmt(self._mem.total - self._mem.available)
|
return self._format.format(**self._mem)
|
||||||
total = bumblebee.util.bytefmt(self._mem.total)
|
|
||||||
|
|
||||||
return self._format.format(used=used, total=total, percent=self._mem.percent)
|
|
||||||
|
|
||||||
def update(self, widgets):
|
def update(self, widgets):
|
||||||
self._mem = psutil.virtual_memory()
|
data = {}
|
||||||
|
with open("/proc/meminfo", "r") as f:
|
||||||
|
for line in f:
|
||||||
|
tmp = re.split(r"[:\s]+", line)
|
||||||
|
value = int(tmp[1])
|
||||||
|
if tmp[2] == "kB": value = value*1024
|
||||||
|
if tmp[2] == "mB": value = value*1024*1024
|
||||||
|
if tmp[2] == "gB": value = value*1024*1024*1024
|
||||||
|
data[tmp[0]] = value
|
||||||
|
self._mem = {
|
||||||
|
"total": bumblebee.util.bytefmt(data["MemTotal"]),
|
||||||
|
"available": bumblebee.util.bytefmt(data["MemAvailable"]),
|
||||||
|
"free": bumblebee.util.bytefmt(data["MemFree"]),
|
||||||
|
"used": bumblebee.util.bytefmt(data["MemTotal"] - data["MemFree"] - data["Buffers"] - data["Cached"] - data["Slab"]),
|
||||||
|
"percent": (float(data["MemTotal"] - data["MemAvailable"])/data["MemTotal"])*100
|
||||||
|
}
|
||||||
|
|
||||||
def state(self, widget):
|
def state(self, widget):
|
||||||
if self._mem.percent > float(self.parameter("critical", 90)):
|
if self._mem["percent"] > float(self.parameter("critical", 90)):
|
||||||
return "critical"
|
return "critical"
|
||||||
if self._mem.percent > float(self.parameter("warning", 80)):
|
if self._mem["percent"] > float(self.parameter("warning", 80)):
|
||||||
return "warning"
|
return "warning"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,9 @@ class Module(bumblebee.engine.Module):
|
||||||
else:
|
else:
|
||||||
self._state = "transition"
|
self._state = "transition"
|
||||||
transition = " ".join(line.split(" ")[2:])
|
transition = " ".join(line.split(" ")[2:])
|
||||||
self._text = "{} {}".format(temp, transition)
|
self._text = temp
|
||||||
|
if transition:
|
||||||
|
self._text = "{} {}".format(temp, transition)
|
||||||
|
|
||||||
def state(self, widget):
|
def state(self, widget):
|
||||||
return self._state
|
return self._state
|
||||||
|
|
67
bumblebee/modules/title.py
Normal file
67
bumblebee/modules/title.py
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays focused i3 window title.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
* i3ipc
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* title.max : Maximum character length for title before truncating. Defaults to 64.
|
||||||
|
* title.placeholder : Placeholder text to be placed if title was truncated. Defaults to "...".
|
||||||
|
* title.scroll : Boolean flag for scrolling title. Defaults to False
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import i3ipc
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
from bumblebee.output import scrollable
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
"""Window title module."""
|
||||||
|
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(
|
||||||
|
engine,
|
||||||
|
config,
|
||||||
|
bumblebee.output.Widget(full_text=self.get_title)
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
self._i3 = i3ipc.Connection()
|
||||||
|
self._full_title = self._i3.get_tree().find_focused().name
|
||||||
|
except Exception:
|
||||||
|
self._full_title = "n/a"
|
||||||
|
|
||||||
|
def get_title(self, widget):
|
||||||
|
if bumblebee.util.asbool(self.parameter("scroll", False)):
|
||||||
|
return self.scrolling_focused_title(widget)
|
||||||
|
else:
|
||||||
|
return self.focused_title(widget)
|
||||||
|
|
||||||
|
def focused_title(self, widget):
|
||||||
|
title = self._full_title[0:self.parameter("max", 64)]
|
||||||
|
placeholder = self.parameter("placeholder", "...")
|
||||||
|
if title != self._full_title:
|
||||||
|
title = self._full_title[0:self.parameter("max", 64) - len(placeholder)]
|
||||||
|
title = "{}{}".format(title, placeholder)
|
||||||
|
|
||||||
|
return title
|
||||||
|
|
||||||
|
@scrollable
|
||||||
|
def scrolling_focused_title(self, widget):
|
||||||
|
return self._full_title
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
"""Update current title."""
|
||||||
|
try:
|
||||||
|
self._full_title = self._i3.get_tree().find_focused().name
|
||||||
|
except Exception:
|
||||||
|
self._full_title = "n/a"
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
@ -5,6 +5,7 @@
|
||||||
Parameters:
|
Parameters:
|
||||||
* traffic.exclude: Comma-separated list of interface prefixes to exclude (defaults to "lo,virbr,docker,vboxnet,veth")
|
* traffic.exclude: Comma-separated list of interface prefixes to exclude (defaults to "lo,virbr,docker,vboxnet,veth")
|
||||||
* traffic.states: Comma-separated list of states to show (prefix with "^" to invert - i.e. ^down -> show all devices that are not in state down)
|
* traffic.states: Comma-separated list of states to show (prefix with "^" to invert - i.e. ^down -> show all devices that are not in state down)
|
||||||
|
* traffic.showname: If set to False, hide network interface name (defaults to True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -23,7 +24,7 @@ class Module(bumblebee.engine.Module):
|
||||||
self._exclude = tuple(filter(len, self.parameter("exclude", "lo,virbr,docker,vboxnet,veth").split(",")))
|
self._exclude = tuple(filter(len, self.parameter("exclude", "lo,virbr,docker,vboxnet,veth").split(",")))
|
||||||
self._status = ""
|
self._status = ""
|
||||||
|
|
||||||
self._showname = self.parameter("showname", "True")
|
self._showname = bumblebee.util.asbool(self.parameter("showname", True))
|
||||||
self._prev = {}
|
self._prev = {}
|
||||||
self._states = {}
|
self._states = {}
|
||||||
self._states["include"] = []
|
self._states["include"] = []
|
||||||
|
@ -87,12 +88,12 @@ class Module(bumblebee.engine.Module):
|
||||||
|
|
||||||
name = "traffic-{}".format(interface)
|
name = "traffic-{}".format(interface)
|
||||||
|
|
||||||
if self._showname != "False":
|
if self._showname:
|
||||||
self.create_widget(widgets, name, interface)
|
self.create_widget(widgets, name, interface)
|
||||||
|
|
||||||
for direction in ["rx", "tx"]:
|
for direction in ["rx", "tx"]:
|
||||||
name = "traffic.{}-{}".format(direction, interface)
|
name = "traffic.{}-{}".format(direction, interface)
|
||||||
widget = self.create_widget(widgets, name, attributes={"theme.minwidth": "100.00MB"})
|
widget = self.create_widget(widgets, name, attributes={"theme.minwidth": "1000.00MB"})
|
||||||
prev = self._prev.get(name, 0)
|
prev = self._prev.get(name, 0)
|
||||||
speed = bumblebee.util.bytefmt(int(data[direction]) - int(prev))
|
speed = bumblebee.util.bytefmt(int(data[direction]) - int(prev))
|
||||||
widget.full_text(speed)
|
widget.full_text(speed)
|
||||||
|
|
|
@ -33,9 +33,9 @@ class Theme(object):
|
||||||
|
|
||||||
def _init(self, data):
|
def _init(self, data):
|
||||||
"""Initialize theme from data structure"""
|
"""Initialize theme from data structure"""
|
||||||
|
self._theme = data
|
||||||
for iconset in data.get("icons", []):
|
for iconset in data.get("icons", []):
|
||||||
self._merge(data, self._load_icons(iconset))
|
self._merge(data, self._load_icons(iconset))
|
||||||
self._theme = data
|
|
||||||
self._defaults = data.get("defaults", {})
|
self._defaults = data.get("defaults", {})
|
||||||
self._cycles = self._theme.get("cycle", [])
|
self._cycles = self._theme.get("cycle", [])
|
||||||
self.reset()
|
self.reset()
|
||||||
|
@ -174,7 +174,8 @@ class Theme(object):
|
||||||
if key in target and isinstance(target[key], dict):
|
if key in target and isinstance(target[key], dict):
|
||||||
self._merge(target[key], value)
|
self._merge(target[key], value)
|
||||||
else:
|
else:
|
||||||
target[key] = copy.deepcopy(value)
|
if not key in target:
|
||||||
|
target[key] = copy.deepcopy(value)
|
||||||
return target
|
return target
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
|
|
BIN
screenshots/title.png
Normal file
BIN
screenshots/title.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -1,61 +0,0 @@
|
||||||
# pylint: disable=C0103,C0111
|
|
||||||
|
|
||||||
import mock
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import tests.mocks as mocks
|
|
||||||
|
|
||||||
from bumblebee.input import LEFT_MOUSE
|
|
||||||
from bumblebee.modules.memory import Module
|
|
||||||
|
|
||||||
class VirtualMemory(object):
|
|
||||||
def __init__(self, percent):
|
|
||||||
self.percent = percent
|
|
||||||
|
|
||||||
class TestMemoryModule(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
mocks.setup_test(self, Module)
|
|
||||||
self._psutil = mock.patch("bumblebee.modules.memory.psutil")
|
|
||||||
self.psutil = self._psutil.start()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self._psutil.stop()
|
|
||||||
mocks.teardown_test(self)
|
|
||||||
|
|
||||||
def test_leftclick(self):
|
|
||||||
mocks.mouseEvent(stdin=self.stdin, button=LEFT_MOUSE, inp=self.input, module=self.module)
|
|
||||||
self.popen.assert_call("gnome-system-monitor")
|
|
||||||
|
|
||||||
def test_warning(self):
|
|
||||||
self.config.set("memory.critical", "80")
|
|
||||||
self.config.set("memory.warning", "70")
|
|
||||||
self.psutil.virtual_memory.return_value = VirtualMemory(75)
|
|
||||||
self.module.update_all()
|
|
||||||
self.assertTrue("warning" in self.module.state(self.anyWidget))
|
|
||||||
|
|
||||||
def test_critical(self):
|
|
||||||
self.config.set("memory.critical", "80")
|
|
||||||
self.config.set("memory.warning", "70")
|
|
||||||
self.psutil.virtual_memory.return_value = VirtualMemory(81)
|
|
||||||
self.module.update_all()
|
|
||||||
self.assertTrue("critical" in self.module.state(self.anyWidget))
|
|
||||||
|
|
||||||
def test_format(self):
|
|
||||||
self.config.set("memory.format", "memory used: {used}")
|
|
||||||
rv = VirtualMemory(50)
|
|
||||||
rv.total = 1000
|
|
||||||
rv.available = 500
|
|
||||||
self.psutil.virtual_memory.return_value = rv
|
|
||||||
self.module.update_all()
|
|
||||||
self.assertEquals("memory used: 500.00B", self.module.memory_usage(self.anyWidget))
|
|
||||||
|
|
||||||
def test_usage(self):
|
|
||||||
rv = VirtualMemory(50)
|
|
||||||
rv.total = 1000
|
|
||||||
rv.available = 500
|
|
||||||
self.psutil.virtual_memory.return_value = rv
|
|
||||||
self.module.update_all()
|
|
||||||
self.assertEquals("500.00B/1000.00B (50.00%)", self.module.memory_usage(self.anyWidget))
|
|
||||||
self.assertEquals(None, self.module.state(self.anyWidget))
|
|
||||||
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
38
themes/solarized-dark-awesome.json
Normal file
38
themes/solarized-dark-awesome.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"icons": [ "awesome-fonts" ],
|
||||||
|
"defaults": {
|
||||||
|
"separator-block-width": 0,
|
||||||
|
"separator": "",
|
||||||
|
"warning": {
|
||||||
|
"fg": "#002b36",
|
||||||
|
"bg": "#b58900"
|
||||||
|
},
|
||||||
|
"critical": {
|
||||||
|
"fg": "#002b36",
|
||||||
|
"bg": "#dc322f"
|
||||||
|
},
|
||||||
|
"fg": "#93a1a1", "bg": "#002b36"
|
||||||
|
},
|
||||||
|
"dnf": {
|
||||||
|
"good": {
|
||||||
|
"fg": "#002b36",
|
||||||
|
"bg": "#859900"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pacman": {
|
||||||
|
"good": {
|
||||||
|
"fg": "#002b36",
|
||||||
|
"bg": "#859900"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"battery": {
|
||||||
|
"charged": {
|
||||||
|
"fg": "#002b36",
|
||||||
|
"bg": "#859900"
|
||||||
|
},
|
||||||
|
"AC": {
|
||||||
|
"fg": "#002b36",
|
||||||
|
"bg": "#859900"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue