Parse theme from a custom simpler format
This commit is contained in:
parent
cb1b95766c
commit
9397687122
4
TODO.md
4
TODO.md
|
@ -2,6 +2,7 @@
|
||||||
- `QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling)`
|
- `QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling)`
|
||||||
|
|
||||||
- Refactoring
|
- Refactoring
|
||||||
|
- Sendbox
|
||||||
- Use .mjs modules
|
- Use .mjs modules
|
||||||
- SignIn/RememberAccount screens
|
- SignIn/RememberAccount screens
|
||||||
- SignIn must be in a flickable
|
- SignIn must be in a flickable
|
||||||
|
@ -14,8 +15,7 @@
|
||||||
- When qml syntax highlighting supports string interpolation, use them
|
- When qml syntax highlighting supports string interpolation, use them
|
||||||
|
|
||||||
- Fixes
|
- Fixes
|
||||||
- Wrong typing notification sending before alias completed
|
- Message position after daybreak delegate
|
||||||
- Message after daybreak delegate
|
|
||||||
- Keyboard flicking against top/bottom edge
|
- Keyboard flicking against top/bottom edge
|
||||||
- Don't strip user spacing in html
|
- Don't strip user spacing in html
|
||||||
- Past events loading (limit 100) freezes the GUI - need to move upsert func
|
- Past events loading (limit 100) freezes the GUI - need to move upsert func
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import random
|
import random
|
||||||
from typing import Any, Dict, Optional, Set, Tuple
|
from typing import Dict, Optional, Set, Tuple
|
||||||
|
|
||||||
from .app import App
|
from .app import App
|
||||||
from .events import users
|
from .events import users
|
||||||
|
@ -104,8 +104,13 @@ class Backend:
|
||||||
|
|
||||||
# General functions
|
# General functions
|
||||||
|
|
||||||
async def load_settings(self) -> Tuple[Dict[str, Any], ...]:
|
async def load_settings(self) -> tuple:
|
||||||
return (await self.ui_settings.read(), await self.ui_state.read())
|
from .config_files import Theme
|
||||||
|
settings = await self.ui_settings.read()
|
||||||
|
ui_state = await self.ui_state.read()
|
||||||
|
theme = await Theme(self, settings["theme"]).read()
|
||||||
|
|
||||||
|
return (settings, ui_state, theme)
|
||||||
|
|
||||||
|
|
||||||
async def request_user_update_event(self, user_id: str) -> None:
|
async def request_user_update_event(self, user_id: str) -> None:
|
||||||
|
|
|
@ -10,6 +10,7 @@ import aiofiles
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from .backend import Backend
|
from .backend import Backend
|
||||||
|
from .theme_parser import convert_to_qml
|
||||||
|
|
||||||
JsonData = Dict[str, Any]
|
JsonData = Dict[str, Any]
|
||||||
|
|
||||||
|
@ -18,16 +19,32 @@ WRITE_LOCK = asyncio.Lock()
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ConfigFile:
|
class ConfigFile:
|
||||||
backend: Backend = field(repr=False)
|
backend: Backend = field(repr=False)
|
||||||
filename: str = field()
|
filename: str = field()
|
||||||
use_data_dir: bool = False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> Path:
|
def path(self) -> Path:
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
dirs = self.backend.app.appdirs
|
return Path(self.backend.app.appdirs.user_config_dir) / self.filename
|
||||||
to = dirs.user_data_dir if self.use_data_dir else dirs.user_config_dir
|
|
||||||
return Path(to) / self.filename
|
|
||||||
|
async def default_data(self):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
async def read(self):
|
||||||
|
try:
|
||||||
|
return self.path.read_text()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return await self.default_data()
|
||||||
|
|
||||||
|
|
||||||
|
async def write(self, data) -> None:
|
||||||
|
async with WRITE_LOCK:
|
||||||
|
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
async with aiofiles.open(self.path, "w") as new:
|
||||||
|
await new.write(data)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -38,8 +55,8 @@ class JSONConfigFile(ConfigFile):
|
||||||
|
|
||||||
async def read(self) -> JsonData:
|
async def read(self) -> JsonData:
|
||||||
try:
|
try:
|
||||||
data = json.loads(self.path.read_text())
|
data = json.loads(await super().read())
|
||||||
except (json.JSONDecodeError, FileNotFoundError):
|
except json.JSONDecodeError:
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
return {**await self.default_data(), **data}
|
return {**await self.default_data(), **data}
|
||||||
|
@ -47,12 +64,7 @@ class JSONConfigFile(ConfigFile):
|
||||||
|
|
||||||
async def write(self, data: JsonData) -> None:
|
async def write(self, data: JsonData) -> None:
|
||||||
js = json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True)
|
js = json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True)
|
||||||
|
await super().write(js)
|
||||||
async with WRITE_LOCK:
|
|
||||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
async with aiofiles.open(self.path, "w") as new:
|
|
||||||
await new.write(js)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -90,14 +102,20 @@ class UISettings(JSONConfigFile):
|
||||||
|
|
||||||
async def default_data(self) -> JsonData:
|
async def default_data(self) -> JsonData:
|
||||||
return {
|
return {
|
||||||
"writeAliases": {}
|
"theme": "Default.qpl",
|
||||||
|
"writeAliases": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class UIState(JSONConfigFile):
|
class UIState(JSONConfigFile):
|
||||||
filename: str = "ui-state.json"
|
filename: str = "ui-state.json"
|
||||||
use_data_dir: bool = True
|
|
||||||
|
@property
|
||||||
|
def path(self) -> Path:
|
||||||
|
# pylint: disable=no-member
|
||||||
|
return Path(self.backend.app.appdirs.user_data_dir) / self.filename
|
||||||
|
|
||||||
|
|
||||||
async def default_data(self) -> JsonData:
|
async def default_data(self) -> JsonData:
|
||||||
return {
|
return {
|
||||||
|
@ -107,3 +125,30 @@ class UIState(JSONConfigFile):
|
||||||
"pageProperties": {},
|
"pageProperties": {},
|
||||||
"sidePaneManualWidth": None,
|
"sidePaneManualWidth": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Theme(ConfigFile):
|
||||||
|
@property
|
||||||
|
def path(self) -> Path:
|
||||||
|
# pylint: disable=no-member
|
||||||
|
data_dir = Path(self.backend.app.appdirs.user_data_dir)
|
||||||
|
user_file = data_dir / "themes" / self.filename
|
||||||
|
|
||||||
|
if user_file.exists():
|
||||||
|
return user_file
|
||||||
|
|
||||||
|
return Path("src") / "themes" / self.filename
|
||||||
|
|
||||||
|
|
||||||
|
async def default_data(self) -> str:
|
||||||
|
async with aiofiles.open("src/themes/Default.qpl", "r") as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
|
|
||||||
|
async def read(self) -> str:
|
||||||
|
return convert_to_qml(await super().read())
|
||||||
|
|
||||||
|
|
||||||
|
async def write(self, data: str) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
69
src/python/theme_parser.py
Normal file
69
src/python/theme_parser.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
# Copyright 2019 miruka
|
||||||
|
# This file is part of harmonyqml, licensed under LGPLv3.
|
||||||
|
|
||||||
|
import re
|
||||||
|
from typing import Generator
|
||||||
|
|
||||||
|
PROPERTY_TYPES = {"bool", "double", "int", "list", "real", "string", "url",
|
||||||
|
"var", "date", "point", "rect", "size", "color"}
|
||||||
|
|
||||||
|
|
||||||
|
def _add_property(line: str) -> str:
|
||||||
|
if re.match(r"^\s*[a-zA-Z0-9_]+\s*:$", line):
|
||||||
|
return re.sub(r"^(\s*)(\S*\s*):$",
|
||||||
|
r"\1readonly property QtObject \2: QtObject",
|
||||||
|
line)
|
||||||
|
|
||||||
|
types = "|".join(PROPERTY_TYPES)
|
||||||
|
if re.match(fr"^\s*({types}) [a-zA-Z\d_]+\s*:", line):
|
||||||
|
return re.sub(r"^(\s*)(\S*)", r"\1readonly property \2", line)
|
||||||
|
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
def _process_lines(content: str) -> Generator[str, None, None]:
|
||||||
|
skip = False
|
||||||
|
indent = " " * 4
|
||||||
|
current_indent = 0
|
||||||
|
|
||||||
|
for line in content.split("\n"):
|
||||||
|
line = line.rstrip()
|
||||||
|
|
||||||
|
if not line.strip() or line.strip().startswith("//"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
start_space_list = re.findall(r"^ +", line)
|
||||||
|
start_space = start_space_list[0] if start_space_list else ""
|
||||||
|
|
||||||
|
line_indents = len(re.findall(indent, start_space))
|
||||||
|
|
||||||
|
if not skip:
|
||||||
|
if line_indents > current_indent:
|
||||||
|
yield "%s{" % (indent * current_indent)
|
||||||
|
current_indent = line_indents
|
||||||
|
|
||||||
|
while line_indents < current_indent:
|
||||||
|
current_indent -= 1
|
||||||
|
yield "%s}" % (indent * current_indent)
|
||||||
|
|
||||||
|
line = _add_property(line)
|
||||||
|
|
||||||
|
yield line
|
||||||
|
|
||||||
|
skip = any((line.endswith(e) for e in "([{+\\,?:"))
|
||||||
|
|
||||||
|
while current_indent:
|
||||||
|
current_indent -= 1
|
||||||
|
yield "%s}" % (indent * current_indent)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_qml(theme_content: str) -> str:
|
||||||
|
lines = [
|
||||||
|
"import QtQuick 2.12",
|
||||||
|
'import "utils.js" as Ut',
|
||||||
|
"QtObject {",
|
||||||
|
" id: theme",
|
||||||
|
]
|
||||||
|
lines += [f" {line}" for line in _process_lines(theme_content)]
|
||||||
|
lines += ["}"]
|
||||||
|
return "\n".join(lines)
|
|
@ -105,7 +105,7 @@ HRectangle {
|
||||||
vals.reduce((a, b) => a.length > b.length ? a: b)
|
vals.reduce((a, b) => a.length > b.length ? a: b)
|
||||||
|
|
||||||
let textNotStartsWithAnyAlias =
|
let textNotStartsWithAnyAlias =
|
||||||
! vals.some(a => text.startsWith(a))
|
! vals.some(a => a.startsWith(text))
|
||||||
|
|
||||||
let textContainsCharNotInAnyAlias =
|
let textContainsCharNotInAnyAlias =
|
||||||
vals.every(a => text.split("").some(c => ! a.includes(c)))
|
vals.every(a => text.split("").some(c => ! a.includes(c)))
|
||||||
|
|
|
@ -53,9 +53,10 @@ Python {
|
||||||
call("APP.is_debug_on", [Qt.application.arguments], on => {
|
call("APP.is_debug_on", [Qt.application.arguments], on => {
|
||||||
window.debug = on
|
window.debug = on
|
||||||
|
|
||||||
callCoro("load_settings", [], ([settings, uiState]) => {
|
callCoro("load_settings", [], ([settings, uiState, theme]) => {
|
||||||
window.settings = settings
|
window.settings = settings
|
||||||
window.uiState = uiState
|
window.uiState = uiState
|
||||||
|
window.theme = Qt.createQmlObject(theme, window, "theme")
|
||||||
|
|
||||||
callCoro("saved_accounts.any_saved", [], any => {
|
callCoro("saved_accounts.any_saved", [], any => {
|
||||||
py.ready = true
|
py.ready = true
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
// Copyright 2019 miruka
|
|
||||||
// This file is part of harmonyqml, licensed under LGPLv3.
|
|
||||||
|
|
||||||
import QtQuick 2.12
|
|
||||||
import "utils.js" as Ut
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: theme
|
|
||||||
|
|
||||||
property int minimumSupportedWidth: 240
|
|
||||||
property int minimumSupportedHeight: 120
|
|
||||||
property int contentIsWideAbove: 439
|
|
||||||
|
|
||||||
property int minimumSupportedWidthPlusSpacing: 240 + spacing * 2
|
|
||||||
property int minimumSupportedHeightPlusSpacing: 120 + spacing * 2
|
|
||||||
|
|
||||||
property int baseElementsHeight: 36
|
|
||||||
property int spacing: 8
|
|
||||||
property int animationDuration: 100
|
|
||||||
|
|
||||||
property QtObject fontSize: QtObject {
|
|
||||||
property int smallest: 6
|
|
||||||
property int smaller: 8
|
|
||||||
property int small: 13
|
|
||||||
property int normal: 16
|
|
||||||
property int big: 22
|
|
||||||
property int bigger: 32
|
|
||||||
property int biggest: 48
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject fontFamily: QtObject {
|
|
||||||
property string sans: "SFNS Display"
|
|
||||||
property string serif: "Roboto Slab"
|
|
||||||
property string mono: "Hack"
|
|
||||||
}
|
|
||||||
|
|
||||||
property int radius: 5
|
|
||||||
|
|
||||||
property QtObject colors: QtObject {
|
|
||||||
property color background0: Ut.hsla(0, 0, 90, 0.5)
|
|
||||||
property color background1: Ut.hsla(0, 0, 90, 0.6)
|
|
||||||
property color background2: Ut.hsla(0, 0, 90, 0.7)
|
|
||||||
property color foreground: "black"
|
|
||||||
property color foregroundDim: Ut.hsl(0, 0, 20)
|
|
||||||
property color foregroundDim2: Ut.hsl(0, 0, 30)
|
|
||||||
property color foregroundError: Ut.hsl(342, 64, 32)
|
|
||||||
property color textBorder: Ut.hsla(0, 0, 0, 0.07)
|
|
||||||
property color accent: Ut.hsl(25, 60, 50)
|
|
||||||
property color accentDarker: Ut.hsl(25, 60, 35)
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject controls: QtObject {
|
|
||||||
property QtObject button: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject interactiveRectangle: QtObject {
|
|
||||||
property color background: "transparent"
|
|
||||||
property color hoveredBackground: Ut.hsla(0, 0, 0, 0.2)
|
|
||||||
property color pressedBackground: Ut.hsla(0, 0, 0, 0.4)
|
|
||||||
property color checkedBackground: Ut.hsla(0, 0, 0, 0.4)
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject textField: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
property color border: "transparent"
|
|
||||||
property color focusedBackground: background
|
|
||||||
property color focusedBorder: colors.accent
|
|
||||||
property int borderWidth: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject textArea: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject sidePane: QtObject {
|
|
||||||
property real autoWidthRatio: 0.33
|
|
||||||
property int maximumAutoWidth: 320
|
|
||||||
|
|
||||||
property int autoCollapseBelowWidth: 128
|
|
||||||
property int collapsedWidth: avatar.size
|
|
||||||
|
|
||||||
property int autoReduceBelowWindowWidth:
|
|
||||||
minimumSupportedWidthPlusSpacing + collapsedWidth
|
|
||||||
|
|
||||||
property color background: colors.background2
|
|
||||||
|
|
||||||
property QtObject account: QtObject {
|
|
||||||
property color background: Qt.lighter(colors.background2, 1.05)
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject settingsButton: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject filterRooms: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject chat: QtObject {
|
|
||||||
property QtObject selectViewBar: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject roomHeader: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject eventList: QtObject {
|
|
||||||
property int ownEventsOnRightUnderWidth: 768
|
|
||||||
property color background: "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject message: QtObject {
|
|
||||||
property color ownBackground: Ut.hsla(25, 40, 82, 0.7)
|
|
||||||
property color background: colors.background2
|
|
||||||
property color body: colors.foreground
|
|
||||||
property color date: colors.foregroundDim
|
|
||||||
|
|
||||||
property color link: colors.accentDarker
|
|
||||||
// property color code: Ut.hsl(0, 0, 80)
|
|
||||||
// property color codeBackground: Ut.hsl(0, 0, 10)
|
|
||||||
property color code: Ut.hsl(265, 60, 35)
|
|
||||||
property color greenText: Ut.hsl(80, 60, 25)
|
|
||||||
|
|
||||||
property string styleSheet:
|
|
||||||
"a { color: " + link + " }" +
|
|
||||||
|
|
||||||
"code { font-family: " + fontFamily.mono + "; " +
|
|
||||||
"color: " + code + " }" +
|
|
||||||
|
|
||||||
"h1, h2 { font-weight: normal }" +
|
|
||||||
"h6 { font-size: small }" +
|
|
||||||
|
|
||||||
".greentext { color: " + greenText + " }"
|
|
||||||
|
|
||||||
property string styleInclude:
|
|
||||||
'<style type"text/css">\n' + styleSheet + '\n</style>\n'
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject daybreak: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
property color foreground: colors.foreground
|
|
||||||
property int radius: theme.radius
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject inviteBanner: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject leftBanner: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject unknownDevices: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject typingMembers: QtObject {
|
|
||||||
property color background: colors.background1
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject sendBox: QtObject {
|
|
||||||
property color background: colors.background2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property color pageHeadersBackground: colors.background2
|
|
||||||
|
|
||||||
property QtObject box: QtObject {
|
|
||||||
property color background: colors.background0
|
|
||||||
property int radius: theme.radius
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject avatar: QtObject {
|
|
||||||
property int size: baseElementsHeight
|
|
||||||
property int radius: theme.radius
|
|
||||||
property color letter: "white"
|
|
||||||
|
|
||||||
property QtObject background: QtObject {
|
|
||||||
property real saturation: 0.22
|
|
||||||
property real lightness: 0.5
|
|
||||||
property real alpha: 1
|
|
||||||
property color unknown: Ut.hsl(0, 0, 22)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property QtObject displayName: QtObject {
|
|
||||||
property real saturation: 0.32
|
|
||||||
property real lightness: 0.3
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,8 +8,8 @@ import "Models"
|
||||||
|
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
id: window
|
id: window
|
||||||
minimumWidth: theme.minimumSupportedWidth
|
minimumWidth: theme ? theme.minimumSupportedWidth : 240
|
||||||
minimumHeight: theme.minimumSupportedHeight
|
minimumHeight: theme ? theme.minimumSupportedHeight : 120
|
||||||
width: 640
|
width: 640
|
||||||
height: 480
|
height: 480
|
||||||
visible: true
|
visible: true
|
||||||
|
@ -34,7 +34,8 @@ ApplicationWindow {
|
||||||
property var uiState: ({})
|
property var uiState: ({})
|
||||||
onUiStateChanged: py.saveConfig("ui_state", uiState)
|
onUiStateChanged: py.saveConfig("ui_state", uiState)
|
||||||
|
|
||||||
Theme { id: theme }
|
property var theme: null
|
||||||
|
|
||||||
Shortcuts { id: shortcuts}
|
Shortcuts { id: shortcuts}
|
||||||
Python { id: py }
|
Python { id: py }
|
||||||
|
|
||||||
|
|
160
src/themes/Default.qpl
Normal file
160
src/themes/Default.qpl
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
// Copyright 2019 miruka
|
||||||
|
// This file is part of harmonyqml, licensed under LGPLv3.
|
||||||
|
// vim: syntax=qml
|
||||||
|
|
||||||
|
int minimumSupportedWidth: 240
|
||||||
|
int minimumSupportedHeight: 120
|
||||||
|
int contentIsWideAbove: 439
|
||||||
|
|
||||||
|
int minimumSupportedWidthPlusSpacing: 240 + spacing * 2
|
||||||
|
int minimumSupportedHeightPlusSpacing: 120 + spacing * 2
|
||||||
|
|
||||||
|
int baseElementsHeight: 36
|
||||||
|
int spacing: 8
|
||||||
|
int radius: 5
|
||||||
|
int animationDuration: 100
|
||||||
|
|
||||||
|
color pageHeadersBackground: colors.background2
|
||||||
|
|
||||||
|
fontSize:
|
||||||
|
int smallest: 6
|
||||||
|
int smaller: 8
|
||||||
|
int small: 13
|
||||||
|
int normal: 16
|
||||||
|
int big: 22
|
||||||
|
int bigger: 32
|
||||||
|
int biggest: 48
|
||||||
|
|
||||||
|
fontFamily:
|
||||||
|
string sans: "SFNS Display"
|
||||||
|
string serif: "Roboto Slab"
|
||||||
|
string mono: "Hack"
|
||||||
|
|
||||||
|
colors:
|
||||||
|
color background0: Ut.hsla(0, 0, 90, 0.5)
|
||||||
|
color background1: Ut.hsla(0, 0, 90, 0.6)
|
||||||
|
color background2: Ut.hsla(0, 0, 90, 0.7)
|
||||||
|
color foreground: "black"
|
||||||
|
color foregroundDim: Ut.hsl(0, 0, 20)
|
||||||
|
color foregroundDim2: Ut.hsl(0, 0, 30)
|
||||||
|
color foregroundError: Ut.hsl(342, 64, 32)
|
||||||
|
color textBorder: Ut.hsla(0, 0, 0, 0.07)
|
||||||
|
color accent: Ut.hsl(25, 60, 50)
|
||||||
|
color accentDarker: Ut.hsl(25, 60, 35)
|
||||||
|
|
||||||
|
controls:
|
||||||
|
button:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
interactiveRectangle:
|
||||||
|
color background: "transparent"
|
||||||
|
color hoveredBackground: Ut.hsla(0, 0, 0, 0.2)
|
||||||
|
color pressedBackground: Ut.hsla(0, 0, 0, 0.4)
|
||||||
|
color checkedBackground: Ut.hsla(0, 0, 0, 0.4)
|
||||||
|
|
||||||
|
textField:
|
||||||
|
color background: colors.background2
|
||||||
|
color border: "transparent"
|
||||||
|
color focusedBackground: background
|
||||||
|
color focusedBorder: colors.accent
|
||||||
|
int borderWidth: 1
|
||||||
|
|
||||||
|
textArea:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
sidePane:
|
||||||
|
real autoWidthRatio: 0.33
|
||||||
|
int maximumAutoWidth: 320
|
||||||
|
|
||||||
|
int autoCollapseBelowWidth: 128
|
||||||
|
int collapsedWidth: avatar.size
|
||||||
|
|
||||||
|
int autoReduceBelowWindowWidth:
|
||||||
|
minimumSupportedWidthPlusSpacing + collapsedWidth
|
||||||
|
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
account:
|
||||||
|
color background: Qt.lighter(colors.background2, 1.05)
|
||||||
|
|
||||||
|
settingsButton:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
filterRooms:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
chat:
|
||||||
|
selectViewBar:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
roomHeader:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
eventList:
|
||||||
|
int ownEventsOnRightUnderWidth: 768
|
||||||
|
color background: "transparent"
|
||||||
|
|
||||||
|
message:
|
||||||
|
color ownBackground: Ut.hsla(25, 40, 82, 0.7)
|
||||||
|
color background: colors.background2
|
||||||
|
color body: colors.foreground
|
||||||
|
color date: colors.foregroundDim
|
||||||
|
|
||||||
|
color link: colors.accentDarker
|
||||||
|
// color code: Ut.hsl(0, 0, 80)
|
||||||
|
// color codeBackground: Ut.hsl(0, 0, 10)
|
||||||
|
color code: Ut.hsl(265, 60, 35)
|
||||||
|
color greenText: Ut.hsl(80, 60, 25)
|
||||||
|
|
||||||
|
string styleSheet:
|
||||||
|
"a { color: " + link + " }" +
|
||||||
|
|
||||||
|
"code { font-family: " + fontFamily.mono + "; " +
|
||||||
|
"color: " + code + " }" +
|
||||||
|
|
||||||
|
"h1, h2 { font-weight: normal }" +
|
||||||
|
"h6 { font-size: small }" +
|
||||||
|
|
||||||
|
".greentext { color: " + greenText + " }"
|
||||||
|
|
||||||
|
string styleInclude:
|
||||||
|
'<style type"text/css">\n' + styleSheet + '\n</style>\n'
|
||||||
|
|
||||||
|
daybreak:
|
||||||
|
color background: colors.background2
|
||||||
|
color foreground: colors.foreground
|
||||||
|
int radius: theme.radius
|
||||||
|
|
||||||
|
inviteBanner:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
leftBanner:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
unknownDevices:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
typingMembers:
|
||||||
|
color background: colors.background1
|
||||||
|
|
||||||
|
sendBox:
|
||||||
|
color background: colors.background2
|
||||||
|
|
||||||
|
box:
|
||||||
|
color background: colors.background0
|
||||||
|
int radius: theme.radius
|
||||||
|
|
||||||
|
avatar:
|
||||||
|
int size: baseElementsHeight
|
||||||
|
int radius: theme.radius
|
||||||
|
color letter: "white"
|
||||||
|
|
||||||
|
background:
|
||||||
|
real saturation: 0.22
|
||||||
|
real lightness: 0.5
|
||||||
|
real alpha: 1
|
||||||
|
color unknown: Ut.hsl(0, 0, 22)
|
||||||
|
|
||||||
|
displayName:
|
||||||
|
real saturation: 0.32
|
||||||
|
real lightness: 0.3
|
Loading…
Reference in New Issue
Block a user