Created
January 31, 2019 11:22
-
-
Save heitzmann/06d3e515274bc9823e4a81aa09984f20 to your computer and use it in GitHub Desktop.
Qtile configuration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import os | |
import subprocess | |
import platform | |
from libqtile.config import Key, Screen, Group, Drag, Click | |
from libqtile.command import lazy | |
from libqtile import layout, bar, widget, hook | |
import custom | |
home = os.path.expanduser('~') | |
icons = home + '/.config_sync/icons/' | |
hostname = platform.uname().node | |
num_monitors = int(subprocess.run('xrandr|grep " connected"|wc -l', shell=True, stdout=subprocess.PIPE).stdout) | |
space = 12 | |
mod = 'mod4' | |
c_bgn = '#000000' | |
c_hig = '#5b5ec0' | |
c_alt = '#e05b5e' | |
c_txt = '#d9e6f2' | |
c_shd = '#939393' | |
@hook.subscribe.startup_once | |
def startup(): | |
subprocess.call([home + '/.config/qtile/startup.sh']) | |
@hook.subscribe.screen_change | |
def randrchange(qtile, ev): | |
qtile.cmd_restart() | |
layout_defaults = dict( | |
border_focus=c_alt, | |
border_normal=c_bgn, | |
border_focus_stack=c_alt, | |
border_normal_stack=c_bgn, | |
grow_amount=10, | |
border_width=2, | |
margin=6) | |
layouts = [ | |
layout.Columns(fair=True, **layout_defaults), | |
layout.Bsp(fair=True, **layout_defaults), | |
] | |
floating_layout = layout.Floating(float_rules=[ | |
{ | |
'wmclass': 'Matplotlib' | |
}, | |
{ | |
'wmclass': 'cataclysm-tiles' | |
}, | |
{ | |
'wmclass': 'file_progress' | |
}, | |
{ | |
'wmclass': 'notification' | |
}, | |
{ | |
'wmclass': 'toolbar' | |
}, | |
{ | |
'wmclass': 'splash' | |
}, | |
{ | |
'wmclass': 'dialog' | |
}, | |
{ | |
'wmclass': 'pinentry' | |
}, | |
{ | |
'wmclass': 'pinentry-gtk-2' | |
}, | |
{ | |
'wname': 'Execute File' | |
}, | |
{ | |
'wname': 'Open' | |
}, | |
{ | |
'wname': 'Confirm File Replacing' | |
}, | |
{ | |
'role': 'about' | |
}, | |
]) | |
groups = [Group(str((i + 1) % 10)) for i in range(10)] | |
keys = [ | |
# System | |
Key(['mod1', 'control'], 'Delete', | |
lazy.spawn(home + '/.config/qtile/shutdown.sh')), | |
Key([mod, 'control'], 'q', lazy.shutdown()), | |
Key([mod, 'control'], 'r', lazy.restart()), | |
Key([mod, 'control'], 'z', lazy.spawn('slock')), | |
Key([mod, 'control', 'shift'], 'z', lazy.spawn('xtrlock')), | |
Key([mod, 'control'], 'Tab', lazy.next_layout()), | |
Key([mod], 'F10', lazy.window.toggle_floating()), | |
Key([mod], 'F11', lazy.window.toggle_fullscreen()), | |
# Layout Columns/Bsp | |
Key([mod], 'j', lazy.layout.down()), | |
Key([mod], 'k', lazy.layout.up()), | |
Key([mod], 'h', lazy.layout.left()), | |
Key([mod], 'l', lazy.layout.right()), | |
Key([mod], 'n', lazy.group.next_window()), | |
Key([mod], 'u', lazy.group.prev_window()), | |
Key([mod, 'shift'], 'j', lazy.layout.shuffle_down()), | |
Key([mod, 'shift'], 'k', lazy.layout.shuffle_up()), | |
Key([mod, 'shift'], 'h', lazy.layout.shuffle_left()), | |
Key([mod, 'shift'], 'l', lazy.layout.shuffle_right()), | |
Key([mod, "mod1"], "j", lazy.layout.flip_down()), | |
Key([mod, "mod1"], "k", lazy.layout.flip_up()), | |
Key([mod, "mod1"], "h", lazy.layout.flip_left()), | |
Key([mod, "mod1"], "l", lazy.layout.flip_right()), | |
Key([mod, 'control'], 'j', lazy.layout.grow_down()), | |
Key([mod, 'control'], 'k', lazy.layout.grow_up()), | |
Key([mod, 'control'], 'h', lazy.layout.grow_left()), | |
Key([mod, 'control'], 'l', lazy.layout.grow_right()), | |
Key([mod, 'shift'], 'n', lazy.layout.normalize()), | |
Key([mod], 'Return', lazy.layout.toggle_split()), | |
# Screen | |
Key([mod], 'F1', lazy.spawn('light -p -U 10')), | |
Key([mod], 'F2', lazy.spawn('light -p -A 10')), | |
Key([mod, 'control'], 'Down', | |
lazy.spawn(home + '/scripts/displayctl.sh inverted')), | |
Key([mod, 'control'], 'Left', | |
lazy.spawn(home + '/scripts/displayctl.sh left')), | |
Key([mod, 'control'], 'Right', | |
lazy.spawn(home + '/scripts/displayctl.sh right')), | |
Key([mod, 'control'], 'Up', | |
lazy.spawn(home + '/scripts/displayctl.sh upright')), | |
Key([mod, 'control'], '0', lazy.spawn(home + '/scripts/displayctl.sh')), | |
Key([mod], 'Tab', lazy.next_screen()), | |
# Audio | |
Key([mod], 'minus', lazy.spawn('amixer sset Master,0 5%-')), | |
Key([mod], 'equal', lazy.spawn('amixer sset Master,0 5%+')), | |
Key([], 'XF86AudioLowerVolume', lazy.spawn('amixer sset Master,0 5%-')), | |
Key([], 'XF86AudioRaiseVolume', lazy.spawn('amixer sset Master,0 5%+')), | |
Key([], 'XF86AudioMute', lazy.spawn('amixer sset Master,0 toggle')), | |
Key([], 'XF86AudioPlay', | |
lazy.spawn( | |
'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify ' | |
'/org/mpris/MediaPlayer2 ' | |
'org.mpris.MediaPlayer2.Player.PlayPause')), | |
Key([], 'XF86AudioStop', | |
lazy.spawn( | |
'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify ' | |
'/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Stop')), | |
Key([], 'XF86AudioNext', | |
lazy.spawn( | |
'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify ' | |
'/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next')), | |
Key([], 'XF86AudioPrev', | |
lazy.spawn( | |
'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify ' | |
'/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous')), | |
# Window | |
Key(['mod1'], 'F4', lazy.window.kill()), | |
Key([mod], 'q', lazy.window.kill()), | |
Key([mod], 'b', lazy.spawn('chromium')), | |
Key([mod], 'f', lazy.spawn('termite -t "File Manager" -e lf')), | |
Key([mod], 't', lazy.spawn('termite')), | |
Key([mod], 'r', lazy.spawn('rofi -show run')), | |
Key([mod], 'space', lazy.spawn('rofi -show drun')), | |
# Group | |
Key([mod], 'Left', lazy.screen.prev_group()), | |
Key([mod], 'Right', lazy.screen.next_group()), | |
] | |
if num_monitors > 1: | |
keys.extend( | |
Key([mod], g.name[:1], lazy.to_screen(i % num_monitors), lazy.group[g.name].toscreen()) | |
for i, g in enumerate(groups)) | |
else: | |
keys.extend( | |
Key([mod], g.name[:1], lazy.group[g.name].toscreen()) | |
for g in groups) | |
keys.extend( | |
Key([mod, 'shift'], g.name[:1].lower(), lazy.window.togroup(g.name)) | |
for g in groups) | |
wid_defaults = dict( | |
font='Lato', | |
fontsize=24 if hostname == 'imac03' else 12, | |
pading=0, | |
foreground=c_txt) | |
def host_widgets(): | |
global hostname | |
if hostname == 'yocto': | |
return [ | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'monitor.png', scale=True), | |
widget.Backlight(backlight_name='intel_backlight', **wid_defaults), | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'battery.png', scale=True), | |
widget.Battery(charge_char='+', discharge_char='-', error_message='error', | |
format='{percent:2.0%} ({char}{hour:d}:{min:02d})', hide_threshold=None, | |
low_percentage=0.1, low_foreground=c_alt[1:], update_delay=10, **wid_defaults), | |
] | |
else: | |
return [ | |
widget.TextBox(' | ', **wid_defaults), | |
widget.ThermalSensor(tag_sensor='temp1', update_interval=10, foreground_alert=c_alt[1:], **wid_defaults), | |
] | |
def system_info(): | |
global hostname | |
return ([] if hostname == 's328a-1' else [ | |
custom.Host(address='XXXXX', label='', label_alert=' s328a-1 down', | |
foreground_alert=c_alt[1:], update_interval=30, **wid_defaults), | |
widget.Spacer(space), | |
]) + [ | |
custom.Host(address='XXXXX', label='', label_alert=' Ras314 down', | |
foreground_alert=c_alt[1:], update_interval=30, **wid_defaults), | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'chip.png', scale=True), | |
custom.Cpu(update_interval=2, foreground_alert=c_alt[1:], **wid_defaults), | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'memory.png', scale=True), | |
custom.Memory(update_interval=2, foreground_alert=c_alt[1:], **wid_defaults), | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'hdd.png', scale=True), | |
*[widget.DF(partition=p, warn_space=2, measure='G', format=' {p}:{uf}{m}', | |
visible_on_warn=False, update_interval=60, warn_color=c_alt[1:], **wid_defaults) | |
for p in (('/', ) if hostname in ['yocto', 'imac03'] else ('/', '/home', '/var'))], | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'temperature.png', scale=True), | |
widget.ThermalSensor(tag_sensor='Package id 0', update_interval=10, foreground_alert=c_alt[1:], **wid_defaults), | |
*host_widgets(), | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'volume.png', scale=True), | |
widget.Volume(update_interval=0.5, step=5, **wid_defaults), | |
] | |
screens = [ | |
Screen( | |
top=bar.Bar([ | |
widget.CurrentLayoutIcon(scale=0.7, **wid_defaults), | |
widget.GroupBox(active=c_txt[1:], inactive=c_shd[1:], urgent_text=c_bgn[1:], | |
this_current_screen_border=c_hig[1:], this_screen_border=c_shd[1:], | |
other_screen_border=c_bgn[1:], urgent_border=c_alt[1:], | |
highlight_method='block', urgent_alert_method='block', rounded=False, | |
disable_drag=True, hide_unused=True, padding=3, **wid_defaults), | |
widget.WindowTabs(selected=('[', ']'), separator=' | ', **wid_defaults), | |
*(system_info() if i == 0 else []), | |
widget.Spacer(space), | |
widget.Image(filename=icons + 'schedule.png', scale=True), | |
widget.Clock(format='%Y-%m-%d %H:%M', **wid_defaults), | |
widget.Spacer(space), | |
*([widget.Systray(), widget.Spacer(space)] if i == 0 else []), | |
widget.LaunchBar(progs=[('Exit', home + '/.config/qtile/shutdown.sh -location 3', 'Exit menu')], | |
default_icon=home + '/.local/share/icons/logout.png', **wid_defaults), | |
], 42 if hostname == 'imac03' else 26, background=c_bgn)) for i in range(num_monitors) | |
] | |
# Drag floating layouts. | |
mouse = [ | |
Drag([mod], 'Button1', lazy.window.set_position_floating(), start=lazy.window.get_position()), | |
Drag([mod], 'Button3', lazy.window.set_size_floating(), start=lazy.window.get_size()), | |
Click([mod], 'Button2', lazy.window.bring_to_front()), | |
] | |
main = None | |
follow_mouse_focus = False | |
bring_front_click = False | |
cursor_warp = False | |
auto_fullscreen = True | |
focus_on_window_activation = 'smart' | |
# XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this | |
# string besides java UI toolkits; you can see several discussions on the | |
# mailing lists, github issues, and other WM documentation that suggest setting | |
# this string if your java app doesn't work correctly. We may as well just lie | |
# and say that we're a working one by default. | |
# | |
# We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in | |
# java that happens to be on java's whitelist. | |
wmname = 'LG3D' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
from libqtile.widget import base | |
from libqtile.widget import groupbox | |
class Cpu(base.ThreadedPollText): | |
"""Display CPU usage""" | |
defaults = [ | |
('update_interval', 1, 'The update interval.'), | |
('threshold', 75, 'Alert treshold value.'), | |
('foreground_alert', 'ff0000', 'Alert color'), | |
] | |
def __init__(self, **config): | |
base.ThreadedPollText.__init__(self, **config) | |
self.add_defaults(Cpu.defaults) | |
self.stats = self.get_stats() | |
def get_stats(self): | |
with open('/proc/stat', 'r') as f: | |
# user, nice, system, idle | |
val = [int(x) for x in f.readline().split(None, 5)[1:-1]] | |
return sum(val[:-1]), sum(val) | |
def poll(self): | |
stats = self.get_stats() | |
use = (100 * (stats[0] - self.stats[0])) // (stats[1] - self.stats[1]) | |
self.stats = stats | |
self.layout.colour = (self.foreground_alert | |
if use > self.threshold else self.foreground) | |
return f'{use}%'.ljust(4) | |
class Hdd(base.ThreadedPollText): | |
"""Display HDD I/O""" | |
defaults = [ | |
('bytes_per_sector', 512, 'Sector size in bytes.'), | |
('update_interval', 1, 'The update interval.'), | |
] | |
def __init__(self, **config): | |
base.ThreadedPollText.__init__(self, **config) | |
self.add_defaults(Hdd.defaults) | |
self.stats = self.get_stats() | |
def get_unit(self, b): | |
for unit, div in [('GB', 2**30), ('MB', 2**20), ('kB', 2**10)]: | |
if b >= div: | |
return b / div, unit | |
return b, 'B' | |
def get_stats(self): | |
r = w = 0 | |
with open('/proc/diskstats', 'r') as f: | |
for line in f: | |
info = line.split() | |
if len(info[2]) == 3: | |
r += int(info[5]) | |
w += int(info[9]) | |
# sectors read, written | |
return r, w | |
def poll(self): | |
stats = self.get_stats() | |
r, ru = self.get_unit((stats[0] - self.stats[0]) * | |
self.bytes_per_sector / self.update_interval) | |
w, wu = self.get_unit((stats[1] - self.stats[1]) * | |
self.bytes_per_sector / self.update_interval) | |
self.stats = stats | |
return f'R:{r:-.3g}{ru}/s'.ljust(11) + f'W:{w:-.3g}{wu}/s'.ljust(10) | |
class Memory(base.ThreadedPollText): | |
"""Display memory usage""" | |
defaults = [ | |
('update_interval', 1, 'The update interval.'), | |
('threshold', 75, 'Alert treshold value.'), | |
('foreground_alert', 'ff0000', 'Alert color'), | |
] | |
def __init__(self, **config): | |
base.ThreadedPollText.__init__(self, **config) | |
self.add_defaults(Memory.defaults) | |
def get_stats(self): | |
total = free = None | |
with open('/proc/meminfo', 'r') as f: | |
for line in f: | |
if line.startswith('MemTotal'): | |
total = int(line.split()[1]) | |
if free is not None: | |
break | |
elif line.startswith('MemAvailable'): | |
free = int(line.split()[1]) | |
if total is not None: | |
break | |
return 100 - (100 * free) // total | |
def poll(self): | |
use = self.get_stats() | |
self.layout.colour = self.foreground_alert if use > self.threshold else self.foreground | |
return f'{use}%'.ljust(4) | |
class Net(base.ThreadedPollText): | |
"""Displays interface down and up speed""" | |
defaults = [ | |
('interface', 'wlan0', 'The interface to monitor'), | |
('update_interval', 1, 'The update interval.'), | |
] | |
def __init__(self, **config): | |
base.ThreadedPollText.__init__(self, **config) | |
self.add_defaults(Net.defaults) | |
self.stats = self.get_stats() | |
def get_unit(self, b): | |
for unit, div in [('GB', 2**30), ('MB', 2**20), ('kB', 2**10)]: | |
if b >= div: | |
return b / div, unit | |
return b, 'B' | |
def get_stats(self): | |
with open('/proc/net/dev', 'r') as f: | |
for line in f.readlines()[2:]: | |
info = line.split() | |
if info[0][:-1] == self.interface: | |
# down, up | |
return float(info[1]), float(info[9]) | |
return 0, 0 | |
def poll(self): | |
stats = self.get_stats() | |
d, du = self.get_unit( | |
(stats[0] - self.stats[0]) / self.update_interval) | |
u, uu = self.get_unit( | |
(stats[1] - self.stats[1]) / self.update_interval) | |
self.stats = stats | |
return f'D:{d:-.3g}{du}/s'.ljust(11) + f'U:{u:-.3g}{uu}/s'.ljust(10) | |
class Host(base.ThreadedPollText): | |
"""Check host status.""" | |
defaults = [ | |
('address', 'localhost', 'Host address to check.'), | |
('update_interval', 10, 'The update interval.'), | |
('label', '{address}', 'Text to display when host is reachable.'), | |
('label_alert', '{address}', | |
'Text to display when host is unreachable.'), | |
('foreground_alert', 'ff0000', 'Alert color'), | |
] | |
def __init__(self, **config): | |
base.ThreadedPollText.__init__(self, **config) | |
self.add_defaults(Host.defaults) | |
def poll(self): | |
ret = subprocess.run(['ping', '-qc', '1', '-W', '1', self.address]) | |
if ret.returncode == 0: | |
label = self.label.format(address=self.address) | |
self.layout.colour = self.foreground | |
else: | |
label = self.label_alert.format(address=self.address) | |
self.layout.colour = self.foreground_alert | |
return label |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment