Leohearts的Blog

拥有一颗坚强而又温柔的心 *博客主题正在开发

cover

折腾笔记: 优雅地一键切换整个KDE系统的主题

如何实现自动深色主题?

Qt主题

在kde中, 这个部分可以用lookandfeeltool一句话, 十分方便.

只需要lookandfeeltool -a 'org.leo.breeze.desktop'即可.

壁纸

Plasma桌面提供了一个名为PlasmaDesktopScripting的功能, 它允许通过D-bus让Plasma桌面执行看起来有点像js的语言, 类似这样.

dbus-send --session --dest=org.kde.plasmashell --type=method_call /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string:
var Desktops = desktops();                                                                                                                       
for (i=0;i<Desktops.length;i++) {
        d = Desktops[i];
        d.wallpaperPlugin = "org.kde.image";
        d.currentConfigGroup = Array("Wallpaper",
                                    "org.kde.image",
                                    "General");
        d.writeConfig("Image", "file:///PATH/TO/IMAGE.png");
}';

我使用Plasma的幻灯片插件(可以在插件市场找到), 所以对于我来说, 只需要设置目标文件夹为一个符号链接, 更改主题时将此链接链接到另一个文件夹, 然后重载插件.

ln ~/图片/壁纸/dark ~/文档/currentslide -s;
dbus-send --session --dest=org.kde.plasmashell --type=method_call /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string: 
var Desktops = desktops(); 
    for (i=0;i<Desktops.length;i++) {
    d = Desktops[i];
    d.wallpaperPlugin = "org.kde.image";
}';
dbus-send --session --dest=org.kde.plasmashell --type=method_call /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string: 
    var Desktops = desktops();
    for (i=0;i<Desktops.length;i++) {
    d = Desktops[i];d.wallpaperPlugin = "org.kde.slideshow";
}'

这样壁纸的部分就完成了.

Konsole主题配置

Konsole的主题配置在~/.config/konsolerc, 只需要复制一份黑色主题然后cp ~/.config/konsolerc.dark ~/.config/konsolerc;就好了. (用sed可能更优雅, 但有点长)

GTK主题配置

这个部分花费了我最长的时间, 我找不到任何现成的资料, 以至于我一度放弃这个部分. 但很多程序遵循GTK主题, 所以非弄不可.

我尝试用change gtk theme command line之类的关键词进行查找, 找到的结果都是要更新~/.config/gtk-3.0/settings.ini和gtk2中的配置文件, 然后重启程序, 或者使用gsettings/kde-config-gtk-style之类的工具, 但问题是:

  • 更新文件后没有起作用或只有界面的一部分更改了主题
  • 我不是gnome
  • kde-config-gtk-style套件不工作

当然, 我可以在系统设置中手动更改GTK主题, 但我想要自动化.

我看了看用系统设置更改GTK主题后配置文件的变化, 我没有搞错. 然后我注意到reload_gtk_apps这个程序组件. 但可惜, 它也没用. (我看了它在github上的源码, 看起来没有问题, 但就是不工作xD)

让我们回到系统设置这边看看: 当我更改GTK设置时, 它实际上做了什么?

strace没有提供任何有用的信息. 后来, 我想到kde中的程序通信大量使用D-bus. 在fish中键入dbus, 然后按tab. 我发现了dbus-monitor.

运行dbus-monitor, 然后更改系统设置...

method call time=1595819538.122715 sender=:1.4266 -> destination=org.kde.GtkConfig serial=70 path=/GtkConfig; interface=org.kde.GtkConfig; member=gtk3Theme
method return time=1595819538.123238 sender=:1.15 -> destination=:1.4266 serial=11557 reply_serial=70
   string "Breeze"
method call time=1595819538.124359 sender=:1.4266 -> destination=org.kde.GtkConfig serial=71 path=/GtkConfig; interface=org.kde.GtkConfig; member=gtk2Theme
method return time=1595819538.124744 sender=:1.15 -> destination=:1.4266 serial=11558 reply_serial=71
   string "Breeze"

bingo. 看来这就是我要找的.

结合第二步中学到的关于D-bus的操作, 我写了这样的脚本:

dbus-send --session --dest=org.kde.GtkConfig --type=method_call /GtkConfig org.kde.GtkConfig.setGtk3Theme 'string:Breeze-Dark';
dbus-send --session --dest=org.kde.GtkConfig --type=method_call /GtkConfig org.kde.GtkConfig.setGtk2Theme 'string:Breeze-Dark'

这样, GTK的部分也解决了. 其实想到d-bus的话也不是很麻烦.

最后..

这是最后的深色脚本, 浅色同理:

lookandfeeltool -a 'org.leo.breeze.desktop';
cp ~/.config/konsolerc.dark ~/.config/konsolerc;
rm ~/文档/currentslide;
ln ~/图片/壁纸/dark ~/文档/currentslide -s;
dbus-send --session --dest=org.kde.plasmashell --type=method_call /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string: var Desktops = desktops();
for (i=0;i<Desktops.length;i++) {
    d = Desktops[i];
    d.wallpaperPlugin = "org.kde.image";
}';
dbus-send --session --dest=org.kde.plasmashell --type=method_call /PlasmaShell org.kde.PlasmaShell.evaluateScript 'string: var Desktops = desktops();
for (i=0;i<Desktops.length;i++) {
    d = Desktops[i];
    d.wallpaperPlugin = "org.kde.slideshow";
}';
dbus-send --session --dest=org.kde.GtkConfig --type=method_call /GtkConfig org.kde.GtkConfig.setGtk3Theme 'string:Breeze-Dark';
dbus-send --session --dest=org.kde.GtkConfig --type=method_call /GtkConfig org.kde.GtkConfig.setGtk2Theme 'string:Breeze-Dark'

写成脚本, 把它们扔到crontab之类的地方, 或者写个.desktop扔进程序启动器里就好了.