mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
stylesheet_wip
This commit is contained in:
parent
51b9bafbeb
commit
a7ac9e8640
12 changed files with 222 additions and 77 deletions
|
|
@ -25,8 +25,12 @@ from PyQt6 import QtCore, QtWidgets
|
|||
|
||||
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__)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -241,6 +246,70 @@ class KeyboardSettings(QtCore.QSettings):
|
|||
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')
|
||||
|
|
|
|||
|
|
@ -19,24 +19,4 @@ VERSION = '0.3.3-dev'
|
|||
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
beeref/default_stylesheet.qss
Normal file
115
beeref/default_stylesheet.qss
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ from PyQt6 import QtCore, QtGui
|
|||
|
||||
from .errors import BeeFileIOError
|
||||
from beeref import constants, widgets
|
||||
from beeref.config import BeeStyleSheet
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -92,7 +93,9 @@ class SceneToPixmapExporter(ExporterBase):
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets
|
|||
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
|
||||
|
||||
|
||||
|
|
@ -568,7 +567,9 @@ class BeeTextItem(BeeItemMixin, QtWidgets.QGraphicsTextItem):
|
|||
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):
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
"""Classes that draw and handle selection stuff for items."""
|
||||
|
||||
from functools import cached_property
|
||||
import logging
|
||||
import math
|
||||
|
||||
|
|
@ -23,15 +24,13 @@ from PyQt6.QtCore import Qt
|
|||
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):
|
||||
|
|
@ -217,13 +216,20 @@ class SelectableMixin(BaseItemMixin):
|
|||
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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -18,36 +18,6 @@ import re
|
|||
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."""
|
||||
|
|
|
|||
|
|
@ -48,9 +48,6 @@ class BeeGraphicsView(MainControlsMixin,
|
|||
self.parent = parent
|
||||
self.settings = BeeSettings()
|
||||
self.welcome_overlay = widgets.welcome_overlay.WelcomeOverlay(self)
|
||||
|
||||
self.setBackgroundBrush(
|
||||
QtGui.QBrush(QtGui.QColor(*constants.COLORS['Scene:Canvas'])))
|
||||
self.setRenderHint(QtGui.QPainter.RenderHint.Antialiasing)
|
||||
self.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ class KeyboardShortcutsEditor(QtWidgets.QKeySequenceEdit):
|
|||
|
||||
def __init__(self, parent, index):
|
||||
super().__init__(parent)
|
||||
#self.setObjectName('QKeySequenceEdit')
|
||||
print('***', self.objectName())
|
||||
self.action = actions[index.row()]
|
||||
try:
|
||||
self.old_value = self.action.get_shortcuts()[index.column() - 2]
|
||||
|
|
@ -322,13 +324,6 @@ class KeyboardShortcutsProxy(QtCore.QSortFilterProxyModel):
|
|||
self.setFilterCaseSensitivity(
|
||||
QtCore.Qt.CaseSensitivity.CaseInsensitive)
|
||||
|
||||
def data(self, index, role):
|
||||
if (role == QtCore.Qt.ItemDataRole.BackgroundRole
|
||||
and index.row() % 2):
|
||||
return QtGui.QColor(*constants.COLORS['Table:AlternativeRow'])
|
||||
else:
|
||||
return super().data(index, role)
|
||||
|
||||
def setData(self, index, value, role, remove_from_other=None):
|
||||
result = self.sourceModel().setData(
|
||||
self.mapToSource(index),
|
||||
|
|
@ -352,6 +347,7 @@ class KeyboardShortcutsView(QtWidgets.QTableView):
|
|||
1, QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
|
||||
self.setSelectionMode(
|
||||
QtWidgets.QHeaderView.SelectionMode.SingleSelection)
|
||||
self.setAlternatingRowColors(True)
|
||||
settings_events.restore_keyboard_defaults.connect(
|
||||
self.on_restore_defaults)
|
||||
|
||||
|
|
|
|||
|
|
@ -106,12 +106,14 @@ class WelcomeOverlay(MainControlsMixin, QtWidgets.QWidget):
|
|||
files_layout.addWidget(self.files_view)
|
||||
files_layout.addStretch(50)
|
||||
self.files_widget.setLayout(files_layout)
|
||||
self.files_widget.setStyleSheet('background: transparent;')
|
||||
self.files_widget.hide()
|
||||
|
||||
# Help text
|
||||
self.label = QtWidgets.QLabel(self.txt, self)
|
||||
self.label.setAlignment(Qt.AlignmentFlag.AlignVCenter
|
||||
| Qt.AlignmentFlag.AlignCenter)
|
||||
self.label.setStyleSheet('background: transparent;')
|
||||
self.layout = QtWidgets.QHBoxLayout()
|
||||
self.layout.addStretch(50)
|
||||
self.layout.addWidget(self.label)
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -13,6 +13,7 @@ setup(
|
|||
'pyQt6-Qt6>=6.5.0,<=6.6.1',
|
||||
'rectangle-packer>=2.0.1,<=2.0.2',
|
||||
'exif>=1.3.5,<=1.6.0',
|
||||
'tinycss2==1.2.1',
|
||||
],
|
||||
packages=[
|
||||
'beeref',
|
||||
|
|
|
|||
Loading…
Reference in a new issue