color generation

This commit is contained in:
end-4 2025-04-26 14:17:13 +02:00
parent 5e9a6bf965
commit a9c40bc86d
22 changed files with 1065 additions and 7 deletions

View file

@ -0,0 +1,31 @@
[config]
version_check = false
[config.wallpaper]
command = "swww"
arguments = ["img", "--transition-step", "100", "--transition-fps", "120", "--transition-type", "grow", "--transition-angle", "30", "--transition-duration", "1"]
[templates.m3colors]
input_path = '~/.config/matugen/templates/colors.json'
output_path = '~/.local/state/quickshell/user/generated/colors.json'
[templates.hyprland]
input_path = '~/.config/matugen/templates/hyprland/colors.conf'
output_path = '~/.config/hypr/hyprland/hyprland/colors.conf'
[templates.hyprlock]
input_path = '~/.config/matugen/templates/hyprland/hyprlock.conf'
output_path = '~/.config/hypr/hyprlock.conf'
[templates.fuzzel]
input_path = '~/.config/matugen/templates/fuzzel/fuzzel.ini'
output_path = '~/.config/fuzzel/fuzzel.ini'
[templates.gtk3]
input_path = '~/.config/matugen/templates/gtk/gtk-colors.css'
output_path = '~/.config/gtk-3.0/gtk.css'
[templates.gtk4]
input_path = '~/.config/matugen/templates/gtk/gtk-colors.css'
output_path = '~/.config/gtk-4.0/gtk.css'

View file

@ -0,0 +1,51 @@
{
"background": "{{colors.background.default.hex}}",
"error": "{{colors.error.default.hex}}",
"error_container": "{{colors.error_container.default.hex}}",
"inverse_on_surface": "{{colors.inverse_on_surface.default.hex}}",
"inverse_primary": "{{colors.inverse_primary.default.hex}}",
"inverse_surface": "{{colors.inverse_surface.default.hex}}",
"on_background": "{{colors.on_background.default.hex}}",
"on_error": "{{colors.on_error.default.hex}}",
"on_error_container": "{{colors.on_error_container.default.hex}}",
"on_primary": "{{colors.on_primary.default.hex}}",
"on_primary_container": "{{colors.on_primary_container.default.hex}}",
"on_primary_fixed": "{{colors.on_primary_fixed.default.hex}}",
"on_primary_fixed_variant": "{{colors.on_primary_fixed_variant.default.hex}}",
"on_secondary": "{{colors.on_secondary.default.hex}}",
"on_secondary_container": "{{colors.on_secondary_container.default.hex}}",
"on_secondary_fixed": "{{colors.on_secondary_fixed.default.hex}}",
"on_secondary_fixed_variant": "{{colors.on_secondary_fixed_variant.default.hex}}",
"on_surface": "{{colors.on_surface.default.hex}}",
"on_surface_variant": "{{colors.on_surface_variant.default.hex}}",
"on_tertiary": "{{colors.on_tertiary.default.hex}}",
"on_tertiary_container": "{{colors.on_tertiary_container.default.hex}}",
"on_tertiary_fixed": "{{colors.on_tertiary_fixed.default.hex}}",
"on_tertiary_fixed_variant": "{{colors.on_tertiary_fixed_variant.default.hex}}",
"outline": "{{colors.outline.default.hex}}",
"outline_variant": "{{colors.outline_variant.default.hex}}",
"primary": "{{colors.primary.default.hex}}",
"primary_container": "{{colors.primary_container.default.hex}}",
"primary_fixed": "{{colors.primary_fixed.default.hex}}",
"primary_fixed_dim": "{{colors.primary_fixed_dim.default.hex}}",
"scrim": "{{colors.scrim.default.hex}}",
"secondary": "{{colors.secondary.default.hex}}",
"secondary_container": "{{colors.secondary_container.default.hex}}",
"secondary_fixed": "{{colors.secondary_fixed.default.hex}}",
"secondary_fixed_dim": "{{colors.secondary_fixed_dim.default.hex}}",
"shadow": "{{colors.shadow.default.hex}}",
"surface": "{{colors.surface.default.hex}}",
"surface_bright": "{{colors.surface_bright.default.hex}}",
"surface_container": "{{colors.surface_container.default.hex}}",
"surface_container_high": "{{colors.surface_container_high.default.hex}}",
"surface_container_highest": "{{colors.surface_container_highest.default.hex}}",
"surface_container_low": "{{colors.surface_container_low.default.hex}}",
"surface_container_lowest": "{{colors.surface_container_lowest.default.hex}}",
"surface_dim": "{{colors.surface_dim.default.hex}}",
"surface_tint": "{{colors.surface_tint.default.hex}}",
"surface_variant": "{{colors.surface_variant.default.hex}}",
"tertiary": "{{colors.tertiary.default.hex}}",
"tertiary_container": "{{colors.tertiary_container.default.hex}}",
"tertiary_fixed": "{{colors.tertiary_fixed.default.hex}}",
"tertiary_fixed_dim": "{{colors.tertiary_fixed_dim.default.hex}}"
}

View file

@ -0,0 +1,21 @@
font=Gabarito
terminal=foot -e
prompt=">> "
layer=overlay
[colors]
background={{colors.background.default.hex_stripped}}ff
text={{colors.on_background.default.hex_stripped}}ff
selection={{colors.surface_variant.default.hex_stripped}}ff
selection-text={{colors.on_surface_variant.default.hex_stripped}}ff
border={{colors.surface_variant.default.hex_stripped}}dd
match={{colors.primary.default.hex_stripped}}ff
selection-match={{colors.primary.default.hex_stripped}}ff
[border]
radius=17
width=1
[dmenu]
exit-immediately-if-empty=yes

View file

@ -0,0 +1,22 @@
/*
* GTK Colors
* Generated with Matugen
*/
@define-color accent_color {{colors.primary.default.hex}};
@define-color accent_fg_color {{colors.on_primary.default.hex}};
@define-color accent_bg_color {{colors.primary.default.hex}};
@define-color window_bg_color {{colors.background.default.hex}};
@define-color window_fg_color {{colors.on_background.default.hex}};
@define-color headerbar_bg_color {{colors.surface_dim.default.hex}};
@define-color headerbar_fg_color {{colors.on_surface.default.hex}};
@define-color popover_bg_color {{colors.surface_dim.default.hex}};
@define-color popover_fg_color {{colors.on_surface.default.hex}};
@define-color view_bg_color {{colors.surface.default.hex}};
@define-color view_fg_color {{colors.on_surface.default.hex}};
@define-color card_bg_color {{colors.surface.default.hex}};
@define-color card_fg_color {{colors.on_surface.default.hex}};
@define-color sidebar_bg_color @window_bg_color;
@define-color sidebar_fg_color @window_fg_color;
@define-color sidebar_border_color @window_bg_color;
@define-color sidebar_backdrop_color @window_bg_color;

View file

@ -0,0 +1,32 @@
general {
col.active_border = rgba({{colors.on_surface.default.hex_stripped}}39)
col.inactive_border = rgba({{colors.outline.default.hex_stripped}}30)
}
misc {
background_color = rgba({{colors.surface.default.hex_stripped}}FF)
}
plugin {
hyprbars {
# Honestly idk if it works like css, but well, why not
bar_text_font = Rubik, Geist, AR One Sans, Reddit Sans, Inter, Roboto, Ubuntu, Noto Sans, sans-serif
bar_height = 30
bar_padding = 10
bar_button_padding = 5
bar_precedence_over_border = true
bar_part_of_window = true
bar_color = rgba({{colors.background.default.hex_stripped}}FF)
col.text = rgba({{colors.on_background.default.hex_stripped}}FF)
# example buttons (R -> L)
# hyprbars-button = color, size, on-click
hyprbars-button = rgb({{colors.on_background.default.hex_stripped}}), 13, 󰖭, hyprctl dispatch killactive
hyprbars-button = rgb({{colors.on_background.default.hex_stripped}}), 13, 󰖯, hyprctl dispatch fullscreen 1
hyprbars-button = rgb({{colors.on_background.default.hex_stripped}}), 13, 󰖰, hyprctl dispatch movetoworkspacesilent special
}
}
windowrulev2 = bordercolor rgba({{colors.primary.default.hex_stripped}}AA) rgba({{colors.primary.default.hex_stripped}}77),pinned:1

View file

@ -0,0 +1,83 @@
$text_color = rgba({{colors.primary_fixed.default.hex_stripped}}FF)
$entry_background_color = rgba({{colors.on_primary_fixed.default.hex_stripped}}11)
$entry_border_color = rgba({{colors.outline.default.hex_stripped}}55)
$entry_color = rgba({{colors.primary_fixed.default.hex_stripped}}FF)
$font_family = Rubik Light
$font_family_clock = Rubik Light
$font_material_symbols = Material Symbols Rounded
background {
color = rgba(181818FF)
# path = {{image}}
# path = screenshot
# blur_size = 15
# blur_passes = 4
}
input-field {
monitor =
size = 250, 50
outline_thickness = 2
dots_size = 0.1
dots_spacing = 0.3
outer_color = $entry_border_color
inner_color = $entry_background_color
font_color = $entry_color
fade_on_empty = true
position = 0, 20
halign = center
valign = center
}
label { # Clock
monitor =
text = $TIME
color = $text_color
font_size = 65
font_family = $font_family_clock
position = 0, 300
halign = center
valign = center
}
label { # Date
monitor =
text = cmd[update:5000] date +"%A, %B %d"
color = $text_color
font_size = 17
font_family = $font_family
position = 0, 240
halign = center
valign = center
}
label { # User
monitor =
text =  $USER
color = $text_color
shadow_passes = 1
shadow_boost = 0.35
outline_thickness = 2
dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8
dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0
dots_center = true
font_size = 20
font_family = $font_family
position = 0, 50
halign = center
valign = bottom
}
label { # Status
monitor =
text = cmd[update:5000] ${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprlock/status.sh
color = $text_color
font_size = 14
font_family = $font_family
position = 30, -30
halign = left
valign = top
}

View file

@ -45,6 +45,9 @@ Singleton {
property int nonAppResultDelay: 30 // This prevents lagging when typing
property string engineBaseUrl: "https://www.google.com/search?q="
property list<string> excludedSites: [ "quora.com" ]
property QtObject prefix: QtObject {
property string action: "/"
}
}
property QtObject hacks: QtObject {

View file

@ -6,6 +6,10 @@ Item {
property int size: 25
property color color: "#000000"
onColorChanged: {
canvas.requestPaint();
}
property QtObject cornerEnum: QtObject {
property int topLeft: 0
property int topRight: 1

View file

@ -1,7 +1,9 @@
import "root:/"
import "root:/services/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import Qt5Compat.GraphicalEffects
import Qt.labs.platform
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@ -11,6 +13,7 @@ import Quickshell.Io
Item { // Wrapper
id: root
required property var panelWindow
readonly property string xdgConfigHome: StandardPaths.standardLocations(StandardPaths.ConfigLocation)[0]
property string searchingText: ""
property bool showResults: searchingText != ""
property real searchBarHeight: searchBar.height + Appearance.sizes.elevationMargin * 2
@ -18,6 +21,41 @@ Item { // Wrapper
implicitHeight: searchWidgetContent.implicitHeight + Appearance.sizes.elevationMargin * 2
property string mathResult: ""
property var searchActions: [
{
action: "img",
execute: () => {
executor.executeCommand(`${xdgConfigHome}/quickshell/scripts/switchwall.sh`.replace(/file:\/\//, ""))
}
},
{
action: "dark",
execute: () => {
executor.executeCommand(`${xdgConfigHome}/quickshell/scripts/switchwall.sh --mode dark --noswitch`.replace(/file:\/\//, ""))
}
},
{
action: "light",
execute: () => {
executor.executeCommand(`${xdgConfigHome}/quickshell/scripts/switchwall.sh --mode light --noswitch`.replace(/file:\/\//, ""))
}
},
{
action: "accentcolor",
execute: (args) => {
console.log(args)
executor.executeCommand(
`${xdgConfigHome}/quickshell/scripts/switchwall.sh --noswitch --color ${args != '' ? ("'"+args+"'") : ""}`
.replace(/file:\/\//, ""))
}
},
{
action: "todo",
execute: (args) => {
Todo.addTask(args)
}
},
]
function focusFirstItemIfNeeded() {
if (searchInput.focus) appResults.currentIndex = 0; // Focus the first item
@ -178,7 +216,8 @@ Item { // Wrapper
Layout.rightMargin: 15
padding: 15
color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant
selectedTextColor: Appearance.m3colors.m3onSurface
selectedTextColor: Appearance.m3colors.m3onPrimary
selectionColor: Appearance.m3colors.m3primary
placeholderText: qsTr("Search, calculate or run")
placeholderTextColor: Appearance.m3colors.m3outline
implicitWidth: root.searchingText == "" ? Appearance.sizes.searchWidthCollapsed : Appearance.sizes.searchWidth
@ -275,6 +314,22 @@ Item { // Wrapper
);
// Add non-app results
// Launcher actions
for (let action of root.searchActions) {
const actionString = `${ConfigOptions.search.prefix.action}${action.action}`
if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) {
result.push({
name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString,
clickActionName: "Run",
type: "Action",
materialSymbol: 'settings_suggest',
execute: () => {
action.execute(root.searchingText.split(" ").slice(1).join(" "))
},
});
}
}
// Qalc math result
result.push({
name: root.mathResult,
clickActionName: "Copy",
@ -285,6 +340,7 @@ Item { // Wrapper
copyText.copyTextToClipboard(root.mathResult);
}
});
// Run command
result.push({
name: searchingText,
clickActionName: "Run",
@ -295,6 +351,7 @@ Item { // Wrapper
executor.executeCommand(searchingText.startsWith('sudo') ? `${ConfigOptions.apps.terminal} fish -C '${root.searchingText}'` : root.searchingText);
}
});
// Web search
result.push({
name: root.searchingText,
clickActionName: "Search",

View file

@ -99,11 +99,11 @@ Scope {
Layout.topMargin: 5
Layout.bottomMargin: 0
CustomIcon {
width: 25
height: 25
source: SystemInfo.distroIcon
}
// CustomIcon {
// width: 25
// height: 25
// source: SystemInfo.distroIcon
// }
StyledText {
font.pixelSize: Appearance.font.pixelSize.normal

View file

@ -273,7 +273,8 @@ Item {
Layout.rightMargin: 16
padding: 10
color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant
selectedTextColor: Appearance.m3colors.m3onSurface
selectedTextColor: Appearance.m3colors.m3onPrimary
selectionColor: Appearance.m3colors.m3primary
placeholderText: qsTr("Task description")
placeholderTextColor: Appearance.m3colors.m3outline
focus: root.showAddDialog

View file

@ -0,0 +1,58 @@
#!/usr/bin/env bash
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
CONFIG_DIR="$XDG_CONFIG_HOME/quickshell"
CACHE_DIR="$XDG_CACHE_HOME/quickshell"
STATE_DIR="$XDG_STATE_HOME/quickshell"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
term_alpha=100 #Set this to < 100 make all your terminals transparent
# sleep 0 # idk i wanted some delay or colors dont get applied properly
if [ ! -d "$CACHE_DIR"/user/generated ]; then
mkdir -p "$CACHE_DIR"/user/generated
fi
cd "$CONFIG_DIR" || exit
colornames=''
colorstrings=''
colorlist=()
colorvalues=()
colornames=$(cat $STATE_DIR/user/generated/material_colors.scss | cut -d: -f1)
colorstrings=$(cat $STATE_DIR/user/generated/material_colors.scss | cut -d: -f2 | cut -d ' ' -f2 | cut -d ";" -f1)
IFS=$'\n'
colorlist=($colornames) # Array of color names
colorvalues=($colorstrings) # Array of color values
apply_term() {
# Check if terminal escape sequence template exists
if [ ! -f "$SCRIPT_DIR"/terminal/sequences.txt ]; then
echo "Template file not found for Terminal. Skipping that."
return
fi
# Copy template
mkdir -p "$CACHE_DIR"/user/generated/terminal
cp "$SCRIPT_DIR"/terminal/sequences.txt "$CACHE_DIR"/user/generated/terminal/sequences.txt
# Apply colors
for i in "${!colorlist[@]}"; do
sed -i "s/${colorlist[$i]} #/${colorvalues[$i]#\#}/g" "$CACHE_DIR"/user/generated/terminal/sequences.txt
done
sed -i "s/\$alpha/$term_alpha/g" "$CACHE_DIR/user/generated/terminal/sequences.txt"
for file in /dev/pts/*; do
if [[ $file =~ ^/dev/pts/[0-9]+$ ]]; then
cat "$CACHE_DIR"/user/generated/terminal/sequences.txt >"$file"
fi
done
}
apply_qt() {
sh "$CONFIG_DIR/scripts/kvantum/materialQT.sh" # generate kvantum theme
python "$CONFIG_DIR/scripts/kvantum/changeAdwColors.py" # apply config colors
}
apply_qt &
apply_term &

View file

@ -0,0 +1,181 @@
#!/usr/bin/env -S\_/bin/sh\_-c\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@""
import argparse
import math
import json
from PIL import Image
from materialyoucolor.quantize import QuantizeCelebi
from materialyoucolor.score.score import Score
from materialyoucolor.hct import Hct
from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors
from materialyoucolor.utils.color_utils import (rgba_from_argb, argb_from_rgb, argb_from_rgba)
from materialyoucolor.utils.math_utils import (sanitize_degrees_double, difference_degrees, rotation_direction)
parser = argparse.ArgumentParser(description='Color generation script')
parser.add_argument('--path', type=str, default=None, help='generate colorscheme from image')
parser.add_argument('--size', type=int , default=128 , help='bitmap image size')
parser.add_argument('--color', type=str, default=None, help='generate colorscheme from color')
parser.add_argument('--mode', type=str, choices=['dark', 'light'], default='dark', help='dark or light mode')
parser.add_argument('--scheme', type=str, default='vibrant', help='material scheme to use')
parser.add_argument('--smart', action='store_true', default=False, help='decide scheme type based on image color')
parser.add_argument('--transparency', type=str, choices=['opaque', 'transparent'], default='opaque', help='enable transparency')
parser.add_argument('--termscheme', type=str, default=None, help='JSON file containg the terminal scheme for generating term colors')
parser.add_argument('--harmony', type=float , default=0.8, help='(0-1) Color hue shift towards accent')
parser.add_argument('--harmonize_threshold', type=float , default=100, help='(0-180) Max threshold angle to limit color hue shift')
parser.add_argument('--term_fg_boost', type=float , default=0.35, help='Make terminal foreground more different from the background')
parser.add_argument('--blend_bg_fg', action='store_true', default=False, help='Shift terminal background or foreground towards accent')
parser.add_argument('--cache', type=str, default=None, help='file path to store the generated color')
parser.add_argument('--debug', action='store_true', default=False, help='debug mode')
args = parser.parse_args()
rgba_to_hex = lambda rgba: "#{:02X}{:02X}{:02X}".format(rgba[0], rgba[1], rgba[2])
argb_to_hex = lambda argb: "#{:02X}{:02X}{:02X}".format(*map(round, rgba_from_argb(argb)))
hex_to_argb = lambda hex_code: argb_from_rgb(int(hex_code[1:3], 16), int(hex_code[3:5], 16), int(hex_code[5:], 16))
display_color = lambda rgba : "\x1B[38;2;{};{};{}m{}\x1B[0m".format(rgba[0], rgba[1], rgba[2], "\x1b[7m \x1b[7m")
def calculate_optimal_size (width: int, height: int, bitmap_size: int) -> (int, int):
image_area = width * height;
bitmap_area = bitmap_size ** 2
scale = math.sqrt(bitmap_area/image_area) if image_area > bitmap_area else 1
new_width = round(width * scale)
new_height = round(height * scale)
if new_width == 0:
new_width = 1
if new_height == 0:
new_height = 1
return new_width, new_height
def harmonize (design_color: int, source_color: int, threshold: float = 35, harmony: float = 0.5) -> int:
from_hct = Hct.from_int(design_color)
to_hct = Hct.from_int(source_color)
difference_degrees_ = difference_degrees(from_hct.hue, to_hct.hue)
rotation_degrees = min(difference_degrees_ * harmony, threshold)
output_hue = sanitize_degrees_double(
from_hct.hue + rotation_degrees * rotation_direction(from_hct.hue, to_hct.hue)
)
return Hct.from_hct(output_hue, from_hct.chroma, from_hct.tone).to_int()
def boost_chroma_tone (argb: int, chroma: float = 1, tone: float = 1) -> int:
hct = Hct.from_int(argb)
return Hct.from_hct(hct.hue, hct.chroma * chroma, hct.tone * tone).to_int()
darkmode = (args.mode == 'dark')
transparent = (args.transparency == 'transparent')
if args.path is not None:
image = Image.open(args.path)
if image.format == "GIF":
image.seek(1)
if image.mode in ["L", "P"]:
image = image.convert('RGB')
wsize, hsize = image.size
wsize_new, hsize_new = calculate_optimal_size(wsize, hsize, args.size)
if wsize_new < wsize or hsize_new < hsize:
image = image.resize((wsize_new, hsize_new), Image.Resampling.BICUBIC)
colors = QuantizeCelebi(list(image.getdata()), 128)
argb = Score.score(colors)[0]
if args.cache is not None:
with open(args.cache, 'w') as file:
file.write(argb_to_hex(argb))
hct = Hct.from_int(argb)
if(args.smart):
if(hct.chroma < 20):
args.scheme = 'neutral'
elif args.color is not None:
argb = hex_to_argb(args.color)
hct = Hct.from_int(argb)
if args.scheme == 'scheme-fruit-salad':
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
elif args.scheme == 'scheme-expressive':
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive as Scheme
elif args.scheme == 'scheme-monochrome':
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome as Scheme
elif args.scheme == 'scheme-rainbow':
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow as Scheme
elif args.scheme == 'scheme-tonal-spot':
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot as Scheme
elif args.scheme == 'scheme-neutral':
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral as Scheme
elif args.scheme == 'scheme-fidelity':
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity as Scheme
elif args.scheme == 'scheme-content':
from materialyoucolor.scheme.scheme_content import SchemeContent as Scheme
elif args.scheme == 'scheme-vibrant':
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant as Scheme
else:
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot as Scheme
# Generate
scheme = Scheme(hct, darkmode, 0.0)
material_colors = {}
term_colors = {}
for color in vars(MaterialDynamicColors).keys():
color_name = getattr(MaterialDynamicColors, color)
if hasattr(color_name, "get_hct"):
rgba = color_name.get_hct(scheme).to_rgba()
material_colors[color] = rgba_to_hex(rgba)
# Extended material
if darkmode == True:
material_colors['success'] = '#B5CCBA'
material_colors['onSuccess'] = '#213528'
material_colors['successContainer'] = '#374B3E'
material_colors['onSuccessContainer'] = '#D1E9D6'
else:
material_colors['success'] = '#4F6354'
material_colors['onSuccess'] = '#FFFFFF'
material_colors['successContainer'] = '#D1E8D5'
material_colors['onSuccessContainer'] = '#0C1F13'
# Terminal Colors
if args.termscheme is not None:
with open(args.termscheme, 'r') as f:
json_termscheme = f.read()
term_source_colors = json.loads(json_termscheme)['dark' if darkmode else 'light']
primary_color_argb = hex_to_argb(material_colors['primary_paletteKeyColor'])
for color, val in term_source_colors.items():
if(args.scheme == 'monochrome') :
term_colors[color] = val
continue
if args.blend_bg_fg and color == "term0":
harmonized = boost_chroma_tone(hex_to_argb(material_colors['surfaceContainerLow']), 1.2, 0.95)
elif args.blend_bg_fg and color == "term15":
harmonized = boost_chroma_tone(hex_to_argb(material_colors['onSurface']), 3, 1)
else:
harmonized = harmonize(hex_to_argb(val), primary_color_argb, args.harmonize_threshold, args.harmony)
harmonized = boost_chroma_tone(harmonized, 1, 1 + (args.term_fg_boost * (1 if darkmode else -1)))
term_colors[color] = argb_to_hex(harmonized)
if args.debug == False:
print(f"$darkmode: {darkmode};")
print(f"$transparent: {transparent};")
for color, code in material_colors.items():
print(f"${color}: {code};")
for color, code in term_colors.items():
print(f"${color}: {code};")
else:
if args.path is not None:
print('\n--------------Image properties-----------------')
print(f"Image size: {wsize} x {hsize}")
print(f"Resized image: {wsize_new} x {hsize_new}")
print('\n---------------Selected color------------------')
print(f"Dark mode: {darkmode}")
print(f"Scheme: {args.scheme}")
print(f"Accent color: {display_color(rgba_from_argb(argb))} {argb_to_hex(argb)}")
print(f"HCT: {hct.hue:.2f} {hct.chroma:.2f} {hct.tone:.2f}")
print('\n---------------Material colors-----------------')
for color, code in material_colors.items():
rgba = rgba_from_argb(hex_to_argb(code))
print(f"{color.ljust(32)} : {display_color(rgba)} {code}")
print('\n----------Harmonize terminal colors------------')
for color, code in term_colors.items():
rgba = rgba_from_argb(hex_to_argb(code))
code_source = term_source_colors[color]
rgba_source = rgba_from_argb(hex_to_argb(code_source))
print(f"{color.ljust(6)} : {display_color(rgba_source)} {code_source} --> {display_color(rgba)} {code}")
print('-----------------------------------------------')

View file

@ -0,0 +1,79 @@
import re
import os
def read_scss(file_path):
"""Reads an SCSS file and returns a dictionary of color variables."""
colors = {}
with open(file_path, 'r') as file:
for line in file:
match = re.match(r'\$(\w+):\s*(#[0-9A-Fa-f]{6});', line.strip())
if match:
variable_name, color = match.groups()
colors[variable_name] = color
return colors
def update_svg_colors(svg_path, old_to_new_colors, output_path):
"""
Updates the colors in an SVG file based on the provided color map.
:param svg_path: Path to the SVG file.
:param old_to_new_colors: Dictionary mapping old colors to new colors.
:param output_path: Path to save the updated SVG file.
"""
# Read the SVG content
with open(svg_path, 'r') as file:
svg_content = file.read()
# Replace old colors with new colors
for old_color, new_color in old_to_new_colors.items():
svg_content = re.sub(old_color, new_color, svg_content, flags=re.IGNORECASE)
# Write the updated SVG content to the output file
with open(output_path, 'w') as file:
file.write(svg_content)
print(f"SVG colors have been updated and saved to {output_path}!")
def main():
xdg_config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
xdg_state_home = os.environ.get("XDG_STATE_HOME", os.path.expanduser("~/.local/state"))
scss_file = os.path.join(xdg_state_home, "quickshell", "user", "generated", "material_colors.scss")
svg_path = os.path.join(xdg_config_home, "Kvantum", "Colloid", "Colloid.svg")
output_path = os.path.join(xdg_config_home, "Kvantum", "MaterialAdw", "MaterialAdw.svg")
# Read colors from the SCSS file
color_data = read_scss(scss_file)
# Specify the old colors and map them to new colors from the SCSS file
old_to_new_colors = {
#'#cccccc': color_data['surfaceDim'], # Map old SVG color to new SCSS color
#'#666666': color_data['surfaceDim'],
'#3c84f7': color_data['primary'],
#'#5a5a5a': color_data['neutral_paletteKeyColor'],
'#000000': color_data['shadow'],
'#f04a50': color_data['error'],
'#4285f4': color_data['primaryFixedDim'],
'#f2f2f2': color_data['background'],
#'#dfdfdf': color_data['surfaceContainerLow'],
'#ffffff': color_data['background'],
'#1e1e1e': color_data['onPrimaryFixed'],
#'#b6b6b6': color_data['surfaceContainer'],
'#333': color_data['inverseSurface'],
'#212121': color_data['onSecondaryFixed'],
'#5b9bf8': color_data['secondaryContainer'],
'#26272a': color_data['term7'],
#'#b3b3b3': color_data['surfaceBright'],
#'#b74aff': color_data['tertiary'],
#'#989898': color_data['surfaceContainerHighest'],
#'#c1c1c1': color_data['surfaceContainerHigh'],
'#444444': color_data['onBackground'],
'#333333': color_data['onPrimaryFixed'],
}
# Update the SVG colors
update_svg_colors(svg_path, old_to_new_colors, output_path)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,87 @@
import re
import os
def read_scss(file_path):
"""Reads an SCSS file and returns a dictionary of color variables."""
colors = {}
with open(file_path, 'r') as file:
for line in file:
match = re.match(r'\$(\w+):\s*(#[0-9A-Fa-f]{6});', line.strip())
if match:
variable_name, color = match.groups()
colors[variable_name] = color
return colors
def update_svg_colors(svg_path, old_to_new_colors, output_path):
"""
Updates the colors in an SVG file based on the provided color map.
:param svg_path: Path to the SVG file.
:param old_to_new_colors: Dictionary mapping old colors to new colors.
:param output_path: Path to save the updated SVG file.
"""
# Read the SVG content
with open(svg_path, 'r') as file:
svg_content = file.read()
# Replace old colors with new colors
for old_color, new_color in old_to_new_colors.items():
svg_content = re.sub(old_color, new_color, svg_content, flags=re.IGNORECASE)
# Write the updated SVG content to the output file
with open(output_path, 'w') as file:
file.write(svg_content)
print(f"SVG colors have been updated and saved to {output_path}!")
def main():
xdg_config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
xdg_state_home = os.environ.get("XDG_STATE_HOME", os.path.expanduser("~/.local/state"))
scss_file = os.path.join(xdg_state_home, "quickshell", "user", "generated", "material_colors.scss")
svg_path = os.path.join(xdg_config_home, "Kvantum", "Colloid", "ColloidDark.svg")
output_path = os.path.join(xdg_config_home, "Kvantum", "MaterialAdw", "MaterialAdw.svg")
# Read colors from the SCSS file
color_data = read_scss(scss_file)
# Specify the old colors and map them to new colors from the SCSS file
old_to_new_colors = {
#'#525252': color_data['surfaceDim'], # Map old SVG color to new SCSS color
#'#666666': color_data['surfaceDim'],
'#31363b': color_data['background'],
#'#eff0f1': color_data['neutral_paletteKeyColor'],
'#000000': color_data['shadow'],
'#5b9bf8': color_data['primary'],
'#93cee9': color_data['onSecondaryContainer'],
'#3daee9': color_data['secondary'],
#'#fff': color_data['term10'],
#'#5a5a5a': color_data['surfaceVariant'],
#'#acb1bc': color_data['onPrimaryFixed'],
'#ffffff': color_data['term11'],
'#5a616e': color_data['surfaceVariant'],
'#f04a50': color_data['error'],
'#4285f4': color_data['secondary'],
'#242424': color_data['background'],
'#2c2c2c': color_data['background'],
#'#dfdfdf': color_data['onSurfaceVariant'],
#'#646464': color_data['surfaceContainerHighest'],
#'#989898': color_data['surfaceContainerHigh'],
#'#c1c1c1': color_data['primaryFixedDim'],
'#1e1e1e': color_data['background'],
'#3c3c3c': color_data['background'],
'#26272a': color_data['surfaceBright'],
'#000000': color_data['shadow'],
'#b74aff': color_data['tertiary'],
#'#b6b6b6': color_data['onSurfaceVariant'],
'#1a1a1a': color_data['background'],
'#333': color_data['term0'],
'#212121': color_data['background'],
}
# Update the SVG colors
update_svg_colors(svg_path, old_to_new_colors, output_path)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,71 @@
import re
import os
def get_colors_from_scss(scss_file):
colors = {}
with open(scss_file, 'r') as file:
for line in file:
match = re.match(r'\$(\w+):\s*(#[0-9A-Fa-f]{6});', line)
if match:
colors[match.group(1)] = match.group(2)
return colors
def update_config_colors(config_file, colors, mappings):
with open(config_file, 'r') as file:
config_content = file.read()
for key, variable in mappings.items():
if variable in colors:
color = colors[variable]
pattern = rf'({key}=)#?\w+\b'
new_line = f'\\1{color}'
if re.search(pattern, config_content):
config_content = re.sub(pattern, new_line, config_content)
else:
config_content += f"\n{key}={color}"
with open(config_file, 'w') as file:
file.write(config_content)
if __name__ == "__main__":
xdg_config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
xdg_state_home = os.environ.get("XDG_STATE_HOME", os.path.expanduser("~/.local/state"))
config_file = os.path.join(xdg_config_home, "Kvantum", "MaterialAdw", "MaterialAdw.kvconfig")
scss_file = os.path.join(xdg_state_home, "quickshell", "user", "generated", "material_colors.scss")
# Define your mappings here
mappings = {
'window.color': 'background',
'base.color': 'background',
'alt.base.color': 'background',
'button.color': 'surfaceContainer',
'light.color': 'surfaceContainerLow',
'mid.light.color': 'surfaceContainer',
'dark.color': 'surfaceContainerHighest',
'mid.color': 'surfaceContainerHigh',
'highlight.color': 'primary',
'inactive.highlight.color': 'primary',
'text.color': 'onBackground',
'window.text.color': 'onBackground',
'button.text.color': 'onBackground',
'disabled.text.color': 'onBackground',
'tooltip.text.color': 'onBackground',
'highlight.text.color': 'onSurface',
'link.color': 'tertiary',
'link.visited.color': 'tertiaryFixed',
'progress.indicator.text.color': 'onBackground',
'text.normal.color': 'onBackground',
'text.focus.color': 'onBackground',
'text.press.color': 'onsecondarycontainer',
'text.toggle.color': 'onsecondarycontainer',
'text.disabled.color': 'surfaceDim',
# Add more mappings as needed
}
colors = get_colors_from_scss(scss_file)
update_config_colors(config_file, colors, mappings)
print("Config colors updated successfully!")

View file

@ -0,0 +1,42 @@
#!/usr/bin/env bash
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
CONFIG_DIR="$XDG_CONFIG_HOME/quickshell"
CACHE_DIR="$XDG_CACHE_HOME/quickshell"
STATE_DIR="$XDG_STATE_HOME/quickshell"
get_light_dark() {
current_mode=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'")
if [[ "$current_mode" == "prefer-dark" ]]; then
echo "dark"
else
echo "light"
fi
}
apply_qt() {
# Check if the theme exists
FOLDER_PATH="$XDG_CONFIG_HOME/Kvantum/Colloid/"
if [ ! -d "$FOLDER_PATH" ]; then
# Send a notification
notify-send "Colloid-kde theme required" " The folder '$FOLDER_PATH' does not exist."
exit 1 # Exit the function if the folder does not exist
fi
lightdark=$(get_light_dark)
if [ "$lightdark" = "light" ]; then
# apply ligght colors
cp "$XDG_CONFIG_HOME/Kvantum/Colloid/Colloid.kvconfig" "$XDG_CONFIG_HOME/Kvantum/MaterialAdw/MaterialAdw.kvconfig"
python "$CONFIG_DIR/scripts/kvantum/adwsvg.py"
else
#apply dark colors
cp "$XDG_CONFIG_HOME/Kvantum/Colloid/ColloidDark.kvconfig" "$XDG_CONFIG_HOME/Kvantum/MaterialAdw/MaterialAdw.kvconfig"
python "$CONFIG_DIR/scripts/kvantum/adwsvgDark.py"
fi
}
apply_qt

View file

@ -0,0 +1,137 @@
#!/usr/bin/env bash
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
CONFIG_DIR="$XDG_CONFIG_HOME/quickshell"
CACHE_DIR="$XDG_CACHE_HOME/quickshell"
STATE_DIR="$XDG_STATE_HOME/quickshell"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
terminalscheme="$XDG_CONFIG_HOME/quickshell/scripts/terminal/scheme-base.json"
pre_process() {
if [ ! -d "$CACHE_DIR"/user/generated ]; then
mkdir -p "$CACHE_DIR"/user/generated
fi
}
post_process() {
local mode_flag="$1"
# Set GNOME color-scheme if mode_flag is dark or light
if [[ "$mode_flag" == "dark" ]]; then
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'
gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3-dark'
elif [[ "$mode_flag" == "light" ]]; then
gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3'
fi
}
switch() {
imgpath="$1"
mode_flag="$2"
type_flag="$3"
color_flag="$4"
color="$5"
read scale screenx screeny screensizey < <(hyprctl monitors -j | jq '.[] | select(.focused) | .scale, .x, .y, .height' | xargs)
cursorposx=$(hyprctl cursorpos -j | jq '.x' 2>/dev/null) || cursorposx=960
cursorposx=$(bc <<< "scale=0; ($cursorposx - $screenx) * $scale / 1")
cursorposy=$(hyprctl cursorpos -j | jq '.y' 2>/dev/null) || cursorposy=540
cursorposy=$(bc <<< "scale=0; ($cursorposy - $screeny) * $scale / 1")
cursorposy_inverted=$((screensizey - cursorposy))
if [[ "$color_flag" == "1" ]]; then
matugen_args=(color hex "$color")
generate_colors_material_args=(--color "$color")
else
if [[ -z "$imgpath" ]]; then
echo 'Aborted'
exit 0
fi
matugen_args=(image "$imgpath")
generate_colors_material_args=(--path "$imgpath")
fi
# Determine mode if not set
if [[ -z "$mode_flag" ]]; then
current_mode=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'")
if [[ "$current_mode" == "prefer-dark" ]]; then
mode_flag="dark"
else
mode_flag="light"
fi
fi
# Dark/light mode, material scheme
[[ -n "$mode_flag" ]] && matugen_args+=(--mode "$mode_flag") && generate_colors_material_args+=(--mode "$mode_flag")
[[ -n "$type_flag" ]] && matugen_args+=(--type "$type_flag") && generate_colors_material_args+=(--scheme "$type_flag")
# Terminal scheme
generate_colors_material_args+=(--termscheme "$terminalscheme" --blend_bg_fg)
generate_colors_material_args+=(--cache "$STATE_DIR/user/color.txt")
pre_process
# Generate with matugen
matugen "${matugen_args[@]}"
# Use custom script for mixing (matugen can't D:)
source "$(eval echo $ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate"
python "$SCRIPT_DIR/generate_colors_material.py" "${generate_colors_material_args[@]}" \
> "$STATE_DIR"/user/generated/material_colors.scss
"$SCRIPT_DIR"/applycolor.sh
deactivate
post_process "$mode_flag"
}
main() {
imgpath=""
mode_flag=""
type_flag=""
color_flag=""
color=""
noswitch_flag=""
while [[ $# -gt 0 ]]; do
case "$1" in
--mode)
mode_flag="$2"
shift 2
;;
--type)
type_flag="$2"
shift 2
;;
--color)
color_flag="1"
if [[ "$2" =~ ^#?[A-Fa-f0-9]{6}$ ]]; then
color="$2"
shift 2
else
color=$(hyprpicker --no-fancy)
shift
fi
;;
--noswitch)
noswitch_flag="1"
imgpath=$(swww query | awk -F 'image: ' '{print $2}')
shift
;;
*)
if [[ -z "$imgpath" ]]; then
imgpath="$1"
fi
shift
;;
esac
done
# Only prompt for wallpaper if not using --color and not using --noswitch and no imgpath set
if [[ -z "$imgpath" && -z "$color_flag" && -z "$noswitch_flag" ]]; then
cd "$(xdg-user-dir PICTURES)/Wallpapers" 2>/dev/null || cd "$(xdg-user-dir PICTURES)" || return 1
imgpath="$(yad --width 1200 --height 800 --file --add-preview --large-preview --title='Choose wallpaper')"
fi
switch "$imgpath" "$mode_flag" "$type_flag" "$color_flag" "$color"
}
main "$@"

View file

@ -0,0 +1,38 @@
{
"dark": {
"term0" : "#282828",
"term1" : "#CC241D",
"term2" : "#98971A",
"term3" : "#D79921",
"term4" : "#458588",
"term5" : "#B16286",
"term6" : "#689D6A",
"term7" : "#A89984",
"term8" : "#928374",
"term9" : "#FB4934",
"term10" : "#B8BB26",
"term11" : "#FABD2F",
"term12" : "#83A598",
"term13" : "#D3869B",
"term14" : "#8EC07C",
"term15" : "#EBDBB2"
},
"light": {
"term0" : "#FDF9F3",
"term1" : "#FF6188",
"term2" : "#A9DC76",
"term3" : "#FC9867",
"term4" : "#FFD866",
"term5" : "#F47FD4",
"term6" : "#78DCE8",
"term7" : "#333034",
"term8" : "#121212",
"term9" : "#FF6188",
"term10" : "#A9DC76",
"term11" : "#FC9867",
"term12" : "#FFD866",
"term13" : "#F47FD4",
"term14" : "#78DCE8",
"term15" : "#333034"
}
}

View file

@ -0,0 +1 @@
]4;0;#$term0 #\]1;0;#$term0 #\]4;1;#$term1 #\]4;2;#$term2 #\]4;3;#$term3 #\]4;4;#$term4 #\]4;5;#$term5 #\]4;6;#$term6 #\]4;7;#$term7 #\]4;8;#$term8 #\]4;9;#$term9 #\]4;10;#$term10 #\]4;11;#$term11 #\]4;12;#$term12 #\]4;13;#$term13 #\]4;14;#$term14 #\]4;15;#$term15 #\]10;#$term7 #\]11;[100]#$term0 #\]12;#$term7 #\]13;#$term7 #\]17;#$term7 #\]19;#$term0 #\]4;232;#$term7 #\]4;256;#$term7 #\]708;[100]#$term0 #\]11;#$term0 #\

View file

@ -0,0 +1,53 @@
pragma Singleton
pragma ComponentBehavior: Bound
import "root:/modules/common"
import QtQuick
import Quickshell
import Quickshell.Io
import Qt.labs.platform
Singleton {
id: root
property string filePath: `${StandardPaths.standardLocations(StandardPaths.StateLocation)[0]}/user/generated/colors.json`
function reapplyTheme() {
themeFileView.reload()
}
function applyColors(fileContent) {
const json = JSON.parse(fileContent)
for (const key in json) {
if (json.hasOwnProperty(key)) {
// Convert snake_case to CamelCase
const camelCaseKey = key.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
const m3Key = `m3${camelCaseKey}`
Appearance.m3colors[m3Key] = json[key]
}
}
}
Timer {
id: delayedFileRead
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
repeat: false
running: false
onTriggered: {
root.applyColors(themeFileView.text())
}
}
FileView {
id: themeFileView
path: root.filePath
watchChanges: true
onFileChanged: {
this.reload()
delayedFileRead.start()
}
onLoadedChanged: {
const fileContent = themeFileView.text()
root.applyColors(fileContent)
}
}
}

View file

@ -12,8 +12,14 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import Quickshell
import "./services/"
ShellRoot {
Component.onCompleted: {
console.log("ShellRoot loaded")
MaterialTheme.reapplyTheme()
}
Bar {}
NotificationPopup {}
OnScreenDisplayBrightness {}