QmlDesigner: Add edit delegate to the CollectionDetailsView

Delegates are added for the Color, Bool, Number, ad String types.
The default delegate is string delegate.

Task-number: QDS-10989
Change-Id: I7dbaf5451d8be778691e72e18bd3124a754e47b7
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Ali Kianian
2023-10-18 11:41:18 +03:00
parent 709bcd640d
commit bf99d08ca1
9 changed files with 239 additions and 4 deletions

View File

@@ -0,0 +1,154 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import CollectionDetails 1.0 as CollectionDetails
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Item {
id: root
required property var columnType
property var __modifier : textEditor
width: itemColumn.width
height: itemColumn.height
TableView.onCommit: edit = __modifier.editValue
Component.onCompleted: {
if (edit && edit !== "")
root.__modifier.editValue = edit
}
onActiveFocusChanged: {
if (root.activeFocus)
root.__modifier.forceActiveFocus()
}
Connections {
id: modifierFocusConnection
target: root.__modifier
function onActiveFocusChanged() {
if (!modifierFocusConnection.target.activeFocus)
TableView.commit()
}
}
Column {
id: itemColumn
StudioControls.TextField {
id: textEditor
property alias editValue: textEditor.text
actionIndicator.visible: false
translationIndicatorVisible: false
enabled: visible
visible: false
}
StudioControls.RealSpinBox {
id: numberEditor
property alias editValue: numberEditor.realValue
actionIndicator.visible: false
enabled: visible
visible: false
realFrom: -9e9
realTo: 9e9
realStepSize: 1.0
decimals: 6
}
StudioControls.CheckBox {
id: boolEditor
property alias editValue: boolEditor.checked
actionIndicatorVisible: false
enabled: visible
visible: false
}
HelperWidgets.ColorPicker {
id: colorEditor
property alias editValue: colorEditor.color
width: 100
enabled: visible
visible: false
}
}
states: [
State {
name: "default"
when: columnType !== CollectionDetails.DataType.Boolean
&& columnType !== CollectionDetails.DataType.Color
&& columnType !== CollectionDetails.DataType.Number
PropertyChanges {
target: root
__modifier: textEditor
}
PropertyChanges {
target: textEditor
visible: true
focus: true
}
},
State {
name: "number"
when: columnType === CollectionDetails.DataType.Number
PropertyChanges {
target: root
__modifier: numberEditor
}
PropertyChanges {
target: numberEditor
visible: true
focus: true
}
},
State {
name: "bool"
when: columnType === CollectionDetails.DataType.Boolean
PropertyChanges {
target: root
__modifier: boolEditor
}
PropertyChanges {
target: boolEditor
visible: true
focus: true
}
},
State {
name: "color"
when: columnType === CollectionDetails.DataType.Color
PropertyChanges {
target: root
__modifier: colorEditor
}
PropertyChanges {
target: colorEditor
visible: true
focus: true
}
}
]
}

View File

@@ -201,6 +201,13 @@ Rectangle {
elide: Text.ElideRight
}
TableView.editDelegate: CollectionDetailsEditDelegate {
anchors {
top: itemText.top
left: itemText.left
}
}
states: [
State {
name: "default"

View File

@@ -4,6 +4,7 @@
#include "collectiondetails.h"
#include <utils/span.h>
#include <qqml.h>
#include <QJsonArray>
#include <QJsonObject>
@@ -220,6 +221,21 @@ bool CollectionDetails::removeElements(int row, int count)
return true;
}
bool CollectionDetails::setPropertyValue(int row, int column, const QVariant &value)
{
if (!d->isValidRowId(row) || !d->isValidColumnId(column))
return false;
QJsonObject &element = d->elements[row];
QVariant currentValue = data(row, column);
if (value == currentValue)
return false;
element.insert(d->properties.at(column).name, QJsonValue::fromVariant(value));
return true;
}
bool CollectionDetails::setPropertyName(int column, const QString &value)
{
if (!d->isValidColumnId(column))
@@ -316,6 +332,20 @@ CollectionDetails::DataType CollectionDetails::typeAt(int column) const
return d->properties.at(column).type;
}
CollectionDetails::DataType CollectionDetails::typeAt(int row, int column) const
{
if (!d->isValidRowId(row) || !d->isValidColumnId(column))
return {};
const QString &propertyName = d->properties.at(column).name;
const QJsonObject &element = d->elements.at(row);
if (element.contains(propertyName))
return collectionDataTypeFromJsonValue(element.value(propertyName));
return {};
}
bool CollectionDetails::containsPropertyName(const QString &propertyName)
{
if (!isValid())
@@ -360,6 +390,13 @@ void CollectionDetails::swap(CollectionDetails &other)
d.swap(other.d);
}
void CollectionDetails::registerDeclarativeType()
{
typedef CollectionDetails::DataType DataType;
qRegisterMetaType<DataType>("DataType");
qmlRegisterUncreatableType<CollectionDetails>("CollectionDetails", 1, 0, "DataType", "Enum type");
}
CollectionDetails &CollectionDetails::operator=(const CollectionDetails &other)
{
CollectionDetails value(other);

View File

@@ -37,8 +37,11 @@ struct CollectionProperty;
class CollectionDetails
{
Q_GADGET
public:
enum class DataType { Unknown, String, Url, Number, Boolean, Image, Color };
Q_ENUM(DataType)
explicit CollectionDetails();
CollectionDetails(const CollectionReference &reference);
@@ -57,6 +60,7 @@ public:
void insertElementAt(std::optional<QJsonObject> object, int row = -1);
void insertEmptyElements(int row = 0, int count = 1);
bool removeElements(int row, int count = 1);
bool setPropertyValue(int row, int column, const QVariant &value);
bool setPropertyName(int column, const QString &value);
bool forcePropertyType(int column, DataType type, bool force = false);
@@ -66,6 +70,7 @@ public:
QVariant data(int row, int column) const;
QString propertyAt(int column) const;
DataType typeAt(int column) const;
DataType typeAt(int row, int column) const;
bool containsPropertyName(const QString &propertyName);
bool isValid() const;
@@ -80,6 +85,8 @@ public:
QJsonArray getJsonCollection() const;
QString getCsvCollection() const;
static void registerDeclarativeType();
CollectionDetails &operator=(const CollectionDetails &other);
private:

View File

@@ -100,6 +100,7 @@ QHash<int, QByteArray> CollectionDetailsModel::roleNames() const
roles.insert(QAbstractTableModel::roleNames());
roles.insert(SelectedRole, "itemSelected");
roles.insert(DataTypeRole, "dataType");
roles.insert(ColumnDataTypeRole, "columnType");
}
return roles;
}
@@ -122,11 +123,31 @@ QVariant CollectionDetailsModel::data(const QModelIndex &index, int role) const
if (role == SelectedRole)
return (index.column() == m_selectedColumn || index.row() == m_selectedRow);
if (role == DataTypeRole)
return QVariant::fromValue(m_currentCollection.typeAt(index.row(), index.column()));
if (role == ColumnDataTypeRole)
return QVariant::fromValue(m_currentCollection.typeAt(index.column()));
if (role == Qt::EditRole)
return m_currentCollection.data(index.row(), index.column());
return m_currentCollection.data(index.row(), index.column()).toString();
}
bool CollectionDetailsModel::setData(const QModelIndex &, const QVariant &, int)
bool CollectionDetailsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return {};
if (role == Qt::EditRole) {
bool changed = m_currentCollection.setPropertyValue(index.row(), index.column(), value);
if (changed) {
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
return true;
}
}
return false;
}
@@ -189,7 +210,7 @@ Qt::ItemFlags CollectionDetailsModel::flags(const QModelIndex &index) const
if (!index.isValid())
return {};
return {Qt::ItemIsSelectable | Qt::ItemIsEnabled};
return {Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable};
}
QVariant CollectionDetailsModel::headerData(int section, Qt::Orientation orientation, int role) const

View File

@@ -22,7 +22,7 @@ class CollectionDetailsModel : public QAbstractTableModel
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
public:
enum DataRoles { SelectedRole = Qt::UserRole + 1, DataTypeRole };
enum DataRoles { SelectedRole = Qt::UserRole + 1, DataTypeRole, ColumnDataTypeRole };
explicit CollectionDetailsModel(QObject *parent = nullptr);

View File

@@ -153,6 +153,11 @@ void CollectionView::addResource(const QUrl &url, const QString &name, const QSt
});
}
void CollectionView::registerDeclarativeType()
{
CollectionDetails::registerDeclarativeType();
}
void CollectionView::refreshModel()
{
if (!model())

View File

@@ -43,6 +43,8 @@ public:
void addResource(const QUrl &url, const QString &name, const QString &type);
static void registerDeclarativeType();
private:
void refreshModel();
NodeMetaInfo jsonCollectionMetaInfo() const;

View File

@@ -4,6 +4,7 @@
#include "qmldesignerplugin.h"
#include "qmldesignertr.h"
#include "collectioneditor/collectionview.h"
#include "coreplugin/iwizardfactory.h"
#include "designmodecontext.h"
#include "designmodewidget.h"
@@ -282,6 +283,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
//TODO Move registering those types out of the property editor, since they are used also in the states editor
Quick2PropertyEditorView::registerQmlTypes();
CollectionView::registerDeclarativeType();
if (checkEnterpriseLicense())
Core::IWizardFactory::registerFeatureProvider(new EnterpriseFeatureProvider);