Plasma/How to create a Unity-like look and feel theme using Plasma’s Desktop Scripting API
In short, desktop scripting lets you control and interact with a Plasma user interface shell via JavaScript like API. You can use an interactive scripting dialog to test your scripts.
plasma-interactiveconsole
As you may know, inside your L&F theme (contents/layout) there is a file called org.kde.plasma.desktop-layout.js which controls your Plasma setup. If you are using Look and Feel Explorer that file and its content is created automatically.
First you need to create a proper L&F package structure with all the files you need and save it in:
/home/[yourusername]/.local/share/plasma/look-and-feel/
You can use Look and Feel Explorer or modify an existing theme like United. Next open org.kde.plasma.desktop-layout.js in your favorite text editor. I am using Kate (Plasma’s default text editor). At the beginning of your file you need to add:
var plasma = getApiVersion(1)
Ok, now let’s create a new plasma panel located at the top of the screen:
panel = new plasma.Panel
panel.location = "top"
Add the height property for the panel (gridUnit * 2 is a default value used in plasma)
panel.height = gridUnit * 2
Once you have a new shiny panel you can add some widgets.
To get a list of widgets installed locally (for example from the KDE Store), do this:
kpackagetool5 --list --type Plasma/Applet
To get a list of all installed widgets (system wide):
kpackagetool5 --list --type Plasma/Applet --global
Once you have a list of installed widgets, you can use the panel.addWidget method to add them to our top panel.
panel.addWidget("org.kde.plasma.appmenu")
panel.addWidget("org.kde.plasma.panelspacer")
panel.addWidget("org.kde.plasma.systemtray")
panel.addWidget("org.kde.plasma.digitalclock")
And here is the result:
You need to add another spacer on the left side of the appmenu (otherwise the appmenu will overlap with the left panel). You also need a user switcher applet on the right side of a digital clock. Let’s start with the spacer:
var spacer = panel.addWidget("org.kde.plasma.panelspacer")
Now our global menu is located at center of the panel. This is because the default spacer takes up all available space in a panel. You need to change that by setting the expanding value to false. You use the currentConfigGroup property and writeConfig method to modify config file /home/.config/plasma-org.kde.plasma.desktop-appletsrc.
var spacer = panel.addWidget("org.kde.plasma.panelspacer")
spacer.currentConfigGroup = ["Configuration", "General"]
spacer.writeConfig("expanding", false)
Next you will add USwitch (https://store.kde.org/p/1194339/), the Unity-like user switcher applet, from the KDE Store. You need to add it as a dependency to your L&F theme. If you want to know how to do that, check out this tutorial. Once added to the panel, USwitch shows full user name by default. However we want to show an icon, just like in Unity.
The good news is that USwitch offers such an option: You only need to change it using plasma desktop scripting. While most of the settings (configuration keys) offered by default widgets are documented, this is not the case with third party widgets.
The simplest way to get such information is to open plasma-org.kde.plasma.desktop-appletsrc in kate, go to USwitcher Settings and change it to Show only icon. Close window settings and you will get something like this
Click View Difference to see what configuration keys were changed.
var uswitcher= panel.addWidget("org.kde.plasma.uswitcher")
uswitcher.currentConfigGroup = ["Configuration", "General"]
uswitcher.writeConfig("showName", false)
uswitcher.writeConfig("showSett", true)
Now org.kde.plasma.desktop-layout.js should looks like this:
var plasma = getApiVersion(1)
// Create top panel
panel = new plasma.Panel
panel.location = "top"
panel.height = gridUnit * 2
// Add widgets to the top panel
var spacer = panel.addWidget("org.kde.plasma.panelspacer")
// Make first spacer non expandable by default
spacer.currentConfigGroup = ["Configuration", "General"]
spacer.writeConfig("expanding", false)
// Appmenu
panel.addWidget("org.kde.plasma.appmenu")
// Spacer
panel.addWidget("org.kde.plasma.panelspacer")
// Systemtray
panel.addWidget("org.kde.plasma.systemtray")
// Clock
panel.addWidget("org.kde.plasma.digitalclock")
// USwitch https://store.kde.org/p/1194339/
var uswitcher= panel.addWidget("org.kde.plasma.uswitcher")
uswitcher.currentConfigGroup = ["Configuration", "General"]
uswitcher.writeConfig("showName", false)
uswitcher.writeConfig("showSett", true)
Let’s create the left panel...
var leftpanel = new plasma.Panel
leftpanel.location = "left"
leftpanel.height = gridUnit * 3.2
… And add a fullscreen launcher and default shortcut:
var menu = leftpanel.addWidget("org.kde.plasma.kickerdash")
menu.currentConfigGroup = ["Shortcuts"]
menu.writeConfig("global", "Alt+F1")
Now you can add an icon-based task manager:
leftpanel.addWidget("org.kde.plasma.icontasks")
Add Present Windows Button widget from KDE Store ( https://store.kde.org/p/1181039/ ) and change its settings to show the desktop grid by default:
var windows = leftpanel.addWidget("com.github.zren.presentwindows")
windows.currentConfigGroup = ["Configuration", "General"]
windows.writeConfig("clickCommand","ShowDesktopGrid")
Add a trash can:
leftpanel.addWidget("org.kde.plasma.trash")
You are almost there and only need to fix overlapping panels...
leftpanel.offset=panel.height
… And remove the desktop toolbox
var activityId = activityIds[0]
var activity = desktopById(activityId)
activity.currentConfigGroup = ["General"]
activity.writeConfig("showToolbox", false)
The final org.kde.plasma.desktop-layout.js should look like this:
var plasma = getApiVersion(1)
var activityId = activityIds[0]
var activity = desktopById(activityId)
//Remove desktop toolbox
activity.currentConfigGroup = ["General"]
activity.writeConfig("showToolbox", false)
//Create top panel
panel = new plasma.Panel
panel.location = "top"
panel.alignment = "left"
panel.height = gridUnit * 2
//Add widgets to the top panel
var spacer = panel.addWidget("org.kde.plasma.panelspacer")
//Make first spacer non expandable by default
spacer.currentConfigGroup = ["Configuration", "General"]
spacer.writeConfig("expanding", false)
//Kickerdash
panel.addWidget("org.kde.plasma.appmenu")
//Spacer
panel.addWidget("org.kde.plasma.panelspacer")
//System tray
panel.addWidget("org.kde.plasma.systemtray")
//Clock
panel.addWidget("org.kde.plasma.digitalclock")
//USwitch https://store.kde.org/p/1194339/
var uswitcher= panel.addWidget("org.kde.plasma.uswitcher")
uswitcher.currentConfigGroup = ["Configuration", "General"]
uswitcher.writeConfig("showName", false)
uswitcher.writeConfig("showSett", true)
//Create left panel
var leftpanel = new plasma.Panel
leftpanel.location = "left"
leftpanel.height = gridUnit * 3.2
leftpanel.offset=panel.height
//Add widgets to the left panel
var menu = leftpanel.addWidget("org.kde.plasma.kickerdash")
//Add default shortcut to the kickerdash menu
menu.currentConfigGroup = ["Shortcuts"]
menu.writeConfig("global", "Alt+F1")
//Icontasks
leftpanel.addWidget("org.kde.plasma.icontasks")
//Present Windows Button https://store.kde.org/p/1181039/
var windows = leftpanel.addWidget("com.github.zren.presentwindows")
//Toggle desktop grid
windows.currentConfigGroup = ["Configuration", "General"]
windows.writeConfig("clickCommand","ShowDesktopGrid")
//Trash
leftpanel.addWidget("org.kde.plasma.trash")