[kwin] Use KPluginTrader and json metadata to find KDecorations
* A KDecoration needs to include json metadata * A KDecoration needs to be installed to kwin/kdecorations * Aurorae and Oxygen adjusted * kcmdeco locates all decorations through the KPluginTrader * libkdecoration uses KPluginTrader to find the plugin * config plugins also need to include json metadata with X-KDE-PluginInfo-Name being the same as the decoration * config plugins need to get installed to kwin/kdecorations/config * kcmdeco locates the config plugin for a deco through the name and KPluginTrader REVIEW: 116765
This commit is contained in:
parent
5e5b1100b2
commit
f74df28450
17 changed files with 81 additions and 80 deletions
|
@ -22,7 +22,9 @@ target_link_libraries(kwin3_aurorae
|
|||
kdecorations
|
||||
)
|
||||
|
||||
install(TARGETS kwin3_aurorae DESTINATION ${PLUGIN_INSTALL_DIR} )
|
||||
kservice_desktop_to_json(kwin3_aurorae aurorae.desktop)
|
||||
|
||||
install(TARGETS kwin3_aurorae DESTINATION ${PLUGIN_INSTALL_DIR}/kwin/kdecorations )
|
||||
|
||||
set(decoration_plugin_SRCS
|
||||
decorationplugin.cpp
|
||||
|
@ -41,7 +43,6 @@ install(TARGETS decorationplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kwin/dec
|
|||
|
||||
########### install files ###############
|
||||
|
||||
install( FILES aurorae.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin )
|
||||
install( FILES aurorae.knsrc DESTINATION ${CONFIG_INSTALL_DIR} )
|
||||
install( FILES
|
||||
qml/aurorae.qml
|
||||
|
|
|
@ -37,8 +37,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KPluginInfo>
|
||||
#include <KServiceTypeTrader>
|
||||
|
||||
K_PLUGIN_FACTORY(AuroraePluginFactory,
|
||||
registerPlugin<Aurorae::AuroraeFactory>(QString(), &Aurorae::AuroraeFactory::createInstance);)
|
||||
K_PLUGIN_FACTORY_WITH_JSON(AuroraePluginFactory,
|
||||
"aurorae.json",
|
||||
registerPlugin<Aurorae::AuroraeFactory>(QString(), &Aurorae::AuroraeFactory::createInstance);)
|
||||
K_EXPORT_PLUGIN_VERSION(KWIN_DECORATION_API_VERSION)
|
||||
|
||||
namespace Aurorae
|
||||
|
|
|
@ -65,4 +65,4 @@ Name[wa]=Moteur di tinme di gåyotaedje Aurorae
|
|||
Name[x-test]=xxAurorae Decoration Theme Enginexx
|
||||
Name[zh_CN]=Aurorae 装饰主题引擎
|
||||
Name[zh_TW]=Aurorae 裝飾主題引擎
|
||||
X-KDE-Library=kwin3_aurorae
|
||||
X-KDE-PluginInfo-Name=aurorae
|
||||
|
|
|
@ -30,11 +30,10 @@ target_link_libraries(kwin3_oxygen kdecorations)
|
|||
|
||||
target_link_libraries(kwin3_oxygen oxygenstyle)
|
||||
|
||||
kservice_desktop_to_json(kwin3_oxygen oxygenclient.desktop)
|
||||
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(kwin3_oxygen XCB::XCB)
|
||||
endif()
|
||||
|
||||
install(TARGETS kwin3_oxygen DESTINATION ${PLUGIN_INSTALL_DIR})
|
||||
|
||||
########### install files ###############
|
||||
install(FILES oxygenclient.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/)
|
||||
install(TARGETS kwin3_oxygen DESTINATION ${PLUGIN_INSTALL_DIR}/kwin/kdecorations)
|
||||
|
|
|
@ -34,4 +34,4 @@ if(X11_FOUND)
|
|||
target_link_libraries(kwin_oxygen_config Qt5::X11Extras)
|
||||
endif()
|
||||
|
||||
install(TARGETS kwin_oxygen_config DESTINATION ${QT_PLUGIN_INSTALL_DIR}/kf5)
|
||||
install(TARGETS kwin_oxygen_config DESTINATION ${QT_PLUGIN_INSTALL_DIR}/kf5/kwin/kdecorations/config)
|
||||
|
|
3
clients/oxygen/config/config.json
Normal file
3
clients/oxygen/config/config.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"X-KDE-PluginInfo-Name": "Oxygen"
|
||||
}
|
|
@ -44,7 +44,9 @@
|
|||
|
||||
//_______________________________________________________________________
|
||||
|
||||
K_PLUGIN_FACTORY(OxygenConfigPlugin, registerPlugin<Oxygen::Config>(QString(), &Oxygen::Config::create); )
|
||||
K_PLUGIN_FACTORY_WITH_JSON(OxygenConfigPlugin,
|
||||
"config.json",
|
||||
registerPlugin<Oxygen::Config>(QString(), &Oxygen::Config::create); )
|
||||
|
||||
namespace Oxygen
|
||||
{
|
||||
|
|
|
@ -169,8 +169,6 @@ Comment[x-test]=xxStyling of the next generation desktopxx
|
|||
Comment[zh_CN]=下一代桌面的风格
|
||||
Comment[zh_TW]=下一代桌面的樣式
|
||||
|
||||
X-KDE-Library=kwin3_oxygen
|
||||
|
||||
X-KDE-PluginInfo-Author=Nuno Pinheiro, Casper Boemann, Riccardo Iaconelli, Huynh Huu Long, Thomas Luebking, Hugo Pereira Da Costa, Matthew Woehlke
|
||||
X-KDE-PluginInfo-Email=nuno@oxygen-icons.org, cbr@boemann.dk, riccardo@kde.org, long.upcase@googlemail.com, thomas.luebking@web.de, hugo.pereira@free.fr, mw_triad@users.sourceforge.net
|
||||
X-KDE-PluginInfo-Name=Oxygen
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <KWindowInfo>
|
||||
#include <kdeversion.h>
|
||||
|
||||
KWIN_DECORATION(OxygenPluginFactory, Oxygen::Factory)
|
||||
KWIN_DECORATION(OxygenPluginFactory, "oxygenclient.json", Oxygen::Factory)
|
||||
|
||||
namespace Oxygen
|
||||
{
|
||||
|
|
|
@ -39,9 +39,9 @@ DecorationPlugin::DecorationPlugin(QObject *parent)
|
|||
, KDecorationPlugins(KSharedConfig::openConfig())
|
||||
, m_disabled(false)
|
||||
{
|
||||
defaultPlugin = QStringLiteral("kwin3_oxygen");
|
||||
defaultPlugin = QStringLiteral("Oxygen");
|
||||
#ifndef KWIN_BUILD_OXYGEN
|
||||
defaultPlugin = QStringLiteral("kwin3_aurorae");
|
||||
defaultPlugin = QStringLiteral("aurorae");
|
||||
#endif
|
||||
#ifdef KWIN_BUILD_DECORATIONS
|
||||
loadPlugin(QString()); // load the plugin specified in cfg file
|
||||
|
|
|
@ -25,8 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KSharedConfig>
|
||||
#include <KLocalizedString>
|
||||
#include <KConfigGroup>
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginTrader>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
|
||||
|
@ -89,25 +88,24 @@ KWinDecorationConfigDialog::KWinDecorationConfigDialog(QString deco, const QList
|
|||
connect(m_buttons, SIGNAL(accepted()), SLOT(accept()));
|
||||
connect(m_buttons, SIGNAL(rejected()), SLOT(reject()));
|
||||
|
||||
KPluginLoader loader(styleToConfigLib(deco));
|
||||
KPluginFactory *factory = loader.factory();
|
||||
if (factory) {
|
||||
m_pluginConfigWidget = new QWidget(this);
|
||||
m_pluginConfigWidget->setLayout(new QVBoxLayout);
|
||||
m_pluginObject = factory->create<QObject>(m_pluginConfigWidget, m_pluginConfigWidget, QString(),
|
||||
QVariantList() << QStringLiteral("kwinrc") << QStringLiteral("Style"));
|
||||
|
||||
m_pluginConfigWidget = new QWidget(this);
|
||||
m_pluginConfigWidget->setLayout(new QVBoxLayout);
|
||||
m_pluginObject = KPluginTrader::self()->createInstanceFromQuery<QObject>(QStringLiteral("kf5/kwin/kdecorations/config"),
|
||||
QString(),
|
||||
QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(deco),
|
||||
m_pluginConfigWidget,
|
||||
m_pluginConfigWidget,
|
||||
QVariantList() << QStringLiteral("kwinrc") << QStringLiteral("Style"));
|
||||
if (m_pluginObject) {
|
||||
// connect required signals and slots together...
|
||||
connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
|
||||
connect(m_pluginObject, SIGNAL(changed()), this, SLOT(slotSelectionChanged()));
|
||||
connect(this, SIGNAL(pluginSave(KConfigGroup&)), m_pluginObject, SLOT(save(KConfigGroup&)));
|
||||
connect(m_buttons->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked(bool)), m_pluginObject, SLOT(defaults()));
|
||||
connect(m_buttons->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked(bool)), SLOT(slotDefault()));
|
||||
}
|
||||
|
||||
if (m_pluginConfigWidget) {
|
||||
layout->addWidget(m_pluginConfigWidget);
|
||||
}
|
||||
|
||||
layout->addWidget(m_buttons);
|
||||
|
||||
if (borderSizes.count() >= 2) {
|
||||
|
@ -160,14 +158,6 @@ void KWinDecorationConfigDialog::slotSelectionChanged()
|
|||
m_buttons->button(QDialogButtonBox::Reset)->setEnabled(true);
|
||||
}
|
||||
|
||||
QString KWinDecorationConfigDialog::styleToConfigLib(const QString& styleLib) const
|
||||
{
|
||||
if (styleLib.startsWith(QLatin1String("kwin3_")))
|
||||
return "kwin_" + styleLib.mid(6) + "_config";
|
||||
else
|
||||
return styleLib + "_config";
|
||||
}
|
||||
|
||||
void KWinDecorationConfigDialog::slotDefault()
|
||||
{
|
||||
if (m_borderSizes.count() >= 2)
|
||||
|
|
|
@ -70,7 +70,6 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
int borderSizeToIndex(KDecorationDefines::BorderSize size, const QList<QVariant>& sizes);
|
||||
QString styleToConfigLib(const QString& styleLib) const;
|
||||
|
||||
private:
|
||||
KWinDecorationConfigForm* m_ui;
|
||||
|
|
|
@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KDE/KLocalizedString>
|
||||
#include <KServiceTypeTrader>
|
||||
#include <KPluginInfo>
|
||||
#include <KPluginTrader>
|
||||
#include "kwindecoration.h"
|
||||
|
||||
/* WARNING -------------------------------------------------------------------------
|
||||
|
@ -47,6 +48,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
* (which is invoked on deco deconstruction)
|
||||
* WARNING ------------------------------------------------------------------------ */
|
||||
|
||||
static const QString s_auroraePluginName = QStringLiteral("aurorae");
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -87,41 +90,33 @@ void DecorationModel::reload()
|
|||
void DecorationModel::findDecorations()
|
||||
{
|
||||
beginResetModel();
|
||||
const QStringList dirList = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kwin", QStandardPaths::LocateDirectory);
|
||||
|
||||
foreach (const QString & dir, dirList) {
|
||||
QDir d(dir);
|
||||
if (d.exists()) {
|
||||
foreach (const QFileInfo & fi, d.entryInfoList()) {
|
||||
const QString filename(fi.absoluteFilePath());
|
||||
if (KDesktopFile::isDesktopFile(filename)) {
|
||||
const KDesktopFile desktopFile(filename);
|
||||
const QString libName = desktopFile.desktopGroup().readEntry("X-KDE-Library");
|
||||
|
||||
if (!libName.isEmpty() && libName.startsWith(QLatin1String("kwin3_"))) {
|
||||
if (libName == "kwin3_aurorae") {
|
||||
// read the Aurorae themes
|
||||
findAuroraeThemes();
|
||||
continue;
|
||||
}
|
||||
DecorationModelData data;
|
||||
data.name = desktopFile.readName();
|
||||
data.libraryName = libName;
|
||||
data.type = DecorationModelData::NativeDecoration;
|
||||
data.borderSize = KDecorationDefines::BorderNormal;
|
||||
data.closeDblClick = false;
|
||||
metaData(data, desktopFile);
|
||||
m_decorations.append(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto decorations = KPluginTrader::self()->query(QStringLiteral("kf5/kwin/kdecorations"));
|
||||
for (const KPluginInfo &plugin : decorations) {
|
||||
if (plugin.pluginName() == s_auroraePluginName) {
|
||||
// read the Aurorae themes
|
||||
findAuroraeThemes();
|
||||
continue;
|
||||
}
|
||||
DecorationModelData data;
|
||||
data.name = plugin.name();
|
||||
data.pluginName = plugin.pluginName();
|
||||
data.type = DecorationModelData::NativeDecoration;
|
||||
data.borderSize = KDecorationDefines::BorderNormal;
|
||||
data.closeDblClick = false;
|
||||
data.comment = plugin.comment();
|
||||
data.author = plugin.author();
|
||||
data.email = plugin.email();
|
||||
data.version = plugin.version();
|
||||
data.license = plugin.license();
|
||||
data.website = plugin.website();
|
||||
m_decorations.append(data);
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("KWin/Decoration");
|
||||
foreach (KService::Ptr service, offers) {
|
||||
DecorationModelData data;
|
||||
data.name = service->name();
|
||||
data.libraryName = "kwin3_aurorae";
|
||||
data.pluginName = s_auroraePluginName;
|
||||
data.type = DecorationModelData::QmlDecoration;
|
||||
data.auroraeName = service->property("X-KDE-PluginInfo-Name").toString();
|
||||
QString scriptName = service->property("X-Plasma-MainScript").toString();
|
||||
|
@ -178,7 +173,7 @@ void DecorationModel::findAuroraeThemes()
|
|||
|
||||
DecorationModelData data;
|
||||
data.name = name;
|
||||
data.libraryName = "kwin3_aurorae";
|
||||
data.pluginName = s_auroraePluginName;
|
||||
data.type = DecorationModelData::AuroraeDecoration;
|
||||
data.auroraeName = packageName;
|
||||
KConfigGroup config(m_config, data.auroraeName);
|
||||
|
@ -216,7 +211,7 @@ QVariant DecorationModel::data(const QModelIndex& index, int role) const
|
|||
case NameRole:
|
||||
return m_decorations[ index.row()].name;
|
||||
case LibraryNameRole:
|
||||
return m_decorations[ index.row()].libraryName;
|
||||
return m_decorations[ index.row()].pluginName;
|
||||
case TypeRole:
|
||||
return m_decorations[ index.row()].type;
|
||||
case AuroraeNameRole:
|
||||
|
@ -238,7 +233,7 @@ QVariant DecorationModel::data(const QModelIndex& index, int role) const
|
|||
case BorderSizesRole: {
|
||||
QList< QVariant > sizes;
|
||||
const bool mustDisablePreview = m_plugins->factory() && m_plugins->factory() == m_preview->factory();
|
||||
if (m_plugins->loadPlugin(m_decorations[index.row()].libraryName) && m_plugins->factory()) {
|
||||
if (m_plugins->loadPlugin(m_decorations[index.row()].pluginName) && m_plugins->factory()) {
|
||||
foreach (KDecorationDefines::BorderSize size, m_plugins->factory()->borderSizes()) // krazy:exclude=foreach
|
||||
sizes << int(size);
|
||||
if (mustDisablePreview) // it's nuked with destroyPreviousPlugin()
|
||||
|
@ -321,7 +316,7 @@ void DecorationModel::setButtons(bool custom, const QList<KDecorationDefines::De
|
|||
QModelIndex DecorationModel::indexOfLibrary(const QString& libraryName) const
|
||||
{
|
||||
for (int i = 0; i < m_decorations.count(); i++) {
|
||||
if (m_decorations.at(i).libraryName.compare(libraryName) == 0)
|
||||
if (m_decorations.at(i).pluginName.compare(libraryName) == 0)
|
||||
return index(i);
|
||||
}
|
||||
return QModelIndex();
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
QmlDecoration = 2
|
||||
};
|
||||
QString name;
|
||||
QString libraryName;
|
||||
QString pluginName;
|
||||
DecorationType type;
|
||||
QString comment;
|
||||
QString author;
|
||||
|
|
|
@ -62,6 +62,8 @@ K_PLUGIN_FACTORY(KWinDecoFactory,
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
static const QString s_defaultPluginName = QStringLiteral("Oxygen");
|
||||
|
||||
KWinDecorationForm::KWinDecorationForm(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
|
@ -183,18 +185,18 @@ void KWinDecorationModule::readConfig(const KConfigGroup & conf)
|
|||
// Find the corresponding decoration name to that of
|
||||
// the current plugin library name
|
||||
|
||||
QString libraryName = conf.readEntry("PluginLib", "kwin3_oxygen");
|
||||
QString libraryName = conf.readEntry("PluginLib", s_defaultPluginName);
|
||||
|
||||
if (libraryName.isEmpty()) {
|
||||
// Selected decoration doesn't exist, use the default
|
||||
libraryName = "kwin3_oxygen";
|
||||
libraryName = s_defaultPluginName;
|
||||
}
|
||||
|
||||
const int bsize = conf.readEntry("BorderSize", (int)BorderNormal);
|
||||
BorderSize borderSize = BorderNormal;
|
||||
if (bsize >= BorderTiny && bsize < BordersCount)
|
||||
borderSize = static_cast< BorderSize >(bsize);
|
||||
if (libraryName == "kwin3_aurorae") {
|
||||
if (libraryName == "aurorae") {
|
||||
KConfig auroraeConfig("auroraerc");
|
||||
KConfigGroup group(&auroraeConfig, "Engine");
|
||||
const QString themeName = group.readEntry("ThemeName", "example-deco");
|
||||
|
|
|
@ -43,13 +43,17 @@ DEALINGS IN THE SOFTWARE.
|
|||
* The KPluginFactory sub class returns a new instance of the specified KDecorationFactory.
|
||||
*
|
||||
* @param pluginfactoryname The name to be used for the KPluginFactory, passed to K_PLUGIN_FACTORY
|
||||
* @param jsonFile Name of the json file to be compiled into the decoration plugin as metadata
|
||||
* @param classname The class name of the KDecorationFactory subclass
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* KWIN_DECORATION(MyDecoPluginFactory, MyDeco::Factory)
|
||||
* KWIN_DECORATION(MyDecoPluginFactory, "mydeco.json", MyDeco::Factory)
|
||||
* @endcode
|
||||
*
|
||||
* Please refer to the documentation of K_PLUGIN_FACTORY_WITH_JSON in KF5::Service for how to
|
||||
* create and use the json file.
|
||||
*
|
||||
* In case the decoration plugin wants to have more control over the created factory (e.g. a singleton)
|
||||
* it is recommended to not use this convenience macro, but specify an own K_PLUGIN_FACTORY. In that
|
||||
* case it is also required to add
|
||||
|
@ -59,9 +63,9 @@ DEALINGS IN THE SOFTWARE.
|
|||
*
|
||||
* to add the correct plugin version. This is also handled by this macro in the default case.
|
||||
**/
|
||||
#define KWIN_DECORATION( pluginfactoryname, classname ) \
|
||||
#define KWIN_DECORATION( pluginfactoryname, json, classname ) \
|
||||
QObject *createDecorationFactory(QWidget *, QObject *, const QList<QVariant> &) { return new classname(); } \
|
||||
K_PLUGIN_FACTORY(pluginfactoryname, registerPlugin<classname>(QString(), &createDecorationFactory);) \
|
||||
K_PLUGIN_FACTORY_WITH_JSON(pluginfactoryname, json, registerPlugin<classname>(QString(), &createDecorationFactory);) \
|
||||
K_EXPORT_PLUGIN_VERSION(KWIN_DECORATION_API_VERSION)
|
||||
|
||||
#define KWIN_DECORATION_BRIDGE_API_VERSION 1
|
||||
|
|
|
@ -31,6 +31,7 @@ DEALINGS IN THE SOFTWARE.
|
|||
#include <klibrary.h>
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginTrader>
|
||||
#include <kconfiggroup.h>
|
||||
#include <KDE/KLocalizedString>
|
||||
#include <assert.h>
|
||||
|
@ -44,7 +45,7 @@ DEALINGS IN THE SOFTWARE.
|
|||
KDecorationPlugins::KDecorationPlugins(const KSharedConfigPtr &cfg)
|
||||
: fact(nullptr),
|
||||
old_fact(nullptr),
|
||||
pluginStr(QStringLiteral("kwin3_undefined ")),
|
||||
pluginStr(QStringLiteral("undefined ")),
|
||||
config(cfg)
|
||||
{
|
||||
}
|
||||
|
@ -105,7 +106,13 @@ bool KDecorationPlugins::loadPlugin(QString nameStr)
|
|||
|
||||
auto createFactory = [](const QString &pluginName) -> KDecorationFactory* {
|
||||
qDebug() << "Trying to load decoration plugin" << pluginName;
|
||||
KPluginLoader loader(pluginName);
|
||||
const QString query = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(pluginName);
|
||||
const auto offers = KPluginTrader::self()->query(QStringLiteral("kf5/kwin/kdecorations"), QString(), query);
|
||||
if (offers.isEmpty()) {
|
||||
qDebug() << "Decoration plugin not found";
|
||||
return nullptr;
|
||||
}
|
||||
KPluginLoader loader(offers.first().libraryPath());
|
||||
if (loader.pluginVersion() != KWIN_DECORATION_API_VERSION) {
|
||||
qWarning() << i18n("The library %1 has wrong API version %2", loader.pluginName(), loader.pluginVersion());
|
||||
return nullptr;
|
||||
|
|
Loading…
Reference in a new issue