Skip to content

Commit

Permalink
stylesheet_wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rbreu committed Feb 27, 2024
1 parent 51b9baf commit a7ac9e8
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 77 deletions.
11 changes: 7 additions & 4 deletions beeref/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@

from beeref import constants
from beeref.assets import BeeAssets
from beeref.config import CommandlineArgs, BeeSettings, logfile_name
from beeref.utils import create_palette_from_dict
from beeref.config import (
BeeSettings,
CommandlineArgs,
BeeStyleSheet,
logfile_name,
)
from beeref.view import BeeGraphicsView

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -110,8 +114,7 @@ def main():

os.environ["QT_DEBUG_PLUGINS"] = "1"
app = BeeRefApplication(sys.argv)
palette = create_palette_from_dict(constants.COLORS)
app.setPalette(palette)
app.setStyleSheet(BeeStyleSheet().qss)
bee = BeeRefMainWindow(app) # NOQA:F841

signal.signal(signal.SIGINT, handle_sigint)
Expand Down
71 changes: 70 additions & 1 deletion beeref/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
"""Handling of command line args and Qt settings."""

import argparse
from functools import lru_cache, cached_property
import logging
import logging.config
import os.path
import shutil

from PyQt6 import QtCore
import tinycss2
import tinycss2.color3

from PyQt6 import QtCore, QtGui

from beeref import constants
from beeref.logging import qt_message_handler
Expand Down Expand Up @@ -241,6 +246,70 @@ def restore_defaults(self):
settings_events.restore_keyboard_defaults.emit()


class BeeStyleSheet:
_instance = None
DEFAULT_PATH = os.path.join(os.path.dirname(__file__),
'default_stylesheet.qss')

def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls, *args, **kwargs)
cls._instance.on_new()
return cls._instance

def on_new(self):
dest = os.path.join(
os.path.dirname(BeeSettings().fileName()),
'stylesheet.qss.example')
shutil.copy(self.DEFAULT_PATH, dest)

path = os.path.join(
os.path.dirname(BeeSettings().fileName()), 'stylesheet.qss')

if os.path.exists(path):
logger.info(f'Found custom stylesheet: {path}')
else:
logger.info(f'Using default stylesheet')
path = self.DEFAULT_PATH

with open(path) as f:
self.qss = f.read()

@cached_property
def parsed(self):
return tinycss2.parse_stylesheet(
self.qss, skip_comments=True, skip_whitespace=True)

def _get_color_from_rule(self, rule, attribute):
found = False
for dec in rule.content:
if found:
color = tinycss2.color3.parse_color(dec.serialize())
if color:
return QtGui.QColor(
int(color.red * 255),
int(color.green * 255),
int(color.blue * 255),
int(color.alpha * 255))
else:
if getattr(dec, 'value', None) == attribute:
found = True

@lru_cache
def get_color(self, element, attribute):
for rule in self.parsed:
for pre in rule.prelude:
if getattr(pre, 'value', None) == element:
return self._get_color_from_rule(rule, attribute)


def get_stylesheet(create_example=False):
"""Read custom stylesheet from settings dir if it exists, else read
default style sheet from source code.
"""



def logfile_name():
return os.path.join(
os.path.dirname(BeeSettings().fileName()), f'{constants.APPNAME}.log')
Expand Down
22 changes: 1 addition & 21 deletions beeref/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,4 @@
WEBSITE = 'https://github.com/rbreu/beeref'
COPYRIGHT = 'Copyright © 2021-2023 Rebecca Breu'

COLORS = {
# Qt:
'Active:Base': (60, 60, 60),
'Active:Window': (40, 40, 40),
'Active:Button': (40, 40, 40),
'Active:Text': (200, 200, 200),
'Active:HighlightedText': (255, 255, 255),
'Active:WindowText': (200, 200, 200),
'Active:ButtonText': (200, 200, 200),
'Active:Highlight': (83, 167, 165),
'Active:Link': (90, 181, 179),
'Disabled:Light': (0, 0, 0, 0),
'Disabled:Text': (140, 140, 140),

# BeeRef specific:
'Scene:Selection': (116, 234, 231),
'Scene:Canvas': (60, 60, 60),
'Scene:Text': (200, 200, 200),
'Table:AlternativeRow': (70, 70, 70),

}
DEFAULT_SELECTION_COLOR = (116, 234, 231)
115 changes: 115 additions & 0 deletions beeref/default_stylesheet.qss
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* This is BeeRef's default stylesheet provided as an example.

Save your own stylesheet as stylesheet.qss
*/

* {
color: rgb(200, 200, 200);
background: rgb(50, 50, 50);
}

QSpinBox::focus,
QKeySequenceEdit::focus {
border: 1px solid rgb(83, 167, 165);
border-radius: 3px;
}

*::item:selected,
*::item:pressed
{
color: rgb(255, 255, 255);
background: rgb(83, 167, 165);
}

*::item:disabled {
color: rgb(140, 140, 140);
}

QMenu {
border: 1px solid rgb(40, 40, 40);
}

QPushButton {
border: 1px solid rgb(140, 140, 140);
border-radius: 3px;
padding: 3px;
background-color: rgb(50, 50, 50);
}

QPushButton {
border: 1px solid rgb(140, 140, 140);
border-radius: 3px;
padding: 3px;
background-color: rgb(60, 60, 60);
}

QPushButton::hover {
background-color: rgb(70, 70, 70);
}

QPushButton::default {
border: 1px solid rgb(83, 167, 165);
}

QPushButton::pressed {
background-color: rgb(50, 50, 50);
}

QProgressBar {
border: 1px solid rgb(40, 40, 40);
border-radius: 3px;
text-align: center;
}

QProgressBar::chunk {
background-color: rgb(83, 167, 165);
border-radius: 3px;
}

QTableView {
alternate-background-color: rgb(60, 60, 60);
selection-background-color: rgb(83, 167, 165);
}

QScrollBar::handle:horizontal,
QScrollBar::handle:vertical {
background: rgb(60, 60, 60);
border: 1px solid rgb(40, 40, 40);
border-radius: 3px;
}

QScrollBar::handle:horizontal:hover,
QScrollBar::handle:vertical:hover {
background: rgb(70, 70, 70);
border: 1px solid rgb(40, 40, 40);
border-radius: 3px;
}

QScrollBar::handle:horizontal:pressed,
QScrollBar::handle:vertical:pressed {
background: rgb(83, 167, 165);
border: 1px solid rgb(40, 40, 40);
border-radius: 3px;
}

/* QScrollBar::add-line:horizontal { */
/* border: 1px solid rgb(40, 40, 40); */
/* border-radius: 3px; */
/* } */


QGraphicsView {
background: rgb(60, 60, 60);
}

BeeTextItem {
color: rgb(200, 200, 200);
}

BeeSelectionItem {
color: rgb(116, 234, 231);
}

BeeRubberbandItem {
color: rgba(116, 234, 231, 0.16);
}
5 changes: 4 additions & 1 deletion beeref/fileio/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from .errors import BeeFileIOError
from beeref import constants, widgets
from beeref.config import BeeStyleSheet


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -92,7 +93,9 @@ def render_to_image(self):
logger.debug(f'Final export margin: {margin}')

image = QtGui.QImage(self.size, QtGui.QImage.Format.Format_RGB32)
image.fill(QtGui.QColor(*constants.COLORS['Scene:Canvas']))
color = BeeStyleSheet().get_color('QGraphicsView', 'background')
if color:
image.fill(color)
painter = QtGui.QPainter(image)
target_rect = QtCore.QRectF(
margin,
Expand Down
7 changes: 4 additions & 3 deletions beeref/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
from PyQt6.QtCore import Qt

from beeref import commands
from beeref.config import BeeSettings
from beeref.constants import COLORS
from beeref.config import BeeSettings, BeeStyleSheet
from beeref.selection import SelectableMixin


Expand Down Expand Up @@ -568,7 +567,9 @@ def __init__(self, text=None):
self.init_selectable()
self.is_editable = True
self.edit_mode = False
self.setDefaultTextColor(QtGui.QColor(*COLORS['Scene:Text']))
color = BeeStyleSheet().get_color('BeeTextItem', 'color')
if color:
self.setDefaultTextColor(color)

@classmethod
def create_from_data(cls, **kwargs):
Expand Down
22 changes: 15 additions & 7 deletions beeref/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

"""Classes that draw and handle selection stuff for items."""

from functools import cached_property
import logging
import math

Expand All @@ -23,15 +24,13 @@
from PyQt6.QtWidgets import QGraphicsItem

from beeref.assets import BeeAssets
from beeref import commands
from beeref.config import CommandlineArgs
from beeref.constants import COLORS
from beeref import commands, constants
from beeref.config import CommandlineArgs, BeeStyleSheet
from beeref import utils


commandline_args = CommandlineArgs()
logger = logging.getLogger(__name__)
SELECT_COLOR = QtGui.QColor(*COLORS['Scene:Selection'])


def with_anchor(func):
Expand Down Expand Up @@ -217,13 +216,20 @@ def paint_debug(self, painter, option, widget):
self.draw_debug_shape(
painter, self.select_handle_free_center(), 255, 0, 255)

@cached_property
def _select_color(self):
color = BeeStyleSheet().get_color('BeeSelectionItem', 'color')
if not color:
color = QtGui.QColor(*constants.DEFAULT_SELECTION_COLOR)
return color

def paint_selectable(self, painter, option, widget):
self.paint_debug(painter, option, widget)

if not self.has_selection_outline():
return

pen = QtGui.QPen(SELECT_COLOR)
pen = QtGui.QPen(self._select_color)
pen.setWidth(self.SELECT_LINE_WIDTH)
pen.setCosmetic(True)
painter.setPen(pen)
Expand Down Expand Up @@ -685,8 +691,10 @@ class RubberbandItem(BaseItemMixin, QtWidgets.QGraphicsRectItem):

def __init__(self):
super().__init__()
color = QtGui.QColor(SELECT_COLOR)
color.setAlpha(40)
color = BeeStyleSheet().get_color('BeeRubberbandItem', 'color')
if not color:
color = QtGui.QColor(*constants.DEFAULT_SELECTION_COLOR)
color.setAlpha(40)
self.setBrush(QtGui.QBrush(color))
pen = QtGui.QPen(QtGui.QColor(0, 0, 0))
pen.setWidth(1)
Expand Down
30 changes: 0 additions & 30 deletions beeref/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,6 @@
from PyQt6 import QtCore, QtGui


def create_palette_from_dict(conf):
"""Create a palette from a config dictionary. Keys are a string of
'ColourGroup:ColorRole' and values are a (r, g, b) tuple. E.g:
{
'Active:WindowText': (80, 100, 0),
...
}
Colors from the Active group will automatically be applied to the
Inactive group as well. Unknown color groups will be ignored.
"""

palette = QtGui.QPalette()
for key, value in conf.items():
group, role = key.split(':')
if hasattr(QtGui.QPalette.ColorGroup, group):
palette.setColor(
getattr(QtGui.QPalette.ColorGroup, group),
getattr(QtGui.QPalette.ColorRole, role),
QtGui.QColor(*value))
if group == 'Active':
# Also set the Inactive colour group.
palette.setColor(
QtGui.QPalette.ColorGroup.Inactive,
getattr(QtGui.QPalette.ColorRole, role),
QtGui.QColor(*value))

return palette


def get_rect_from_points(point1, point2):
"""Constructs a QRectF from the given QPointF. The points can be *any*
two opposing corners of the rectangle."""
Expand Down
Loading

0 comments on commit a7ac9e8

Please sign in to comment.