Plasma/DeveloperGuide: Difference between revisions
(draft structure for new developer guide) |
(use a working git URL for plasma-frameworks) |
||
(61 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
The Ultimate Guide to Plasma Development | ''The Ultimate Guide to Plasma Development'' | ||
=Introduction= | =Introduction= | ||
This guide explains the basic steps to build a fully integrated application. This guide is targeted at developers with basic knowledge of QML. It guides through the complete process of developing an application from scratch. | |||
Plasma allows to write applications that work well on different form factors or devices. Plasma is built to adapt to different input methods (mouse, touch, keyboard, etc.) screen sizes and to be resolution-independent. Most of the information in this guide is applicable to all form factors. Topics that may differ for different form factors are indicated as such. | |||
A well-architectured Plasma application will be able to offer different user interface per form factor. For desktops, a landscape layout with quite a lot of space for display and interaction can be used, while the same underlying components in a different, portrait-oriented layout can be used to present the user interface on a phone. A tablet user interface may use either, or combine the components in yet another fashion to make the best use of available screen real estate. | |||
In general, Plasma widgets such as buttons and other controls, work well on touch, mouse and with keyboard input, but can be switched at application start or runtime, transparently to the application using it. | |||
In this guide, you will learn how to use all these features to create an application that works well on wide range of target devices. | |||
==Is this guide for you?== | |||
Plasma makes extensive use of QtQuick and QML to write the user interface and business logic of your application. Basic understanding of QtQuick is necessary, though Plasma is also a great environment to learn by doing it. This guide targets developers that are familiar with common programming paradigms, but do not have special knowledge of the Plasma APIs, libraries and mechanisms to solve certain problems. | |||
Many things can be implemented without knowing or being able to write C++ code. Plasma provides high-level APIs to solve a great number of tasks and provide common functionality such as retrieving data, displaying information as well as widgets for common interaction patterns and themes and artwork to make your app beautiful and consistent. | |||
= | In some cases, or in more complex apps, you may extend the functionality by writing a C++ plugin (or "import"). This allows to access custom functionality in your system, leverage an existing library, or move logic into a type-safe language that is easier to test (using unit tests, for example) or performs better. | ||
In this guide, we assume that you can find your way around in a command-line based environment and be familiar with tools such as git and code editors. | |||
==Apps, Widgets and Plasmoids?== | |||
Plasma offers user interfaces for applications as well as workspaces (the environment you run your app in, the | |||
desktop, or phone user interface offering a launcher, task switcher, settings, for example). | |||
The workspace can be extended using Plasma Widgets, or in more technical terms, plasmoids. A plasmoid is a package containing metadata, images, configuration defaults and the QML files that make up the UI. Most of Plasma Desktop's functionality is offered using plasmoids. The application launcher in the bottom-left corner is a plasmoid, the task manager in the panel which allows you to switch between running applications is a plasmoid, many of the widgets in the notification area on both, Plasma Mobile and Plasma Desktop are plasmoids. You can also put Plasmoids on your desktop, the analog clock widgets and the "post-it" notes plasmoids are popular examples. | |||
Apps are loaded from packages as well. The main difference, aside from the layout probably being different, is that instead of loading the QML code inside a panel, or widget on the desktop, the application is loaded into its own window. (There are certain API features which may only make sense in the workspace, but those are usually implementation details that can be ignored where they don't make sense.) | |||
An app or a plasmoid would typically load the main layout for the window, popup or widget from a QML file, and then use imports to load additional libraries or make APIs available from within the applications QML code. | |||
=An App in 5 Easy Steps= | |||
Creating a simple application in Plasma is very easy. You can try the following quickguide to create your first little app. | |||
# Download a template | |||
# Adjust the metadata | |||
# Edit the code | |||
# Install the app | |||
# Start and try it | |||
==Download a Template== | |||
You can create your own plasmoid from a simple example, shipped with the plasma-framework source code from git: | |||
git clone https://invent.kde.org/frameworks/plasma-framework | |||
Then copy a basic example, which is going to be your new plasmoid. Let's call it "myplasmoid": | |||
cp -R plasma-framework/examples/developerguide/basic myplasmoid | |||
Alternatively, you can create a new Plasmoid using [[#KAppTemplate]]. Pick Plasmoid / QML Plasmoid / Plasma QML Applet to generate your app skeleton for this example. | |||
==Adjust the Metadata== | |||
Open ''myplasmoid/metadata.desktop'' with your favorite text editor (mine is "Kate"): | |||
kate myplasmoid/metadata.desktop | |||
and change the ''Name'' and ''Comment'' fields. These will identify your Plasmoid in the widget chooser and is the default window name. | |||
Name=My Plasmoid | |||
Comment=Plasma Hacker 101 | |||
You can also pick a nice icon here. Use for example the ''cuttlefish'' tool to pick a nice one. | |||
Now make sure that the line containing the ''X-KDE-PluginInfo-Name'' contains a unique plugin id: | |||
X-KDE-PluginInfo-Name=org.example.myplasmoid | |||
The plugin name is used to identify the plugin on the system, make sure you pick a unique plugin name. It's advised to use a reverse domain name pattern. The plugin name will also be used in the installation path. | |||
==Edit the QML code== | |||
In order to change the template and write your own code, open its main QML file and hack away. | |||
kate myplasmoid/contents/ui/main.qml | |||
Play around with it a bit, try to change something, add a few new things, make yourself comfortable with it. | |||
For simple, first testing, you can also just skip this step for now, install as is to see if everything works in a clean environment and get back to actually changing the code later on. | |||
==Install the App== | |||
To install a plasmoid, you can use the "kpackagetool5" program: | |||
kpackagetool5 -i myplasmoid | |||
This will install the plasmoid locally in your home directory, into ~/.local/share/kpackage/genericqml/org.example.myplasmoid on my system -- your installation path may vary. To update an already-installed package on your system, use | |||
kpackagetool5 -u myplasmoid | |||
to remove it, use | |||
kpackagetool5 -r myplasmoid | |||
==Start your App== | |||
You can now start your brand-new app using kpackagelauncherqml: | |||
kpackagelauncherqml -a org.example.myplasmoid | |||
And a window will show up with your application. You can now start hacking. | |||
=Requirements Analysis & Design= | |||
The first step to building an application is to analyze the problem that you want to solve and come up with a way how you can solve this problem. This allows you to make a list of required features for your application. A clear purpose and understanding of what want to achieve and how you want to get there helps you to make smart choices regarding features, their design and presentation. It can also avoid bloat and helps to set priorities for the app's development work. | |||
In the design phase, you care about three things: interaction, visual and technical design. | |||
The '''interaction design''' is the workflow for the user. You can visualize this in a [https://en.wikipedia.org/wiki/Flowchart flowchart], for example. This flowchart should give you an idea of which steps or views you want to present to the user, and which options should be available in each of them. | |||
In the '''visual design''' phase, you draw you user interfaces, views, screens and plan how things are laid out on screen. You can use pen and paper for it, but also tools like inkscape and the [https://community.kde.org/Plasma/Mobile/Design#Mockup_toolkit Plasma mockup toolkit]. KDE's [https://techbase.kde.org/Projects/Usability/HIG Human Interface Guidelines] provide many useful tips how you can create intuitive user interfaces with a high level of consistency. | |||
We encourage you to present your ideas, concepts and design and discuss it, for example in the [http://forums.kde.org KDE Forums] or on the [FIXME Plasma Mailinglist] to refine your design further and get input from more points of view. | |||
You can find more information about design workflows, tools and resources on [https://community.kde.org/Plasma/Mobile/Design this page]. | |||
In this guide, you will learn about the implementation of your design. You will come across many features that may be useful to use in your app. Try to not make the mistake to implement things that do not directly contribute to the goal of your app. Having a clear idea of the purpose and design of your app helps to prevent scope creep, bloat and a less effective app. Many of the features described are optional, pick only the ones you need. This guide gives you an overview over what kind of tools there are, pick wisely. | |||
=Software Stack= | |||
The software stack consists of a number of components that are interesting for application development. This chapter gives an overview of the most important pieces to consider. | |||
==QML & QtQuick== | |||
[https://en.wikipedia.org/wiki/QML Wikipedia] has an excellent description | |||
''QML (Qt Meta Language or Qt Modeling Language) is a user interface markup language. It is a JavaScript-based, declarative language for designing user interface–centric applications. It is part of Qt Quick, the UI creation kit within the Qt framework. QML is used for desktop and mobile applications where touch input, fluid animations (60 FPS) and user experience are crucial. QML documents describe an object tree of elements. QML elements shipped with Qt are a sophisticated set of building blocks, graphical (e.g., rectangle, image) and behavioral (e.g., state, transition, animation). These elements can be combined to build components ranging in complexity from simple buttons and sliders, to complete internet-enabled programs.'' | |||
''QML elements can be augmented by standard JavaScript both inline and via included .js files. Elements can also be seamlessly integrated and extended by C++ components using the Qt framework.'' | |||
''QML is the language; its runtime is the Javascript V4 engine and Qt Quick is the scenegraph-based UI framework.'' (slightly redacted for clarity purposes) | |||
Your QtQuick code "tree" describes an object-tree structure of visual items, such as images or text and non-visual items, such as data models or object collections. The visual structure is displayed in an OpenGL scenegraph. This allows us to manipulate and compose visual items in the UI directly on the graphics card. This leads to high-performance graphics on the one, and energy savings on the other hand. Graphics hardware is much more efficient for graphics manipulation than the central system processor. | |||
QtQuick code is loaded at runtime and just-in-time compiled into the javascript's engine's binary representation on application startup. | |||
QtQuick makes it very easy to create attractive user interfaces with smooth animations. QtQuick UIs support multitouch, mouse and keyboard inputs, allow handling of gestures. Most importantly, QtQuick is easy to write and change, and it is an intuitive language very well suited for creating modern UI with a gentle learning curve. | |||
On top of these fundamentals, you will want more high-level functionality. This is where "imports" enter the picture. | |||
==Imports== | |||
QtQuick applications, such as your Plasma app, can be extended using imports. An import is a Qt plugin that is dynamically loaded at runtime. imports can consist of QML items (used as custom types once imported) or compiled libraries that export C++ functions and objects (often QObject based) to the QML runtime. Import plugins can contain QML files, a C++ plugins or both. QML imports are also often referred to as ''components''. | |||
Imports allow you to use libraries from QML and javascript and to re-use or share code between different applications, for example across packages. QtQuick items 'understand' a useful number of Qt's standard types, such as QString, QAbstractItemModel, QColor, QDate, etc.. Builtin javascript types such as string, int, float are also supported. | |||
You can write an import yourself, though most of the time you will find yourself using already existing imports. | |||
In your app, you can import additional functionality like this: | |||
import QtQuick 2.3 | |||
import org.kde.plasma.components 2.0 as PlasmaComponents | |||
This imports QtQuick's standard items into the global namespace, that means you can now use types like '''Item {}'''. The second line imports the org.kde.plasma.components plugin into the '''PlasmaComponents''' QML namespace. This means you refer to its types like this: | |||
PlasmaComponents.Label { | |||
text: "Ultimate Plasma Hacking" | |||
/* ... */ | |||
} | |||
It's recommended to always import QtQuick into the global namespace and to import other modules into their respective namespaces, such as in this case ''PlasmaComponents''. This also improves code readability and makes it easier to debug since the code tells us where to look or where something actually comes from. It also avoids naming clashes -- there may be other UI components using the same name for a different element. This can lead to your app refusing to start or undetected runtime errors. | |||
Commonly useful imports are: | |||
===PlasmaCore=== | |||
import org.kde.plasma.core 2.0 as PlasmaCore | |||
PlasmaCore provides lower-level functionality for your app: | |||
* '''units''' for DPI support, units.gridUnit is commonly used to describe sizes, gridUnits provide consistent sizing across the complete spectrum and has been tested to work between 100 and 500 DPI. | |||
* '''IconItem''' for scalable rendering of themed icons. | |||
* '''SvgItem''' and its friends allow to you load and use scalable SVG graphics in your UI. SvgItem and friends are backed by a rendering cache and offload as much as possible to the GPU. '''FrameSvgItem''' provides a correctly scaled and efficient mechanism to render and resize frame-like SVG graphics with correct sizing of corners. | |||
* '''[[#ColorScope]]''' allows you to change the color scheme for a part of your application in a consistent way. | |||
* Window thumbnails, tooltips, bindings for DataEngines, data models, and more. | |||
KDE's API documentation has a comprehensive list of [http://api.kde.org/frameworks-api/frameworks5-apidocs/plasma-framework/html/core.html PlasmaCore's API]. | |||
===PlasmaComponents=== | |||
import org.kde.plasma.components 2.0 as PlasmaComponents | |||
PlasmaCore provides widgets, such as buttons, sliders and scrollviews for your app. | |||
KDE's API documentation has a comprehensive list of the [http://api.kde.org/frameworks-api/frameworks5-apidocs/plasma-framework/html/plasmacomponents.html PlasmaComponents API]. | |||
===PlasmaExtras=== | |||
import org.kde.plasma.extras 2.0 as PlasmaExtras | |||
PlasmaExtras provides visually integrated, semantic items, such as Title, Heading, Parapraph. These allow you to achieve a more consistent rendering of text content, with standardized sizing, spacing and text layout. PlasmaExtras also gives you a standard set of pre-made animations you can use in your application. | |||
KDE's API documentation has a comprehensive list of the [http://api.kde.org/frameworks-api/frameworks5-apidocs/plasma-framework/html/plasmaextracomponents.html PlasmaExtras API]. | |||
==Plasma Framework== | |||
The '''plasma-framework''' git repository contains the core libraries on which Plasma is based, applets, containments, the corona, as well as the SVG C++ classes. These are located in libplasma. | |||
Under src/declarativeimports in the git repository, you can find the source code for the Plasma* imports, the QtQuick style, the calendar import. under examples/, you will find a lot of useful code examples. You can use a tool such as ''grep'' to find usages of a specific type to learn how it can be used. | |||
Imports includes in plasma-framework are: | |||
* '''org.kde.plasma.core''' -- tooltips, svg items, themes, icons, units | |||
* '''org.kde.plasma.components''' -- plasma-styled QtQuick components, labels, buttons, controls, views, etc.; the basic widget set | |||
* '''org.kde.plasma.extras''' -- headings, titles, standard animations; these components can be used to improve the visual coherence across apps | |||
* '''org.kde.plasma.calendar''' -- a calendar widget | |||
==KDeclarative== | |||
KDeclarative contains two important parts: a library used by the C++ part of your application to integrate QML with KDE Frameworks specific features, and a series of QML imports that offer bindings to some of the Frameworks. | |||
The KDeclarative library contains hooks to provide translations through the i18n() functions. It also manages proper loading of system icons, and the runtime-resolution of paths to load platform-specific components depending on the form factor. This resolution mechanism is managed by the ''PLASMA_PLATFORM'' environmental variable, see [FIXME fallback mechanism]. | |||
There is also a number of interesting imports in KDeclarative: | |||
* '''org.kde.kcoreaddons''' -- provides data format conversion and [http://api.kde.org/frameworks-api/frameworks5-apidocs/kdeclarative/html/classKUserProxy.html KUser], a class providing information about the current user, such as name and avatar. | |||
* '''org.kde.kquickcontrolsaddons''' -- Advanced interaction with the clipboard, native QImage, QPixmap and QIcon Items, a non-event block mouse event listener, a plotter item, icon picker dialog, access to preferred applications for a give mimetype, opening of a system settings module. | |||
* '''org.kde.kwindowsystem''' -- Interaction with the window manager, handling of virtual desktops and activities. | |||
* '''org.kde.kio''' -- KRun allows you to start a new process. | |||
* '''org.kde.kquickcontrols''' -- Color button and key sequence input. | |||
* '''org.kde.draganddrop''' -- DragArea and DropArea for mimetype-aware drag and drop functionality. | |||
KDE's API documentation has a comprehensive list of the [http://api.kde.org/frameworks-api/frameworks5-apidocs/kdeclarative/html/annotated.html KDeclarative module]. | |||
==KPackage== | |||
The Package framework lets the user install and load packages of non binary content such as scripted extensions or graphic assets, as if they were traditional plugins. | |||
Among the C++ bits that take care of loading content from a package, you can also find the ''kpackagetool5'' program in the "kpackage" git repository. | |||
===Use case=== | |||
KPackage is a framework intended for applications that want to provide additional user-installable modules that don't involve native code, such as scripts, images and sounds. the framework provides a way to install, upgrade and uninstall compressed packages of such modules, via command line or via the GUI, and an easy integration with Get Hot New Stuff to search and install such addons from the internet. | |||
The framework is composed of a library, a plugin system and a command line tool. | |||
===Structure of a Package=== | |||
A KPackage-sompatible package file is a zip or tarball file that has in its root a "metadata.desktop" file that describes it and a "contents" subdirectory with the actual assets provided by the addon. | |||
The filesystem structure under contents is defined by the PackageStructure plugins (see [[Plasma/DeveloperGuide#Plugin System|Plugin System]]). | |||
* '''metadata.desktop''': freedesktop-compliant metadata file that can describe the package in question | |||
** ''Name'': User readable name for the addon | |||
** ''Name[countrycode]'': translation for the name in a certain language: packages in the KDE infrastructure will automatically get their name translated by the KDE i18n team | |||
** ''Comment'': An user readable description for the addon, translations are supported too | |||
** ''Icon'': freedesktop compatible icon name | |||
** ''X-KDE-PluginInfo-Author'': addon author name | |||
** ''X-KDE-PluginInfo-Email': addon author email | |||
** ''X-KDE-PluginInfo-Name'': an unique name for the addon: it will be installed under a folder with the same name. It is advised to use reverse domain notation, like org.kde.pluginname for the"official" ones, or com.companyname.pluginname, com.developername.pluginname | |||
** ''X-KDE-PluginInfo-Version'' | |||
** ''X-KDE-PluginInfo-Website'' | |||
** ''X-KDE-PluginInfo-Category'': depends from your application: for plasmoid packages see [[Plasma/DeveloperGuide#Choosing_a_Category|Choosing a Category]] | |||
** ''X-KDE-PluginInfo-License'': such as GPL2+, LGPL3.0 etc | |||
* '''contents/''': subdirectory containing the actual package files: the filesystem structure in this folder is defined in the PackageStructure plugin | |||
For Plasma package, commonly used paths in the package are: | |||
* '''contents/ui''': QtQuick code, basically all .qml files | |||
* '''contents/images''': Images and graphical elements | |||
===Commandline Tool=== | |||
The '''kpackagetool5''' command line tool can be used to install, upgrade or remove the application addons, either by the user from the terminal or automatically invoked by KNewStuff, provided a .knsrc file. | |||
InstallationCommand=kpackagetool5 -t type -i %f | |||
UninstallCommand=kpackagetool5 -t type -r %f | |||
Where '''type''' is the PackageStructure plugin that your application provides for its addons (see [[#Plugin System]]). | |||
===Library=== | |||
The following classes provide the basic entry points of the KPackage library. | |||
* Package -- Enapsulates a package object, provides access to metadata and contents of the package | |||
* PackageStructure -- Describes the structure of a type of package | |||
* PackageLoader -- Provides helpers for loading the package from disk | |||
More detailed documentation is available on [http://api.kde.org/frameworks-api/frameworks5-apidocs/kpackage/html/annotated.html api.kde.org]. | |||
===Plugin System=== | |||
What's allowed in the addons and where they are installed depends completely from the application and the specific use case, so the application should provide a plugin that implements a PackageStructure subclass that defines the installation root of the package and the allowed files and subdirectories that will be contained in the package | |||
The subclass can be completely internal in the application instead of a plugin, but in this case that type would not be accessible from the kpackagetool5 commandline tool. | |||
Line 29: | Line 278: | ||
==Creating the empty package== | ==Creating the empty package== | ||
You can create your app skeleton from a simple example, shipped with the plasma-framework source code from git: | |||
git clone git://anongit.kde.org/plasma-framework | |||
Then copy a basic example, which is going to be your new plasmoid. Let's call it "myplasmoid": | |||
cp -R plasma-framework/examples/developerguide/basic myplasmoid | |||
This gives you | |||
===filesystem structure=== | |||
* '''contents/''': all the files are under this subdirectory | |||
** '''ui/''': all the UI related files, such as the QML files go there, | |||
** '''config/''': KConfigXT xml file for the scheme of the allowed configuration values in the plasmoid and optional "config.qml" file that defines the categories of the applet configuration dialog | |||
** '''data/''': generic data files | |||
** '''images/''': extra image assets the plasmoid needs | |||
** '''screenshot.png''': a little preview thumbnail of the plasmoid | |||
The files can be specific for a particular platform or form factor as well. depending on the PLASMA_PLATFORM environment variable, the files can be searched also in the '''platformcontents/platformname''' subdirectory, for instance if the platform is "touch" searching for the file ''ui/Message.qml'' it will try: | |||
* '''platformcontents/touch/ui/Message.qml''': if not found, the existence of the file | |||
* '''contents/ui/Message.qml''' will be checked | |||
so platform specific content only needs to have the minimum amount possible of files changed | |||
The platform can also have multiple fallback steps, so for instance if PLASMA_PLATFORM is set to "touch,phone" the files will be searched for phone specific, then touch specific, then generic. Using the same example, | |||
* '''platformcontents/phone/ui/Message.qml''': if not found, the existence of the file | |||
* '''platformcontents/touch/ui/Message.qml''' will be checked; if not found either, the existence of the file | |||
* '''contents/ui/Message.qml''' will be checked | |||
===metadata.desktop=== | ===metadata.desktop=== | ||
The metadata.desktop file contains metadata such as the user-visible name ("Name"), a short description ("Comment"), the icon ("Icon") and a few other bits of information that will be used by the Plasma system. | |||
Next to the mostly self-explanatory keys, there is a number of interesting properties in the metadata file, which allow to place the Plasmoid in the notification area (the system tray), load it automatically when a DBus service become available, or associate it with a certain type of file (a "mimetype") for example. | |||
====Choosing a Category==== | |||
The following are acceptable known entries for Plasmoids. If your Plasmoid does not fall within one of the following categories, leave the category field empty (it will be automatically categorized under "Miscellaneous" for the time being) and contact the Plasma development team to have a suitable category added to the list (at which point you may then use that category). | |||
*'''Accessibility''' tools that help those with special needs or disabilities use their computer | |||
*'''Application Launchers''' application starters and file openers. | |||
*'''Astronomy''' anything to do with the night sky or other celestial bodies. | |||
*'''Date and Time''' clocks, calendars, scheduling, etc | |||
*'''Development Tools''' tools and utilities to aid software developers | |||
*'''Education''' teaching and educational aides | |||
*'''Environment and Weather''' add-ons that display information regarding the weather or other environmentally related data | |||
*'''Examples''' samples that are not meant for production systems | |||
*'''File System''' anything that operates on files or the file system as it's 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 amusements | |||
*'''Graphics''' for add-ons where displaying images, photos or graphical eye candy is the primary purpose | |||
*'''Language''' add-ons whose primary purpose is language related, such as dictionaries and translators. | |||
*'''Mapping''' geography and geographic data add-ons | |||
*'''Multimedia''' 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, etc | |||
*'''Utilities''' Useful tools like calculators | |||
*'''Windows and Tasks''' managers for application windows and/or tasks, such as taskbars | |||
===Installation=== | |||
There are two ways to install a Plasmoid. You can either use CMake or plasmapkg2 tool. While plasmapkg2 allows you to install a plasmoid or package manually, the CMake mechanism is used from the tarballs KDE provides. The CMake way is also what packagers expect. Fortunately, you don't have to be a build system expert to use CMake. | |||
If you want to install your Plasmoid using [https://techbase.kde.org/Development/Tutorials/CMake CMake], there are some macros you get when you use the Plasma framework in your source code. | |||
In your CMakeLists.txt file, a line like this will install the plasmoid as a Plasmoid or Plasma/Applet: | |||
plasma_install_package(basic org.kde.example.developerguide.basic) | |||
The first argument is the directory name containing the metadata.desktop file and the contents directory, the second argument is the plugin name. The plasma_install_package() CMake macro defaults to Plasma/Applets, if you want to install something different, you'll need to specify the subdirectory. | |||
The KPackage framework contains a similar macro for generic packages. For a QML-based System Settings module, something like this will install the directory "package" as "kcm_settings_devel" under the kcms subdirectory (for example into /share/kpackage/kcms/kcm_settings_devel): | |||
kpackage_install_package(package kcm_settings_devel kcms) | |||
With plasmapkg2, the same can be achieved with this command: | |||
plasmapkg2 -g -i package | |||
- | |||
Note the -g switch, which will install the package into the system location (on a package-based system, usually somewhere under /usr). If you want to install the plasmoid locally, into your homedir, just leave the -g out. | |||
==Starting the Code== | ==Starting the Code== | ||
Line 53: | Line 364: | ||
===Plasma API=== | ===Plasma API=== | ||
- kdeclarative's useful stuff: kcmOpen? more useful imports | - kdeclarative's useful stuff: kcmOpen? more useful imports | ||
- general guidelines: units, iconSizes, | |||
===Advanced: Plasmoids using C++=== | |||
When possible write a plasmoid using only QML, with imports that can be easily found on most systems, that will ensure that your plasmoid can be shipped and installed without compilation involved, such as via services like Get Hot New Stuff. | |||
However, sometimes it's not possible and you need to perform some operations for which you need the power of native code. Plasma offers an API for adding a custom, private C++ plugin in your plasmoid. | |||
The package/scripted part of a plasmoid written partly in C++ is identical to a pure QML plasmoid. | |||
A C++ plugin is provided as well alongside the scripted package, so in this case the plasmoid cannot be distributed via Get Hot New Stuff, but will need to use the distribution's packaging system. | |||
The plugin will implement a subclass of the Plasma::Applet class from Plasma-framework (or Plasma::Containment if the plasmoid implements a container such as a desktop or a panel) | |||
(TODO: documentation on how to write KPluginLoader-compatible C++ plugins?) | |||
The plugin should be exported with the same plugin name as the name indicated in the metadata.desktop file, and installed in the '''plasma/applets''' subdirectory of the KF5 binary plugins directory. | |||
=Tools= | |||
Knowing your toolbox can ease many development tasks. In this section, we introduce a number of useful tools that make developing Plasma apps more productive. | |||
==Editor and Commandline== | |||
Usually, you can develop Plasmoids with your favorite text editor. Some editor are a bit more suitable than others, however. KDE's Kate editor provides all the basics you need, it comes with good QML code highlighting and project management, it is nimble, fast and powerful. KDevelop is a more full-featured alternative that provides you deep language integration features and more advanced development tools. If you're used to working Qt Creator, that one will also work fine. | |||
In the following, we assume a relatively basic code editor, Kate. | |||
You'll find yourself working on the command line a bit, since that's the easiest way to list and install packages. Any terminal emulator will work fine here. If you're looking for a good one, try "Konsole". | |||
==KAppTemplate== | |||
KAppTemplate is an application that lets you create skeletons for all kinds of applications. Plasma provides app templates for different purposes, for example a simple QML Plasmoid, and a Plasmoid that is extended using C++. | |||
==Installation: kpackagetool5== | |||
* relation to plasmapkg2 | |||
* which one to use? | |||
==Previewer: plasmoidviewer== | |||
==Theme Viewer: plasmathemeexplorer== | |||
plasmathemeexplorer allows you to view theme elements that you can re-use in your application. It provides previews for installed themes and you can switch between them. In the top-right corner, you find a link to the [https://techbase.kde.org/Development/Tutorials/Plasma5/ThemeDetails theme documentation], which lists elements contained in Plasma themes. | |||
plasmathemeexplorer is shipped in the plasma-sdk git repository, on Debian, the package name is "plasma-sdk". | |||
==Icon Viewer: Cuttlefish== | |||
Cuttlefish is designed to render the icons as closely as possible to how Plasma is handling them, so it provides a better idea of how the icons will look in use, than a simple image viewer does. | |||
Cuttlefish allows you to preview and search icons. You can search installed icons, find information about available sizes and preview icons in different sizes. During development, you may find the option to copy the icon name, or QML code producing an icon item useful. | |||
Cuttlefish is shipped in the plasma-sdk git repository, on Debian, the package name is "plasma-sdk". | |||
=Display and Rendering= | |||
==Theming== | |||
Plasma provides a powerful theming engine, based on SVG graphics. Plasma's theming provides the following features: | |||
* Access to a complete set of graphical elements for application user interfaces | |||
* Coloring for different elements of the user interface | |||
* Global and application-specific themes | |||
* Dynamic coloring of elements at runtime | |||
The [https://techbase.kde.org/Development/Tutorials/Plasma5/ThemeDetails Theme Guide] provides an extensive list of available theme elements, and how to create them. | |||
Plasma Theme's elements are usually used together with PlasmaCore.Svg and PlasmaCore.FrameSvg item classes. | |||
==ColorScope== | |||
Plasma apps can change the color of specific sub-trees. This is achieved using the ColorScope type, which is available in the [[#PlasmaCore]] import. ColorScope can be used as follows: | |||
PlasmaCore.ColorScope { | |||
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup | |||
Rectangle { | |||
color: PlasmaCore.ColorScope.backgroundColor | |||
anchors.fill: parent | |||
} | |||
} | |||
==Image Display== | |||
Scalable vector graphics (SVG) are the preferred way to provide graphics with your code, as they allow scalable UI elements. | |||
The Plasma Svg* types are highly optimized, avoid re-rendering the SVG as much as possible, and cache pre-rendered pixmaps. Internally, textures are shared as much as possible and offloaded onto the GPU. These classes are highly efficient and work well across a wide range of display DPI. | |||
For displaying bitmap images, e.g. photos in your app, use the QtQuick Image type. Use this wisely, as loading images can take lots of memory and disk access. Use the asynchronous mode if possible as to not freeze your UI. | |||
==Pixel density and DPI== | |||
==Wayland vs. X11== | |||
=Supporting Multiple Devices= | |||
==Touch-friendliness== | |||
==Layout Considerations== | |||
(responsive vs. layout switching, portrait vs. landscape, laptop vs. tablet vs. phone )== | |||
==Formfactors== | |||
A plasmoid can provide a suggestion which type of device it supports, or it makes sense on. This allows to provide per-device specific Plasmoids. The Kickoff application launcher, for example, is written for desktops, it is not optimized for use on touchscreens and might show interaction problems. To allow only showing or loading Plasmoids specific to a device, the "X-KDE-FormFactors" key is used in the metadata. Kickoff, for example has this line in its metadata.desktop file: | |||
X-KDE-FormFactors=desktop | |||
A phone or tablet specific component would use: | |||
X-KDE-FormFactors=handset,tablet | |||
Developers are encouraged to add this metadata to their metadata.desktop files. Simply adding a line like the FormFactors one in the above examples will help to offer the application on different devices. This mechanism is implemented in KPluginMetada, so at a fairly low-level. This means that this feature can be used in all kinds of cases: application launcher .desktop files, plugins for all purposes. It depends on the application listing or loading the plugins how the filtering is done exactly. Plasma desktop's systemtray Plasmoid for example shows only plugins without this key, and if the key exists it has to be or contain "desktop". A list of values supported separated by "," (comma), as well as single keys. | |||
More information about formfactor support can be found [http://vizzzion.org/blog/2015/07/convergence-through-divergence/ in this article]. | |||
==Touch-Specific Overrides== | |||
=Workspace Integration= | |||
==Mimetypes== | |||
==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 Kickoff or Kicker menu in the Plasma desktop panel, you'll see that a number of different Plasmoids are offered here as alternatives, these are the Plasmoids installed on the system which specify "X-Plasma-Provides=org.kde.plasma.launchermenu"; so they're telling the system that they are application launchers. The media controller Plasmoid, for example, uses: | |||
X-Plasma-Provides=org.kde.plasma.multimediacontrols | |||
These "Provides" are in fact arbitrary, so you can choose your own here. The field accepts multiple values separated by ",". | |||
Here are some possible values that are used throughout Plasma: | |||
* "org.kde.plasma.multimediacontrols" -- Multimedia controls | |||
* "org.kde.plasma.time" -- Clocks | |||
* "org.kde.plasma.date" -- Calendars | |||
* "org.kde.plasma.time,org.kde.plasma.date" -- Clocks with calendars | |||
* "org.kde.plasma.powermanagement" -- Power management (e.g. battery indicator) | |||
* "org.kde.plasma.notifications" -- Notifications | |||
* "org.kde.plasma.removabledevices" -- Removable devices, auto mounter, etc. | |||
* "org.kde.plasma.multitasking" -- Task switchers | |||
* "org.kde.plasma.virtualdesktops" -- Virtual desktop switcher | |||
* "org.kde.plasma.activities" -- Switchers for Plasma activities | |||
* "org.kde.plasma.trash" -- Trash / file deletion | |||
==Notification Area (Systemtray)== | |||
The "Media Controller" Plasmoid, (shipped in the kde-workspace repository under applets/mediacontroller) serves as a good example, since it uses most of these features. Its metadata contains the following: | |||
X-Plasma-NotificationArea=true | |||
X-Plasma-NotificationAreaCategory=ApplicationStatus | |||
X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.* | |||
Let's look at these keys one by one. | |||
By specifying | |||
X-Plasma-NotificationArea=true | |||
X-Plasma-NotificationAreaCategory=ApplicationStatus | |||
this Plasmoid will be found by the systemtray Plasmoid (lower left in the default panel of Plasma desktop) and included in it by default. It's prudent for the Plasmoid to also set the "X-Plasma-NotificationAreaCategory" key, allowed values are: | |||
* "ApplicationStatus" -- indicates that this item represents an active application | |||
* "Hardware" -- 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. | |||
Note that these categories are only for the sorting and placement in the notification area, the "general" category of a Plasmoid is arbitrary to this key. | |||
===Plasmoid Status=== | |||
A Plasmoid running in the systemtray can indicate its status, it does so from the QML code by setting the global plasmoid.status. Possible values are: | |||
* plasmoid.status = PlasmaCore.Types.ActiveStatus -- The Plasmoid is useful to have on the screen, either because it has something to show, or should be accessible easily. | |||
* plasmoid.status = PlasmaCore.Types.PassiveStatus -- Nothing interesting is going on, the systemtray will usually hide these Plasmoid in the popup as to have them not take up valuable space in the panel. | |||
* plasmoid.status = PlasmaCore.Types.NeedsAttentionStatus -- Something special is going on, for example a highlight in a messenger app, or an important system event. | |||
* plasmoid.status = PlasmaCore.Types.Hidden -- The Plasmoid is entirely invisible and won't even be loaded in the system tray. | |||
==DBus autolaunched Plasmoids== | |||
Plasmoids can be loaded and unloaded in the systemtray automatically when a DBus service becomes avaiable or is stopped. This is very convenient to load Plasmoids automatically, so the user doesn't have to explicitely go to the notification area settings and enable or remove a Plasmoid, it just happens automatically. This is for example used by the Media Controller Plasmoid, which is auto-loaded as soon as an application starts offering the "org.mpris.MediaPlayer2" DBus service in the session. As you can see, this key accepts wildcards, which makes it a bit easier to match DBus names. | |||
This key can also be very useful to avoid having a Plasmoid loaded when it's unnecessary, so it can help to avoid visual clutter and wasted memory. | |||
This function is used like this for the MPRIS2 interface: | |||
X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.* | |||
The "Networks" Plasmoid, which is used to control NetworkManager uses this: | |||
X-Plasma-DBusActivationService=org.freedesktop.NetworkManager | |||
==Settings Modules== | |||
* ServiceType=KCModule | |||
* C++ KCMs vs | |||
* plasma-settings | |||
* systemsettings | |||
=Translations= | |||
==i18n() & friends== | |||
* Which strings to translate? | |||
* How to use i18n() | |||
* How does i18n() become available? | |||
* link to i18n docs | |||
=Localization= | |||
* units, | |||
* date & time formats | |||
* KLocale | |||
==Testing Translations== | |||
* making sure i18n is set up correctly: checklist | |||
* how to use x-test | |||
=Distribution= | |||
==Plasmoid Package== | |||
Simple Plasma apps without compiled code can be passed around as .plasmoid packages. These are essentially zip files with a specific content structure. Plasmoid packages can be installed using "plasmapkg2" or "kpackagetool5". | |||
==Appstream Metadata== | |||
As more and more tool make use of appstream metadata, adding this to your project allows users to find your app more easily. | |||
* File format, etc. | |||
* Guidelines | |||
==Get Hot New Stuff== | |||
==Linux Distributions== | |||
==Android== | |||
* mobilecomponents light | |||
* apk creation and deployment | |||
==Upstreaming Code== | |||
The ultimate way of distributing your app may be to ship it with the official Plasma pacakges and develop it further together with other developers. Plasma is created in an open development process. You can take part in it. | |||
If you think your new app or improvement to an existing code-base would be a sensible addition to the official Plasma code, please get in contact with us. | |||
* Phabricator | |||
= | =Contacting the Plasma Team= | ||
* bugs.kde.org | |||
* mailinglist | |||
* IRC | |||
* Plasma forums | |||
Latest revision as of 09:34, 18 April 2023
The Ultimate Guide to Plasma Development
Introduction
This guide explains the basic steps to build a fully integrated application. This guide is targeted at developers with basic knowledge of QML. It guides through the complete process of developing an application from scratch.
Plasma allows to write applications that work well on different form factors or devices. Plasma is built to adapt to different input methods (mouse, touch, keyboard, etc.) screen sizes and to be resolution-independent. Most of the information in this guide is applicable to all form factors. Topics that may differ for different form factors are indicated as such.
A well-architectured Plasma application will be able to offer different user interface per form factor. For desktops, a landscape layout with quite a lot of space for display and interaction can be used, while the same underlying components in a different, portrait-oriented layout can be used to present the user interface on a phone. A tablet user interface may use either, or combine the components in yet another fashion to make the best use of available screen real estate. In general, Plasma widgets such as buttons and other controls, work well on touch, mouse and with keyboard input, but can be switched at application start or runtime, transparently to the application using it.
In this guide, you will learn how to use all these features to create an application that works well on wide range of target devices.
Is this guide for you?
Plasma makes extensive use of QtQuick and QML to write the user interface and business logic of your application. Basic understanding of QtQuick is necessary, though Plasma is also a great environment to learn by doing it. This guide targets developers that are familiar with common programming paradigms, but do not have special knowledge of the Plasma APIs, libraries and mechanisms to solve certain problems.
Many things can be implemented without knowing or being able to write C++ code. Plasma provides high-level APIs to solve a great number of tasks and provide common functionality such as retrieving data, displaying information as well as widgets for common interaction patterns and themes and artwork to make your app beautiful and consistent.
In some cases, or in more complex apps, you may extend the functionality by writing a C++ plugin (or "import"). This allows to access custom functionality in your system, leverage an existing library, or move logic into a type-safe language that is easier to test (using unit tests, for example) or performs better.
In this guide, we assume that you can find your way around in a command-line based environment and be familiar with tools such as git and code editors.
Apps, Widgets and Plasmoids?
Plasma offers user interfaces for applications as well as workspaces (the environment you run your app in, the desktop, or phone user interface offering a launcher, task switcher, settings, for example).
The workspace can be extended using Plasma Widgets, or in more technical terms, plasmoids. A plasmoid is a package containing metadata, images, configuration defaults and the QML files that make up the UI. Most of Plasma Desktop's functionality is offered using plasmoids. The application launcher in the bottom-left corner is a plasmoid, the task manager in the panel which allows you to switch between running applications is a plasmoid, many of the widgets in the notification area on both, Plasma Mobile and Plasma Desktop are plasmoids. You can also put Plasmoids on your desktop, the analog clock widgets and the "post-it" notes plasmoids are popular examples.
Apps are loaded from packages as well. The main difference, aside from the layout probably being different, is that instead of loading the QML code inside a panel, or widget on the desktop, the application is loaded into its own window. (There are certain API features which may only make sense in the workspace, but those are usually implementation details that can be ignored where they don't make sense.)
An app or a plasmoid would typically load the main layout for the window, popup or widget from a QML file, and then use imports to load additional libraries or make APIs available from within the applications QML code.
An App in 5 Easy Steps
Creating a simple application in Plasma is very easy. You can try the following quickguide to create your first little app.
- Download a template
- Adjust the metadata
- Edit the code
- Install the app
- Start and try it
Download a Template
You can create your own plasmoid from a simple example, shipped with the plasma-framework source code from git:
git clone https://invent.kde.org/frameworks/plasma-framework
Then copy a basic example, which is going to be your new plasmoid. Let's call it "myplasmoid":
cp -R plasma-framework/examples/developerguide/basic myplasmoid
Alternatively, you can create a new Plasmoid using #KAppTemplate. Pick Plasmoid / QML Plasmoid / Plasma QML Applet to generate your app skeleton for this example.
Adjust the Metadata
Open myplasmoid/metadata.desktop with your favorite text editor (mine is "Kate"):
kate myplasmoid/metadata.desktop
and change the Name and Comment fields. These will identify your Plasmoid in the widget chooser and is the default window name.
Name=My Plasmoid Comment=Plasma Hacker 101
You can also pick a nice icon here. Use for example the cuttlefish tool to pick a nice one.
Now make sure that the line containing the X-KDE-PluginInfo-Name contains a unique plugin id:
X-KDE-PluginInfo-Name=org.example.myplasmoid
The plugin name is used to identify the plugin on the system, make sure you pick a unique plugin name. It's advised to use a reverse domain name pattern. The plugin name will also be used in the installation path.
Edit the QML code
In order to change the template and write your own code, open its main QML file and hack away.
kate myplasmoid/contents/ui/main.qml
Play around with it a bit, try to change something, add a few new things, make yourself comfortable with it. For simple, first testing, you can also just skip this step for now, install as is to see if everything works in a clean environment and get back to actually changing the code later on.
Install the App
To install a plasmoid, you can use the "kpackagetool5" program:
kpackagetool5 -i myplasmoid
This will install the plasmoid locally in your home directory, into ~/.local/share/kpackage/genericqml/org.example.myplasmoid on my system -- your installation path may vary. To update an already-installed package on your system, use
kpackagetool5 -u myplasmoid
to remove it, use
kpackagetool5 -r myplasmoid
Start your App
You can now start your brand-new app using kpackagelauncherqml:
kpackagelauncherqml -a org.example.myplasmoid
And a window will show up with your application. You can now start hacking.
Requirements Analysis & Design
The first step to building an application is to analyze the problem that you want to solve and come up with a way how you can solve this problem. This allows you to make a list of required features for your application. A clear purpose and understanding of what want to achieve and how you want to get there helps you to make smart choices regarding features, their design and presentation. It can also avoid bloat and helps to set priorities for the app's development work.
In the design phase, you care about three things: interaction, visual and technical design. The interaction design is the workflow for the user. You can visualize this in a flowchart, for example. This flowchart should give you an idea of which steps or views you want to present to the user, and which options should be available in each of them.
In the visual design phase, you draw you user interfaces, views, screens and plan how things are laid out on screen. You can use pen and paper for it, but also tools like inkscape and the Plasma mockup toolkit. KDE's Human Interface Guidelines provide many useful tips how you can create intuitive user interfaces with a high level of consistency.
We encourage you to present your ideas, concepts and design and discuss it, for example in the KDE Forums or on the [FIXME Plasma Mailinglist] to refine your design further and get input from more points of view.
You can find more information about design workflows, tools and resources on this page.
In this guide, you will learn about the implementation of your design. You will come across many features that may be useful to use in your app. Try to not make the mistake to implement things that do not directly contribute to the goal of your app. Having a clear idea of the purpose and design of your app helps to prevent scope creep, bloat and a less effective app. Many of the features described are optional, pick only the ones you need. This guide gives you an overview over what kind of tools there are, pick wisely.
Software Stack
The software stack consists of a number of components that are interesting for application development. This chapter gives an overview of the most important pieces to consider.
QML & QtQuick
Wikipedia has an excellent description
QML (Qt Meta Language or Qt Modeling Language) is a user interface markup language. It is a JavaScript-based, declarative language for designing user interface–centric applications. It is part of Qt Quick, the UI creation kit within the Qt framework. QML is used for desktop and mobile applications where touch input, fluid animations (60 FPS) and user experience are crucial. QML documents describe an object tree of elements. QML elements shipped with Qt are a sophisticated set of building blocks, graphical (e.g., rectangle, image) and behavioral (e.g., state, transition, animation). These elements can be combined to build components ranging in complexity from simple buttons and sliders, to complete internet-enabled programs. QML elements can be augmented by standard JavaScript both inline and via included .js files. Elements can also be seamlessly integrated and extended by C++ components using the Qt framework. QML is the language; its runtime is the Javascript V4 engine and Qt Quick is the scenegraph-based UI framework. (slightly redacted for clarity purposes)
Your QtQuick code "tree" describes an object-tree structure of visual items, such as images or text and non-visual items, such as data models or object collections. The visual structure is displayed in an OpenGL scenegraph. This allows us to manipulate and compose visual items in the UI directly on the graphics card. This leads to high-performance graphics on the one, and energy savings on the other hand. Graphics hardware is much more efficient for graphics manipulation than the central system processor.
QtQuick code is loaded at runtime and just-in-time compiled into the javascript's engine's binary representation on application startup.
QtQuick makes it very easy to create attractive user interfaces with smooth animations. QtQuick UIs support multitouch, mouse and keyboard inputs, allow handling of gestures. Most importantly, QtQuick is easy to write and change, and it is an intuitive language very well suited for creating modern UI with a gentle learning curve.
On top of these fundamentals, you will want more high-level functionality. This is where "imports" enter the picture.
Imports
QtQuick applications, such as your Plasma app, can be extended using imports. An import is a Qt plugin that is dynamically loaded at runtime. imports can consist of QML items (used as custom types once imported) or compiled libraries that export C++ functions and objects (often QObject based) to the QML runtime. Import plugins can contain QML files, a C++ plugins or both. QML imports are also often referred to as components.
Imports allow you to use libraries from QML and javascript and to re-use or share code between different applications, for example across packages. QtQuick items 'understand' a useful number of Qt's standard types, such as QString, QAbstractItemModel, QColor, QDate, etc.. Builtin javascript types such as string, int, float are also supported. You can write an import yourself, though most of the time you will find yourself using already existing imports.
In your app, you can import additional functionality like this:
import QtQuick 2.3 import org.kde.plasma.components 2.0 as PlasmaComponents
This imports QtQuick's standard items into the global namespace, that means you can now use types like Item {}. The second line imports the org.kde.plasma.components plugin into the PlasmaComponents QML namespace. This means you refer to its types like this:
PlasmaComponents.Label { text: "Ultimate Plasma Hacking" /* ... */ }
It's recommended to always import QtQuick into the global namespace and to import other modules into their respective namespaces, such as in this case PlasmaComponents. This also improves code readability and makes it easier to debug since the code tells us where to look or where something actually comes from. It also avoids naming clashes -- there may be other UI components using the same name for a different element. This can lead to your app refusing to start or undetected runtime errors.
Commonly useful imports are:
PlasmaCore
import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore provides lower-level functionality for your app:
- units for DPI support, units.gridUnit is commonly used to describe sizes, gridUnits provide consistent sizing across the complete spectrum and has been tested to work between 100 and 500 DPI.
- IconItem for scalable rendering of themed icons.
- SvgItem and its friends allow to you load and use scalable SVG graphics in your UI. SvgItem and friends are backed by a rendering cache and offload as much as possible to the GPU. FrameSvgItem provides a correctly scaled and efficient mechanism to render and resize frame-like SVG graphics with correct sizing of corners.
- #ColorScope allows you to change the color scheme for a part of your application in a consistent way.
- Window thumbnails, tooltips, bindings for DataEngines, data models, and more.
KDE's API documentation has a comprehensive list of PlasmaCore's API.
PlasmaComponents
import org.kde.plasma.components 2.0 as PlasmaComponents
PlasmaCore provides widgets, such as buttons, sliders and scrollviews for your app.
KDE's API documentation has a comprehensive list of the PlasmaComponents API.
PlasmaExtras
import org.kde.plasma.extras 2.0 as PlasmaExtras
PlasmaExtras provides visually integrated, semantic items, such as Title, Heading, Parapraph. These allow you to achieve a more consistent rendering of text content, with standardized sizing, spacing and text layout. PlasmaExtras also gives you a standard set of pre-made animations you can use in your application.
KDE's API documentation has a comprehensive list of the PlasmaExtras API.
Plasma Framework
The plasma-framework git repository contains the core libraries on which Plasma is based, applets, containments, the corona, as well as the SVG C++ classes. These are located in libplasma. Under src/declarativeimports in the git repository, you can find the source code for the Plasma* imports, the QtQuick style, the calendar import. under examples/, you will find a lot of useful code examples. You can use a tool such as grep to find usages of a specific type to learn how it can be used.
Imports includes in plasma-framework are:
- org.kde.plasma.core -- tooltips, svg items, themes, icons, units
- org.kde.plasma.components -- plasma-styled QtQuick components, labels, buttons, controls, views, etc.; the basic widget set
- org.kde.plasma.extras -- headings, titles, standard animations; these components can be used to improve the visual coherence across apps
- org.kde.plasma.calendar -- a calendar widget
KDeclarative
KDeclarative contains two important parts: a library used by the C++ part of your application to integrate QML with KDE Frameworks specific features, and a series of QML imports that offer bindings to some of the Frameworks.
The KDeclarative library contains hooks to provide translations through the i18n() functions. It also manages proper loading of system icons, and the runtime-resolution of paths to load platform-specific components depending on the form factor. This resolution mechanism is managed by the PLASMA_PLATFORM environmental variable, see [FIXME fallback mechanism].
There is also a number of interesting imports in KDeclarative:
- org.kde.kcoreaddons -- provides data format conversion and KUser, a class providing information about the current user, such as name and avatar.
- org.kde.kquickcontrolsaddons -- Advanced interaction with the clipboard, native QImage, QPixmap and QIcon Items, a non-event block mouse event listener, a plotter item, icon picker dialog, access to preferred applications for a give mimetype, opening of a system settings module.
- org.kde.kwindowsystem -- Interaction with the window manager, handling of virtual desktops and activities.
- org.kde.kio -- KRun allows you to start a new process.
- org.kde.kquickcontrols -- Color button and key sequence input.
- org.kde.draganddrop -- DragArea and DropArea for mimetype-aware drag and drop functionality.
KDE's API documentation has a comprehensive list of the KDeclarative module.
KPackage
The Package framework lets the user install and load packages of non binary content such as scripted extensions or graphic assets, as if they were traditional plugins. Among the C++ bits that take care of loading content from a package, you can also find the kpackagetool5 program in the "kpackage" git repository.
Use case
KPackage is a framework intended for applications that want to provide additional user-installable modules that don't involve native code, such as scripts, images and sounds. the framework provides a way to install, upgrade and uninstall compressed packages of such modules, via command line or via the GUI, and an easy integration with Get Hot New Stuff to search and install such addons from the internet.
The framework is composed of a library, a plugin system and a command line tool.
Structure of a Package
A KPackage-sompatible package file is a zip or tarball file that has in its root a "metadata.desktop" file that describes it and a "contents" subdirectory with the actual assets provided by the addon. The filesystem structure under contents is defined by the PackageStructure plugins (see Plugin System).
- metadata.desktop: freedesktop-compliant metadata file that can describe the package in question
- Name: User readable name for the addon
- Name[countrycode]: translation for the name in a certain language: packages in the KDE infrastructure will automatically get their name translated by the KDE i18n team
- Comment: An user readable description for the addon, translations are supported too
- Icon: freedesktop compatible icon name
- X-KDE-PluginInfo-Author: addon author name
- X-KDE-PluginInfo-Email': addon author email
- X-KDE-PluginInfo-Name: an unique name for the addon: it will be installed under a folder with the same name. It is advised to use reverse domain notation, like org.kde.pluginname for the"official" ones, or com.companyname.pluginname, com.developername.pluginname
- X-KDE-PluginInfo-Version
- X-KDE-PluginInfo-Website
- X-KDE-PluginInfo-Category: depends from your application: for plasmoid packages see Choosing a Category
- X-KDE-PluginInfo-License: such as GPL2+, LGPL3.0 etc
- contents/: subdirectory containing the actual package files: the filesystem structure in this folder is defined in the PackageStructure plugin
For Plasma package, commonly used paths in the package are:
- contents/ui: QtQuick code, basically all .qml files
- contents/images: Images and graphical elements
Commandline Tool
The kpackagetool5 command line tool can be used to install, upgrade or remove the application addons, either by the user from the terminal or automatically invoked by KNewStuff, provided a .knsrc file.
InstallationCommand=kpackagetool5 -t type -i %f UninstallCommand=kpackagetool5 -t type -r %f
Where type is the PackageStructure plugin that your application provides for its addons (see #Plugin System).
Library
The following classes provide the basic entry points of the KPackage library.
- Package -- Enapsulates a package object, provides access to metadata and contents of the package
- PackageStructure -- Describes the structure of a type of package
- PackageLoader -- Provides helpers for loading the package from disk
More detailed documentation is available on api.kde.org.
Plugin System
What's allowed in the addons and where they are installed depends completely from the application and the specific use case, so the application should provide a plugin that implements a PackageStructure subclass that defines the installation root of the package and the allowed files and subdirectories that will be contained in the package The subclass can be completely internal in the application instead of a plugin, but in this case that type would not be accessible from the kpackagetool5 commandline tool.
Developing a Plasmoid
Creating the empty package
You can create your app skeleton from a simple example, shipped with the plasma-framework source code from git:
git clone git://anongit.kde.org/plasma-framework
Then copy a basic example, which is going to be your new plasmoid. Let's call it "myplasmoid":
cp -R plasma-framework/examples/developerguide/basic myplasmoid
This gives you
filesystem structure
- contents/: all the files are under this subdirectory
- ui/: all the UI related files, such as the QML files go there,
- config/: KConfigXT xml file for the scheme of the allowed configuration values in the plasmoid and optional "config.qml" file that defines the categories of the applet configuration dialog
- data/: generic data files
- images/: extra image assets the plasmoid needs
- screenshot.png: a little preview thumbnail of the plasmoid
The files can be specific for a particular platform or form factor as well. depending on the PLASMA_PLATFORM environment variable, the files can be searched also in the platformcontents/platformname subdirectory, for instance if the platform is "touch" searching for the file ui/Message.qml it will try:
- platformcontents/touch/ui/Message.qml: if not found, the existence of the file
- contents/ui/Message.qml will be checked
so platform specific content only needs to have the minimum amount possible of files changed
The platform can also have multiple fallback steps, so for instance if PLASMA_PLATFORM is set to "touch,phone" the files will be searched for phone specific, then touch specific, then generic. Using the same example,
- platformcontents/phone/ui/Message.qml: if not found, the existence of the file
- platformcontents/touch/ui/Message.qml will be checked; if not found either, the existence of the file
- contents/ui/Message.qml will be checked
metadata.desktop
The metadata.desktop file contains metadata such as the user-visible name ("Name"), a short description ("Comment"), the icon ("Icon") and a few other bits of information that will be used by the Plasma system. Next to the mostly self-explanatory keys, there is a number of interesting properties in the metadata file, which allow to place the Plasmoid in the notification area (the system tray), load it automatically when a DBus service become available, or associate it with a certain type of file (a "mimetype") for example.
Choosing a Category
The following are acceptable known entries for Plasmoids. If your Plasmoid does not fall within one of the following categories, leave the category field empty (it will be automatically categorized under "Miscellaneous" for the time being) and contact the Plasma development team to have a suitable category added to the list (at which point you may then use that category).
- Accessibility tools that help those with special needs or disabilities use their computer
- Application Launchers application starters and file openers.
- Astronomy anything to do with the night sky or other celestial bodies.
- Date and Time clocks, calendars, scheduling, etc
- Development Tools tools and utilities to aid software developers
- Education teaching and educational aides
- Environment and Weather add-ons that display information regarding the weather or other environmentally related data
- Examples samples that are not meant for production systems
- File System anything that operates on files or the file system as it's 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 amusements
- Graphics for add-ons where displaying images, photos or graphical eye candy is the primary purpose
- Language add-ons whose primary purpose is language related, such as dictionaries and translators.
- Mapping geography and geographic data add-ons
- Multimedia 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, etc
- Utilities Useful tools like calculators
- Windows and Tasks managers for application windows and/or tasks, such as taskbars
Installation
There are two ways to install a Plasmoid. You can either use CMake or plasmapkg2 tool. While plasmapkg2 allows you to install a plasmoid or package manually, the CMake mechanism is used from the tarballs KDE provides. The CMake way is also what packagers expect. Fortunately, you don't have to be a build system expert to use CMake.
If you want to install your Plasmoid using CMake, there are some macros you get when you use the Plasma framework in your source code.
In your CMakeLists.txt file, a line like this will install the plasmoid as a Plasmoid or Plasma/Applet:
plasma_install_package(basic org.kde.example.developerguide.basic)
The first argument is the directory name containing the metadata.desktop file and the contents directory, the second argument is the plugin name. The plasma_install_package() CMake macro defaults to Plasma/Applets, if you want to install something different, you'll need to specify the subdirectory.
The KPackage framework contains a similar macro for generic packages. For a QML-based System Settings module, something like this will install the directory "package" as "kcm_settings_devel" under the kcms subdirectory (for example into /share/kpackage/kcms/kcm_settings_devel):
kpackage_install_package(package kcm_settings_devel kcms)
With plasmapkg2, the same can be achieved with this command:
plasmapkg2 -g -i package
Note the -g switch, which will install the package into the system location (on a package-based system, usually somewhere under /usr). If you want to install the plasmoid locally, into your homedir, just leave the -g out.
Starting the Code
main.qml stuffz
- Layouts - plasmoid object - fullRepresentation vs. popup
Plasma API
- kdeclarative's useful stuff: kcmOpen? more useful imports - general guidelines: units, iconSizes,
Advanced: Plasmoids using C++
When possible write a plasmoid using only QML, with imports that can be easily found on most systems, that will ensure that your plasmoid can be shipped and installed without compilation involved, such as via services like Get Hot New Stuff.
However, sometimes it's not possible and you need to perform some operations for which you need the power of native code. Plasma offers an API for adding a custom, private C++ plugin in your plasmoid.
The package/scripted part of a plasmoid written partly in C++ is identical to a pure QML plasmoid. A C++ plugin is provided as well alongside the scripted package, so in this case the plasmoid cannot be distributed via Get Hot New Stuff, but will need to use the distribution's packaging system.
The plugin will implement a subclass of the Plasma::Applet class from Plasma-framework (or Plasma::Containment if the plasmoid implements a container such as a desktop or a panel) (TODO: documentation on how to write KPluginLoader-compatible C++ plugins?) The plugin should be exported with the same plugin name as the name indicated in the metadata.desktop file, and installed in the plasma/applets subdirectory of the KF5 binary plugins directory.
Tools
Knowing your toolbox can ease many development tasks. In this section, we introduce a number of useful tools that make developing Plasma apps more productive.
Editor and Commandline
Usually, you can develop Plasmoids with your favorite text editor. Some editor are a bit more suitable than others, however. KDE's Kate editor provides all the basics you need, it comes with good QML code highlighting and project management, it is nimble, fast and powerful. KDevelop is a more full-featured alternative that provides you deep language integration features and more advanced development tools. If you're used to working Qt Creator, that one will also work fine.
In the following, we assume a relatively basic code editor, Kate.
You'll find yourself working on the command line a bit, since that's the easiest way to list and install packages. Any terminal emulator will work fine here. If you're looking for a good one, try "Konsole".
KAppTemplate
KAppTemplate is an application that lets you create skeletons for all kinds of applications. Plasma provides app templates for different purposes, for example a simple QML Plasmoid, and a Plasmoid that is extended using C++.
Installation: kpackagetool5
- relation to plasmapkg2
- which one to use?
Previewer: plasmoidviewer
Theme Viewer: plasmathemeexplorer
plasmathemeexplorer allows you to view theme elements that you can re-use in your application. It provides previews for installed themes and you can switch between them. In the top-right corner, you find a link to the theme documentation, which lists elements contained in Plasma themes.
plasmathemeexplorer is shipped in the plasma-sdk git repository, on Debian, the package name is "plasma-sdk".
Icon Viewer: Cuttlefish
Cuttlefish is designed to render the icons as closely as possible to how Plasma is handling them, so it provides a better idea of how the icons will look in use, than a simple image viewer does.
Cuttlefish allows you to preview and search icons. You can search installed icons, find information about available sizes and preview icons in different sizes. During development, you may find the option to copy the icon name, or QML code producing an icon item useful.
Cuttlefish is shipped in the plasma-sdk git repository, on Debian, the package name is "plasma-sdk".
Display and Rendering
Theming
Plasma provides a powerful theming engine, based on SVG graphics. Plasma's theming provides the following features:
- Access to a complete set of graphical elements for application user interfaces
- Coloring for different elements of the user interface
- Global and application-specific themes
- Dynamic coloring of elements at runtime
The Theme Guide provides an extensive list of available theme elements, and how to create them.
Plasma Theme's elements are usually used together with PlasmaCore.Svg and PlasmaCore.FrameSvg item classes.
ColorScope
Plasma apps can change the color of specific sub-trees. This is achieved using the ColorScope type, which is available in the #PlasmaCore import. ColorScope can be used as follows:
PlasmaCore.ColorScope { colorGroup: PlasmaCore.Theme.ComplementaryColorGroup Rectangle { color: PlasmaCore.ColorScope.backgroundColor anchors.fill: parent } }
Image Display
Scalable vector graphics (SVG) are the preferred way to provide graphics with your code, as they allow scalable UI elements. The Plasma Svg* types are highly optimized, avoid re-rendering the SVG as much as possible, and cache pre-rendered pixmaps. Internally, textures are shared as much as possible and offloaded onto the GPU. These classes are highly efficient and work well across a wide range of display DPI.
For displaying bitmap images, e.g. photos in your app, use the QtQuick Image type. Use this wisely, as loading images can take lots of memory and disk access. Use the asynchronous mode if possible as to not freeze your UI.
Pixel density and DPI
Wayland vs. X11
Supporting Multiple Devices
Touch-friendliness
Layout Considerations
(responsive vs. layout switching, portrait vs. landscape, laptop vs. tablet vs. phone )==
Formfactors
A plasmoid can provide a suggestion which type of device it supports, or it makes sense on. This allows to provide per-device specific Plasmoids. The Kickoff application launcher, for example, is written for desktops, it is not optimized for use on touchscreens and might show interaction problems. To allow only showing or loading Plasmoids specific to a device, the "X-KDE-FormFactors" key is used in the metadata. Kickoff, for example has this line in its metadata.desktop file:
X-KDE-FormFactors=desktop
A phone or tablet specific component would use:
X-KDE-FormFactors=handset,tablet
Developers are encouraged to add this metadata to their metadata.desktop files. Simply adding a line like the FormFactors one in the above examples will help to offer the application on different devices. This mechanism is implemented in KPluginMetada, so at a fairly low-level. This means that this feature can be used in all kinds of cases: application launcher .desktop files, plugins for all purposes. It depends on the application listing or loading the plugins how the filtering is done exactly. Plasma desktop's systemtray Plasmoid for example shows only plugins without this key, and if the key exists it has to be or contain "desktop". A list of values supported separated by "," (comma), as well as single keys.
More information about formfactor support can be found in this article.
Touch-Specific Overrides
Workspace Integration
Mimetypes
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 Kickoff or Kicker menu in the Plasma desktop panel, you'll see that a number of different Plasmoids are offered here as alternatives, these are the Plasmoids installed on the system which specify "X-Plasma-Provides=org.kde.plasma.launchermenu"; so they're telling the system that they are application launchers. The media controller Plasmoid, for example, uses:
X-Plasma-Provides=org.kde.plasma.multimediacontrols
These "Provides" are in fact arbitrary, so you can choose your own here. The field accepts multiple values separated by ",". Here are some possible values that are used throughout Plasma:
- "org.kde.plasma.multimediacontrols" -- Multimedia controls
- "org.kde.plasma.time" -- Clocks
- "org.kde.plasma.date" -- Calendars
- "org.kde.plasma.time,org.kde.plasma.date" -- Clocks with calendars
- "org.kde.plasma.powermanagement" -- Power management (e.g. battery indicator)
- "org.kde.plasma.notifications" -- Notifications
- "org.kde.plasma.removabledevices" -- Removable devices, auto mounter, etc.
- "org.kde.plasma.multitasking" -- Task switchers
- "org.kde.plasma.virtualdesktops" -- Virtual desktop switcher
- "org.kde.plasma.activities" -- Switchers for Plasma activities
- "org.kde.plasma.trash" -- Trash / file deletion
Notification Area (Systemtray)
The "Media Controller" Plasmoid, (shipped in the kde-workspace repository under applets/mediacontroller) serves as a good example, since it uses most of these features. Its metadata contains the following:
X-Plasma-NotificationArea=true X-Plasma-NotificationAreaCategory=ApplicationStatus X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.*
Let's look at these keys one by one.
By specifying
X-Plasma-NotificationArea=true X-Plasma-NotificationAreaCategory=ApplicationStatus
this Plasmoid will be found by the systemtray Plasmoid (lower left in the default panel of Plasma desktop) and included in it by default. It's prudent for the Plasmoid to also set the "X-Plasma-NotificationAreaCategory" key, allowed values are:
- "ApplicationStatus" -- indicates that this item represents an active application
- "Hardware" -- 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.
Note that these categories are only for the sorting and placement in the notification area, the "general" category of a Plasmoid is arbitrary to this key.
Plasmoid Status
A Plasmoid running in the systemtray can indicate its status, it does so from the QML code by setting the global plasmoid.status. Possible values are:
- plasmoid.status = PlasmaCore.Types.ActiveStatus -- The Plasmoid is useful to have on the screen, either because it has something to show, or should be accessible easily.
- plasmoid.status = PlasmaCore.Types.PassiveStatus -- Nothing interesting is going on, the systemtray will usually hide these Plasmoid in the popup as to have them not take up valuable space in the panel.
- plasmoid.status = PlasmaCore.Types.NeedsAttentionStatus -- Something special is going on, for example a highlight in a messenger app, or an important system event.
- plasmoid.status = PlasmaCore.Types.Hidden -- The Plasmoid is entirely invisible and won't even be loaded in the system tray.
DBus autolaunched Plasmoids
Plasmoids can be loaded and unloaded in the systemtray automatically when a DBus service becomes avaiable or is stopped. This is very convenient to load Plasmoids automatically, so the user doesn't have to explicitely go to the notification area settings and enable or remove a Plasmoid, it just happens automatically. This is for example used by the Media Controller Plasmoid, which is auto-loaded as soon as an application starts offering the "org.mpris.MediaPlayer2" DBus service in the session. As you can see, this key accepts wildcards, which makes it a bit easier to match DBus names. This key can also be very useful to avoid having a Plasmoid loaded when it's unnecessary, so it can help to avoid visual clutter and wasted memory.
This function is used like this for the MPRIS2 interface:
X-Plasma-DBusActivationService=org.mpris.MediaPlayer2.*
The "Networks" Plasmoid, which is used to control NetworkManager uses this:
X-Plasma-DBusActivationService=org.freedesktop.NetworkManager
Settings Modules
- ServiceType=KCModule
- C++ KCMs vs
- plasma-settings
- systemsettings
Translations
i18n() & friends
- Which strings to translate?
- How to use i18n()
- How does i18n() become available?
- link to i18n docs
Localization
- units,
- date & time formats
- KLocale
Testing Translations
- making sure i18n is set up correctly: checklist
- how to use x-test
Distribution
Plasmoid Package
Simple Plasma apps without compiled code can be passed around as .plasmoid packages. These are essentially zip files with a specific content structure. Plasmoid packages can be installed using "plasmapkg2" or "kpackagetool5".
Appstream Metadata
As more and more tool make use of appstream metadata, adding this to your project allows users to find your app more easily.
- File format, etc.
- Guidelines
Get Hot New Stuff
Linux Distributions
Android
- mobilecomponents light
- apk creation and deployment
Upstreaming Code
The ultimate way of distributing your app may be to ship it with the official Plasma pacakges and develop it further together with other developers. Plasma is created in an open development process. You can take part in it. If you think your new app or improvement to an existing code-base would be a sensible addition to the official Plasma code, please get in contact with us.
- Phabricator
Contacting the Plasma Team
- bugs.kde.org
- mailinglist
- IRC
- Plasma forums