QmlDesigner: Use Int and Real types instead of Number in Model Editor

* If a column has both integer and real numbers, it will be considered
as a real type.
* The edit delegate for integer has no decimals, and it's limited to
integer range.
* Data types are ordered for the column editor dialog

Task-number: QDS-11675
Change-Id: I43364e8dddd3fc9c336723f4db337088ffdd97ed
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Ali Kianian
2024-01-24 12:09:41 +02:00
parent 6c026c703f
commit 58dd1405fe
5 changed files with 105 additions and 27 deletions

View File

@@ -74,16 +74,16 @@ Item {
} }
Component { Component {
id: numberEditor id: realEditor
EditorPopup { EditorPopup {
editor: numberField editor: realField
StudioControls.RealSpinBox { StudioControls.RealSpinBox {
id: numberField id: realField
property alias editValue: numberField.realValue property alias editValue: realField.realValue
actionIndicator.visible: false actionIndicator.visible: false
realFrom: -9e9 realFrom: -9e9
@@ -95,6 +95,27 @@ Item {
} }
} }
Component {
id: integerEditor
EditorPopup {
editor: integerField
StudioControls.SpinBox {
id: integerField
property alias editValue: integerField.value
actionIndicatorVisible: false
spinBoxIndicatorVisible: true
from: -2147483647
to: 2147483647
decimals: 0
}
}
}
Component { Component {
id: boolEditor id: boolEditor
@@ -150,7 +171,8 @@ Item {
name: "default" name: "default"
when: columnType !== CollectionDetails.DataType.Boolean when: columnType !== CollectionDetails.DataType.Boolean
&& columnType !== CollectionDetails.DataType.Color && columnType !== CollectionDetails.DataType.Color
&& columnType !== CollectionDetails.DataType.Number && columnType !== CollectionDetails.DataType.Integer
&& columnType !== CollectionDetails.DataType.Real
PropertyChanges { PropertyChanges {
target: editorLoader target: editorLoader
@@ -158,12 +180,21 @@ Item {
} }
}, },
State { State {
name: "number" name: "integer"
when: columnType === CollectionDetails.DataType.Number when: columnType === CollectionDetails.DataType.Integer
PropertyChanges { PropertyChanges {
target: editorLoader target: editorLoader
sourceComponent: numberEditor sourceComponent: integerEditor
}
},
State {
name: "real"
when: columnType === CollectionDetails.DataType.Real
PropertyChanges {
target: editorLoader
sourceComponent: realEditor
} }
}, },
State { State {

View File

@@ -126,8 +126,11 @@ static CollectionProperty::DataType collectionDataTypeFromJsonValue(const QJsonV
return DataType::Unknown; return DataType::Unknown;
case JsonType::Bool: case JsonType::Bool:
return DataType::Boolean; return DataType::Boolean;
case JsonType::Double: case JsonType::Double: {
return DataType::Number; if (qFuzzyIsNull(std::remainder(value.toDouble(), 1)))
return DataType::Integer;
return DataType::Real;
}
case JsonType::String: { case JsonType::String: {
const QString stringValue = value.toString(); const QString stringValue = value.toString();
if (isValidColorName(stringValue)) if (isValidColorName(stringValue))
@@ -152,7 +155,9 @@ static QVariant valueToVariant(const QJsonValue &value, CollectionDetails::DataT
switch (type) { switch (type) {
case DataType::String: case DataType::String:
return variantValue.toString(); return variantValue.toString();
case DataType::Number: case DataType::Integer:
return variantValue.toInt();
case DataType::Real:
return variantValue.toDouble(); return variantValue.toDouble();
case DataType::Boolean: case DataType::Boolean:
return variantValue.toBool(); return variantValue.toBool();
@@ -180,8 +185,8 @@ static QJsonValue variantToJsonValue(
if (type == CollectionDetails::DataType::Unknown) { if (type == CollectionDetails::DataType::Unknown) {
static const QHash<VariantType, DataType> typeMap = {{VariantType::Bool, DataType::Boolean}, static const QHash<VariantType, DataType> typeMap = {{VariantType::Bool, DataType::Boolean},
{VariantType::Double, DataType::Number}, {VariantType::Double, DataType::Real},
{VariantType::Int, DataType::Number}, {VariantType::Int, DataType::Integer},
{VariantType::String, DataType::String}, {VariantType::String, DataType::String},
{VariantType::Color, DataType::Color}, {VariantType::Color, DataType::Color},
{VariantType::Url, DataType::Url}}; {VariantType::Url, DataType::Url}};
@@ -191,8 +196,10 @@ static QJsonValue variantToJsonValue(
switch (type) { switch (type) {
case DataType::Boolean: case DataType::Boolean:
return variant.toBool(); return variant.toBool();
case DataType::Number: case DataType::Real:
return variant.toDouble(); return variant.toDouble();
case DataType::Integer:
return variant.toInt();
case DataType::Image: { case DataType::Image: {
const QUrl url(variant.toUrl()); const QUrl url(variant.toUrl());
if (url.isValid()) if (url.isValid())
@@ -489,13 +496,19 @@ DataTypeWarning::Warning CollectionDetails::cellWarningCheck(int row, int column
const QString &propertyName = d->properties.at(column).name; const QString &propertyName = d->properties.at(column).name;
const QJsonObject &element = d->elements.at(row); const QJsonObject &element = d->elements.at(row);
if (typeAt(column) == DataType::Unknown || element.isEmpty() const DataType columnType = typeAt(column);
const DataType cellType = typeAt(row, column);
if (columnType == DataType::Unknown || element.isEmpty()
|| data(row, column) == QVariant::fromValue(nullptr)) { || data(row, column) == QVariant::fromValue(nullptr)) {
return DataTypeWarning::Warning::None; return DataTypeWarning::Warning::None;
} }
if (element.contains(propertyName) && typeAt(column) != typeAt(row, column)) if (element.contains(propertyName)) {
if (columnType == DataType::Real && cellType == DataType::Integer)
return DataTypeWarning::Warning::None;
else if (columnType != cellType)
return DataTypeWarning::Warning::CellDataTypeMismatch; return DataTypeWarning::Warning::CellDataTypeMismatch;
}
return DataTypeWarning::Warning::None; return DataTypeWarning::Warning::None;
} }
@@ -577,16 +590,23 @@ void CollectionDetails::resetPropertyType(const QString &propertyName)
void CollectionDetails::resetPropertyType(CollectionProperty &property) void CollectionDetails::resetPropertyType(CollectionProperty &property)
{ {
const QString &propertyName = property.name; const QString &propertyName = property.name;
DataType type = DataType::Unknown; DataType columnType = DataType::Unknown;
for (const QJsonObject &element : std::as_const(d->elements)) { for (const QJsonObject &element : std::as_const(d->elements)) {
if (element.contains(propertyName)) { if (element.contains(propertyName)) {
type = collectionDataTypeFromJsonValue(element.value(propertyName)); const DataType cellType = collectionDataTypeFromJsonValue(element.value(propertyName));
if (type != DataType::Unknown) if (cellType != DataType::Unknown) {
if (columnType == DataType::Integer && cellType != DataType::Real)
continue;
columnType = cellType;
if (columnType == DataType::Integer)
continue;
break; break;
} }
} }
}
property.type = type; property.type = columnType;
} }
void CollectionDetails::resetPropertyTypes() void CollectionDetails::resetPropertyTypes()

View File

@@ -60,7 +60,7 @@ class CollectionDetails
Q_GADGET Q_GADGET
public: public:
enum class DataType { Unknown, String, Url, Number, Boolean, Image, Color }; enum class DataType { Unknown, String, Url, Integer, Real, Boolean, Image, Color };
Q_ENUM(DataType) Q_ENUM(DataType)
explicit CollectionDetails(); explicit CollectionDetails();

View File

@@ -66,7 +66,7 @@ public:
static QStringList typesStringList() static QStringList typesStringList()
{ {
static const QStringList typesList = typeToStringHash().values(); static const QStringList typesList = orderedTypeNames();
return typesList; return typesList;
} }
@@ -79,7 +79,8 @@ private:
{DataType::Unknown, "Unknown"}, {DataType::Unknown, "Unknown"},
{DataType::String, "String"}, {DataType::String, "String"},
{DataType::Url, "Url"}, {DataType::Url, "Url"},
{DataType::Number, "Number"}, {DataType::Real, "Real"},
{DataType::Integer, "Integer"},
{DataType::Boolean, "Boolean"}, {DataType::Boolean, "Boolean"},
{DataType::Image, "Image"}, {DataType::Image, "Image"},
{DataType::Color, "Color"}, {DataType::Color, "Color"},
@@ -95,6 +96,29 @@ private:
return stringTypeHash; return stringTypeHash;
} }
static QStringList orderedTypeNames()
{
const QList<DataType> orderedtypes{
DataType::String,
DataType::Integer,
DataType::Real,
DataType::Image,
DataType::Color,
DataType::Url,
DataType::Boolean,
DataType::Unknown,
};
QStringList orderedNames;
QHash<DataType, QString> typeStringHash = typeToStringHash();
for (const DataType &type : orderedtypes)
orderedNames.append(typeStringHash.take(type));
Q_ASSERT(typeStringHash.isEmpty());
return orderedNames;
}
}; };
} // namespace } // namespace

View File

@@ -26,7 +26,7 @@
namespace { namespace {
using CollectionDataVariant = std::variant<QString, bool, double, QUrl, QColor>; using CollectionDataVariant = std::variant<QString, bool, double, int, QUrl, QColor>;
inline bool operator<(const QColor &a, const QColor &b) inline bool operator<(const QColor &a, const QColor &b)
{ {
@@ -40,12 +40,15 @@ inline CollectionDataVariant valueToVariant(const QVariant &value,
switch (type) { switch (type) {
case DataType::String: case DataType::String:
return value.toString(); return value.toString();
case DataType::Number: case DataType::Real:
return value.toDouble(); return value.toDouble();
case DataType::Integer:
return value.toInt();
case DataType::Boolean: case DataType::Boolean:
return value.toBool(); return value.toBool();
case DataType::Color: case DataType::Color:
return value.value<QColor>(); return value.value<QColor>();
case DataType::Image:
case DataType::Url: case DataType::Url:
return value.value<QUrl>(); return value.value<QUrl>();
default: default: