[plasma/union] /: Base style loading on packages rather than plugins
Arjen Hiemstra <[email protected]> Wed, 5 Aug 2026 10:33:23 +0000 (UTC)
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 9b32f4940ead3ef70cb9ca1f0c5db2e82d74766b by Arjen Hiemstra.
Committed on 05/08/2026 at 10:24.
Pushed by ahiemstra into branch 'master'.
Base style loading on packages rather than plugins
This changes the style loading to look for a package by ID, then load
that package and use it to create a style instance. This makes packages
a core part of Union and removes the need for input plugin names when
looking for styles, as the input plugin needed for a style is now
determined by the package.
M +2 -2 autotests/TestStyle.cpp
M +1 -2 autotests/output/quick/TestControls.cpp
M +1 -1 src/InputPlugin.h
M +7 -8 src/Style.cpp
M +13 -12 src/Style.h
M +2 -4 src/StyleCache.cpp
M +26 -33 src/StyleRegistry.cpp
M +3 -5 src/StyleRegistry.h
M +1 -2 src/Style_p.h
M +5 -11 src/input/css/CssLoader.cpp
M +3 -2 src/input/css/CssPlugin.cpp
M +2 -1 src/input/css/CssPlugin.h
https://invent.kde.org/plasma/union/-/commit/9b32f4940ead3ef70cb9ca1f0c5db2e82d74766b
diff --git a/autotests/TestStyle.cpp b/autotests/TestStyle.cpp
index 9cfc7c32..1c8a9de8 100644
--- a/autotests/TestStyle.cpp
+++ b/autotests/TestStyle.cpp
@@ -26,7 +26,7 @@ class TestStyle : public QObject
private Q_SLOTS:
void testLoad()
{
- auto style = Style::create(u"test"_s, u"test"_s, std::make_unique<TestLoader>());
+ auto style = Style::create(std::filesystem::path(), std::make_unique<TestLoader>());
QVERIFY(style->load());
@@ -37,7 +37,7 @@ private Q_SLOTS:
void testMatches()
{
- auto style = Style::create(u"test"_s, u"test"_s, std::make_unique<TestLoader>());
+ auto style = Style::create(std::filesystem::path(), std::make_unique<TestLoader>());
QVERIFY(style->load());
QList<Element::Ptr> elements;
diff --git a/autotests/output/quick/TestControls.cpp b/autotests/output/quick/TestControls.cpp
index f9e4e99d..4fa9fdc1 100644
--- a/autotests/output/quick/TestControls.cpp
+++ b/autotests/output/quick/TestControls.cpp
@@ -32,12 +32,11 @@ private Q_SLOTS:
void initTestCase()
{
qputenv("UNION_DISABLE_INPUT_PLUGINS", "1");
- qputenv("UNION_STYLE_PLUGIN", "test");
qputenv("UNION_STYLE_NAME", "test");
Union::StyleRegistry::instance()->load();
- auto testStyle = Union::Style::create(u"test"_s, u"test"_s, std::make_unique<TestStyleLoader>());
+ auto testStyle = Union::Style::create(std::filesystem::path("test"), std::make_unique<TestStyleLoader>());
Union::StyleRegistry::instance()->addStyle(testStyle);
}
diff --git a/src/InputPlugin.h b/src/InputPlugin.h
index e3fe7296..15aa0f7a 100644
--- a/src/InputPlugin.h
+++ b/src/InputPlugin.h
@@ -44,7 +44,7 @@ public:
* This should be reimplemented by subclasses and create a new instance of
* Style using an appropriate StyleLoader and other input specific data.
*/
- virtual std::shared_ptr<Style> createStyle(const QString &styleName) const = 0;
+ virtual std::shared_ptr<Style> createStyle(const StylePackage &package) const = 0;
/*!
* Returns an input plugin by type name.
diff --git a/src/Style.cpp b/src/Style.cpp
index 2465be70..c4c698f2 100644
--- a/src/Style.cpp
+++ b/src/Style.cpp
@@ -34,14 +34,14 @@ Style::Style(std::unique_ptr<StylePrivate> &&d)
Style::~Style() = default;
-QString Style::name() const
+std::filesystem::path Style::path() const
{
- return d->styleName;
+ return d->path;
}
-QString Style::pluginName() const
+QString Style::id() const
{
- return d->pluginName;
+ return QString::fromStdString(d->path.filename());
}
bool Style::hasErrors() const
@@ -95,7 +95,7 @@ QList<StyleRule::Ptr> Union::Style::matches(const QList<Element::Ptr> &elements)
QList<StyleRule::Ptr> result;
if (d->rules.isEmpty()) {
- qCInfo(UNION_QUERY) << "No style rules found for theme" << d->styleName << "so we will never match anything!";
+ qCInfo(UNION_QUERY) << "No style rules found for style" << d->path.filename().string() << "so we will never match anything!";
}
for (auto rule : d->rules) {
@@ -115,11 +115,10 @@ QList<StyleRule::Ptr> Union::Style::matches(const QList<Element::Ptr> &elements)
return result;
}
-std::shared_ptr<Style> Style::create(const QString &pluginName, const QString &styleName, std::unique_ptr<StyleLoader> &&loader)
+std::shared_ptr<Style> Style::create(const std::filesystem::path &path, std::unique_ptr<StyleLoader> &&loader)
{
auto d = std::make_unique<StylePrivate>();
- d->pluginName = pluginName;
- d->styleName = styleName;
+ d->path = path;
d->loader = std::move(loader);
return std::make_shared<Style>(std::move(d));
}
diff --git a/src/Style.h b/src/Style.h
index 2bd2609c..32ef1a47 100644
--- a/src/Style.h
+++ b/src/Style.h
@@ -41,20 +41,22 @@ public:
~Style() override;
/*!
- * \property Union::Style::name
+ * \property Union::Style::path
*
- * The name of the style.
+ * The path where the package for this style is located.
*/
- Q_PROPERTY(QString name READ name CONSTANT)
- QString name() const;
+ Q_PROPERTY(std::filesystem::path path READ path CONSTANT)
+ std::filesystem::path path() const;
/*!
- * \property Union::Style::pluginName
+ * \property Union::Style::id
*
- * The name of the plugin used to load rules for this Style.
+ * The identifier of the style.
+ *
+ * This is effectively the filename of path().
*/
- Q_PROPERTY(QString pluginName READ pluginName CONSTANT)
- QString pluginName() const;
+ Q_PROPERTY(QString id READ id CONSTANT)
+ QString id() const;
/*!
* \property Union::Style::hasErrors
@@ -102,14 +104,13 @@ public:
QList<StyleRule::Ptr> rules();
/*!
- * Create a new instance of Style.
+ * Create a new instance of Style from a path.
*
- * \a pluginName The name of the plugin responsible for creating this style.
- * \a styleName The name of this style.
+ * \a path The path to create a style from.
* \a loader An instance of StyleLoader responsible for loading the actual
* data of this style.
*/
- static Ptr create(const QString &pluginName, const QString &styleName, std::unique_ptr<StyleLoader> &&loader);
+ static Ptr create(const std::filesystem::path &path, std::unique_ptr<StyleLoader> &&loader);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
diff --git a/src/StyleCache.cpp b/src/StyleCache.cpp
index 24e2292e..4a5f48b0 100644
--- a/src/StyleCache.cpp
+++ b/src/StyleCache.cpp
@@ -117,8 +117,7 @@ std::unique_ptr<StylePrivate> StyleCache::load(const StyleId &styleId) const
}
auto result = std::make_unique<StylePrivate>();
- reader >> result->pluginName;
- reader >> result->styleName;
+ reader >> result->path;
if (result->pluginName.toStdString() != styleId.first || result->styleName.toStdString() != styleId.second) {
qCDebug(UNION_GENERAL) << "Ignoring cache file" << path.string() << "plugin/style name mismatch";
@@ -197,8 +196,7 @@ bool Union::StyleCache::save(const StylePrivate *style) const
writer << CacheMagic;
writer << CacheVersion;
- writer << style->pluginName;
- writer << style->styleName;
+ writer << style->path;
writer << style->cachePaths;
writer << style->modificationTimes;
diff --git a/src/StyleRegistry.cpp b/src/StyleRegistry.cpp
index 5e5d43ee..53ef8d1f 100644
--- a/src/StyleRegistry.cpp
+++ b/src/StyleRegistry.cpp
@@ -138,7 +138,7 @@ public:
std::unique_ptr<StyleCache> styleCache;
- QHash<StyleCache::StyleId, std::shared_ptr<Style>> styles;
+ QHash<fs::path, Style::Ptr> styles;
std::shared_ptr<PluginRegistry<PlatformPlugin>> platformRegistry;
std::shared_ptr<PlatformPlugin> platform;
@@ -179,62 +179,55 @@ void StyleRegistry::save()
std::shared_ptr<Style> StyleRegistry::defaultStyle()
{
- static auto environmentPlugin = qEnvironmentVariable("UNION_STYLE_PLUGIN", QString{});
static auto environmentName = qEnvironmentVariable("UNION_STYLE_NAME", QString{});
- auto plugin = environmentPlugin;
- if (plugin.isEmpty()) {
- plugin = platform()->defaultInputPlugin();
- }
-
auto name = environmentName;
if (name.isEmpty()) {
name = platform()->defaultStyleName();
}
- return style(name, plugin);
+ return style(name);
}
-std::shared_ptr<Style> StyleRegistry::style(const QString &styleName, const QString &pluginName)
+std::shared_ptr<Style> StyleRegistry::style(const QString &styleId)
{
- if (!pluginName.isEmpty()) {
- return d->loadStyle(styleName, pluginName);
+ auto itr = std::ranges::find_if(d->styles, [styleId](const Style::Ptr &style) {
+ return style->id() == styleId;
+ });
+ if (itr != d->styles.end()) {
+ return itr.value();
}
- // pluginName is empty so we don't know which exact input plugin provides
- // the style. Search through all input plugins until we find one that
- // returns a valid style for styleName.
+ auto stylePackage = d->packageHandler->package(styleId);
+ if (!stylePackage.isValid()) {
+ qCWarning(UNION_GENERAL) << "Could not find style" << styleId;
+ return nullptr;
+ }
- // First search through already-loaded plugins
- const auto objects = d->inputRegistry->pluginObjects();
- for (const auto &object : objects) {
- if (auto style = d->loadStyle(styleName, object); style) {
- return style;
- }
+ auto style = stylePackage.load();
+ if (!style) {
+ qCWarning(UNION_GENERAL) << "Style" << styleId << "failed to load";
+ return nullptr;
}
- // Nothing found in loaded plugins, try and load each available plugin and
- // see if that returns something.
- const auto plugins = d->inputRegistry->plugins();
- for (const auto &plugin : plugins) {
- if (auto style = d->loadStyle(styleName, plugin.name); style) {
- return style;
- }
+ if (!style->load()) {
+ qCWarning(UNION_GENERAL) << "Style" << styleId << "failed to load";
+ return nullptr;
}
- qCWarning(UNION_GENERAL) << "Requested style" << styleName << "which could not be found in any plugin!";
- return nullptr;
+ d->styles.insert(stylePackage.path(), style);
+ qCDebug(UNION_GENERAL) << "Loaded style" << styleId << "from" << stylePackage.path().string();
+ return style;
}
void Union::StyleRegistry::addStyle(const std::shared_ptr<Style> &style)
{
- auto styleId = std::make_pair(style->pluginName().toStdString(), style->name().toStdString());
- if (d->styles.contains(styleId)) {
- qCWarning(UNION_GENERAL) << "A style from plugin" << style->pluginName() << "with name" << style->name() << "is already registered";
+ if (d->styles.contains(style->path())) {
+ qCWarning(UNION_GENERAL) << "A style with path" << style->path().string() << "is already registered";
return;
}
- d->styles.insert(styleId, style);
+ d->styles.insert(style->path(), style);
}
std::shared_ptr<PlatformPlugin> StyleRegistry::platform() const
diff --git a/src/StyleRegistry.h b/src/StyleRegistry.h
index b4082598..4d71837a 100644
--- a/src/StyleRegistry.h
+++ b/src/StyleRegistry.h
@@ -55,13 +55,11 @@ public:
* Get a style instance by name.
*
* \a styleName The name of the style to retrieve.
- * \a pluginName The name of the input plugin that provides the style. If
- * empty, the style will be searched for in available plugins.
*
- * Returns a Style instance that matches `styleName` and `pluginName`, or
- * `nullptr` if it could not be found.
+ * Returns a Style instance that matches `styleName`, or `nullptr` if it
+ * could not be found.
*/
- std::shared_ptr<Style> style(const QString &styleName, const QString &pluginName = QString{});
+ std::shared_ptr<Style> style(const QString &styleId);
/*!
* Programatically add a style to the registry.
diff --git a/src/Style_p.h b/src/Style_p.h
index dc77cbab..9e40eed3 100644
--- a/src/Style_p.h
+++ b/src/Style_p.h
@@ -18,8 +18,7 @@ class StylePrivate
public:
std::unique_ptr<StyleLoader> loader;
- QString pluginName;
- QString styleName;
+ std::filesystem::path path;
bool modified = false;
bool hasErrors = false;
diff --git a/src/input/css/CssLoader.cpp b/src/input/css/CssLoader.cpp
index 6e6cfa2f..f46e2488 100644
--- a/src/input/css/CssLoader.cpp
+++ b/src/input/css/CssLoader.cpp
@@ -383,15 +383,9 @@ inline void setDirectionValue(T *output, const std::string &baseName, const cssp
}
}
-bool CssLoader::load(Style::Ptr theme)
+bool CssLoader::load(Style::Ptr style)
{
- QString relativeStylePath = u"union/css/styles/"_s + theme->name() + u"/style.css"_s;
- m_stylePath = fs::path(QStandardPaths::locate(QStandardPaths::GenericDataLocation, relativeStylePath, QStandardPaths::LocateFile).toStdString());
-
- if (!fs::exists(m_stylePath)) {
- qCWarning(UNION_CSS) << theme->name() << "does not exist!";
- return false;
- }
+ m_stylePath = style->path() / "contents" / "css" / "style.css";
cssparser::StyleSheet styleSheet(m_stylePath);
@@ -402,11 +396,11 @@ bool CssLoader::load(Style::Ptr theme)
const auto paths = styleSheet.paths();
for (const auto &path : paths) {
- theme->addCachePath(path);
+ style->addCachePath(path);
}
if (styleSheet.errors().size() > 0) {
- theme->setHasErrors(true);
+ style->setHasErrors(true);
qCWarning(UNION_CSS) << "Errors encountered while parsing CSS:";
for (const auto &error : styleSheet.errors()) {
@@ -425,7 +419,7 @@ bool CssLoader::load(Style::Ptr theme)
auto properties = std::make_unique<StylePropertyGroup>();
createProperties(properties.get(), rule.properties());
styleRule->setProperties(std::move(properties));
- theme->insert(styleRule);
+ style->insert(styleRule);
}
return true;
diff --git a/src/input/css/CssPlugin.cpp b/src/input/css/CssPlugin.cpp
index 467451bb..2e880924 100644
--- a/src/input/css/CssPlugin.cpp
+++ b/src/input/css/CssPlugin.cpp
@@ -4,6 +4,7 @@
#include "CssPlugin.h"
#include <Style.h>
+#include <StylePackage.h>
#include "CssLoader.h"
@@ -25,9 +26,9 @@ Union::StylePackage::Error CssPlugin::validatePackage(const Union::StylePackage
return StylePackage::Error::None;
}
-std::shared_ptr<Union::Style> CssPlugin::createStyle(const QString &styleName) const
+std::shared_ptr<Union::Style> CssPlugin::createStyle(const Union::StylePackage &package) const
{
- return Union::Style::create(name(), styleName, std::make_unique<CssLoader>());
+ return Union::Style::create(package.path(), std::make_unique<CssLoader>());
}
#include "moc_CssPlugin.cpp"
diff --git a/src/input/css/CssPlugin.h b/src/input/css/CssPlugin.h
index 256ac2c6..8a31ef95 100644
--- a/src/input/css/CssPlugin.h
+++ b/src/input/css/CssPlugin.h
@@ -8,6 +8,7 @@
namespace Union
{
class Style;
+class StylePackage;
}
class CssPlugin : public Union::InputPlugin
@@ -20,5 +21,5 @@ public:
Union::StylePackage::Error validatePackage(const Union::StylePackage &package) override;
- std::shared_ptr<Union::Style> createStyle(const QString &styleName) const override;
+ std::shared_ptr<Union::Style> createStyle(const Union::StylePackage &package) const override;
};