#!/usr/bin/env python3 import argparse import json import logging from os.path import expanduser import subprocess import dialog class NoMatchingProfile(ValueError): pass class LogLevel: def __init__(self, value: str) -> None: try: self.numerical_level = logging.getLevelNamesMapping()[value.upper()] except KeyError: raise ValueError("invalid value") class MonitorMenu(): def __init__(self, config_file='~/.config/monitor-profiles.json'): with open(expanduser(config_file)) as fh: self.profiles = json.load(fh) self.d = dialog.Dialog(autowidgetsize=True) def run(self, profile_idx=None): choices = [] if profile_idx is None: i = 0 for p in self.profiles: choices.append((str(i), p['name'])) i += 1 code, profile_idx = self.d.menu( 'Select the profile you want to use.', choices=choices) if code in (self.d.ESC, self.d.CANCEL): return try: profile = self.profiles[int(profile_idx)] except IndexError: raise NoMatchingProfile from None # We build the command line starting from just "xrandr" and adding # arguments. xrandr_cmd = ['xrandr'] feh_cmd = ['feh', '--bg-fill'] try: xrandr_cmd += profile['xrandr-opts'] except KeyError: pass for monitor in profile['monitors']: xrandr_cmd.extend(monitor['xrandr-opts']) if monitor.get('background') is not None: feh_cmd.append(monitor['background']) logging.debug("Executing: %s", xrandr_cmd) subprocess.run(xrandr_cmd, check=False) logging.debug("Executing: %s", feh_cmd) subprocess.run(feh_cmd, check=False) def main(): parser = argparse.ArgumentParser() parser.add_argument("--log-level", "--loglevel", type=LogLevel, default="info") parser.add_argument("--index", type=int, required=False) args = parser.parse_args() logging.basicConfig(level=args.log_level.numerical_level) menu = MonitorMenu() if args.index is not None: menu.run(profile_idx=args.index) else: menu.run() if __name__ == '__main__': main()