From a5c63938cd66d632b6e8bdfe555ff915c1c733c9 Mon Sep 17 00:00:00 2001 From: hellerve Date: Tue, 25 Jun 2019 17:01:44 +0200 Subject: [PATCH] gui: better font section --- alacritty_config_gui.py | 217 ++++++++++++++++++++++++++++++++-------- 1 file changed, 178 insertions(+), 39 deletions(-) diff --git a/alacritty_config_gui.py b/alacritty_config_gui.py index c852982..3e88d69 100644 --- a/alacritty_config_gui.py +++ b/alacritty_config_gui.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 import os +import platform import sys import yaml -from PyQt5 import QtWidgets, QtGui +from PyQt5 import QtWidgets, QtGui, QtCore ALACRITTY_CONFIG = os.path.expanduser("~/.config/alacritty/alacritty.yml") @@ -14,9 +15,9 @@ class ColorSelect(QtWidgets.QPushButton): def __init__(self, value): super().__init__() self.set_value(value.replace('0x', '#')) - self.pressed.connect(self.handle_pressed) + self.clicked.connect(self.handle_clicked) - def handle_pressed(self): + def handle_clicked(self): color = QtWidgets.QColorDialog.getColor() if color.isValid(): @@ -49,6 +50,43 @@ class ColorSelect(QtWidgets.QPushButton): return self._value.replace('#', '0x') +class FontSelect(QtWidgets.QPushButton): + def __init__(self, family, style): + super().__init__() + self.set_value(family, style) + self.clicked.connect(self.handle_clicked) + + def handle_clicked(self): + font, valid = QtWidgets.QFontDialog.getFont() + + if valid: + self.set_value(font.family(), font.styleName()) + + def set_value(self, family, style): + self.family = family + self.style = style + self.setStyleSheet(""" + QPushButton {{ + background-color: white; + font-family: {0}; + }} + QPushButton:checked{{ + background-color: white; + }} + QPushButton:hover{{ + background-color: white; + }} + """.format(family)) + self.setText(self.family) + self.update() + + def value(self): + return { + 'family': self.family, + 'style': self.style + } + + class ConfigWidget(QtWidgets.QWidget): def __init__(self): super().__init__() @@ -57,42 +95,65 @@ class ConfigWidget(QtWidgets.QWidget): def prettify(self, s): return ' '.join(x.capitalize() for x in s.split('_') if x) + def render_item(self, layout, name, widget): + sub_layout = QtWidgets.QHBoxLayout() + sub_layout.addWidget(QtWidgets.QLabel(self.prettify(name))) + sub_layout.addWidget(widget) + layout.addLayout(sub_layout) + + def render_section(self, widgets, sup=None, name=None): + layout = QtWidgets.QVBoxLayout() + + if name and sup is not None: + layout.setContentsMargins(10, 0, 0, 0) + label = QtWidgets.QLabel(self.prettify(name)) + font = label.font() + font.setBold(True) + label.setFont(font) + + sup.addWidget(label) + + for name, widget in widgets.items(): + if type(widget) is dict: + sub_layout = self.render_section(widget, layout, name) + layout.addLayout(sub_layout) + else: + self.render_item(layout, name, widget) + layout.setAlignment(QtCore.Qt.AlignTop) + return layout + def render_state(self): - self.layout = QtWidgets.QVBoxLayout() - for name, widget in self.widgets.items(): - sub_layout = QtWidgets.QHBoxLayout() - sub_layout.addWidget(QtWidgets.QLabel(self.prettify(name))) - sub_layout.addWidget(widget) - self.layout.addLayout(sub_layout) + self.layout = self.render_section(self.widgets) self.setLayout(self.layout) - def gather_state(self): + def widget_value(self, widget): + typ = type(widget) + if typ is QtWidgets.QComboBox: + return widget.currentText() + if typ is QtWidgets.QCheckBox: + return widget.isChecked() + if typ is QtWidgets.QLineEdit: + return widget.text() + return widget.value() + + def widgets_to_state(self, widgets): state = {} - for name, widget in self.widgets.items(): - path = name.split('__') - mut_state = state - for elem in path[:-1]: - if elem not in mut_state: - mut_state[elem] = {} - mut_state = mut_state[elem] - typ = type(widget) - name = path[-1] - if typ is QtWidgets.QComboBox: - mut_state[name] = widget.currentText() - elif typ is QtWidgets.QCheckBox: - mut_state[name] = widget.isChecked() - elif typ is QtWidgets.QLineEdit: - mut_state[name] = widget.text() + for name, widget in widgets.items(): + if type(widget) is dict: + state[name] = self.widgets_to_state(widget) else: - mut_state[name] = widget.value() + state[name] = self.widget_value(widget) return state + def gather_state(self): + return self.widgets_to_state(self.widgets) + class Debug(ConfigWidget): def __init__(self, config): super().__init__() self.widgets['render_timer'] = QtWidgets.QCheckBox() - self.widgets['render_timer'].setCheckState(config.get('render_timer')) + self.widgets['render_timer'].setChecked(config.get('render_timer')) self.render_state() @@ -133,12 +194,26 @@ class Font(ConfigWidget): use_thin_strokes = QtWidgets.QCheckBox() use_thin_strokes.setChecked(config.get('use_thin_strokes')) + normal_config = config.get('normal', {}) + normal = FontSelect(normal_config['family'], normal_config['style']) + + italic_config = config.get('italic', {}) + italic = FontSelect(italic_config['family'], italic_config['style']) + + bold_config = config.get('bold', {}) + bold = FontSelect(bold_config['family'], bold_config['style']) + self.widgets = { - 'glyph_offset__x': glyph_offset_x, - 'glyph_offset__y': glyph_offset_y, 'scale_with_dpi': scale_with_dpi, 'size': size, 'use_thin_strokes': use_thin_strokes, + 'glyph_offset': { + 'x': glyph_offset_x, + 'y': glyph_offset_y, + }, + 'normal': normal, + 'italic': italic, + 'bold': bold, } self.render_state() @@ -155,20 +230,72 @@ class Colors(ConfigWidget): config.get('primary', {}).get('foreground') ) + cursor_background = ColorSelect( + config.get('cursor', {}).get('cursor') + ) + cursor_foreground = ColorSelect( + config.get('cursor', {}).get('text') + ) + + normal_black = ColorSelect( + config.get('normal', {}).get('black') + ) + normal_blue = ColorSelect( + config.get('normal', {}).get('blue') + ) + normal_cyan = ColorSelect( + config.get('normal', {}).get('cyan') + ) + normal_green = ColorSelect( + config.get('normal', {}).get('green') + ) + normal_magenta = ColorSelect( + config.get('normal', {}).get('magenta') + ) + normal_red = ColorSelect( + config.get('normal', {}).get('red') + ) + normal_white = ColorSelect( + config.get('normal', {}).get('white') + ) + normal_yellow = ColorSelect( + config.get('normal', {}).get('yellow') + ) + self.widgets = { - 'primary__background': primary_background, - 'primary__foreground': primary_foreground, + 'primary': { + 'background': primary_background, + 'foreground': primary_foreground, + }, + 'cursor': { + 'cursor': cursor_background, + 'text': cursor_foreground, + }, + 'normal': { + 'black': normal_black, + 'blue': normal_blue, + 'cyan': normal_cyan, + 'green': normal_green, + 'magenta': normal_magenta, + 'red': normal_red, + 'white': normal_white, + 'yellow': normal_yellow, + }, } self.render_state() class Window(ConfigWidget): - # TODO: transparent and buttonless only on OS X - decoration_options = ['full', 'none', 'transparent', 'buttonless'] + decoration_options = ( + ['full', 'none'] + + (['transparent', 'buttonless'] if platform.system() == 'Darwin' else []) + ) - # TODO: simplewindowed only on OS X - startup_options = ['Windowed', 'FullScreen', 'SimpleWindowed', 'Maximized'] + startup_options = ( + ['Windowed', 'FullScreen', 'Maximized'] + + (['SimpleFullScreen'] if platform.system() == 'Darwin' else []) + ) def __init__(self, config): super().__init__() decorations = QtWidgets.QComboBox() @@ -198,16 +325,28 @@ class Window(ConfigWidget): dynamic_padding = QtWidgets.QCheckBox() dynamic_padding.setChecked(config.get('dynamic_padding', False)) + title = QtWidgets.QLineEdit(config.get('title', 'Alacritty')) + self.widgets = { + 'title': title, 'decorations': decorations, 'startup_mode': startup_mode, - 'dimensions__columns': columns, - 'dimensions__lines': lines, - 'padding__x': padding_x, - 'padding__y': padding_y, 'dynamic_padding': dynamic_padding, + 'padding': { + 'x': padding_x, + 'y': padding_y, + }, + 'dimensions': { + 'columns': columns, + 'lines': lines, + } } + if platform.system() == 'Linux': + self.widgets['class'] = QtWidgets.QLineEdit( + config.get('class', 'Alacritty') + ) + self.render_state()