qt: add flexible theming with sensible defaults (#780)

This extends the Qt theming improvements for KDE from PR [1] ("kde:
replace kdeglobals with Kvantum theme") to provide generic Qt theming
support in KDE and non-KDE environments.

[1]: https://github.com/danth/stylix/pull/142

Link: https://github.com/danth/stylix/pull/780

Co-authored-by: Blusk <bluskript@gmail.com>
Co-authored-by: Jackaed <ed.andy.jackson@gmail.com>
Co-authored-by: Kilian Mio <86004375+Mikilio@users.noreply.github.com>
Reviewed-by: NAHO <90870942+trueNAHO@users.noreply.github.com>
Tested-by: https://github.com/Mistrustfully
Tested-by: https://github.com/eblechschmidt
Tested-by: NAHO <90870942+trueNAHO@users.noreply.github.com>
This commit is contained in:
Kilian Mio 2025-02-03 18:40:41 +01:00 committed by GitHub
parent b00c9f46ae
commit b7f50a56c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 2587 additions and 0 deletions

104
modules/qt/hm.nix Normal file
View file

@ -0,0 +1,104 @@
{
pkgs,
config,
lib,
...
}:
{
options.stylix.targets.qt = {
enable = config.lib.stylix.mkEnableTarget "QT" pkgs.stdenv.hostPlatform.isLinux;
platform = lib.mkOption {
description = ''
Selects the platform theme to use for Qt applications.
Defaults to the standard platform theme used in the configured DE in NixOS when
`stylix.homeManagerIntegration.followSystem = true`.
'';
type = lib.types.str;
default = "qtct";
};
};
config = lib.mkIf config.stylix.targets.qt.enable (
let
iconTheme =
if (config.stylix.polarity == "dark") then
config.stylix.iconTheme.dark
else
config.stylix.iconTheme.light;
recommendedStyles = {
gnome = if config.stylix.polarity == "dark" then "adwaita-dark" else "adwaita";
kde = "breeze";
qtct = "kvantum";
};
recommendedStyle = recommendedStyles."${config.qt.platformTheme.name}" or null;
kvantumPackage =
let
kvconfig = config.lib.stylix.colors {
template = ./kvconfig.mustache;
extension = ".kvconfig";
};
svg = config.lib.stylix.colors {
template = ./kvantum-svg.mustache;
extension = "svg";
};
in
pkgs.runCommandLocal "base16-kvantum" { } ''
directory="$out/share/Kvantum/Base16Kvantum"
mkdir --parents "$directory"
cp ${kvconfig} "$directory/Base16Kvantum.kvconfig"
cp ${svg} "$directory/Base16Kvantum.svg"
'';
in
{
warnings =
(lib.optional (config.stylix.targets.qt.platform != "qtct")
"stylix: qt: `config.stylix.targets.qt.platform` other than 'qtct' are currently unsupported: ${config.stylix.targets.qt.platform}. Support may be added in the future."
)
++ (lib.optional (config.qt.style.name != recommendedStyle)
"stylix: qt: Changing `config.qt.style` is unsupported and may result in breakage! Use with caution!"
);
home.packages = lib.optional (config.qt.style.name == "kvantum") kvantumPackage;
qt = {
enable = true;
style.name = recommendedStyle;
platformTheme.name = config.stylix.targets.qt.platform;
};
xdg.configFile =
let
qtctConf =
''
[Appearance]
''
+ lib.optionalString (config.qt.style ? name) ''
style=${config.qt.style.name}
''
+ lib.optionalString (iconTheme != null) ''
icon_theme=${iconTheme}
'';
in
lib.mkMerge [
(lib.mkIf (config.qt.style.name == "kvantum") {
"Kvantum/kvantum.kvconfig".source =
(pkgs.formats.ini { }).generate "kvantum.kvconfig"
{ General.theme = "Base16Kvantum"; };
"Kvantum/Base16Kvantum".source =
"${kvantumPackage}/share/Kvantum/Base16Kvantum";
})
(lib.mkIf (config.qt.platformTheme.name == "qtct") {
"qt5ct/qt5ct.conf".text = qtctConf;
"qt5ct/qt6ct.conf".text = qtctConf;
})
];
}
);
}

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 151 KiB

View file

@ -0,0 +1,466 @@
[%General]
author=Bluskript based on Catppuccin Frappe Mauve theme
comment=base16-qt
spread_menuitems=true
left_tabs=true
mirror_doc_tabs=true
scroll_width=8
attach_active_tab=true
composite=true
menu_shadow_depth=7
tooltip_shadow_depth=0
splitter_width=7
check_size=16
slider_width=4
slider_handle_width=18
slider_handle_length=18
textless_progressbar=false
menubar_mouse_tracking=true
slim_toolbars=false
toolbutton_style=1
x11drag=menubar_and_primary_toolbar
double_click=false
translucent_windows=false
blurring=false
popup_blurring=true
opaque=kaffeine,kmplayer,subtitlecomposer,kdenlive,vlc,smplayer,smplayer2,avidemux,avidemux2_qt4,avidemux3_qt4,avidemux3_qt5,kamoso,QtCreator,VirtualBox,trojita,dragon,digikam,qmplay2
group_toolbar_buttons=false
vertical_spin_indicators=false
fill_rubberband=false
spread_progressbar=true
merge_menubar_with_toolbar=true
small_icon_size=16
large_icon_size=32
button_icon_size=16
scroll_arrows=false
iconless_pushbutton=true
toolbar_icon_size=16
combo_as_lineedit=true
button_contents_shift=false
groupbox_top_label=true
inline_spin_indicators=true
joined_inactive_tabs=false
layout_spacing=2
submenu_overlap=0
tooltip_delay=-1
animate_states=false
transient_scrollbar=true
alt_mnemonic=true
combo_menu=true
layout_margin=4
no_window_pattern=false
respect_DE=true
scroll_min_extent=36
scrollable_menu=false
scrollbar_in_view=false
spin_button_width=16
submenu_delay=250
tree_branch_line=true
progressbar_thickness=8
click_behavior=0
contrast=1.00
dialog_button_layout=0
drag_from_buttons=false
hide_combo_checkboxes=false
intensity=1.00
no_inactiveness=false
reduce_menu_opacity=0
reduce_window_opacity=10
saturation=1.00
shadowless_popup=false
transient_groove=false
[GeneralColors]
window.color=#{{base01-hex}}
base.color=#{{base00-hex}}
alt.base.color=#{{base00-hex}}
button.color=#{{base02-hex}}
light.color=#{{base03-hex}}
mid.light.color=#{{base03-hex}}
dark.color=#{{base00-hex}}
mid.color=#{{base00-hex}}
highlight.color=#{{base03-hex}}
inactive.highlight.color=#{{base03-hex}}
text.color=#{{base05-hex}}
window.text.color=#{{base05-hex}}
button.text.color=#{{base05-hex}}
disabled.text.color=#{{base04-hex}}
tooltip.text.color=#{{base05-hex}}
highlight.text.color=#{{base00-hex}}
link.color=#{{base06-hex}}
link.visited.color=#{{base07-hex}}
[ItemView]
inherits=PanelButtonCommand
frame.element=itemview
interior.element=itemview
frame=true
interior=true
text.iconspacing=3
text.toggle.color=#{{base01-hex}}
[RadioButton]
inherits=PanelButtonCommand
frame=false
interior.element=radio
[CheckBox]
inherits=PanelButtonCommand
frame=false
interior.element=checkbox
[TreeExpander]
indicator.element=tree
indicator.size=8
[ToolTip]
frame.top=4
frame.right=4
frame.bottom=4
frame.left=4
frame=true
[PanelButtonCommand]
inherits=PanelButtonCommand
interior.element=button
frame.element=button
text.normal.color=#{{base05-hex}}
text.focus.color=#{{base05-hex}}
text.press.color=#{{base01-hex}}
text.toggle.color=#{{base01-hex}}
[PanelButtonTool]
inherits=PanelButtonCommand
[DockTitle]
inherits=PanelButtonCommand
interior=false
frame=false
text.margin.top=5
text.margin.bottom=5
text.margin.left=5
text.margin.right=5
indicator.size=0
[Dock]
interior.element=toolbar
frame.element=toolbar
frame=true
interior=true
[GroupBox]
inherits=PanelButtonCommand
interior.element=tabframe
interior=true
frame=false
[Focus]
inherits=PanelButtonCommand
frame=true
frame.element=focus
frame.top=1
frame.bottom=1
frame.left=1
frame.right=1
frame.patternsize=20
[GenericFrame]
inherits=PanelButtonCommand
frame.element=common
frame.top=1
frame.bottom=1
frame.left=1
frame.right=1
[Slider]
inherits=PanelButtonCommand
interior=true
frame.element=slider
interior.element=slider
frame.top=3
frame.bottom=3
frame.left=3
frame.right=3
focusFrame=true
[SliderCursor]
inherits=PanelButtonCommand
interior=true
interior.element=slidercursor
frame=false
[LineEdit]
inherits=PanelButtonCommand
frame.element=lineedit
interior.element=lineedit
[IndicatorSpinBox]
inherits=LineEdit
frame.element=lineedit
interior.element=lineedit
frame.top=0
frame.bottom=2
frame.left=2
frame.right=2
indicator.size=8
[DropDownButton]
inherits=PanelButtonCommand
frame.top=2
frame.bottom=2
frame.left=0
frame.right=1
indicator.size=8
[ToolboxTab]
inherits=PanelButtonCommand
frame.element=tabframe
frame.top=1
frame.bottom=1
frame.left=1
frame.right=1
[Tab]
inherits=PanelButtonCommand
interior.element=tab
frame.element=tab
frame.top=2
frame.bottom=3
frame.left=3
frame.right=3
indicator.size=10
; TODO: we should have different shades of the same color
text.normal.color=#{{base04-hex}}
text.focus.color=#{{base05-hex}}
text.press.color=#{{base05-hex}}
text.toggle.color=#{{base05-hex}}
focusFrame=true
[TabBarFrame]
inherits=GenericFrame
frame=true
frame.element=tabBarFrame
interior=false
frame.top=4
frame.bottom=4
frame.left=4
frame.right=4
[TabFrame]
inherits=PanelButtonCommand
frame.element=tabframe
interior.element=tabframe
[Dialog]
inherits=TabBarFrame
frame.element=tabframe
interior=false
frame=false
frame.top=1
frame.bottom=1
frame.left=1
frame.right=1
[HeaderSection]
inherits=PanelButtonCommand
interior.element=header
frame.element=header
frame.top=0
frame.bottom=1
frame.left=1
frame.right=1
frame.expansion=0
text.normal.color=#{{base05-hex}}
text.focus.color=#{{base0E-hex}}
text.press.color=#{{base05-hex}}
text.toggle.color=#{{base05-hex}}
indicator.element=harrow
[SizeGrip]
inherits=PanelButtonCommand
frame=false
interior=false
indicator.element=resize-grip
indicator.size=0
[Toolbar]
inherits=PanelButtonCommand
interior.element=menubar
frame.element=menubar
frame=true
frame.bottom=4
frame.left=4
frame.right=4
text.normal.color=#{{base05-hex}}
text.focus.color=#{{base05-hex}}
text.press.color=#{{base0E-hex}}
text.toggle.color=#{{base0E-hex}}
text.bold=false
[MenuBar]
inherits=PanelButtonCommand
frame.element=menubar
interior.element=menubar
frame.bottom=0
text.normal.color=#{{base05-hex}}
frame.expansion=0
text.bold=false
[ToolbarButton]
frame.element=tbutton
interior.element=tbutton
indicator.element=arrow
text.normal.color=#{{base05-hex}}
text.focus.color=#{{base05-hex}}
text.press.color=#{{base01-hex}}
text.toggle.color=#{{base01-hex}}
text.bold=false
[Scrollbar]
inherits=PanelButtonCommand
indicator.size=0
interior=false
frame=false
[ScrollbarGroove]
inherits=PanelButtonCommand
interior=false
frame=false
[ScrollbarSlider]
inherits=PanelButtonCommand
interior=false
frame.element=scrollbarslider
frame.top=4
frame.bottom=4
frame.left=4
frame.right=4
[ProgressbarContents]
inherits=PanelButtonCommand
frame=true
frame.element=progress-pattern
interior.element=progress-pattern
frame.top=2
frame.bottom=2
frame.left=2
frame.right=2
[Progressbar]
inherits=PanelButtonCommand
frame.element=progress
interior.element=progress
frame.top=2
frame.bottom=2
frame.left=2
frame.right=2
text.margin=0
text.normal.color=#{{base05-hex}}
text.focus.color=#{{base05-hex}}
text.press.color=#{{base01-hex}}
text.toggle.color=#{{base01-hex}}
text.bold=false
frame.expansion=18
[RadioButton]
inherits=PanelButtonCommand
[Menu]
frame.element=menu
interior.element=menu
inherits=PanelButtonCommand
text.press.color=#{{base01-hex}}
text.toggle.color=#{{base01-hex}}
text.bold=false
frame.top=3
frame.bottom=3
frame.left=3
frame.right=3
[MenuItem]
inherits=PanelButtonCommand
interior.element=menuitem
indicator.size=8
text.focus.color=#{{base05-hex}}
text.press.color=#{{base05-hex}}
[MenuBarItem]
inherits=PanelButtonCommand
interior.element=menubaritem
frame=false
text.margin.top=3
text.margin.bottom=3
text.margin.left=5
text.margin.right=5
[StatusBar]
inherits=Toolbar
frame.element=toolbar
font.bold=true
text.normal.color=#{{base05-hex}}
frame=true
frame.top=0
frame.bottom=0
[TitleBar]
inherits=PanelButtonCommand
frame=false
interior=false
text.margin.top=2
text.margin.bottom=2
text.margin.left=3
text.margin.right=3
[ComboBox]
inherits=PanelButtonCommand
indicator.size=8
frame.top=3
frame.bottom=3
frame.left=3
frame.right=3
text.margin.top=1
text.margin.bottom=1
text.margin.left=3
text.margin.right=3
text.toggle.color=#{{base05-hex}}
[ToolboxTab]
inherits=PanelButtonCommand
text.normal.color=#{{base05-hex}}
text.press.color=#{{base05-hex}}
text.focus.color=#{{base05-hex}}
[Hacks]
transparent_dolphin_view=false
blur_konsole=true
transparent_ktitle_label=true
transparent_menutitle=true
respect_darkness=true
kcapacitybar_as_progressbar=true
force_size_grip=false
iconless_pushbutton=true
iconless_menu=false
disabled_icon_opacity=100
lxqtmainmenu_iconsize=0
normal_default_pushbutton=true
single_top_toolbar=false
tint_on_mouseover=0
transparent_pcmanfm_sidepane=true
transparent_pcmanfm_view=false
blur_translucent=true
centered_forms=false
kinetic_scrolling=false
middle_click_scroll=false
no_selection_tint=false
noninteger_translucency=false
style_vertical_toolbars=false
blur_only_active_window=false
[Window]
interior=true
interior.element=window
frame.top=0
frame.bottom=0
frame.left=0
frame.right=0

51
modules/qt/nixos.nix Normal file
View file

@ -0,0 +1,51 @@
{
lib,
pkgs,
config,
...
}:
let
recommendedStyle = {
gnome = if config.stylix.polarity == "dark" then "adwaita-dark" else "adwaita";
kde = "breeze";
qtct = "kvantum";
};
in
{
options.stylix.targets.qt = {
enable = config.lib.stylix.mkEnableTarget "QT" pkgs.stdenv.hostPlatform.isLinux;
platform = lib.mkOption {
description = ''
Selects the platform theme to use for Qt applications.
Defaults to the standard platform used in the configured DE.
'';
type = lib.types.str;
};
};
config = lib.mkIf (config.stylix.enable && config.stylix.targets.qt.enable) {
stylix.targets.qt.platform =
with config.services.xserver.desktopManager;
if gnome.enable && !(plasma5.enable || lxqt.enable) then
lib.mkDefault "gnome"
else if plasma5.enable && !(gnome.enable || lxqt.enable) then
lib.mkDefault "kde"
else if lxqt.enable && !(gnome.enable || plasma5.enable) then
lib.mkDefault "lxqt"
else
lib.mkDefault "qtct";
qt = {
enable = true;
style = recommendedStyle."${config.qt.platformTheme}" or null;
platformTheme =
if config.stylix.targets.qt.platform == "qtct" then
"qt5ct"
else
config.stylix.targets.qt.platform;
};
};
}

View file

@ -174,6 +174,14 @@ let
"polarity"
];
}
{
path = [
"stylix"
"targets"
"qt"
"platform"
];
}
];
in