feat(cosmic-theme): produce QPalette ini for more compatibility

This commit is contained in:
Adil Hanney 2026-03-31 16:02:52 +01:00 • committed by GitHub
parent 413e63f62a
commit f06d15ae35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 303 additions and 20 deletions

View file

@ -14,10 +14,11 @@ impl Theme {
/// Produces a color scheme ini file for Qt.
///
/// Some high-level documentation for this file can be found at:
/// https://web.archive.org/web/20250402234329/https://docs.kde.org/stable5/en/plasma-workspace/kcontrol/colors/
/// - https://api.kde.org/kcolorscheme.html
/// - https://web.archive.org/web/20250402234329/https://docs.kde.org/stable5/en/plasma-workspace/kcontrol/colors/
#[must_use]
#[cold]
pub fn as_qt(&self) -> String {
pub fn as_kcolorscheme(&self) -> String {
// Usually, disabled elements will have strongly reduced contrast and are often notably darker or lighter
let disabled_color_effects = IniColorEffects {
color: self.button.disabled,
@ -41,7 +42,7 @@ impl Theme {
let bg = self.background.base;
// the background container
let view_colors = IniColors {
let window_colors = IniColors {
background_alternate: bg.mix(self.accent.base, 0.05),
background_normal: bg,
decoration_focus: self.accent_text_color(),
@ -56,16 +57,17 @@ impl Theme {
foreground_visited: self.accent_text_color(),
};
// components inside the background container
let window_colors = IniColors {
let view_colors = IniColors {
background_alternate: self.background.component.base.mix(self.accent.base, 0.05),
background_normal: self.background.component.base,
..view_colors
..window_colors
};
// selected text and items
let selection_colors = {
let selected = self.background.component.selected;
let selected_text = self.background.component.selected_text;
// selection colors are swapped to fix menu bar contrast
let selected = self.background.component.selected_text;
let selected_text = self.background.component.selected;
IniColors {
background_alternate: selected.mix(bg, 0.5),
background_normal: selected,
@ -116,10 +118,10 @@ impl Theme {
};
// headers in cosmic don't have a background
let header_colors = &view_colors;
let header_colors_inactive = &view_colors;
let header_colors = &window_colors;
let header_colors_inactive = &window_colors;
// tool tips, "What's This" tips, and similar elements
let tooltip_colors = &window_colors;
let tooltip_colors = &view_colors;
let general_color_scheme = if self.is_dark {
"CosmicDark"
@ -198,7 +200,7 @@ widgetStyle=qt6ct-style
format_ini_colors(&tooltip_colors, bg),
format_ini_colors(&view_colors, bg),
format_ini_colors(&window_colors, bg),
format_ini_wm_colors(&view_colors, self.is_dark),
format_ini_wm_colors(&window_colors, self.is_dark),
)
}
@ -212,14 +214,14 @@ widgetStyle=qt6ct-style
/// Returns an `OutputError` if there is an error writing the colors file.
#[cold]
pub fn write_qt(&self) -> Result<(), OutputError> {
let colors = self.as_qt();
let file_path = Self::get_qt_colors_path(self.is_dark)?;
let kcolorscheme = self.as_kcolorscheme();
let file_path = Self::get_kcolorscheme_path(self.is_dark)?;
let tmp_file_path = file_path.with_extension("colors.new");
// Write to tmp_file_path first, then move it to file_path
let mut tmp_file = File::create(&tmp_file_path).map_err(OutputError::Io)?;
let res = tmp_file
.write_all(colors.as_bytes())
.write_all(kcolorscheme.as_bytes())
.and_then(|_| tmp_file.flush())
.and_then(|_| std::fs::rename(&tmp_file_path, file_path));
if let Err(e) = res {
@ -245,7 +247,7 @@ widgetStyle=qt6ct-style
let kdeglobals_file = config_dir.join("kdeglobals");
let mut kdeglobals_ini = Self::read_ini(&kdeglobals_file)?;
let src_file = Self::get_qt_colors_path(is_dark)?;
let src_file = Self::get_kcolorscheme_path(is_dark)?;
let src_ini = Self::read_ini(&src_file)?;
Self::backup_non_cosmic_kdeglobals(&kdeglobals_ini, &kdeglobals_file)
@ -288,7 +290,7 @@ widgetStyle=qt6ct-style
}
let is_dark = false; // doesn't matter since we're only reading keys
let src_file = Self::get_qt_colors_path(is_dark)?;
let src_file = Self::get_kcolorscheme_path(is_dark)?;
let src_ini = Self::read_ini(&src_file)?;
for (section, key_value) in src_ini.get_map_ref() {
@ -303,8 +305,8 @@ widgetStyle=qt6ct-style
Ok(())
}
/// Gets a path like `~/.config/color-schemes/CosmicDark.colors`
pub fn get_qt_colors_path(is_dark: bool) -> Result<PathBuf, OutputError> {
/// Gets a path like `~/.local/share/color-schemes/CosmicDark.colors`
fn get_kcolorscheme_path(is_dark: bool) -> Result<PathBuf, OutputError> {
let Some(mut data_dir) = dirs::data_dir() else {
return Err(OutputError::MissingDataDir);
};