Plasma/How to create a Unity-like look and feel theme using Plasma’s Desktop Scripting API

    From KDE UserBase Wiki

    Information

    You will find some background on Plasma Look and Feel packages here. More background on Plasma scripting here.


    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")