Development/Tutorials/Plasma4/PackageOverview
Introduction
Many times in a Plasma based application or addon there is the need to reference a set of files for consistent and easy access and redistribution. For instance, Plasma widgets (or "Plasmoids") written in an interpreted language (e.g. QML, Javascript, HTML, Ruby or Python) are often made up of several files containing code, images, configuration descriptions and other resources. These are distributed and shipped as one compressed file and at run time the contents are made easily available to the Plasmoid. This is the role that the Plasma Package plays.
A Plasma Package allows easy deployment and later referencing of a group of platform-independent files. Plasma Packages are used with wallpaper images and plugins, themes, Plasmoids, DataEngines, Runners, QML file sets, Plasma desktop scripting templates and other similar contexts. Plasma Package is therefore quite flexible and with very few rules can be extended to cover a wide variety of uses in applications that need a way to redistribute and/or reference sets of files easily.
Plasma Package is intended to be a simple system that does not include things more complex packaging systems such as the Debian package format or RPM provides. While Plasma Packages do not have the concept of things such as dependencies or architecture targets, it also does not require a complex system with a database and (slow) management applications.
Note: only interpreted languages are currently supported (that might change in the future). So if your plasmoid is written in Qt/C++ you have to distribute it as a distribution package (ie: rpm or deb).
Plasma Package Format
Plasma Packages usually have two things in common: a metadata.desktop file and a contents/ directory.
The metadata.desktop is an INI format file which contains a description of the contents of the package. This includes translatable strings for user visible text such as a name and description as well as content that is programmatically useful such as, in the case of Plasmoids, the scripting API used to write the Plasmoid the Package contains.
In the case of Plasmoids, the metadata.desktop contains the following mandatory fields:
- Name of the Plasmoid
- Author
- A version number for the Plasmoid
- Icon
- can be an icon from the user KDE theme;
- can be a file name (with extension) if you want to use a custom icon;
- omit this line if you do not want an icon.
- Used License
- This will be from a pre-selected list of possibilities.
- You can use a custom licence, specifying it in a file called COPYING.
- Should Plasma refuse to load improperly licensed Plasmoids?
- The API the plasmoid is written in (e.g. javascript, webkit, ruby, python, edje ..)
- Description of the Plasmoid giving the user a nice overview of the Plasmoid capabilities
Optionally these fields can be added:
- Category of widget that the Plasmoids belongs to, see [Projects/Plasma/PIG|the Plasma Interface Guidelies] for a lit of recognized category names
- Homepage for more information to the Plasmoid
- EMail of the author
- Release notes
- Required scripting version
- A minimum version number for Plasma
- path to the main code file, relative to contents/
- default size of the plasmoid (if unset, the default is 200,200)
An example file can be seen here:
[Desktop Entry]
Name=Analog Clock
Comment=An SVG themable clock
Icon=chronometer
Type=Service
X-Plasma-API=javascript
X-Plasma-MainScript=code/main.js
X-Plasma-DefaultSize=150,150
X-KDE-ServiceTypes=Plasma/Applet
X-KDE-PluginInfo-Author=John Doe
X-KDE-PluginInfo-Email=[email protected]
X-KDE-PluginInfo-Name=clock
X-KDE-PluginInfo-Version=pre0.1
X-KDE-PluginInfo-Website=http://plasma.kde.org/
X-KDE-PluginInfo-Category=Date and Time
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
meta.desktop files for other Plasma components such as DataEngines, Runners and Wallpapers are very similar. It is recommended when creating new package types to adhere to the general style above as much as possible for consistency.
Packages may add additional top-level contents directories. This is used by Plasmoids to allow device-specific files to be made available. A package may also have no special content directory at all, though this is discouraged since it makes accidental overwriting of files such has the metadata or hash files very easy.
What appears within the contents directories is up to the Package itself. For Plasmoids, the following structure is supported:
- $PlasmoidName-$PlasmoidVersion/ (root)
- metadata.desktop
- contents/
- code/ files containing scripting code
- main the main file that will be loaded at plasmoid start (unless you specify a different name in metadata.desktop)
- images/ image files in svg, png or jpeg format
- locale/ translation files in a standard localization hierarchy; e.g. German translation would appear in locale/l10n/de/
- ui/ user interface files, such as Qt Designer layouts
- config.ui the main configuration dialog layout
- config/ KConfigXt files describing the configuration
- main.xml the main configuration description
- ... additional plasmoid-specific files
- code/ files containing scripting code
Plasmoids can then reference these resources directly as if that was all that existed in the file system with simple directives such as
include("someOtherFile")
which will cause a lookup in the contents/code/ directory. Plasmoids (and other Plasma components) are sandboxed into their respective Packages, something that Plasma::Package enforces unless allowExternalPaths is set to true.
Device specific user interface
Different kind of devices may require a different kind of user interface, due to input method (ie mouse vs touch vs remote), screen size, distance of viewing (ten foot interface) or any other reason.
QML code inside plasma packages should of course behave in the most flexible way as possible, never doing assumptions on things like screen size, but sometimes some device specific code is needed.
If you have to put some particular assets in your package that are intended for a specific kind of device, the Package structure supports separate hyerarchies for that, so you could have:
- $PlasmoidName-$PlasmoidVersion/ (root)
- metadata.desktop
- contents/
- code/
- images/
- ui/
- platformcontents/
- touch/
- images/
- ui/
- tablet/
- ui/
- touch/
- contents/
In this case on touch platforms, every file that is found under platformcontents/touch will override the file with the same name under contents/ if present. Some files can also be present only in a particular profile. For every file that isn't found in a particular profile, the version under contents/ will be used as a fallback. More than one level of fallback is possible.
At the moment the following fallback chain is supported:
tablet -> touch -> final one in contents
Use platformcontents/tablet only if really necessary, when something should really be different than a generic touchscreen interaction.
More profiles for different devices will be eventually added in next versions.
Defining Formats
New formats can be defined programmatically using PackageStructure plugins. PackageStructure plugins call addDirectoryDefinition and addFileDefinition methods which define a key string that can be used to reference that resource, the path within the contents directories that it is expected to exist at, supported mimetypes, descriptions suitable for showing to a user (e.g. in an IDE or package creator tool) and whether or not the resource is required. Contents directories are also defined by the PackageStructure plugin.
The structure can be created dynamically at run-time depending on the package itself. This is accomplished by reimplementing the pathChanged method. This also allows one PackageStructure object to be re-used multiple times.
Together, these mechanisms allow for virtually unlimited flexibility in how a Package is structured on disk and what it contains. This makes Plasma Package suitable for the wide variety of use cases it currently fulfills.
Signing Packages
A Plasma Package may be signed with a GPG key. First, a SHA1 hash of the metadata.desktop file and the contents directories must be created and placed in a file called contents.hash that resides at the top level. A GPG signature of the contents.hash file can then be placed in a file called contents.hash.sig. This can then be used to verify the contents of the package at runtime.
Hashes may be generated with the plasmapkg tool as of version 0.2 with the --hash command line option.
Compression for Redistribution
A Plasma Package can be packed into one zip file that contains all the required files. The gzip format is also supported, though zip is generally recommended due to the ability to easily perform random access operations on zip archives. The resulting file is then suffixed with an appropriate identifying ending, such as ".plasmoid" in the case of plasmoids.
Installation
Installation can be done by hand, but generally this is accomplished either by using Plasma::PackageStructure::installPackage or with the plasmapkg command line utility. When a Plasma Package is installed, the archive is uncompressed and stored under the package root defined by the Package's structure definition. By default, this is $APPDATA/plasma/packages. By default, the metadata.desktop is copied into the the services directory so that it can easily be found later by KTrader to find all Plasmoids whether they are written in C++ or an interpreted language.