DesignSystem: Resolve design system bindings

Task-number: QDS-14261
Change-Id: I24215950c556f201bbfb53d043b63fd596ccc6aa
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Vikas Pachdha
2024-12-30 00:04:03 +01:00
parent 4789783d12
commit 2a721d5937
8 changed files with 74 additions and 17 deletions

View File

@@ -121,13 +121,14 @@ Rectangle {
} }
component Cell: Rectangle { component Cell: Rectangle {
required property string display required property var display
required property int row required property int row
required property int column required property int column
required property bool editing required property bool editing
required property bool isBinding required property bool isBinding
required property var propertyValue
color: root.backgroundColor color: root.backgroundColor
implicitWidth: root.cellWidth implicitWidth: root.cellWidth
@@ -227,7 +228,7 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
leftPadding: root.leftPadding leftPadding: root.leftPadding
value: parseInt(numberDelegate.display) value: numberDelegate.display
from: -1000 // TODO define min/max from: -1000 // TODO define min/max
to: 1000 to: 1000
editable: true editable: true
@@ -261,7 +262,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: root.leftPadding anchors.leftMargin: root.leftPadding
checked: flagDelegate.display === "true" checked: flagDelegate.display
text: flagDelegate.display text: flagDelegate.display
onToggled: { onToggled: {
@@ -328,7 +329,7 @@ Rectangle {
height: parent.height height: parent.height
verticalAlignment: Qt.AlignVCenter verticalAlignment: Qt.AlignVCenter
color: StudioTheme.Values.themeTextColor color: StudioTheme.Values.themeTextColor
text: colorDelegate.display text: colorDelegate.propertyValue
} }
} }

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "collectionmodel.h" #include "collectionmodel.h"
#include <designsystem/dsstore.h>
#include <designsystem/dsthemegroup.h> #include <designsystem/dsthemegroup.h>
#include <designsystem/dsthememanager.h> #include <designsystem/dsthememanager.h>
@@ -9,8 +10,9 @@
namespace QmlDesigner { namespace QmlDesigner {
CollectionModel::CollectionModel(DSThemeManager *collection) CollectionModel::CollectionModel(DSThemeManager *collection, const DSStore *store)
: m_collection(collection) : m_collection(collection)
, m_store(store)
{ {
updateCache(); updateCache();
} }
@@ -47,14 +49,22 @@ QVariant CollectionModel::data(const QModelIndex &index, int role) const
if (!property) if (!property)
return {}; return {};
const QVariant propertyValue = property->value.toString();
const QVariant displayValue = property->isBinding
? m_store->resolvedDSBinding(propertyValue.toString()).value
: property->value;
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
return property->value.toString(); case Roles::ResolvedValueRole:
case static_cast<int>(Roles::GroupRole): return displayValue;
case Roles::PropertyValueRole:
return propertyValue;
case Roles::GroupRole:
return QVariant::fromValue<GroupType>(groupType); return QVariant::fromValue<GroupType>(groupType);
case static_cast<int>(Roles::BindingRole): case Roles::BindingRole:
return property->isBinding; return property->isBinding;
case static_cast<int>(Roles::ActiveThemeRole): case Roles::ActiveThemeRole:
return m_collection->activeTheme() == themeId; return m_collection->activeTheme() == themeId;
} }
@@ -86,7 +96,7 @@ QVariant CollectionModel::headerData(int section, Qt::Orientation orientation, i
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
return QString::fromLatin1(m_collection->themeName(themeId)); return QString::fromLatin1(m_collection->themeName(themeId));
case static_cast<int>(Roles::ActiveThemeRole): case Roles::ActiveThemeRole:
return m_collection->activeTheme() == themeId; return m_collection->activeTheme() == themeId;
default: default:
break; break;
@@ -97,7 +107,7 @@ QVariant CollectionModel::headerData(int section, Qt::Orientation orientation, i
if (auto propInfo = findPropertyName(section)) { if (auto propInfo = findPropertyName(section)) {
if (role == Qt::DisplayRole) if (role == Qt::DisplayRole)
return QString::fromLatin1(propInfo->second); return QString::fromLatin1(propInfo->second);
if (role == static_cast<int>(Roles::GroupRole)) if (role == Roles::GroupRole)
return QVariant::fromValue<GroupType>(propInfo->first); return QVariant::fromValue<GroupType>(propInfo->first);
} }
} }
@@ -112,9 +122,11 @@ Qt::ItemFlags CollectionModel::flags(const QModelIndex &index) const
QHash<int, QByteArray> CollectionModel::roleNames() const QHash<int, QByteArray> CollectionModel::roleNames() const
{ {
auto roles = QAbstractItemModel::roleNames(); auto roles = QAbstractItemModel::roleNames();
roles.insert(static_cast<int>(Roles::GroupRole), "group"); roles.insert(Roles::ResolvedValueRole, "resolvedValue");
roles.insert(static_cast<int>(Roles::BindingRole), "isBinding"); roles.insert(Roles::GroupRole, "group");
roles.insert(static_cast<int>(Roles::ActiveThemeRole), "isActive"); roles.insert(Roles::BindingRole, "isBinding");
roles.insert(Roles::ActiveThemeRole, "isActive");
roles.insert(Roles::PropertyValueRole, "propertyValue");
return roles; return roles;
} }

View File

@@ -10,6 +10,7 @@
namespace QmlDesigner { namespace QmlDesigner {
class DSThemeManager; class DSThemeManager;
class DSStore;
using PropInfo = std::pair<GroupType, PropertyName>; using PropInfo = std::pair<GroupType, PropertyName>;
class CollectionModel : public QAbstractItemModel class CollectionModel : public QAbstractItemModel
@@ -17,11 +18,17 @@ class CollectionModel : public QAbstractItemModel
Q_OBJECT Q_OBJECT
public: public:
enum class Roles { GroupRole = Qt::UserRole + 1, BindingRole, ActiveThemeRole }; enum Roles {
GroupRole = Qt::UserRole + 1,
BindingRole,
ActiveThemeRole,
ResolvedValueRole,
PropertyValueRole
};
Q_PROPERTY(QStringList themeNames READ themeNameList NOTIFY themeNameChanged FINAL) Q_PROPERTY(QStringList themeNames READ themeNameList NOTIFY themeNameChanged FINAL)
CollectionModel(DSThemeManager *collection); CollectionModel(DSThemeManager *collection, const DSStore *store);
QStringList themeNameList() const; QStringList themeNameList() const;
Q_INVOKABLE void setActiveTheme(const QString &themeName); Q_INVOKABLE void setActiveTheme(const QString &themeName);
@@ -66,6 +73,7 @@ private:
private: private:
DSThemeManager *m_collection = nullptr; DSThemeManager *m_collection = nullptr;
const DSStore *m_store;
// cache // cache
std::vector<ThemeId> m_themeIdList; std::vector<ThemeId> m_themeIdList;

View File

@@ -74,7 +74,8 @@ QStringList DesignSystemInterface::collections() const
CollectionModel *DesignSystemInterface::createModel(const QString &typeName, DSThemeManager *collection) CollectionModel *DesignSystemInterface::createModel(const QString &typeName, DSThemeManager *collection)
{ {
auto [newItr, success] = m_models.try_emplace(typeName, auto [newItr, success] = m_models.try_emplace(typeName,
std::make_unique<CollectionModel>(collection)); std::make_unique<CollectionModel>(collection,
m_store));
if (success) { if (success) {
// Otherwise the model will be deleted by the QML engine. // Otherwise the model will be deleted by the QML engine.
QQmlEngine::setObjectOwnership(newItr->second.get(), QQmlEngine::CppOwnership); QQmlEngine::setObjectOwnership(newItr->second.get(), QQmlEngine::CppOwnership);

View File

@@ -248,6 +248,28 @@ QStringList DSStore::collectionNames() const
return names; return names;
} }
ThemeProperty DSStore::resolvedDSBinding(QStringView binding) const
{
const auto parts = binding.split('.', Qt::SkipEmptyParts);
if (parts.size() != 3)
return {};
const auto &collectionName = parts[0];
auto itr = m_collections.find(collectionName.toString());
if (itr == m_collections.end())
return {};
const DSThemeManager &boundCollection = itr->second;
const auto &propertyName = parts[2].toLatin1();
if (const auto group = boundCollection.groupType(propertyName)) {
auto property = boundCollection.property(boundCollection.activeTheme(), *group, propertyName);
if (property)
return property->isBinding ? resolvedDSBinding(property->value.toString()) : *property;
}
return {};
}
QString DSStore::uniqueCollectionName(const QString &hint) const QString DSStore::uniqueCollectionName(const QString &hint) const
{ {
return UniqueName::generateTypeName(hint, "Collection", [this](const QString &t) { return UniqueName::generateTypeName(hint, "Collection", [this](const QString &t) {

View File

@@ -38,6 +38,8 @@ public:
std::optional<Utils::FilePath> moduleDirPath() const; std::optional<Utils::FilePath> moduleDirPath() const;
QStringList collectionNames() const; QStringList collectionNames() const;
ThemeProperty resolvedDSBinding(QStringView binding) const;
private: private:
QString uniqueCollectionName(const QString &hint) const; QString uniqueCollectionName(const QString &hint) const;
std::optional<QString> loadCollection(const QString &typeName, const Utils::FilePath &qmlFilePath); std::optional<QString> loadCollection(const QString &typeName, const Utils::FilePath &qmlFilePath);

View File

@@ -150,6 +150,15 @@ void DSThemeManager::duplicateTheme(ThemeId from, ThemeId to)
group->duplicateValues(from, to); group->duplicateValues(from, to);
} }
std::optional<GroupType> DSThemeManager::groupType(const PropertyName &name) const
{
for (const auto &[gt, group] : m_groups) {
if (group->hasProperty(name))
return gt;
}
return {};
}
std::optional<ThemeProperty> DSThemeManager::property(ThemeId themeId, std::optional<ThemeProperty> DSThemeManager::property(ThemeId themeId,
GroupType gType, GroupType gType,
const PropertyName &name) const const PropertyName &name) const

View File

@@ -50,6 +50,8 @@ public:
void duplicateTheme(ThemeId from, ThemeId to); void duplicateTheme(ThemeId from, ThemeId to);
std::optional<GroupType> groupType(const PropertyName &name) const;
bool addProperty(GroupType gType, const ThemeProperty &p); bool addProperty(GroupType gType, const ThemeProperty &p);
std::optional<ThemeProperty> property(ThemeId themeId, std::optional<ThemeProperty> property(ThemeId themeId,
GroupType gType, GroupType gType,