How to create a theme that looks and feels like Unity using Plasma’s Desktop Scripting API

Plasma is probably one of the most configurable desktop environments around. With Plasma 5 developers wanted to make the configurability even easier and more straightforward than ever before by applying the rule “simple by default, powerful when needed”. To make that happen, the concept of Plasma look and feel themes was born.

Plasma look and feel themes (L&F) let you change the look of your Plasma desktop with just a few clicks. The simplest way to create look and feel theme is by using utility called Look and Feel Explorer, as described in the official documentation. You should also check out this video tutorial.

However if you want to have more granular control over what exactly happens with your theme, especially with the layout you can use Plasma desktop scripting. Some time ago I rewrote my L&F theme (United) using desktop scripting API. In this post I am going to describe step by step how you too can create a Unity-like desktop layout by using Plasma’s desktop scripting API.

Let’s get started.

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.

qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.showInteractiveConsole

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 your 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”)

Are you still there? I hope you weren’t bored too much ;)

That said, if you want all the work done for you, you can download United from KDE Store or from GitHub. I also added documentation to the official KDE wiki.

This theme also uses:

-Color Scheme (Ambiance) made by CHICHOVOTO
https://store.kde.org/p/1001434/

-Plasma theme (Unity Ambiance) made by DARKBEASTOFPREY
https://store.kde.org/p/998797

- Plasmoids 
Present Windows Button made by ZREN
https://store.kde.org/p/1181039/

USwitch made by DIVINAE
https://store.kde.org/p/1194339/

Like what you read? Give Łukasz Sawicki a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.