From b7f50a56c3ccda1e6020e62b77a9f9ea80d6a656 Mon Sep 17 00:00:00 2001 From: Kilian Mio <86004375+Mikilio@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:40:41 +0100 Subject: [PATCH] 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 Co-authored-by: Jackaed 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> --- modules/qt/hm.nix | 104 ++ modules/qt/kvantum-svg.mustache | 1958 +++++++++++++++++++++++++++ modules/qt/kvconfig.mustache | 466 +++++++ modules/qt/nixos.nix | 51 + stylix/home-manager-integration.nix | 8 + 5 files changed, 2587 insertions(+) create mode 100644 modules/qt/hm.nix create mode 100644 modules/qt/kvantum-svg.mustache create mode 100644 modules/qt/kvconfig.mustache create mode 100644 modules/qt/nixos.nix diff --git a/modules/qt/hm.nix b/modules/qt/hm.nix new file mode 100644 index 00000000..ee3283bb --- /dev/null +++ b/modules/qt/hm.nix @@ -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; + }) + ]; + } + ); +} diff --git a/modules/qt/kvantum-svg.mustache b/modules/qt/kvantum-svg.mustache new file mode 100644 index 00000000..b440f3d3 --- /dev/null +++ b/modules/qt/kvantum-svg.mustache @@ -0,0 +1,1958 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/qt/kvconfig.mustache b/modules/qt/kvconfig.mustache new file mode 100644 index 00000000..00dec250 --- /dev/null +++ b/modules/qt/kvconfig.mustache @@ -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 diff --git a/modules/qt/nixos.nix b/modules/qt/nixos.nix new file mode 100644 index 00000000..834743fc --- /dev/null +++ b/modules/qt/nixos.nix @@ -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; + }; + }; +} diff --git a/stylix/home-manager-integration.nix b/stylix/home-manager-integration.nix index eb4a3bb0..fefae047 100644 --- a/stylix/home-manager-integration.nix +++ b/stylix/home-manager-integration.nix @@ -174,6 +174,14 @@ let "polarity" ]; } + { + path = [ + "stylix" + "targets" + "qt" + "platform" + ]; + } ]; in