Plasma's QML API
Intro
KDE Frameworks ships with a number of useful extensions to Qt’s QML. The API documentation is a good start if you need to know what a specific property does. If you want to browse any of the sources easier, it’s also available on GitLab.
PlasmaComponents Controls
QML ships with various controls, like CheckBox , RadioButton , ComboBox (dropdown menu), SpinBox , Slider , TextField , TextArea , Button , ToolButton . Plasma extends these controls to style them using the SVGs from the Plasma Style. It also assigns a number of default settings like setting the text color to follow the panel’s color scheme.
PlasmaComponents 3 is a QML library that extends the Qt Quick Controls 2 components with defaults adapted to fit into Plasma widgets. Because PlasmaComponents 3 inherits from Qt Quick Controls 2, they have the same API, so the Qt documentation can be followed. For Plasma’s specific behaviour changes, you can read the QML source code for each control in:
plasma-framework
/src/declarativeimports/plasmacomponents3/
You may see leftover imports to PlasmaComponents 2 in some widgets. It uses the older Qt Quick Controls 1 components which are deprecated. The source code for the older controls can also be found in the plasma-frameworks
repo:
plasma-framework
/src/declarativeimports/plasmacomponents/qml/
Label
Labels are used for displaying text to the user. Plasma’s Label are assigned a number of defaults. One thing is it sets the text color to follow the panel’s color scheme.
For the specifics, you can read the Label.qml
source code.
// main.qml
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.Label {
text: i18n("Hello World")
}
CheckBox - Toggle
For a simple toggle, QML ships with CheckBox . For Plasma’s specific changes, you can read the QML source code at:
// main.qml
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.CheckBox {
text: i18n("Hello World")
checked: true
}
RadioButton - Multiple Choice
For multiple choices, QML ships with RadioButton . For Plasma’s specific changes, you can read the QML source code at:
Note the KDE Human Interface Guidelines suggest using a ComboBox (dropdown menu) when your list is greater than 5 options.
// main.qml
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
ColumnLayout {
PlasmaComponents3.RadioButton {
text: i18n("Top")
checked: true
autoExclusive: true
}
PlasmaComponents3.RadioButton {
text: i18n("Bottom")
autoExclusive: true
}
}
ComboBox - Multiple Choice
For multiple choices, QML also ships with ComboBox (dropdown menu). For Plasma’s specific changes, you can read the QML source code at:
Note that ComboBox.valueRole
and ComboBox.currentValue
was introduced in Qt 5.14. Ubuntu 20.04 only has Qt 5.12 so you will need to use your own _valueRole
and _currentValue
properties until Ubuntu 22.04. Make sure to not define a valueRole
or currentValue
property or it will break when your users upgrade to Qt 5.14.
// main.qml
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.ComboBox {
textRole: "text"
valueRole: "value"
model: [
{ value: "a", text: i18n("A") },
{ value: "b", text: i18n("B") },
{ value: "c", text: i18n("C") },
]
}
PlasmaComponents3.ComboBox {
textRole: "text"
property string _valueRole: "value"
readonly property var _currentValue: _valueRole && currentIndex >= 0 ? model[currentIndex][_valueRole] : null
}
Slider - Numbers
To control Integer or Real numbers, QML ships with SpinBox and Slider . For Plasma’s specific changes, you can read the QML source code at:
See the KDE Human Interface Guidelines to determine wither to use a Slider or a SpinBox.
// main.qml
import QtQuick 2.4
import QtQuick.Layouts 1.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
RowLayout {
PlasmaComponents3.Slider {
id: slider
Layout.fillWidth: true
from: 0
to: 100
value: 50
stepSize: 5
}
PlasmaComponents3.Label {
id: sliderValueLabel
function formatText(value) {
return i18n("%1%", value)
}
text: formatText(slider.value)
TextMetrics {
id: textMetrics
font.family: sliderValueLabel.font.family
font.pointSize: sliderValueLabel.font.pointSize
text: sliderValueLabel.formatText(slider.to)
}
Layout.minimumWidth: textMetrics.width
}
}
SpinBox - Numbers
To control Integer or Real numbers, QML ships with SpinBox and Slider . For Plasma’s specific changes, you can read the QML source code at:
See the KDE Human Interface Guidelines to determine wither to use a SpinBox or a Slider.
// main.qml
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
RowLayout {
PlasmaComponents3.Label {
text: i18n("Label:")
Layout.alignment: Qt.AlignRight
}
PlasmaComponents3.SpinBox {
from: 0
to: 100
value: 25
stepSize: 1
}
}
TextField, TextArea - Input
To enter text, QML ships with TextField and TextArea . For Plasma’s specific changes, you can read the QML source code for each:
See the KDE Human Interface Guidelines to determine wither to use a TextField (HIG calls it a Line Edit) or a TextArea.
// main.qml
import QtQuick 2.0
import QtQuick.Layouts 1.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
RowLayout {
PlasmaComponents3.Label {
Layout.alignment: Qt.AlignRight
text: i18n("Name:")
}
PlasmaComponents3.TextField {
placeholderText: i18n("Name")
}
}
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.TextArea {
text: "Lorem ipsum\ndolor sit amet,\nconsectetur adipisicing elit"
}
Button, ToolButton
For buttons, QML ships with Button and the flat ToolButton version. For Plasma’s specific changes, you can read the QML source code for each:
// main.qml
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.Button {
icon.name: "view-refresh"
text: i18n("Refresh")
}
// main.qml
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.ToolButton {
icon.name: "view-refresh-symbolic"
text: i18n("Refresh")
}
ScrollView
To add a scrollbar to manage overflow, QML ships with ScrollView . For Plasma’s specific changes, you can read the QML source code at:
// main.qml
import QtQuick 2.0
import org.kde.plasma.components 3.0 as PlasmaComponents3
PlasmaComponents3.ScrollView {
id: scrollView
ListView {
model: 100
delegate: PlasmaComponents3.CheckBox {
text: i18n("CheckBox #%1", index+1)
}
}
}
PlasmaExtras
To be consistent with elsewhere in Plasma, Plasma ships with a couple of special components. These components have their own API and are particularly helpful when creating a Plasma Widget.
You will need to import PlasmaExtras
to use them.
Heading, Paragraph
To be consistent with elsewhere in Plasma, Plasma ships with a couple different Label/Text
types with preset default sizes. The first one is
Heading
for subsections of texts and the second one is
Paragraph
.
Both wraps by default with Layout.fillWidth: true
.
// main.qml
import QtQuick 2.0
import QtQuick.Layouts 1.0
import org.kde.plasma.extras 2.0 as PlasmaExtras
ColumnLayout {
spacing: 0
Repeater {
model: 5
PlasmaExtras.Heading {
Layout.fillWidth: true
level: index + 1
text: i18n("Header level %1", level)
}
}
PlasmaExtras.Paragraph {
Layout.fillWidth: true
text: i18n("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sit amet turpis eros, in luctus lectus. Curabitur pulvinar ligula at leo pellentesque non faucibus mauris elementum. Pellentesque convallis porttitor sodales. Maecenas risus erat, viverra blandit vestibulum eu, suscipit in est. Praesent quis mattis eros. Sed ante ante, adipiscing non gravida sed, ultrices ultrices urna. Etiam congue mattis convallis. Maecenas sollicitudin mauris at lorem aliquam in venenatis erat convallis. Fusce eleifend scelerisque porttitor. Praesent metus sapien, hendrerit ac congue eget, feugiat id enim. Morbi venenatis gravida felis, vitae varius nunc dictum a. Etiam accumsan, velit ac tempor convallis, leo nibh consequat purus, sit amet fringilla nisi mi et libero.")
}
}
PlasmaCore
import org.kde.plasma.core 2.0 as PlasmaCore
- The very useful
Theme
andUnits
singletons. - A number of enums listed in
Types
. IconItem
for drawing icons.SvgItem
,Svg
andFrameSvgItem
for drawing SVGs coloured with the Plasma Style color palette.DataSource
for connecting to a Plasma DataEngine.
See the API docs for the full list of types in PlasmaCore
. You can also skim the generated .../core/plugins.qmltypes
file.
PlasmaCore.Theme
PlasmaCore.Theme
contains the Plasma Style color palette.
PlasmaCore.Theme.textColor
PlasmaCore.Theme.highlightColor
PlasmaCore.Theme.highlightedTextColor
PlasmaCore.Theme.backgroundColor
PlasmaCore.Theme.linkColor
PlasmaCore.Theme.visitedLinkColor
PlasmaCore.Theme.positiveTextColor
PlasmaCore.Theme.neutralTextColor
PlasmaCore.Theme.negativeTextColor
PlasmaCore.Theme.disabledTextColor
There is also properties for the various color groups using a prefix.
PlasmaCore.Theme.buttonTextColor
PlasmaCore.Theme.viewTextColor
PlasmaCore.Theme.complementaryTextColor
PlasmaCore.Theme.headerTextColor
The full list of PlasmaCore.Theme
color properties can be found in the QuickTheme
class definition:plasma-framework/src/declarativeimports/core/quicktheme.h
The QuickTheme
class extends
Plasma::Theme
which also contains:
PlasmaCore.Theme.defaultFont
font
PlasmaCore.Theme.palette
palette
PlasmaCore.Theme.smallestFont
font
PlasmaCore.Theme.styleSheet
string
PlasmaCore.Theme.themeName
string
PlasmaCore.Theme.useGlobalSettings
bool
PlasmaCore.Theme.wallpaperPath
string
PlasmaCore.Units.devicePixelRatio
In order to scale an Item by display scaling to support HiDPI monitors, you will need to multiply a pixel value by
PlasmaCore.Units.devicePixelRatio
. Plasma also ships with a few preset values for consistent spacing throughout Plasma.
PlasmaCore.Units.devicePixelRatio
=
QScreen::logicalDotsPerInchX
/ 96
(Primary Screen)PlasmaCore.Units.smallSpacing
= max(2, gridUnit/4)
PlasmaCore.Units.largeSpacing
= gridUnit
PlasmaCore.Units.gridUnit
(width of the capital letter M)
Note that Kirigami.Units
does not use the exact same logic as PlasmaCore.Units
.
import QtQuick 2.0
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
RowLayout {
spacing: PlasmaCore.Units.smallSpacing
Rectangle {
implicitWidth: 4 * PlasmaCore.Units.devicePixelRatio
Layout.fillHeight: true
color: PlasmaCore.Theme.highlightColor
}
PlasmaComponents3.Label {
text: i18n("Label")
}
}
PlasmaCore.Units.iconSizes
PlasmaCore.Units.iconSizes
is scaled by DPI.
PlasmaCore.Units.iconSizes.small
= 16px
PlasmaCore.Units.iconSizes.smallMedium
= 22px
PlasmaCore.Units.iconSizes.medium
= 32px
PlasmaCore.Units.iconSizes.large
= 48px
PlasmaCore.Units.iconSizes.huge
= 64px
PlasmaCore.Units.iconSizes.enormous
= 128px

PlasmaCore.Units.shortDuration
These properties are scaled by the Animation Speed in System Settings.
PlasmaCore.Units.veryShortDuration
= 50ms
PlasmaCore.Units.shortDuration
= 100ms
PlasmaCore.Units.longDuration
= 200ms
PlasmaCore.Units.veryLongDuration
= 400ms
This property is a hardcoded value and shouldn’t be used for animations. Instead, it can be used to measure how long to wait until the user should be informed of something, or can be used as the limit for how long something should wait before being automatically initiated.
PlasmaCore.Units.humanMoment
= 2000ms
Plasmoid property group
As discussed in the main.qml
setup widget section, when you import org.kde.plasma.plasmoid 2.0
, the main Item
in your widget will have the Plasmoid
(with a capital) property group similar to when you import QtQuick.Layouts 1.0
. This Plasmoid
property group has properties from
AppletInterface
which inherits a few properties from PlasmaQuick::AppletQuickItem
.
Plasmoid.compactRepresentation
The compact representation uses DefaultCompactRepresentation.qml
by default. To summarize, it:
- Draws the
plasmoid.icon
using aPlasmaCore.IconItem
- Defines a
MouseArea
to toggle theexpanded
property which displays the full representation.
Plasmoid.fullRepresentation
If there’s enough room (more than Plasmoid.switchHeight
) then the widget’s full representation can be drawn directly in the panel or on the desktop. If you want to force this behaviour you can set Plasmoid.preferredRepresentation
.
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation
If there isn’t enough room, then the widget will display Plasmoid.compactRepresentation
instead, and the full representation will be visible when plasmoid.expanded
is true
.
In a plasma widget, the full representation will be shown in a
PlasmaCore.Dialog
which you cannot access directly. You can manipulate the dialog with:
- Set
Layout.preferredWidth
andLayout.preferredHeight
in your full representationItem
to change to dialog size. - Set
Plasmoid.hideOnWindowDeactivate
to prevent the dialog from closing. You can use this to have a configurable “pin” like the digital clock widget does.
The dialog’s source code can be found in CompactApplet.qml
to see the exact behavior.
// main.qml
import QtQuick 2.0
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
Item {
// Always display the compact view.
// Never show the full popup view even if there is space for it.
Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation
Plasmoid.fullRepresentation: Item {
Layout.minimumWidth: label.implicitWidth
Layout.minimumHeight: label.implicitHeight
Layout.preferredWidth: 640 * PlasmaCore.Units.devicePixelRatio
Layout.preferredHeight: 480 * PlasmaCore.Units.devicePixelRatio
PlasmaComponents.Label {
id: label
anchors.fill: parent
text: "Hello World!"
horizontalAlignment: Text.AlignHCenter
}
}
}
Plasmoid.icon
As discussed in the metadata.desktop
setup widget section, by default the plasmoid icon is populated with Icon=
in metadata.desktop
.
To set a dynamic or user configurable icon, you will need to assign an icon name to Plasmoid.icon
.
You can search for icon names in the /usr/share/icon
folder. You can also look for an icon name by right clicking your app launcher widget then editing the icon in its settings. It uses a searchable interface and lists them by category. Plasma’s SDK also has the Cuttlefish app (screenshot) which you can install with sudo apt install plasma-sdk
.
Also checkout the configurable panel icon example
// main.qml
import QtQuick 2.0
import org.kde.plasma.plasmoid 2.0
Item {
id: widget
property bool hasUnread: true
Plasmoid.icon: hasUnread ? "mail-unread" : "mail-message"
Timer {
interval: 1000
repeat: true
running: true
onTriggered: widget.hasUnread = !widget.hasUnread
}
}
metadata.desktop
The common metadata.desktop
properties are covered in the setup widget section.
The full list of custom .desktop
file properties for widgets is defined in the Plasma/Applet
service type.
metadata.desktop
is the original format while metadata.json
is the newer replacement format. The .desktop
file is simpler to script using kreadconfig5
which is the reason why this tutorial prefers it. You can read up on
metadata.json
in the API Documentation
.
Name, Comment
Name[fr]
. The translated Name
is used in the “Add Widgets” list. The Comment
(or in the json file names Description
) is only used for the default tooltip subtext when the widget is added to a panel.[Desktop Entry]
Name=Calendar
Name[fr]=Calendrier
Comment=Month display with your appointments and events
Comment[fr]=Vue mensuelle avec vos rendez-vous et évènements
{
"KPlugin": {
"Description": "Month display with your appointments and events",
"Description[fr]": "Vue mensuelle avec vos rendez-vous et évènements",
"Name": "Calendar",
"Name[fr]": "Calendrier"
}
}
Icon
Icon
is the icon name associated with the widget. You can search for icon names in the /usr/share/icon
folder. You can also look for an icon name by right clicking your app launcher widget then editing the icon in its settings. It uses a searchable interface and lists them by category. Plasma’s SDK also has the Cuttlefish app which you can install with sudo apt install plasma-sdk
.[Desktop Entry]
Icon=office-calendar
X-KDE-PluginInfo-Name
X-KDE-PluginInfo-Name
needs to be a unique name, since it’s used for the folder name it’s installed into. You could use com.github.zren.helloworld
if you’re on github, or use org.kde.plasma.helloworld
if you’re planning on contributing the widget to KDE. You should consider this the widget’s namespace.~/.local/share/plasma/plasmoids/com.github.zren.helloworld/
/usr/share/plasma/plasmoids/com.github.zren.helloworld/
X-KDE-PluginInfo-Category
X-KDE-PluginInfo-Category
is the category the widget can be filtered within the widget list.
[Desktop Entry]
X-KDE-PluginInfo-Category=Date and Time
Accessibility
: tools that help those with special needs or disabilities use their computerApplication Launchers
: application starters and file openers.Astronomy
: anything to do with the night sky or other celestial bodies.Date and Time
: clocks, calendars, scheduling, etcDevelopment Tools
: tools and utilities to aid software developersEducation
: teaching and educational aidesEnvironment and Weather
: add-ons that display information regarding the weather or other environmentally related dataExamples
: samples that are not meant for production systemsFile System
: anything that operates on files or the file system as its primary purpose, such as file watchers or directory listings. Simply using a file as storage does not qualify the add-on for this category.Fun and Games
: for games and amusementsGraphics
: for add-ons where displaying images, photos or graphical eye candy is the primary purposeLanguage
: add-ons whose primary purpose is language related, such as dictionaries and translators.Mapping
: geography and geographic data add-onsMultimedia
: music and video.Online Services
: add-ons that provide an interface to online services such as social networking or blogging sites. If there is another more appropriate category for the add-on given the topic (e.g. mapping if the applet’s purpose is to show maps), even if the data is retrieved from the Internet prefer that other category over this one.System Information
: display and interaction with information about the computer such as network activity, hardware health, memory usage, etcUtilities
: Useful tools like calculatorsWindows and Tasks
: managers for application windows and/or tasks, such as taskbars
This list was taken from: https://techbase.kde.org/Projects/Plasma/PIG
X-KDE-ServiceTypes
X-KDE-ServiceTypes
is a comma-separated list of types. For a plasma widget, it should be Plasma/Applet
. You may encounter widgets with Plasma/Containment
as well, like the System Tray widget.
The defined plasma service types and their custom .desktop
file properties are found in:plasma-framework/src/plasma/data/servicetypes
X-Plasma-API, X-Plasma-MainScript
X-Plasma-API
tells plasma what script engine to use. declarativeappletscript
is the standard QML
loader.
X-Plasma-MainScript
is the entry point of your qml code. The standard throughout plasma is to use ui/main.qml
.
[Desktop Entry]
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=ui/main.qml
X-Plasma-Provides (Alternatives)
A Plasmoid can specify the type of functionality it offers, for example whether it’s a clock, an application launcher, etc. This mechanism is used to list alternative plasmoids for a certain function. When you open the context menu of the Application Launcher (aka kickoff) in the Plasma desktop panel, you’ll see that a number of different Plasmoids are offered here as alternatives, like the Application Menu (aka kicker) and Application Dashboard (aka kickerdash). All three of these widgets define:
[Desktop Entry]
X-Plasma-Provides=org.kde.plasma.launchermenu
These “Provides” are in fact arbitrary, so you can choose your own here. The field accepts multiple values separated by a comma. Here are some possible values that are used throughout Plasma:
org.kde.plasma.launchermenu
: App Launcher Menusorg.kde.plasma.multimediacontrols
: Multimedia controlsorg.kde.plasma.time
: Clocksorg.kde.plasma.date
: Calendarsorg.kde.plasma.time,org.kde.plasma.date
: Clocks with calendars (Eg: Digital Clock)org.kde.plasma.powermanagement
: Power management (Eg: Battery and Brightness)org.kde.plasma.notifications
: Notificationsorg.kde.plasma.removabledevices
: Removable devices, auto mounter, etc.org.kde.plasma.multitasking
: Task switchersorg.kde.plasma.virtualdesktops
: Virtual desktop switcherorg.kde.plasma.activities
: Switchers for Plasma activitiesorg.kde.plasma.trash
: Trash / file deletion
You can search plasma’s code for more examples:
- Search
plasma-workspace
forX-Plasma-Provides
- Search
plasma-desktop
forX-Plasma-Provides
- Search
kdeplasma-addons
forX-Plasma-Provides
X-Plasma-NotificationArea (System Tray)
The Media Controller widget serves as a good example since it uses most of the systemtray metadata features. Its metadata contains the following:
[Desktop Entry]
X-KDE-PluginInfo-EnabledByDefault=true
X-Plasma-NotificationArea=true
X-Plasma-NotificationAreaCategory=ApplicationStatus
X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.*
{
"KPlugin": {
"EnabledByDefault": true
},
"X-Plasma-DBusActivationService": "org.mpris.MediaPlayer2.*",
"X-Plasma-NotificationArea": "true",
"X-Plasma-NotificationAreaCategory": "ApplicationStatus"
}
By specifying X-Plasma-NotificationArea
, this widget will be found by the systemtray widget.
X-KDE-PluginInfo-EnabledByDefault
will make sure it’s enabled in the systemtray by default.
It’s prudent for the widget to also set the X-Plasma-NotificationAreaCategory
so that the icons are grouped together. Its allowed values are:
ApplicationStatus
: indicates that this item represents an active applicationHardware
: indicates that this item allows managing hardware (could be a battery monitor or the wifi applet)SystemServices
: indicates that this item shows information about system services, for example the status of file indexing, software updates, etc.
You can search plasma’s code for more examples:
- Search
plasma-workspace
forX-Plasma-NotificationArea
- Search
plasma-desktop
forX-Plasma-NotificationArea
- Search
kdeplasma-addons
forX-Plasma-NotificationArea
X-Plasma-DBusActivationService
X-Plasma-DBusActivationService
will load and unload widgets in the systemtray automatically when a DBus service becomes available or is stopped. This is very convenient to load widgets automatically, so the user doesn’t have to explicitly go to the notification area settings and enable or remove a widget.
An example of this is the Media Controller widget, which is auto-loaded as soon as an application starts offering the org.mpris.MediaPlayer2
DBus service in the session. As you can see in its metadata.desktop
file, X-Plasma-DBusActivationService
accepts wildcards which makes it a bit easier to match DBus names. This key can also be very useful to avoid having a widget loaded when it’s unnecessary, so it can help to avoid visual clutter and wasted memory.
[Desktop Entry]
X-Plasma-NotificationArea=true
X-Plasma-NotificationAreaCategory=ApplicationStatus
X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.*
Search plasma-workspace
for X-Plasma-DBusActivationService
for more examples.