Add dot_config/qtile/.keep

Add dot_config/qtile/__pycache__/.keep
Add dot_config/qtile/__pycache__/bars.cpython-38.pyc
Add dot_config/qtile/__pycache__/bars.cpython-39.pyc
Add dot_config/qtile/__pycache__/colors.cpython-38.pyc
Add dot_config/qtile/__pycache__/colors.cpython-39.pyc
Add dot_config/qtile/__pycache__/config-done.cpython-38.pyc
Add dot_config/qtile/__pycache__/config.cpython-38.pyc
Add dot_config/qtile/__pycache__/config.cpython-39.pyc
Add dot_config/qtile/__pycache__/groups.cpython-38.pyc
Add dot_config/qtile/__pycache__/groups.cpython-39.pyc
Add dot_config/qtile/__pycache__/keys.cpython-38.pyc
Add dot_config/qtile/__pycache__/keys.cpython-39.pyc
Add dot_config/qtile/__pycache__/layouts.cpython-38.pyc
Add dot_config/qtile/__pycache__/layouts.cpython-39.pyc
Add dot_config/qtile/__pycache__/screens.cpython-38.pyc
Add dot_config/qtile/__pycache__/screens.cpython-39.pyc
Add dot_config/qtile/bars.py
Add dot_config/qtile/colors.py
Add dot_config/qtile/config.py
Add dot_config/qtile/groups.py
Add dot_config/qtile/keys.py
Add dot_config/qtile/layouts.py
Add dot_config/qtile/old_configs/.keep
Add dot_config/qtile/old_configs/config.py
Add dot_config/qtile/old_configs/sweenu/.keep
Add dot_config/qtile/old_configs/sweenu/bars.py
Add dot_config/qtile/old_configs/sweenu/colors.py
Add dot_config/qtile/old_configs/sweenu/config.py
Add dot_config/qtile/old_configs/sweenu/keys.py
Add dot_config/qtile/old_configs/sweenu/util/.keep
Add dot_config/qtile/old_configs/sweenu/util/__main__.py
Add dot_config/qtile/old_configs/sweenu/util/backlight.py
Add dot_config/qtile/old_configs/sweenu/util/monitor.py
Add dot_config/qtile/old_configs/sweenu/util/screenshot.py
Add dot_config/qtile/old_configs/sweenu/util/soundcard.py
Add dot_config/qtile/old_configs/sweenu/widgets.py
Add dot_config/qtile/screens.py
Add dot_config/qtile/scripts/.keep
Add dot_config/qtile/scripts/executable_autostart.sh
Add dot_config/qtile/themes/.keep
Add dot_config/qtile/themes/ayu-dark.json
Add dot_config/qtile/themes/dracula.json
Add dot_config/qtile/themes/hopscotch.json
Add dot_config/qtile/themes/material-darker.json
Add dot_config/qtile/themes/nord.json
Add dot_config/qtile/themes/one-dark.json
Add dot_config/qtile/themes/operator.json
Add dot_config/qtile/themes/royal.json
Add dot_config/qtile/themes/seashells.json
Add dot_config/qtile/themes/smyck.json
Add dot_config/qtile/themes/spacedust.json
Add dot_config/qtile/themes/spacegray.json
Add dot_config/qtile/themes/square.json
Add dot_config/qtile/themes/tomorrow-nb.json
This commit is contained in:
eeleater 2021-08-26 20:17:03 +02:00
parent d84f84d6cd
commit bc838a571d
55 changed files with 1181 additions and 0 deletions

View file

@ -0,0 +1,127 @@
from pathlib import Path
from libqtile import bar, widget
from colors import theme, border_color
icon_theme_path = Path.home() / '{{ icon_dir | replace(user_dir + '/', '') }}'
bar_size = 36
groupbox = {
'center_aligned': True,
'foreground': theme['very_light_white'],
'inactive': theme['gray'],
'other_current_screen_border': theme['gray'],
'this_current_screen_border': theme['dark_blue'],
'this_screen_border': theme['dark_blue'],
'urgent_border': theme['red'],
'urgent_text': theme['red']}
sep = {
'linewidth': 2,
'size_percent': 100,
'padding': 12}
soft_sep = {
'linewidth': 2,
'size_percent': 70,
'foreground': theme['dark_gray'],
'padding': 7}
tasklist = {
'border': border_color,
'max_title_width': 200,
'txt_floating': '🗗',
'txt_maximized': '🗖',
'txt_minimized': '🗕'}
volume = {'theme_path': icon_theme_path}
clock = {
'timezone': 'Europe/Paris',
'format': '%B %-d, %H:%M'}
music = widget.Mpris2(
background=theme['dark_blue'],
name='spotify',
scroll_chars=0,
stop_pause_text='',
display_metadata=['xesam:title', 'xesam:artist'],
objname="org.mpris.MediaPlayer2.spotify")
disk = widget.DF(
update_interval=3600,
warn_space=5,
format='{p} ({uf}{m})')
updates = widget.CheckUpdates(
distro='Arch_checkupdates',
display_format='{updates}',
execute='termite -e "pikaur -Syu"',
colour_have_updates=theme['dark_blue'],
colour_no_updates=theme['dark_green'],
update_interval=600)
battery = widget.Battery(
foreground=theme['green'],
low_percentage=0.10,
low_foreground=theme['red'],
update_delay=10,
format='{percent:.0%} {hour:d}:{min:02d} {watt:.2}W')
battery_icon = widget.BatteryIcon(
theme_path=icon_theme_path,
update_interval=120)
systray = widget.Systray(
icon_size=24
)
main_bar = bar.Bar(
[
widget.GroupBox(**groupbox, visible_groups=['a', 's', 'd', 'f',
'music', 'chat', 'game']),
widget.Sep(**sep),
widget.Volume(**volume),
music,
widget.TaskList(**tasklist),
systray,
widget.Sep(**sep),
disk,
updates,
widget.Sep(**soft_sep),
battery_icon,
battery,
widget.Sep(**soft_sep),
widget.Clock(**clock),
], bar_size)
bar1 = bar.Bar(
[
widget.GroupBox(**groupbox, visible_groups=['a', 's', 'd', 'f', 'game']),
widget.Sep(**sep),
widget.Volume(**volume),
music,
widget.TaskList(**tasklist),
systray,
widget.Sep(**sep),
disk,
updates,
widget.Sep(**soft_sep),
widget.Clock(**clock),
], bar_size)
bar2 = bar.Bar(
[
widget.GroupBox(**groupbox, visible_groups=['u', 'i', 'o', 'p', 'music', 'chat']),
widget.Sep(**sep),
widget.Volume(**volume),
widget.TaskList(**tasklist),
battery_icon,
battery,
widget.Sep(**soft_sep),
widget.Clock(**clock),
], bar_size)

View file

@ -0,0 +1,40 @@
# gruvbox
theme = {
'dark_black': '{{ theme.dark_black }}',
'black': '{{ theme.black }}',
'light_black': '{{ theme.light_black }}',
'very_light_black': '{{ theme.very_light_black }}',
'dark_gray': '{{ theme.dark_gray }}',
'gray': '{{ theme.gray }}',
'light_gray': '{{ theme.light_gray }}',
'very_light_gray': '{{ theme.very_light_gray }}',
'dark_white': '{{ theme.dark_white }}',
'white': '{{ theme.white }}',
'light_white': '{{ theme.light_white }}',
'very_light_white': '{{ theme.very_light_white }}',
'dark_red': '{{ theme.dark_red }}',
'red': '{{ theme.red }}',
'dark_green': '{{ theme.dark_green }}',
'green': '{{ theme.green }}',
'dark_yellow': '{{ theme.dark_yellow }}',
'yellow': '{{ theme.yellow }}',
'dark_blue': '{{ theme.dark_blue }}',
'blue': '{{ theme.blue }}',
'dark_purple': '{{ theme.dark_purple }}',
'purple': '{{ theme.purple }}',
'dark_teal': '{{ theme.dark_teal }}',
'teal': '{{ theme.teal }}',
'dark_orange': '{{ theme.dark_orange }}',
'orange': '{{ theme.orange }}',
}
border_color = theme['white']

View file

@ -0,0 +1,131 @@
import re
from subprocess import run
from pathlib import Path
from typing import List
from libqtile import layout, hook
from libqtile.config import Group, Match, Screen, Rule
from bars import main_bar, bar1, bar2
from keys import keys, mouse, sc, get_backlight_keys
from colors import border_color, theme
from util import qtile_func
from util.monitor import enable_monitor
keys = keys
mouse = mouse
screens: List[Screen] = []
groups = [
Group('game', layouts=[layout.Max()], persist=False, init=False,
matches=[Match(wm_class=['Steam'])], label=''),
Group('chat', layouts=[layout.Max()], persist=False, init=False,
matches=[Match(wm_class=['discord'])], label=''),
Group('music', layouts=[layout.Max()], persist=False, init=False,
matches=[Match(wm_class=[re.compile('spotify', re.I)])], label=''),
]
float_rules = [
{'wmclass': 'confirm'},
{'wmclass': 'dialog'},
{'wmclass': 'download'},
{'wmclass': 'error'},
{'wmclass': 'file_progress'},
{'wmclass': 'notification'},
{'wmclass': 'splash'},
{'wmclass': 'toolbar'},
{'wmclass': 'Xephyr'},
{'wmclass': 'feh'},
{'wmclass': 'Sms.py'},
{'wmclass': 'leagueclientux.exe'},
{'wmclass': 'Gcr-prompter'},
{'wmclass': 'scrcpy'},
{'wname': 'Friends'},
]
floating_layout = layout.Floating(border_focus=f'#{border_color}',
float_rules=float_rules)
layouts = [
layout.Max(),
layout.Stack(num_stacks=2, border_focus=f'#{border_color}')
]
widget_defaults = {'font': 'DejaVu Sans',
'fontsize': 18,
'padding': 4,
'foreground': theme['very_light_white'],
'background': theme['dark_black']}
def setup_monitors(qtile):
monitors = qtile.conn.monitors
nb_monitors = len(monitors)
if nb_monitors == 1:
run('xrandr --auto'.split())
elif nb_monitors == 2:
laptop_monitor = None
other_monitor = None
for monitor in monitors:
if monitor.name.startswith('eDP'):
laptop_monitor = monitor
else:
other_monitor = monitor
enable_monitor(other_monitor, primary=True, side='left-of',
relative_monitor=laptop_monitor)
def setup_screens(qtile, screens, groups):
nb_monitors = len(qtile.conn.monitors)
if nb_monitors == 1:
screens.append(Screen(top=main_bar))
groups += [Group(i) for i in 'asdf']
else:
screens += [Screen(top=bar1), Screen(top=bar2)]
groups += [Group(i) for i in 'asdfuiop']
def main(qtile):
global keys
setup_monitors(qtile)
setup_screens(qtile, screens, groups)
keys += get_backlight_keys(qtile)
def wallpaper():
wallpaper_path = Path.home() / '.wallpaper'
run(['feh', '--bg-scale', wallpaper_path])
@hook.subscribe.startup
def autostart():
wallpaper()
sc.set_profile('analog')
@hook.subscribe.addgroup
def go_to_group(qtile, group):
try:
qtile.groupMap[group].cmd_toscreen()
except AttributeError:
pass
@hook.subscribe.screen_change
def configure_monitors(qtile, ev):
setup_monitors(qtile)
qtile.cmd_restart()
dgroups_app_rules: List[Rule] = []
dgroups_key_binder = None
follow_mouse_focus = False
bring_front_click = False
cursor_warp = False
auto_fullscreen = True
focus_on_window_activation = 'focus'
wmname = 'LG3D'

View file

@ -0,0 +1,124 @@
from libqtile.config import Key, Drag
from libqtile.command import lazy
from util.backlight import Backlight
from util.screenshot import screenshot
from util.soundcard import SoundCard
from util import qtile_func
# super = mod4, alt = mod1
mod = 'mod4'
BROWSER = '{{ browser }}'
TERM= '{{ term }}'
MUSIC_PLAYER = 'spotify'
# add 'PlayPause', 'Next' or 'Previous'
spotify_cmd = ('dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify '
'/org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.')
amixer_cmd = 'amixer -D pulse set Master'
rofi_cmd = 'rofi -combi-modi window,run -show combi -modi combi -monitor -4'
sc = SoundCard('alsa_card.pci-0000_00_1f.3')
def app_or_group(group, app):
"""Go to app if already open else open it."""
def f(qtile):
if group in {'music'}:
qtile.cmd_to_screen(1)
try:
qtile.groupMap[group].cmd_toscreen()
except KeyError:
qtile.cmd_spawn(app)
return f
def go_to_group(group):
"""The groups 'asdf' are accessible on screen 1, 'uiop' on screen 2."""
def f(qtile):
if group in 'asdf':
qtile.cmd_to_screen(0)
qtile.groupMap[group].cmd_toscreen()
elif group in 'uiop':
qtile.cmd_to_screen(1)
qtile.groupMap[group].cmd_toscreen()
return f
# TODO: make this function work for more than two monitors
def get_backlight_keys(qtile):
monitors = qtile.conn.monitors
keys = []
for monitor in monitors:
bl = Backlight(ctrl=monitor.backlight_ctrl)
if monitor.name.startswith('eDP'):
keys.append(Key([], 'XF86MonBrightnessUp', lazy.function(bl.change_backlight('inc'))))
keys.append(Key([], 'XF86MonBrightnessDown', lazy.function(bl.change_backlight('dec'))))
keys.append(Key([], 'F7', lazy.function(bl.turn_off_screen(monitor.x))))
else:
keys.append(Key([mod], 'Up', lazy.function(bl.change_backlight('inc'))))
keys.append(Key([mod], 'Down', lazy.function(bl.change_backlight('dec'))))
keys.append(Key([mod], 'F7', lazy.function(bl.turn_off_screen(monitor.x))))
return keys
keys = [
Key([mod, 'control'], 'p', lazy.spawn('xbacklight -set 50')),
Key([mod], 'k', lazy.layout.down()), # noqa
Key([mod], 'j', lazy.layout.up()), # noqa
Key([mod], 'space', lazy.layout.next()), # noqa
Key([mod, 'control'], 'k', lazy.layout.shuffle_down()), # noqa
Key([mod, 'control'], 'j', lazy.layout.shuffle_up()), # noqa
Key([mod, 'shift'], 'h', lazy.layout.client_to_previous()), # noqa
Key([mod, 'shift'], 'l', lazy.layout.client_to_next()), # noqa
Key([mod, 'shift'], 'space', lazy.layout.rotate()), # noqa
Key([mod, 'shift'], 'Return', lazy.layout.toggle_split()), # noqa
Key([mod], 'slash', lazy.screen.toggle_group()), # noqa
Key([mod], 'x', lazy.window.kill()), # noqa
Key([mod], 'y', lazy.window.toggle_floating()), # noqa
Key([mod], '1', lazy.to_screen(0)), # noqa
Key([mod], '2', lazy.to_screen(1)), # noqa
Key([mod], 'Tab', lazy.next_layout()), # noqa
Key([mod, 'control'], 'r', lazy.restart()), # noqa
Key([mod, 'control'], 'q', lazy.shutdown()), # noqa
# Audio
Key([], 'XF86AudioMute', lazy.spawn(amixer_cmd + ' 1+ toggle')), # noqa
Key([], 'XF86AudioRaiseVolume', lazy.spawn(amixer_cmd + ' 5%+')), # noqa
Key([], 'XF86AudioLowerVolume', lazy.spawn(amixer_cmd + ' 5%-')), # noqa
Key([], 'XF86AudioPlay', lazy.spawn(spotify_cmd + 'PlayPause')), # noqa
Key([], 'XF86AudioNext', lazy.spawn(spotify_cmd + 'Next')), # noqa
Key([], 'XF86AudioPrev', lazy.spawn(spotify_cmd + 'Previous')), # noqa
Key([mod], 'bracketleft', lazy.function(sc.change_sink('prev'))), # noqa
Key([mod], 'bracketright', lazy.function(sc.change_sink('next'))), # noqa
Key([], 'F8', lazy.function(sc.swap_profile())), # noqa
# Apps
Key([mod], 't', lazy.spawn(rofi_cmd)), # noqa
Key([mod], 'Return', lazy.spawn(TERM)), # noqa
Key([mod], 'b', lazy.spawn(BROWSER)), # noqa
Key([mod], 'g', lazy.function(app_or_group('game', 'steam'))), # noqa
Key([mod], 'n', lazy.function(app_or_group('chat', 'discord'))), # noqa
Key([mod], 'm', lazy.function(app_or_group('music', MUSIC_PLAYER))), # noqa
# Screenshots
Key([], 'Print', lazy.function(screenshot())), # noqa
Key(['control'], 'Print', lazy.spawn('deepin-screenshot')), # noqa
]
for i in 'asdfuiop':
keys.append(Key([mod], i, lazy.function(go_to_group(i)))) # noqa
keys.append(Key([mod, 'shift'], i, lazy.window.togroup(i))) # noqa
mouse = [
Drag([mod], "Button1", lazy.window.set_position_floating(),
start=lazy.window.get_position()),
Drag([mod, 'control'], "Button1", lazy.window.set_size_floating(),
start=lazy.window.get_size()),
]

View file

@ -0,0 +1,23 @@
from functools import wraps
from subprocess import run, PIPE
from typing import Callable, Any
import parse
def qtile_func(func: Callable[..., Any]) -> Callable[..., Any]:
"""
This decorator makes a function suitable to be used as a parameter for
`lazy.function()` by making the wrapped function return a function that
takes the qtile instance as first parameter.
"""
@wraps(func)
def wrapper(*args, **kwargs):
def f(qtile):
func(*args, **kwargs)
return f
return wrapper
def notify(summary: str, body: str, urgency: str='normal') -> None:
run(['notify-send', '-u', urgency, summary, body])

View file

@ -0,0 +1,50 @@
from subprocess import run, PIPE
from typing import Optional
from pynput import mouse
from . import qtile_func
class Backlight:
def __init__(self, ctrl: Optional[str]=None) -> None:
self.command = ['xbacklight']
if ctrl:
self.command += ['-ctrl', ctrl]
def _get_brightness(self) -> int:
return int(run(self.command + ['-get'], stdout=PIPE).stdout)
def _set_brightness(self, percentage: int) -> None:
run(self.command + [f'-set', str(percentage)])
@qtile_func
def change_backlight(self, action: str) -> None:
"""
Increase or decrease bightness.
Takes 'dec' or 'inc' as parameter. Goes 1% percent at a time from
1% to 40% and 10% at a time from 40% to 100%.
"""
brightness = self._get_brightness()
if brightness != 1 or action != 'dec':
if (brightness > 49 and action == 'dec') \
or (brightness > 39 and action == 'inc'):
run(self.command + [f'-{action}', '10', '-fps', '10'])
else:
run(self.command + [f'-{action}', '1'])
@qtile_func
def turn_off_screen(self, screen_offset: int) -> None:
"""
Turn off the laptop's screen.
Use xset if there is only one screen, else, set backlight to
zero. In both case, moving the mouse will turn on the screen.
"""
current_brightness = self._get_brightness()
self._set_brightness(0)
def on_move(x: int, y: int):
if x > screen_offset:
self._set_brightness(current_brightness)
raise mouse.Listener.StopException
mouse.Listener(on_move=on_move).start()

View file

@ -0,0 +1,24 @@
from subprocess import run
from pathlib import Path
from typing import Optional
from libqtile.log_utils import logger
from libqtile.xcbq import Monitor
from .backlight import Backlight
Side = str # one of 'left-of', 'right-of', 'above', 'below' or 'same-as'
def enable_monitor(monitor: Monitor, primary: bool=False, side: Optional[Side]=None,
relative_monitor: Optional[Monitor]=None) -> None:
command = ['xrandr', '--output', monitor.name, '--auto']
if primary:
command += ['--primary']
if side:
if not relative_monitor:
raise Exception('Need a monitor to be relative to')
command += ['--{}'.format(side), relative_monitor.name]
run(command)
logger.info(f'Running command: {" ".join(command)}')

View file

@ -0,0 +1,16 @@
from time import time
from pathlib import Path
from subprocess import run, PIPE
from . import qtile_func
@qtile_func
def screenshot(save: bool=True, copy: bool=True) -> None:
shot = run(['maim'], stdout=PIPE)
if save:
path = Path.home() / 'Pictures'
path /= f'screenshot_{str(int(time() * 100))}.png'
with open(path, 'wb') as sc:
sc.write(shot.stdout)
if copy:
run('xclip -sel clip -t image/png'.split(), input=shot.stdout)

View file

@ -0,0 +1,79 @@
from subprocess import run, PIPE
import parse
from . import qtile_func, notify
class SoundCard():
def __init__(self, primary_card_name):
self.primary_card = primary_card_name
def get_current_sink(self):
cp = run(['pactl', 'info'], stdout=PIPE)
output = cp.stdout.decode('utf-8')
return parse.search('Default Sink: {}\n', output)[0]
def list_sinks(self):
"""Generator that yields for each sink, the sink and card name."""
cp = run(['pactl', 'list', 'sinks'], stdout=PIPE)
output = cp.stdout.decode('utf-8')
for sink in output.split('\nSink'):
sink_name = parse.search('Name: {}\n', sink)[0]
card_name = parse.search('alsa.card_name = "{}"', sink)[0]
yield sink_name, card_name
def set_new_sink(self, sink_card_tuple):
run(['pactl', 'set-default-sink', sink_card_tuple[0]])
def list_sink_inputs(self):
cp = run(['pactl', 'list', 'short', 'sink-inputs'], stdout=PIPE)
output = cp.stdout.decode('utf-8')
return {line.split()[0] for line in output.split('\n') if line}
def move_sink_input(self, name, new_sink):
run(['pactl', 'move-sink-input', name, new_sink])
def get_current_profile(self):
cp = run(['pactl', 'list', 'cards'], stdout=PIPE)
cp = run(['grep', 'Active'], stdout=PIPE, input=cp.stdout)
return 'hdmi' if b'hdmi' in cp.stdout else 'analog'
def set_profile(self, profile):
cmd = f'output:{profile}-stereo+input:analog-stereo'
run(['pactl', 'set-card-profile', self.primary_card, cmd])
@qtile_func
def change_sink(self, direction):
sinks = list(self.list_sinks())
# get the index of the tuple containing the current default sink
current_sink = self.get_current_sink()
for index, tup in enumerate(sinks):
if current_sink in tup:
default_sink_index = index
break
if direction == 'next':
new_sink = sinks[default_sink_index - 1]
elif direction == 'prev':
new_sink = sinks[(default_sink_index + 1) % len(sinks)]
self.set_new_sink(new_sink)
notify('Sound Card', new_sink[1])
# move current sink inputs, if any, to the new default sink
sink_inputs = self.list_sink_inputs()
if sink_inputs:
for sink_input in sink_inputs:
self.move_sink_input(sink_input, new_sink[0])
@qtile_func
def swap_profile(self):
profile = self.get_current_profile()
if profile == 'analog':
self.set_profile('hdmi')
notify('Sound Profile', 'HDMI')
elif profile == 'hdmi':
self.set_profile('analog')
notify('Sound Profile', 'Analog')

View file

@ -0,0 +1,9 @@
import subprocess
from libqtile import widget
class CheckUpdates(widget.CheckUpdates):
def __init__(self, **config):
super().__init__(**config)
self.cmd_dict.update({'Arch': ('pikaur -Sup', 0)})