diff --git a/design/plasmoids b/design/plasmoids index 701857317..63f05d617 100644 --- a/design/plasmoids +++ b/design/plasmoids @@ -1,82 +1,82 @@ Plasmoids ========= What is a widget? ================ In the context of Plasma, a "widget" is a single, self-contained graphical object on the canvas. They can be added and removed individually, configured separately from other widgets, etc. These "mini appliations" are sometimes referred to in other widget platforms as "applets", "apps", "gadgets", "karambas", "desklets". We chose the word "widget" for Plasma as it is used by other some other existing systems. The API of a widget is defined by the host "ScriptEngine", with the exception of native Plasma widgets written in C++ which allows plugins in loadable librareis which use the API of the Plasma library directly. Currently Plasma supports both such "native" widgets written in C++, ones written in various dynamic languages (Plasmoids) as well as: * SuperKaramba's karambas * Enlightenment 17 edje content * MacOS dashboard widgets (though not all) These are loaded via host AppletScriptEngine plugins that bridge between the widget itself and Plasma's canvas. What is a Plasmoid? ================== A Plasmoid is a widget that can be loaded into Plasma that uses the native Plasma API and comes packaged in a single archive file that includes the code, metadata, images, configuration defintions, etc. Plasmoids may be currently written in the following languages / APIs: * HTML/JavaScript widgets (essentially "web pages for Plasma"): they are limited to a small subset of the Plasma library API and DataEngines * Simplified JavaScript: these are written in JavaScript but use a managed set of API from the Plasma library and elsewhere; these are the most likely to be widely portable between Plasma instances and are the most securable. * Full JavaScript: a work in progress, this provides full access to the Plasma, KDE and Qt APIs * Ruby: full access to the Plasma, KDE, Qt and other Ruby APIs are provided * Python: full access to the Plasma, KDE, Qt and other Python APIs are provided There are tutorials for the various APIs avaiable here: http://techbase.kde.org/Development/Tutorials/Plasma The Plasmoid Package ==================== A Plasmoid package is a single archive file compressed using the zip compression algorithm. By convention they have a .plasmoid suffix. The layout of a Plasmoid package is as follows, starting with the root (/) being the top of the zip archive: metadata.desktop: a .desktop file (INI format) following the standard KPluginInfo layout. See more about this file below. contents/ code/ -> where all the scripts are kept main -> by default, the name of the script to start the Plasmoid from config/ -> KConfigXT and INI files describing configuration variables main.xml -> main config file, KConfigXT xml default-configrc -> default configuration, INI file configui/ -> Qt Designer files describing configuration dialog pages config.ui -> main configuration UI images/ -> image files of various formats translations/ -> po files for individual translations; each translation should appear in subdirectories named after the language code ui/ -> user interface description files, usually Qt Designer The Metadata File ================= The metadata.desktop file contains information about the widget that is critical to proper function. This file is a standard "INI format" file with one group in it called [Desktop Entry]. A typical such file appears below: [Desktop Entry] Name=JavaScript Animations Comment=An example showing how animations can be used from JavaScript Encoding=UTF-8 Icon=plasma ServiceTypes=Plasma/Applet Type=Service X-KDE-PluginInfo-Author=Aaron Seigo X-KDE-PluginInfo-Category=Examples X-KDE-PluginInfo-Depends= X-KDE-PluginInfo-Email=plasma-devel@kde.org X-KDE-PluginInfo-EnabledByDefault=true X-KDE-PluginInfo-License=BSD X-KDE-PluginInfo-Name=javascript-animations-example X-KDE-PluginInfo-Version=0.1 X-KDE-PluginInfo-Website=http://plasma.kde.org/ X-Plasma-API=javascript The icon can either refer to a file in the root of the package by the same name, or a standard icon theme icon name. Important fields include: * X-KDE-PluginInfo-Name= what the widget will be referred to internally and MUST be unique; as such a "reverse domain name" approach is a good idea, e.g. "org.foo.somewidget". * X-Plasma-API entry defines which language and API the widget is written for and dictates which ScriptEngine will be loaded for it. Useful optional fields include: * X-Plasma-MainScript= path relative to the contents/ dir of the package; used to override the default of "contents/code/main" Installing and Replacing ======================== -Plasmoid packages can be installed and removed from the Add Widgets interfaces of various Plasma applications, such as plasma desktop, or directly using the plasmapkg binary. See the output of `plasmapkg --help` for more information on using that utility. +Plasmoid packages can be installed and removed from the Add Widgets interfaces of various Plasma applications, such as plasma desktop, or directly using the kpackagetool5 binary. See the output of `kpackagetool5 --help` for more information on using that utility. diff --git a/kcms/desktoptheme/kcm.cpp b/kcms/desktoptheme/kcm.cpp index 478ee0e37..94c9fd09a 100644 --- a/kcms/desktoptheme/kcm.cpp +++ b/kcms/desktoptheme/kcm.cpp @@ -1,284 +1,283 @@ /* This file is part of the KDE Project Copyright (c) 2014 Marco Martin Copyright (c) 2014 Vishesh Handa Copyright (c) 2016 David Rosca This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include Q_LOGGING_CATEGORY(KCM_DESKTOP_THEME, "kcm_desktoptheme") K_PLUGIN_FACTORY_WITH_JSON(KCMDesktopThemeFactory, "kcm_desktoptheme.json", registerPlugin();) KCMDesktopTheme::KCMDesktopTheme(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) , m_defaultTheme(new Plasma::Theme(this)) { //This flag seems to be needed in order for QQuickWidget to work //see https://bugreports.qt-project.org/browse/QTBUG-40765 //also, it seems to work only if set in the kcm, not in the systemsettings' main qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); qmlRegisterType(); KAboutData* about = new KAboutData(QStringLiteral("kcm_desktoptheme"), i18n("Configure Desktop Theme"), QStringLiteral("0.1"), QString(), KAboutLicense::LGPL); about->addAuthor(i18n("David Rosca"), QString(), QStringLiteral("nowrep@gmail.com")); setAboutData(about); setButtons(Apply | Default | Help); m_model = new QStandardItemModel(this); QHash roles = m_model->roleNames(); roles[PluginNameRole] = QByteArrayLiteral("pluginName"); roles[ThemeNameRole] = QByteArrayLiteral("themeName"); roles[IsLocalRole] = QByteArrayLiteral("isLocal"); m_model->setItemRoleNames(roles); } KCMDesktopTheme::~KCMDesktopTheme() { delete m_defaultTheme; } QStandardItemModel *KCMDesktopTheme::desktopThemeModel() const { return m_model; } QString KCMDesktopTheme::selectedPlugin() const { return m_selectedPlugin; } void KCMDesktopTheme::setSelectedPlugin(const QString &plugin) { if (m_selectedPlugin == plugin) { return; } m_selectedPlugin = plugin; Q_EMIT selectedPluginChanged(m_selectedPlugin); updateNeedsSave(); } void KCMDesktopTheme::getNewThemes() { KNS3::DownloadDialog *dialog = new KNS3::DownloadDialog(QStringLiteral("plasma-themes.knsrc")); dialog->open(); connect(dialog, &QDialog::accepted, this, [this, dialog]() { if (!dialog->changedEntries().isEmpty()) { load(); delete dialog; } }); } void KCMDesktopTheme::installThemeFromFile(const QUrl &file) { qCDebug(KCM_DESKTOP_THEME) << "Installing ... " << file; - QString program = QStringLiteral("plasmapkg2"); - QStringList arguments; - arguments << QStringLiteral("-t") << QStringLiteral("theme") << QStringLiteral("-i") << file.toLocalFile(); + const QString program = QStringLiteral("kpackagetool5"); + const QStringList arguments = { QStringLiteral("--type"), QStringLiteral("Plasma/Theme"), QStringLiteral("--install"), file.toLocalFile()}; qCDebug(KCM_DESKTOP_THEME) << program << arguments.join(QStringLiteral(" ")); QProcess *myProcess = new QProcess(this); connect(myProcess, static_cast(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus); if (exitCode == 0) { qCDebug(KCM_DESKTOP_THEME) << "Theme installed successfully :)"; load(); Q_EMIT showInfoMessage(i18n("Theme installed successfully.")); } else { qCWarning(KCM_DESKTOP_THEME) << "Theme installation failed." << exitCode; Q_EMIT showInfoMessage(i18n("Theme installation failed.")); } }); connect(myProcess, static_cast(&QProcess::error), this, [this](QProcess::ProcessError e) { qCWarning(KCM_DESKTOP_THEME) << "Theme installation failed: " << e; Q_EMIT showInfoMessage(i18n("Theme installation failed.")); }); myProcess->start(program, arguments); } void KCMDesktopTheme::removeTheme(const QString &name) { Q_ASSERT(!m_pendingRemoval.contains(name)); Q_ASSERT(!m_model->findItems(name).isEmpty()); m_pendingRemoval.append(name); m_model->removeRow(m_model->findItems(name).at(0)->row()); updateNeedsSave(); } void KCMDesktopTheme::applyPlasmaTheme(QQuickItem *item, const QString &themeName) { if (!item) { return; } Plasma::Theme *theme = m_themes[themeName]; if (!theme) { theme = new Plasma::Theme(themeName, this); m_themes[themeName] = theme; } Q_FOREACH (Plasma::Svg *svg, item->findChildren()) { svg->setTheme(theme); svg->setUsingRenderingCache(false); } } Q_INVOKABLE int KCMDesktopTheme::indexOf(const QString &themeName) const { for (int i = 0; i < m_model->rowCount(); ++i) { if (m_model->data(m_model->index(i, 0), PluginNameRole).toString() == themeName) { return i; } } return -1; } void KCMDesktopTheme::load() { m_pendingRemoval.clear(); // Get all desktop themes QStringList themes; const QStringList &packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/desktoptheme"), QStandardPaths::LocateDirectory); Q_FOREACH (const QString &ppath, packs) { const QDir cd(ppath); const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); Q_FOREACH (const QString &pack, entries) { const QString _metadata = ppath + QLatin1Char('/') + pack + QStringLiteral("/metadata.desktop"); if (QFile::exists(_metadata)) { themes << _metadata; } } } m_model->clear(); Q_FOREACH (const QString &theme, themes) { int themeSepIndex = theme.lastIndexOf('/', -1); const QString themeRoot = theme.left(themeSepIndex); int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); const QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); KDesktopFile df(theme); if (df.noDisplay()) { continue; } QString name = df.readName(); if (name.isEmpty()) { name = packageName; } const bool isLocal = QFileInfo(theme).isWritable(); if (m_model->findItems(packageName).isEmpty()) { QStandardItem *item = new QStandardItem; item->setText(packageName); item->setData(packageName, PluginNameRole); item->setData(name, ThemeNameRole); item->setData(isLocal, IsLocalRole); m_model->appendRow(item); } } KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("plasmarc")), "Theme"); setSelectedPlugin(cg.readEntry("name", m_defaultTheme->themeName())); updateNeedsSave(); } void KCMDesktopTheme::save() { if (m_defaultTheme->themeName() == m_selectedPlugin) { return; } m_defaultTheme->setThemeName(m_selectedPlugin); removeThemes(); updateNeedsSave(); } void KCMDesktopTheme::defaults() { setSelectedPlugin(QStringLiteral("default")); } void KCMDesktopTheme::updateNeedsSave() { setNeedsSave(!m_pendingRemoval.isEmpty() || m_selectedPlugin != m_defaultTheme->themeName()); } void KCMDesktopTheme::removeThemes() { const QString program = QStringLiteral("plasmapkg2"); Q_FOREACH (const QString &name, m_pendingRemoval) { const QStringList arguments = {QStringLiteral("-t"), QStringLiteral("theme"), QStringLiteral("-r"), name}; qCDebug(KCM_DESKTOP_THEME) << program << arguments.join(QStringLiteral(" ")); QProcess *process = new QProcess(this); connect(process, static_cast(&QProcess::finished), this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus); if (exitCode == 0) { qCDebug(KCM_DESKTOP_THEME) << "Theme removed successfully :)"; load(); } else { qCWarning(KCM_DESKTOP_THEME) << "Theme removal failed." << exitCode; Q_EMIT showInfoMessage(i18n("Theme removal failed.")); } process->deleteLater(); }); connect(process, static_cast(&QProcess::error), this, [this, process](QProcess::ProcessError e) { qCWarning(KCM_DESKTOP_THEME) << "Theme removal failed: " << e; Q_EMIT showInfoMessage(i18n("Theme removal failed.")); process->deleteLater(); }); process->start(program, arguments); } } #include "kcm.moc" diff --git a/kcms/desktoptheme/plasma-themes.knsrc b/kcms/desktoptheme/plasma-themes.knsrc index d2a83b1d3..34f8a6c48 100644 --- a/kcms/desktoptheme/plasma-themes.knsrc +++ b/kcms/desktoptheme/plasma-themes.knsrc @@ -1,26 +1,26 @@ [KNewStuff3] Name=Plasma Themes Name[ca]=Temes del Plasma Name[ca@valencia]=Temes del Plasma Name[de]=Plasma-Designs Name[en_GB]=Plasma Themes Name[es]=Temas de Plasma Name[it]=Temi di Plasma Name[nl]=Plasma-thema's Name[pl]=Wyglądy Plazmy Name[pt]=Temas do Plasma Name[sk]=Témy Plasma Name[sr]=Плазма теме Name[sr@ijekavian]=Плазма теме Name[sr@ijekavianlatin]=Plasma teme Name[sr@latin]=Plasma teme Name[sv]=Plasmateman Name[uk]=Теми Плазми Name[x-test]=xxPlasma Themesxx Name[zh_CN]=Plasma 主题 ProvidersUrl=http://download.kde.org/ocs/providers.xml Categories=Plasma Theme StandardResource=tmp -InstallationCommand=plasmapkg2 -t theme -i %f -UninstallCommand=plasmapkg2 -t theme -r %f +InstallationCommand=kpackagetool5 -t Plasma/Theme -i %f +UninstallCommand=kpackagetool5 -t Plasma/Theme -r %f