wip: theme system

- Add theme id
- WIP theme cache key
- Force scheme (light/dark) for dynamic theme
- でびるんちゃんかわいい
This commit is contained in:
2025-11-09 00:32:28 +08:00
parent 7a3c186743
commit 3679831201
12 changed files with 221 additions and 968 deletions

View File

@ -20,7 +20,9 @@
<file>lang/zh_CN.qm</file> <file>lang/zh_CN.qm</file>
<file>lang/en_US.qm</file> <file>lang/en_US.qm</file>
<file>themes/default.json</file> <file>themes/m3-dynamic_default.json</file>
<file>themes/tempest.json</file> <file>themes/m3-dynamic_tempest.json</file>
<file>themes/m3-dynamic_devilun.json</file>
<file>themes/m3-dynamic_kupya.json</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -1,427 +0,0 @@
{
"//url": "http://material-foundation.github.io/material-theme-builder/?primary=%234E486C&custom%3ASuccess=%2300C555&colorMatch=true",
"name": "default",
"description": "TYPE: CUSTOM\nMaterial Theme Builder export",
"seed": "#4E486C",
"coreColors": {
"primary": "#4E486C"
},
"extendedColors": [
{
"name": "Success",
"color": "#00C555",
"description": "",
"harmonized": true
}
],
"schemes": {
"light": {
"primary": "#373154",
"surfaceTint": "#605A7F",
"onPrimary": "#FFFFFF",
"primaryContainer": "#4E486C",
"onPrimaryContainer": "#C0B8E3",
"secondary": "#605C6C",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#E3DDF0",
"onSecondaryContainer": "#646071",
"tertiary": "#4F2B40",
"onTertiary": "#FFFFFF",
"tertiaryContainer": "#684157",
"onTertiaryContainer": "#E3B0CA",
"error": "#BA1A1A",
"onError": "#FFFFFF",
"errorContainer": "#FFDAD6",
"onErrorContainer": "#93000A",
"background": "#FDF8FC",
"onBackground": "#1C1B1E",
"surface": "#FDF8FC",
"onSurface": "#1C1B1E",
"surfaceVariant": "#E6E1EA",
"onSurfaceVariant": "#48464D",
"outline": "#79767E",
"outlineVariant": "#C9C5CE",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#313033",
"inverseOnSurface": "#F4EFF3",
"inversePrimary": "#C9C1EC",
"primaryFixed": "#E6DEFF",
"onPrimaryFixed": "#1C1738",
"primaryFixedDim": "#C9C1EC",
"onPrimaryFixedVariant": "#484266",
"secondaryFixed": "#E6E0F3",
"onSecondaryFixed": "#1C1A27",
"secondaryFixedDim": "#C9C4D7",
"onSecondaryFixedVariant": "#484554",
"tertiaryFixed": "#FFD8EA",
"onTertiaryFixed": "#301024",
"tertiaryFixedDim": "#ECB8D2",
"onTertiaryFixedVariant": "#613B51",
"surfaceDim": "#DDD9DC",
"surfaceBright": "#FDF8FC",
"surfaceContainerLowest": "#FFFFFF",
"surfaceContainerLow": "#F7F2F6",
"surfaceContainer": "#F1ECF0",
"surfaceContainerHigh": "#EBE7EA",
"surfaceContainerHighest": "#E6E1E5"
},
"light-medium-contrast": {
"primary": "#373154",
"surfaceTint": "#605A7F",
"onPrimary": "#FFFFFF",
"primaryContainer": "#4E486C",
"onPrimaryContainer": "#EDE7FF",
"secondary": "#373443",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#6F6B7B",
"onSecondaryContainer": "#FFFFFF",
"tertiary": "#4E2B40",
"onTertiary": "#FFFFFF",
"tertiaryContainer": "#684157",
"onTertiaryContainer": "#FFE4EF",
"error": "#740006",
"onError": "#FFFFFF",
"errorContainer": "#CF2C27",
"onErrorContainer": "#FFFFFF",
"background": "#FDF8FC",
"onBackground": "#1C1B1E",
"surface": "#FDF8FC",
"onSurface": "#121113",
"surfaceVariant": "#E6E1EA",
"onSurfaceVariant": "#37353D",
"outline": "#545159",
"outlineVariant": "#6F6C74",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#313033",
"inverseOnSurface": "#F4EFF3",
"inversePrimary": "#C9C1EC",
"primaryFixed": "#6F688E",
"onPrimaryFixed": "#FFFFFF",
"primaryFixedDim": "#565075",
"onPrimaryFixedVariant": "#FFFFFF",
"secondaryFixed": "#6F6B7B",
"onSecondaryFixed": "#FFFFFF",
"secondaryFixedDim": "#565363",
"onSecondaryFixedVariant": "#FFFFFF",
"tertiaryFixed": "#8B6078",
"onTertiaryFixed": "#FFFFFF",
"tertiaryFixedDim": "#71495F",
"onTertiaryFixedVariant": "#FFFFFF",
"surfaceDim": "#C9C5C9",
"surfaceBright": "#FDF8FC",
"surfaceContainerLowest": "#FFFFFF",
"surfaceContainerLow": "#F7F2F6",
"surfaceContainer": "#EBE7EA",
"surfaceContainerHigh": "#E0DCDF",
"surfaceContainerHighest": "#D4D0D4"
},
"light-high-contrast": {
"primary": "#2D2749",
"surfaceTint": "#605A7F",
"onPrimary": "#FFFFFF",
"primaryContainer": "#4A4468",
"onPrimaryContainer": "#FFFFFF",
"secondary": "#2D2A39",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#4A4757",
"onSecondaryContainer": "#FFFFFF",
"tertiary": "#432135",
"onTertiary": "#FFFFFF",
"tertiaryContainer": "#643D53",
"onTertiaryContainer": "#FFFFFF",
"error": "#600004",
"onError": "#FFFFFF",
"errorContainer": "#98000A",
"onErrorContainer": "#FFFFFF",
"background": "#FDF8FC",
"onBackground": "#1C1B1E",
"surface": "#FDF8FC",
"onSurface": "#000000",
"surfaceVariant": "#E6E1EA",
"onSurfaceVariant": "#000000",
"outline": "#2D2B32",
"outlineVariant": "#4A4850",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#313033",
"inverseOnSurface": "#FFFFFF",
"inversePrimary": "#C9C1EC",
"primaryFixed": "#4A4468",
"onPrimaryFixed": "#FFFFFF",
"primaryFixedDim": "#342E50",
"onPrimaryFixedVariant": "#FFFFFF",
"secondaryFixed": "#4A4757",
"onSecondaryFixed": "#FFFFFF",
"secondaryFixedDim": "#34313F",
"onSecondaryFixedVariant": "#FFFFFF",
"tertiaryFixed": "#643D53",
"onTertiaryFixed": "#FFFFFF",
"tertiaryFixedDim": "#4A273C",
"onTertiaryFixedVariant": "#FFFFFF",
"surfaceDim": "#BBB8BB",
"surfaceBright": "#FDF8FC",
"surfaceContainerLowest": "#FFFFFF",
"surfaceContainerLow": "#F4EFF3",
"surfaceContainer": "#E6E1E5",
"surfaceContainerHigh": "#D7D3D7",
"surfaceContainerHighest": "#C9C5C9"
},
"dark": {
"primary": "#C9C1EC",
"surfaceTint": "#C9C1EC",
"onPrimary": "#312C4E",
"primaryContainer": "#4E486C",
"onPrimaryContainer": "#C0B8E3",
"secondary": "#C9C4D7",
"onSecondary": "#312E3D",
"secondaryContainer": "#4A4757",
"onSecondaryContainer": "#BBB6C8",
"tertiary": "#ECB8D2",
"onTertiary": "#48253A",
"tertiaryContainer": "#684157",
"onTertiaryContainer": "#E3B0CA",
"error": "#FFB4AB",
"onError": "#690005",
"errorContainer": "#93000A",
"onErrorContainer": "#FFDAD6",
"background": "#141315",
"onBackground": "#E6E1E5",
"surface": "#141315",
"onSurface": "#E6E1E5",
"surfaceVariant": "#48464D",
"onSurfaceVariant": "#C9C5CE",
"outline": "#938F98",
"outlineVariant": "#48464D",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#E6E1E5",
"inverseOnSurface": "#313033",
"inversePrimary": "#605A7F",
"primaryFixed": "#E6DEFF",
"onPrimaryFixed": "#1C1738",
"primaryFixedDim": "#C9C1EC",
"onPrimaryFixedVariant": "#484266",
"secondaryFixed": "#E6E0F3",
"onSecondaryFixed": "#1C1A27",
"secondaryFixedDim": "#C9C4D7",
"onSecondaryFixedVariant": "#484554",
"tertiaryFixed": "#FFD8EA",
"onTertiaryFixed": "#301024",
"tertiaryFixedDim": "#ECB8D2",
"onTertiaryFixedVariant": "#613B51",
"surfaceDim": "#141315",
"surfaceBright": "#3A393B",
"surfaceContainerLowest": "#0F0E10",
"surfaceContainerLow": "#1C1B1E",
"surfaceContainer": "#201F22",
"surfaceContainerHigh": "#2B292C",
"surfaceContainerHighest": "#363437"
},
"dark-medium-contrast": {
"primary": "#E0D7FF",
"surfaceTint": "#C9C1EC",
"onPrimary": "#262142",
"primaryContainer": "#938CB4",
"onPrimaryContainer": "#000000",
"secondary": "#DFD9ED",
"onSecondary": "#262432",
"secondaryContainer": "#938EA0",
"onSecondaryContainer": "#000000",
"tertiary": "#FFCFE7",
"onTertiary": "#3C1A2E",
"tertiaryContainer": "#B2839C",
"onTertiaryContainer": "#000000",
"error": "#FFD2CC",
"onError": "#540003",
"errorContainer": "#FF5449",
"onErrorContainer": "#000000",
"background": "#141315",
"onBackground": "#E6E1E5",
"surface": "#141315",
"onSurface": "#FFFFFF",
"surfaceVariant": "#48464D",
"onSurfaceVariant": "#DFDAE4",
"outline": "#B4B0BA",
"outlineVariant": "#928F98",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#E6E1E5",
"inverseOnSurface": "#2B292C",
"inversePrimary": "#494367",
"primaryFixed": "#E6DEFF",
"onPrimaryFixed": "#120C2D",
"primaryFixedDim": "#C9C1EC",
"onPrimaryFixedVariant": "#373254",
"secondaryFixed": "#E6E0F3",
"onSecondaryFixed": "#120F1D",
"secondaryFixedDim": "#C9C4D7",
"onSecondaryFixedVariant": "#373443",
"tertiaryFixed": "#FFD8EA",
"onTertiaryFixed": "#230619",
"tertiaryFixedDim": "#ECB8D2",
"onTertiaryFixedVariant": "#4E2B40",
"surfaceDim": "#141315",
"surfaceBright": "#454447",
"surfaceContainerLowest": "#080709",
"surfaceContainerLow": "#1E1D20",
"surfaceContainer": "#28272A",
"surfaceContainerHigh": "#333235",
"surfaceContainerHighest": "#3F3D40"
},
"dark-high-contrast": {
"primary": "#F3EDFF",
"surfaceTint": "#C9C1EC",
"onPrimary": "#000000",
"primaryContainer": "#C6BDE8",
"onPrimaryContainer": "#0B0627",
"secondary": "#F3EDFF",
"onSecondary": "#000000",
"secondaryContainer": "#C5C0D3",
"onSecondaryContainer": "#0C0916",
"tertiary": "#FFEBF3",
"onTertiary": "#000000",
"tertiaryContainer": "#E7B4CE",
"onTertiaryContainer": "#1C0213",
"error": "#FFECE9",
"onError": "#000000",
"errorContainer": "#FFAEA4",
"onErrorContainer": "#220001",
"background": "#141315",
"onBackground": "#E6E1E5",
"surface": "#141315",
"onSurface": "#FFFFFF",
"surfaceVariant": "#48464D",
"onSurfaceVariant": "#FFFFFF",
"outline": "#F3EEF8",
"outlineVariant": "#C5C1CA",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#E6E1E5",
"inverseOnSurface": "#000000",
"inversePrimary": "#494367",
"primaryFixed": "#E6DEFF",
"onPrimaryFixed": "#000000",
"primaryFixedDim": "#C9C1EC",
"onPrimaryFixedVariant": "#120C2D",
"secondaryFixed": "#E6E0F3",
"onSecondaryFixed": "#000000",
"secondaryFixedDim": "#C9C4D7",
"onSecondaryFixedVariant": "#120F1D",
"tertiaryFixed": "#FFD8EA",
"onTertiaryFixed": "#000000",
"tertiaryFixedDim": "#ECB8D2",
"onTertiaryFixedVariant": "#230619",
"surfaceDim": "#141315",
"surfaceBright": "#514F52",
"surfaceContainerLowest": "#000000",
"surfaceContainerLow": "#201F22",
"surfaceContainer": "#313033",
"surfaceContainerHigh": "#3C3B3E",
"surfaceContainerHighest": "#484649"
}
},
"palettes": {
"primary": {
"0": "#000000",
"5": "#110B2C",
"10": "#1C1738",
"15": "#272142",
"20": "#312C4E",
"25": "#3C375A",
"30": "#484266",
"35": "#544E72",
"40": "#605A7F",
"50": "#797299",
"60": "#938CB4",
"70": "#AEA6CF",
"80": "#C9C1EC",
"90": "#E6DEFF",
"95": "#F4EEFF",
"98": "#FDF8FF",
"99": "#FFFBFF",
"100": "#FFFFFF"
},
"secondary": {
"0": "#000000",
"5": "#111018",
"10": "#1C1A23",
"15": "#26252D",
"20": "#312F38",
"25": "#3C3A43",
"30": "#48454F",
"35": "#54515B",
"40": "#605D67",
"50": "#797580",
"60": "#938F9A",
"70": "#AEA9B5",
"80": "#C9C4D0",
"90": "#E6E0EC",
"95": "#F4EEFB",
"98": "#FDF8FF",
"99": "#FFFBFF",
"100": "#FFFFFF"
},
"tertiary": {
"0": "#000000",
"5": "#1B0C13",
"10": "#27171E",
"15": "#322128",
"20": "#3E2B33",
"25": "#49363E",
"30": "#564149",
"35": "#624D55",
"40": "#6F5861",
"50": "#897179",
"60": "#A38A93",
"70": "#BFA4AD",
"80": "#DCBFC9",
"90": "#F9DBE5",
"95": "#FFECF1",
"98": "#FFF8F8",
"99": "#FFFBFF",
"100": "#FFFFFF"
},
"neutral": {
"0": "#000000",
"5": "#111112",
"10": "#1C1B1D",
"15": "#262527",
"20": "#313032",
"25": "#3C3B3D",
"30": "#484648",
"35": "#545254",
"40": "#605E60",
"50": "#797678",
"60": "#939092",
"70": "#ADAAAC",
"80": "#C9C5C7",
"90": "#E5E1E3",
"95": "#F4EFF1",
"98": "#FDF8FA",
"99": "#FFFBFF",
"100": "#FFFFFF"
},
"neutral-variant": {
"0": "#000000",
"5": "#111014",
"10": "#1C1B1F",
"15": "#262529",
"20": "#313034",
"25": "#3C3B3F",
"30": "#48464A",
"35": "#545256",
"40": "#605D62",
"50": "#79767B",
"60": "#939094",
"70": "#AEAAAF",
"80": "#C9C5CA",
"90": "#E6E1E6",
"95": "#F4EFF4",
"98": "#FDF8FD",
"99": "#FFFBFF",
"100": "#FFFFFF"
}
}
}

View File

@ -0,0 +1,8 @@
{
"id": "default",
"name": "Default",
"colors": {
"primary": "#4e486c"
},
"options": {}
}

View File

@ -0,0 +1,11 @@
{
"id": "devilun",
"name": "Devilun",
"colors": {
"primary": "#d1779d",
"secondary": "#85a9a5"
},
"options": {
"forceScheme": "dark"
}
}

View File

@ -0,0 +1,10 @@
{
"id": "kupya",
"name": "Kupya",
"colors": {
"primary": "#ffeb9e"
},
"options": {
"forceScheme": "light"
}
}

View File

@ -0,0 +1,8 @@
{
"id": "tempest",
"name": "Tempest",
"colors": {
"primary": "#186d98"
},
"options": {}
}

View File

@ -1,427 +0,0 @@
{
"//url": "http://material-foundation.github.io/material-theme-builder/?primary=%23186D98&custom%3ASuccess=%2300C555&colorMatch=true",
"name": "tempest",
"description": "TYPE: CUSTOM\nMaterial Theme Builder export",
"seed": "#186D98",
"coreColors": {
"primary": "#186D98"
},
"extendedColors": [
{
"name": "Success",
"color": "#00C555",
"description": "",
"harmonized": true
}
],
"schemes": {
"light": {
"primary": "#005479",
"surfaceTint": "#03658F",
"onPrimary": "#FFFFFF",
"primaryContainer": "#186D98",
"onPrimaryContainer": "#CEE9FF",
"secondary": "#496173",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#C9E3F8",
"onSecondaryContainer": "#4D6678",
"tertiary": "#683D7A",
"onTertiary": "#FFFFFF",
"tertiaryContainer": "#825594",
"onTertiaryContainer": "#F9DCFF",
"error": "#BA1A1A",
"onError": "#FFFFFF",
"errorContainer": "#FFDAD6",
"onErrorContainer": "#93000A",
"background": "#F7F9FD",
"onBackground": "#191C1F",
"surface": "#F7F9FD",
"onSurface": "#191C1F",
"surfaceVariant": "#DCE3EB",
"onSurfaceVariant": "#40484E",
"outline": "#70787F",
"outlineVariant": "#C0C7CF",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#2D3134",
"inverseOnSurface": "#EFF1F5",
"inversePrimary": "#88CEFE",
"primaryFixed": "#C8E6FF",
"onPrimaryFixed": "#001E2E",
"primaryFixedDim": "#88CEFE",
"onPrimaryFixedVariant": "#004C6D",
"secondaryFixed": "#CCE6FB",
"onSecondaryFixed": "#021E2D",
"secondaryFixedDim": "#B0CADF",
"onSecondaryFixedVariant": "#314A5B",
"tertiaryFixed": "#F8D8FF",
"onTertiaryFixed": "#300443",
"tertiaryFixedDim": "#E8B4FA",
"onTertiaryFixedVariant": "#603572",
"surfaceDim": "#D8DADE",
"surfaceBright": "#F7F9FD",
"surfaceContainerLowest": "#FFFFFF",
"surfaceContainerLow": "#F2F4F7",
"surfaceContainer": "#ECEEF2",
"surfaceContainerHigh": "#E6E8EC",
"surfaceContainerHighest": "#E0E2E6"
},
"light-medium-contrast": {
"primary": "#003A55",
"surfaceTint": "#03658F",
"onPrimary": "#FFFFFF",
"primaryContainer": "#186D98",
"onPrimaryContainer": "#FFFFFF",
"secondary": "#203949",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#577082",
"onSecondaryContainer": "#FFFFFF",
"tertiary": "#4E2460",
"onTertiary": "#FFFFFF",
"tertiaryContainer": "#825594",
"onTertiaryContainer": "#FFFFFF",
"error": "#740006",
"onError": "#FFFFFF",
"errorContainer": "#CF2C27",
"onErrorContainer": "#FFFFFF",
"background": "#F7F9FD",
"onBackground": "#191C1F",
"surface": "#F7F9FD",
"onSurface": "#0E1214",
"surfaceVariant": "#DCE3EB",
"onSurfaceVariant": "#2F373D",
"outline": "#4C535A",
"outlineVariant": "#666E75",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#2D3134",
"inverseOnSurface": "#EFF1F5",
"inversePrimary": "#88CEFE",
"primaryFixed": "#23749F",
"onPrimaryFixed": "#FFFFFF",
"primaryFixedDim": "#005B82",
"onPrimaryFixedVariant": "#FFFFFF",
"secondaryFixed": "#577082",
"onSecondaryFixed": "#FFFFFF",
"secondaryFixedDim": "#3F5869",
"onSecondaryFixedVariant": "#FFFFFF",
"tertiaryFixed": "#895C9B",
"onTertiaryFixed": "#FFFFFF",
"tertiaryFixedDim": "#6F4381",
"onTertiaryFixedVariant": "#FFFFFF",
"surfaceDim": "#C4C7CA",
"surfaceBright": "#F7F9FD",
"surfaceContainerLowest": "#FFFFFF",
"surfaceContainerLow": "#F2F4F7",
"surfaceContainer": "#E6E8EC",
"surfaceContainerHigh": "#DBDDE1",
"surfaceContainerHighest": "#CFD2D5"
},
"light-high-contrast": {
"primary": "#003046",
"surfaceTint": "#03658F",
"onPrimary": "#FFFFFF",
"primaryContainer": "#004E71",
"onPrimaryContainer": "#FFFFFF",
"secondary": "#152F3F",
"onSecondary": "#FFFFFF",
"secondaryContainer": "#344C5D",
"onSecondaryContainer": "#FFFFFF",
"tertiary": "#421955",
"onTertiary": "#FFFFFF",
"tertiaryContainer": "#623874",
"onTertiaryContainer": "#FFFFFF",
"error": "#600004",
"onError": "#FFFFFF",
"errorContainer": "#98000A",
"onErrorContainer": "#FFFFFF",
"background": "#F7F9FD",
"onBackground": "#191C1F",
"surface": "#F7F9FD",
"onSurface": "#000000",
"surfaceVariant": "#DCE3EB",
"onSurfaceVariant": "#000000",
"outline": "#252D33",
"outlineVariant": "#424A51",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#2D3134",
"inverseOnSurface": "#FFFFFF",
"inversePrimary": "#88CEFE",
"primaryFixed": "#004E71",
"onPrimaryFixed": "#FFFFFF",
"primaryFixedDim": "#003650",
"onPrimaryFixedVariant": "#FFFFFF",
"secondaryFixed": "#344C5D",
"onSecondaryFixed": "#FFFFFF",
"secondaryFixedDim": "#1C3546",
"onSecondaryFixedVariant": "#FFFFFF",
"tertiaryFixed": "#623874",
"onTertiaryFixed": "#FFFFFF",
"tertiaryFixedDim": "#4A205C",
"onTertiaryFixedVariant": "#FFFFFF",
"surfaceDim": "#B6B9BD",
"surfaceBright": "#F7F9FD",
"surfaceContainerLowest": "#FFFFFF",
"surfaceContainerLow": "#EFF1F5",
"surfaceContainer": "#E0E2E6",
"surfaceContainerHigh": "#D2D4D8",
"surfaceContainerHighest": "#C4C7CA"
},
"dark": {
"primary": "#88CEFE",
"surfaceTint": "#88CEFE",
"onPrimary": "#00344D",
"primaryContainer": "#186D98",
"onPrimaryContainer": "#CEE9FF",
"secondary": "#B0CADF",
"onSecondary": "#1A3343",
"secondaryContainer": "#314A5B",
"onSecondaryContainer": "#9FB8CD",
"tertiary": "#E8B4FA",
"onTertiary": "#471E59",
"tertiaryContainer": "#825594",
"onTertiaryContainer": "#F9DCFF",
"error": "#FFB4AB",
"onError": "#690005",
"errorContainer": "#93000A",
"onErrorContainer": "#FFDAD6",
"background": "#101417",
"onBackground": "#E0E2E6",
"surface": "#101417",
"onSurface": "#E0E2E6",
"surfaceVariant": "#40484E",
"onSurfaceVariant": "#C0C7CF",
"outline": "#8A9299",
"outlineVariant": "#40484E",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#E0E2E6",
"inverseOnSurface": "#2D3134",
"inversePrimary": "#03658F",
"primaryFixed": "#C8E6FF",
"onPrimaryFixed": "#001E2E",
"primaryFixedDim": "#88CEFE",
"onPrimaryFixedVariant": "#004C6D",
"secondaryFixed": "#CCE6FB",
"onSecondaryFixed": "#021E2D",
"secondaryFixedDim": "#B0CADF",
"onSecondaryFixedVariant": "#314A5B",
"tertiaryFixed": "#F8D8FF",
"onTertiaryFixed": "#300443",
"tertiaryFixedDim": "#E8B4FA",
"onTertiaryFixedVariant": "#603572",
"surfaceDim": "#101417",
"surfaceBright": "#363A3D",
"surfaceContainerLowest": "#0B0F11",
"surfaceContainerLow": "#191C1F",
"surfaceContainer": "#1D2023",
"surfaceContainerHigh": "#272A2D",
"surfaceContainerHighest": "#323538"
},
"dark-medium-contrast": {
"primary": "#BBE1FF",
"surfaceTint": "#88CEFE",
"onPrimary": "#00293D",
"primaryContainer": "#5098C5",
"onPrimaryContainer": "#000000",
"secondary": "#C6E0F5",
"onSecondary": "#0D2838",
"secondaryContainer": "#7B94A7",
"onSecondaryContainer": "#000000",
"tertiary": "#F5D0FF",
"onTertiary": "#3B114E",
"tertiaryContainer": "#AF7FC1",
"onTertiaryContainer": "#000000",
"error": "#FFD2CC",
"onError": "#540003",
"errorContainer": "#FF5449",
"onErrorContainer": "#000000",
"background": "#101417",
"onBackground": "#E0E2E6",
"surface": "#101417",
"onSurface": "#FFFFFF",
"surfaceVariant": "#40484E",
"onSurfaceVariant": "#D6DDE5",
"outline": "#ABB3BB",
"outlineVariant": "#899199",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#E0E2E6",
"inverseOnSurface": "#272A2D",
"inversePrimary": "#004D6F",
"primaryFixed": "#C8E6FF",
"onPrimaryFixed": "#00131F",
"primaryFixedDim": "#88CEFE",
"onPrimaryFixedVariant": "#003A55",
"secondaryFixed": "#CCE6FB",
"onSecondaryFixed": "#00131F",
"secondaryFixedDim": "#B0CADF",
"onSecondaryFixedVariant": "#203949",
"tertiaryFixed": "#F8D8FF",
"onTertiaryFixed": "#220032",
"tertiaryFixedDim": "#E8B4FA",
"onTertiaryFixedVariant": "#4E2460",
"surfaceDim": "#101417",
"surfaceBright": "#424548",
"surfaceContainerLowest": "#05080A",
"surfaceContainerLow": "#1B1E21",
"surfaceContainer": "#25282B",
"surfaceContainerHigh": "#303336",
"surfaceContainerHighest": "#3B3E41"
},
"dark-high-contrast": {
"primary": "#E3F2FF",
"surfaceTint": "#88CEFE",
"onPrimary": "#000000",
"primaryContainer": "#84CAFA",
"onPrimaryContainer": "#000D17",
"secondary": "#E3F2FF",
"onSecondary": "#000000",
"secondaryContainer": "#ACC6DB",
"onSecondaryContainer": "#000D17",
"tertiary": "#FDEAFF",
"onTertiary": "#000000",
"tertiaryContainer": "#E4B0F6",
"onTertiaryContainer": "#190026",
"error": "#FFECE9",
"onError": "#000000",
"errorContainer": "#FFAEA4",
"onErrorContainer": "#220001",
"background": "#101417",
"onBackground": "#E0E2E6",
"surface": "#101417",
"onSurface": "#FFFFFF",
"surfaceVariant": "#40484E",
"onSurfaceVariant": "#FFFFFF",
"outline": "#E9F1F9",
"outlineVariant": "#BCC3CB",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#E0E2E6",
"inverseOnSurface": "#000000",
"inversePrimary": "#004D6F",
"primaryFixed": "#C8E6FF",
"onPrimaryFixed": "#000000",
"primaryFixedDim": "#88CEFE",
"onPrimaryFixedVariant": "#00131F",
"secondaryFixed": "#CCE6FB",
"onSecondaryFixed": "#000000",
"secondaryFixedDim": "#B0CADF",
"onSecondaryFixedVariant": "#00131F",
"tertiaryFixed": "#F8D8FF",
"onTertiaryFixed": "#000000",
"tertiaryFixedDim": "#E8B4FA",
"onTertiaryFixedVariant": "#220032",
"surfaceDim": "#101417",
"surfaceBright": "#4D5054",
"surfaceContainerLowest": "#000000",
"surfaceContainerLow": "#1D2023",
"surfaceContainer": "#2D3134",
"surfaceContainerHigh": "#383C3F",
"surfaceContainerHighest": "#44474A"
}
},
"palettes": {
"primary": {
"0": "#000000",
"5": "#00131F",
"10": "#001E2E",
"15": "#00293D",
"20": "#00344D",
"25": "#00405D",
"30": "#004C6D",
"35": "#00587E",
"40": "#03658F",
"50": "#317EAA",
"60": "#5098C5",
"70": "#6CB3E1",
"80": "#88CEFE",
"90": "#C8E6FF",
"95": "#E5F2FF",
"98": "#F6FAFF",
"99": "#FBFCFF",
"100": "#FFFFFF"
},
"secondary": {
"0": "#000000",
"5": "#05121B",
"10": "#0F1D26",
"15": "#1A2731",
"20": "#25323C",
"25": "#303D47",
"30": "#3B4853",
"35": "#46545F",
"40": "#52606B",
"50": "#6B7984",
"60": "#84929E",
"70": "#9FADB9",
"80": "#BAC8D5",
"90": "#D6E4F2",
"95": "#E5F2FF",
"98": "#F6FAFF",
"99": "#FBFCFF",
"100": "#FFFFFF"
},
"tertiary": {
"0": "#000000",
"5": "#140D25",
"10": "#1E1730",
"15": "#29223B",
"20": "#342C46",
"25": "#3F3752",
"30": "#4B425E",
"35": "#564E6A",
"40": "#635A76",
"50": "#7C7290",
"60": "#968CAB",
"70": "#B1A6C6",
"80": "#CDC1E2",
"90": "#E9DDFF",
"95": "#F6EDFF",
"98": "#FEF7FF",
"99": "#FFFBFF",
"100": "#FFFFFF"
},
"neutral": {
"0": "#000000",
"5": "#0F1113",
"10": "#1A1C1E",
"15": "#242628",
"20": "#2F3132",
"25": "#3A3B3D",
"30": "#454749",
"35": "#515254",
"40": "#5D5E60",
"50": "#767779",
"60": "#909193",
"70": "#AAABAD",
"80": "#C6C6C8",
"90": "#E2E2E4",
"95": "#F1F0F3",
"98": "#F9F9FB",
"99": "#FCFCFE",
"100": "#FFFFFF"
},
"neutral-variant": {
"0": "#000000",
"5": "#0C1215",
"10": "#171C20",
"15": "#21262B",
"20": "#2C3135",
"25": "#373C40",
"30": "#42474C",
"35": "#4E5358",
"40": "#5A5F64",
"50": "#73787D",
"60": "#8C9196",
"70": "#A7ACB1",
"80": "#C2C7CC",
"90": "#DEE3E8",
"95": "#EDF1F7",
"98": "#F6FAFF",
"99": "#FBFCFF",
"100": "#FFFFFF"
}
}
}

View File

@ -4,17 +4,17 @@ from typing import overload
import structlog import structlog
from PySide6.QtCore import Property, QObject, QResource, Qt, Signal from PySide6.QtCore import Property, QObject, QResource, Qt, Signal
from PySide6.QtGui import QColor, QGuiApplication, QPalette from PySide6.QtGui import QGuiApplication, QPalette
from .material3 import Material3DynamicThemeImpl, Material3ThemeImpl from .material3 import Material3DynamicThemeImpl, Material3ThemeImpl
from .qml import ThemeQmlExposer from .qml import ThemeQmlExposer
from .shared import ThemeImpl, ThemeInfo, _TCustomPalette, _TScheme from .shared import ThemeImpl, ThemeInfo, TThemeInfoCacheKey, _TCustomPalette, _TScheme
QML_IMPORT_NAME = "internal.ui.theme" QML_IMPORT_NAME = "internal.ui.theme"
QML_IMPORT_MAJOR_VERSION = 1 QML_IMPORT_MAJOR_VERSION = 1
QML_IMPORT_MINOR_VERSION = 0 QML_IMPORT_MINOR_VERSION = 0
_THEME_CACHES: dict[ThemeInfo, ThemeImpl] = {} _THEME_CACHES: dict[TThemeInfoCacheKey, ThemeImpl] = {}
logger: structlog.stdlib.BoundLogger = structlog.get_logger() logger: structlog.stdlib.BoundLogger = structlog.get_logger()
@ -27,30 +27,18 @@ class ThemeManager(QObject):
super().__init__(parent) super().__init__(parent)
self._qPalette = QPalette() self._qPalette = QPalette()
self._customPalette: _TCustomPalette = { self._customPalette: _TCustomPalette = ThemeImpl.DEFAULT_CUSTOM_PALETTE
"primary": QColor.fromString("#616161"),
"success": QColor.fromString("#616161"),
"error": QColor.fromString("#616161"),
}
self._lastThemeInfo = ThemeInfo( self._lastThemeInfo = ThemeImpl().info
series="material3",
name="default",
scheme=self.getCurrentScheme(),
)
self._qmlExposer = ThemeQmlExposer(themeImpl=ThemeImpl()) self._qmlExposer = ThemeQmlExposer(themeImpl=ThemeImpl())
self._cacheMaterial3Theme(themeName="default", scheme="light") self._cacheMaterial3DynamicTheme(themeId="default")
self._cacheMaterial3Theme(themeName="default", scheme="dark") self._cacheMaterial3DynamicTheme(themeId="tempest")
self._cacheMaterial3Theme(themeName="tempest", scheme="light")
self._cacheMaterial3Theme(themeName="tempest", scheme="dark")
self._cacheMaterial3DynamicTheme(themeName="default", scheme="light") self._cacheMaterial3DynamicTheme(themeId="devilun")
self._cacheMaterial3DynamicTheme(themeName="default", scheme="dark") self._cacheMaterial3DynamicTheme(themeId="kupya")
self._cacheMaterial3DynamicTheme(themeName="tempest", scheme="light")
self._cacheMaterial3DynamicTheme(themeName="tempest", scheme="dark")
self.setTheme("material3-dynamic", "default") self.setTheme("material3-dynamic", "devilun")
def getCurrentScheme(self) -> _TScheme: def getCurrentScheme(self) -> _TScheme:
qApp: QGuiApplication = QGuiApplication.instance() # pyright: ignore[reportAssignmentType] qApp: QGuiApplication = QGuiApplication.instance() # pyright: ignore[reportAssignmentType]
@ -60,52 +48,47 @@ class ThemeManager(QObject):
else "light" else "light"
) )
def getMaterial3Theme(self, themeName: str, scheme: _TScheme) -> Material3ThemeImpl: def _loadQResourceJson(self, resourcePath: str):
themeDataResource = QResource(f":/themes/{themeName}.json") resource = QResource(resourcePath)
if not themeDataResource.isValid(): if not resource.isValid():
raise ValueError(f"Material3 theme {themeName!r} not found") raise ValueError(f"Resource {resourcePath!r} invalid")
themeData = json.loads( return json.loads(resource.uncompressedData().data().decode("utf-8"))
themeDataResource.uncompressedData().data().decode("utf-8")
)
def getMaterial3Theme(self, themeId: str, scheme: _TScheme) -> Material3ThemeImpl:
themeData = self._loadQResourceJson(f":/themes/m3_{themeId}.json")
return Material3ThemeImpl(themeData=themeData, scheme=scheme) return Material3ThemeImpl(themeData=themeData, scheme=scheme)
def getMaterial3DynamicTheme( def getMaterial3DynamicTheme(
self, themeName: str, scheme: _TScheme self, themeId: str, scheme: _TScheme
) -> Material3DynamicThemeImpl: ) -> Material3DynamicThemeImpl:
themeDataResource = QResource(f":/themes/{themeName}.json") themeData = self._loadQResourceJson(f":/themes/m3-dynamic_{themeId}.json")
if not themeDataResource.isValid(): return Material3DynamicThemeImpl(themeData=themeData, scheme=scheme)
raise ValueError(f"Material3 theme {themeName!r} not found")
themeData = json.loads(
themeDataResource.uncompressedData().data().decode("utf-8")
)
return Material3DynamicThemeImpl(
sourceColorHex=themeData["seed"],
scheme=scheme,
name=themeName,
)
def _cacheTheme(self, *, themeImpl: ThemeImpl): def _cacheTheme(self, *, themeImpl: ThemeImpl):
_THEME_CACHES[themeImpl.info] = themeImpl _THEME_CACHES[themeImpl.info.cacheKey()] = themeImpl
logger.debug("Theme %r cached", themeImpl.info) logger.debug("Theme %r cached", themeImpl.info)
def _getCachedTheme(self, *, themeInfo: ThemeInfo): def _getCachedTheme(self, *, key: TThemeInfoCacheKey):
cachedTheme = _THEME_CACHES.get(themeInfo) cachedTheme = _THEME_CACHES.get(key)
if cachedTheme is None: if cachedTheme is None:
raise KeyError(f"Theme {themeInfo!r} not cached") raise KeyError(f"Theme {key!r} not cached")
return cachedTheme return cachedTheme
def _cacheMaterial3Theme(self, *, themeName: str, scheme: _TScheme): def _cacheMaterial3Theme(self, *, themeId: str):
self._cacheTheme( self._cacheTheme(
themeImpl=self.getMaterial3Theme(themeName=themeName, scheme=scheme), themeImpl=self.getMaterial3Theme(themeId=themeId, scheme="light"),
)
self._cacheTheme(
themeImpl=self.getMaterial3Theme(themeId=themeId, scheme="dark"),
) )
def _cacheMaterial3DynamicTheme(self, *, themeName: str, scheme: _TScheme): def _cacheMaterial3DynamicTheme(self, *, themeId: str):
self._cacheTheme( self._cacheTheme(
themeImpl=self.getMaterial3DynamicTheme(themeName=themeName, scheme=scheme) themeImpl=self.getMaterial3DynamicTheme(themeId=themeId, scheme="light")
)
self._cacheTheme(
themeImpl=self.getMaterial3DynamicTheme(themeId=themeId, scheme="dark")
) )
@overload @overload
@ -113,29 +96,29 @@ class ThemeManager(QObject):
@overload @overload
def setTheme( def setTheme(
self, themeSeries: str, themeName: str, scheme: _TScheme | None = None, / self, themeSeries: str, themeId: str, scheme: _TScheme | None = None, /
): ... ): ...
def setTheme(self, *args, **kwargs): def setTheme(self, *args, **kwargs):
if "themeInfo" in kwargs: if "themeInfo" in kwargs:
themeInfo = kwargs["themeInfo"] cacheKey = kwargs["themeInfo"].cacheKey()
elif 2 <= len(args) <= 3: elif 2 <= len(args) <= 3:
themeSeries = args[0] themeSeries = args[0]
themeName = args[1] themeId = args[1]
schemeArg = args[2] if len(args) > 2 else None schemeArg = args[2] if len(args) > 2 else None
scheme = schemeArg or self.getCurrentScheme() scheme = schemeArg or self.getCurrentScheme()
themeInfo = ThemeInfo(series=themeSeries, name=themeName, scheme=scheme) cacheKey: TThemeInfoCacheKey = (themeSeries, themeId, scheme)
else: else:
raise TypeError("Invalid setTheme() call") raise TypeError("Invalid setTheme() call")
logger.debug("Preparing to set theme %r", themeInfo) logger.debug("Preparing to set theme %r", cacheKey)
cachedTheme = self._getCachedTheme(themeInfo=themeInfo) cachedTheme = self._getCachedTheme(key=cacheKey)
self._qPalette = cachedTheme.qPalette self._qPalette = cachedTheme.qPalette
self._customPalette = cachedTheme.customPalette self._customPalette = cachedTheme.customPalette
self._lastThemeInfo = themeInfo self._lastThemeInfo = cachedTheme.info
self._qmlExposer.themeImpl = cachedTheme self._qmlExposer.themeImpl = cachedTheme
self.themeChanged.emit() self.themeChanged.emit()

View File

@ -1,5 +1,3 @@
from typing import TypedDict
from materialyoucolor.blend import Blend from materialyoucolor.blend import Blend
from materialyoucolor.dynamiccolor.contrast_curve import ContrastCurve from materialyoucolor.dynamiccolor.contrast_curve import ContrastCurve
from materialyoucolor.dynamiccolor.dynamic_color import DynamicColor, FromPaletteOptions from materialyoucolor.dynamiccolor.dynamic_color import DynamicColor, FromPaletteOptions
@ -10,48 +8,12 @@ from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
from PySide6.QtGui import QColor, QPalette from PySide6.QtGui import QColor, QPalette
from .shared import ThemeImpl, ThemeInfo, _TCustomPalette, _TScheme from .shared import ThemeImpl, ThemeInfo, _TCustomPalette, _TScheme
from .types import (
TMaterial3DynamicThemeData,
class _M3ThemeDataExtendedColorItem(TypedDict): TMaterial3ThemeData,
name: str TMaterial3ThemeDataExtendedColorItem,
color: str
description: str
harmonized: bool
_M3ThemeDataSchemes = TypedDict(
"_M3ThemeDataSchemes",
{
"light": dict[str, str],
"light-medium-contrast": dict[str, str],
"light-high-contrast": dict[str, str],
"dark": dict[str, str],
"dark-medium-contrast": dict[str, str],
"dark-high-contrast": dict[str, str],
},
) )
_M3ThemeDataPalettes = TypedDict(
"_M3ThemeDataPalettes",
{
"primary": dict[str, str],
"secondary": dict[str, str],
"tertiary": dict[str, str],
"neutral": dict[str, str],
"neutral-variant": dict[str, str],
},
)
class _M3ThemeData(TypedDict):
name: str
description: str
seed: str
coreColors: dict[str, str]
extendedColors: list[_M3ThemeDataExtendedColorItem]
schemes: _M3ThemeDataSchemes
palettes: _M3ThemeDataPalettes
def _hexToHct(hexColor: str) -> Hct: def _hexToHct(hexColor: str) -> Hct:
pureHexPart = hexColor[1:] if hexColor.startswith("#") else hexColor pureHexPart = hexColor[1:] if hexColor.startswith("#") else hexColor
@ -87,7 +49,7 @@ class Material3ThemeImpl(ThemeImpl):
QPalette.ColorRole.LinkVisited: "tertiaryContainer", QPalette.ColorRole.LinkVisited: "tertiaryContainer",
} }
def __init__(self, *, themeData: _M3ThemeData, scheme: _TScheme): def __init__(self, *, themeData: TMaterial3ThemeData, scheme: _TScheme):
self.themeData = themeData self.themeData = themeData
self.scheme: _TScheme = scheme self.scheme: _TScheme = scheme
@ -96,7 +58,7 @@ class Material3ThemeImpl(ThemeImpl):
def _findExtendedColor( def _findExtendedColor(
self, colorName: str self, colorName: str
) -> _M3ThemeDataExtendedColorItem | None: ) -> TMaterial3ThemeDataExtendedColorItem | None:
return next( return next(
(it for it in self.themeData["extendedColors"] if it["name"] == colorName), (it for it in self.themeData["extendedColors"] if it["name"] == colorName),
None, None,
@ -106,6 +68,7 @@ class Material3ThemeImpl(ThemeImpl):
def info(self): def info(self):
return ThemeInfo( return ThemeInfo(
series="material3", series="material3",
id=self.themeData["id"],
name=self.themeData["name"], name=self.themeData["name"],
scheme=self.scheme, scheme=self.scheme,
) )
@ -137,6 +100,8 @@ class Material3ThemeImpl(ThemeImpl):
"primary": _hctToQColor(primaryHct), "primary": _hctToQColor(primaryHct),
"success": _hctToQColor(successHarmonizedHct), "success": _hctToQColor(successHarmonizedHct),
"error": QColor.fromString(self.themeData["schemes"][self.scheme]["error"]), "error": QColor.fromString(self.themeData["schemes"][self.scheme]["error"]),
"toolTipBase": self.qPalette.color(QPalette.ColorRole.ToolTipBase),
"toolTipText": self.qPalette.color(QPalette.ColorRole.ToolTipText),
} }
@ -169,20 +134,45 @@ class Material3DynamicThemeImpl(ThemeImpl):
"success": "#00c555", "success": "#00c555",
} }
def __init__(self, sourceColorHex: str, scheme: _TScheme, *, name: str): def __init__(self, themeData: TMaterial3DynamicThemeData, scheme: _TScheme):
force_scheme = themeData["options"].get("forceScheme")
if force_scheme:
is_dark = force_scheme == "dark"
else:
is_dark = scheme == "dark"
# TODO: more elegant way?
self.preferredScheme: _TScheme = scheme # for theme caching
self.actualScheme = "dark" if is_dark else "light"
self.themeId = themeData["id"]
self.themeName = themeData["name"]
self.material3Scheme = SchemeTonalSpot( self.material3Scheme = SchemeTonalSpot(
_hexToHct(sourceColorHex), _hexToHct(themeData["colors"]["primary"]),
is_dark=scheme == "dark", is_dark=is_dark,
contrast_level=0.0, contrast_level=0.0,
) )
self.name = name
secondary_color = themeData["colors"].get("secondary")
if secondary_color:
self.material3Scheme.secondary_palette = TonalPalette.from_hct(
_hexToHct(secondary_color)
)
tertiary_color = themeData["colors"].get("tertiary")
if tertiary_color:
self.material3Scheme.tertiary_palette = TonalPalette.from_hct(
_hexToHct(tertiary_color)
)
@property @property
def info(self): def info(self):
return ThemeInfo( return ThemeInfo(
series="material3-dynamic", series="material3-dynamic",
name=self.name, id=self.themeId,
scheme="dark" if self.material3Scheme.is_dark else "light", name=self.themeName,
scheme=self.preferredScheme,
) )
@property @property
@ -242,4 +232,6 @@ class Material3DynamicThemeImpl(ThemeImpl):
extendedPalettes["success"].get_hct(self.material3Scheme) extendedPalettes["success"].get_hct(self.material3Scheme)
), ),
"error": _hctToQColor(errorHct), "error": _hctToQColor(errorHct),
"toolTipBase": self.qPalette.color(QPalette.ColorRole.ToolTipBase),
"toolTipText": self.qPalette.color(QPalette.ColorRole.ToolTipText),
} }

View File

@ -35,3 +35,11 @@ class ThemeQmlExposer(QObject):
@Property(QColor, notify=themeChanged) @Property(QColor, notify=themeChanged)
def error(self): def error(self):
return self._themeImpl.customPalette["error"] return self._themeImpl.customPalette["error"]
@Property(QColor, notify=themeChanged)
def toolTipBase(self):
return self._themeImpl.customPalette["toolTipBase"]
@Property(QColor, notify=themeChanged)
def toolTipText(self):
return self._themeImpl.customPalette["toolTipText"]

View File

@ -9,30 +9,43 @@ class _TCustomPalette(TypedDict):
success: QColor success: QColor
error: QColor error: QColor
toolTipBase: QColor
toolTipText: QColor
_TScheme = Literal["light", "dark"] _TScheme = Literal["light", "dark"]
TThemeInfoCacheKey = tuple[str, str, _TScheme]
@dataclass @dataclass
class ThemeInfo: class ThemeInfo:
series: str series: str
id: str
name: str name: str
scheme: _TScheme scheme: _TScheme
def __hash__(self) -> int: def cacheKey(self) -> TThemeInfoCacheKey:
return hash((self.series, self.name, self.scheme)) return (self.series, self.id, self.scheme)
class ThemeImpl: class ThemeImpl:
DEFAULT_CUSTOM_PALETTE = { DEFAULT_CUSTOM_PALETTE: _TCustomPalette = {
"primary": QColor.fromString("#616161"), "primary": QColor.fromString("#616161"),
"success": QColor.fromString("#616161"), "success": QColor.fromString("#616161"),
"error": QColor.fromString("#616161"), "error": QColor.fromString("#616161"),
"toolTipBase": QColor.fromString("#616161"),
"toolTipText": QColor.fromString("#616161"),
} }
@property @property
def info(self) -> ThemeInfo: def info(self) -> ThemeInfo:
return ThemeInfo(series="placeholder", name="placeholder", scheme="dark") return ThemeInfo(
series="placeholder",
id="placeholder",
name="placeholder",
scheme="dark",
)
@property @property
def qPalette(self) -> QPalette: def qPalette(self) -> QPalette:

72
ui/theme/types.py Normal file
View File

@ -0,0 +1,72 @@
from typing import TypedDict
from .shared import _TScheme
# region material3
class TMaterial3ThemeDataExtendedColorItem(TypedDict):
name: str
color: str
description: str
harmonized: bool
TMaterial3ThemeDataSchemes = TypedDict(
"TMaterial3ThemeDataSchemes",
{
"light": dict[str, str],
"light-medium-contrast": dict[str, str],
"light-high-contrast": dict[str, str],
"dark": dict[str, str],
"dark-medium-contrast": dict[str, str],
"dark-high-contrast": dict[str, str],
},
)
TMaterial3ThemeDataPalettes = TypedDict(
"TMaterial3ThemeDataPalettes",
{
"primary": dict[str, str],
"secondary": dict[str, str],
"tertiary": dict[str, str],
"neutral": dict[str, str],
"neutral-variant": dict[str, str],
},
)
class TMaterial3ThemeData(TypedDict):
id: str
name: str
description: str
seed: str
coreColors: dict[str, str]
extendedColors: list[TMaterial3ThemeDataExtendedColorItem]
schemes: TMaterial3ThemeDataSchemes
palettes: TMaterial3ThemeDataPalettes
# endregion
# region material3-dynamic
class TMaterial3DynamicThemeDataColors(TypedDict):
primary: str
secondary: str | None
tertiary: str | None
class TMaterial3DynamicThemeDataOptions(TypedDict):
forceScheme: _TScheme | None
class TMaterial3DynamicThemeData(TypedDict):
id: str
name: str
colors: TMaterial3DynamicThemeDataColors
options: TMaterial3DynamicThemeDataOptions
# endregion