Fix char conversions in QML
This is a partial revert of 90b06e2773
, as it had unwanted side
effects. The original intention was to make assignment from char to
string possible, or more specifically, we wanted a solution where a
QChar could be assigned to a QString, as a character and not a string
representation of its value. While this behavior is desirable for
QChar, we most likely want the opposite for the regular character types.
Task-number: QTBUG-49232
Change-Id: I82d5f72b900fe984c4db1478fd52a9eb69ad2ee6
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
31ca52cee4
commit
35597f3014
|
@ -1143,8 +1143,13 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
|
|||
return value.integerValue();
|
||||
if (value.isNumber())
|
||||
return value.asDouble();
|
||||
if (value.isString())
|
||||
return value.stringValue()->toQString();
|
||||
if (value.isString()) {
|
||||
const QString &str = value.toQString();
|
||||
// QChars are stored as a strings
|
||||
if (typeHint == QVariant::Char && str.size() == 1)
|
||||
return str.at(0);
|
||||
return str;
|
||||
}
|
||||
if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
|
||||
return ld->d()->locale;
|
||||
if (const QV4::DateObject *d = value.as<DateObject>())
|
||||
|
@ -1284,9 +1289,9 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
|
|||
case QMetaType::UShort:
|
||||
return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
|
||||
case QMetaType::Char:
|
||||
return newString(QChar::fromLatin1(*reinterpret_cast<const char *>(ptr)))->asReturnedValue();
|
||||
return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
|
||||
case QMetaType::UChar:
|
||||
return newString(QChar::fromLatin1(*reinterpret_cast<const unsigned char *>(ptr)))->asReturnedValue();
|
||||
return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
|
||||
case QMetaType::QChar:
|
||||
return newString(*reinterpret_cast<const QChar *>(ptr))->asReturnedValue();
|
||||
case QMetaType::QDateTime:
|
||||
|
|
|
@ -1327,29 +1327,8 @@ bool QQmlPropertyPrivate::write(QObject *object,
|
|||
|
||||
bool ok = false;
|
||||
QVariant v;
|
||||
if (variantType == QVariant::String) {
|
||||
const QString &str = value.toString();
|
||||
const bool targetIsChar = (propertyType == qMetaTypeId<QChar>()
|
||||
|| propertyType == qMetaTypeId<char>()
|
||||
|| propertyType == qMetaTypeId<unsigned char>());
|
||||
// If the string contains only one character and the target is a char, try converting it.
|
||||
if (targetIsChar) {
|
||||
if (str.size() != 1)
|
||||
return false; // We can only convert if the string contains exactly one character.
|
||||
|
||||
const QChar &qChar = str.at(0);
|
||||
if (propertyType == qMetaTypeId<QChar>()) {
|
||||
v = qChar;
|
||||
ok = true;
|
||||
} else if (propertyType == qMetaTypeId<char>() || propertyType == qMetaTypeId<unsigned char>()) {
|
||||
const char c = qChar.toLatin1();
|
||||
v = c;
|
||||
ok = (qChar == c);
|
||||
}
|
||||
} else {
|
||||
v = QQmlStringConverters::variantFromString(str, propertyType, &ok);
|
||||
}
|
||||
}
|
||||
if (variantType == QVariant::String)
|
||||
v = QQmlStringConverters::variantFromString(value.toString(), propertyType, &ok);
|
||||
|
||||
if (!ok) {
|
||||
v = value;
|
||||
|
|
|
@ -66,6 +66,7 @@ private slots:
|
|||
void qtbug_22535();
|
||||
void evalAfterInvalidate();
|
||||
void qobjectDerived();
|
||||
void qtbug_49232();
|
||||
|
||||
private:
|
||||
QQmlEngine engine;
|
||||
|
@ -205,6 +206,8 @@ class TestObject : public QObject
|
|||
Q_PROPERTY(int a READ a NOTIFY aChanged)
|
||||
Q_PROPERTY(int b READ b NOTIFY bChanged)
|
||||
Q_PROPERTY(int c READ c NOTIFY cChanged)
|
||||
Q_PROPERTY(char d READ d NOTIFY dChanged)
|
||||
Q_PROPERTY(uchar e READ e NOTIFY eChanged)
|
||||
|
||||
public:
|
||||
TestObject() : _a(10), _b(10), _c(10) {}
|
||||
|
@ -218,15 +221,25 @@ public:
|
|||
int c() const { return _c; }
|
||||
void setC(int c) { _c = c; emit cChanged(); }
|
||||
|
||||
char d() const { return _d; }
|
||||
void setD(char d) { _d = d; emit dChanged(); }
|
||||
|
||||
uchar e() const { return _e; }
|
||||
void setE(uchar e) { _e = e; emit eChanged(); }
|
||||
|
||||
signals:
|
||||
void aChanged();
|
||||
void bChanged();
|
||||
void cChanged();
|
||||
void dChanged();
|
||||
void eChanged();
|
||||
|
||||
private:
|
||||
int _a;
|
||||
int _b;
|
||||
int _c;
|
||||
char _d;
|
||||
uchar _e;
|
||||
};
|
||||
|
||||
#define TEST_CONTEXT_PROPERTY(ctxt, name, value) \
|
||||
|
@ -699,6 +712,22 @@ void tst_qqmlcontext::qobjectDerived()
|
|||
QCOMPARE(command.count, 2);
|
||||
}
|
||||
|
||||
void tst_qqmlcontext::qtbug_49232()
|
||||
{
|
||||
TestObject testObject;
|
||||
testObject.setD('a');
|
||||
testObject.setE(97);
|
||||
|
||||
QQmlEngine engine;
|
||||
engine.rootContext()->setContextProperty("TestObject", &testObject);
|
||||
QQmlComponent component(&engine);
|
||||
component.setData("import QtQuick 2.0; QtObject { property int valueOne: TestObject.d; property int valueTwo: TestObject.e }", QUrl());
|
||||
QScopedPointer<QObject> obj(component.create());
|
||||
|
||||
QCOMPARE(obj->property("valueOne"), QVariant('a'));
|
||||
QCOMPARE(obj->property("valueTwo"), QVariant(97));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qqmlcontext)
|
||||
|
||||
#include "tst_qqmlcontext.moc"
|
||||
|
|
|
@ -329,11 +329,8 @@ class PropertyObject : public QObject
|
|||
Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
|
||||
Q_PROPERTY(MyQObject *qObject READ qObject WRITE setQObject NOTIFY qObjectChanged)
|
||||
Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty)
|
||||
Q_PROPERTY(char charProperty READ charProperty WRITE setCharProperty)
|
||||
Q_PROPERTY(QChar qcharProperty READ qcharProperty WRITE setQcharProperty)
|
||||
Q_PROPERTY(QChar constQChar READ constQChar STORED false CONSTANT FINAL)
|
||||
Q_PROPERTY(char constChar READ constChar STORED false CONSTANT FINAL)
|
||||
Q_PROPERTY(int constInt READ constInt STORED false CONSTANT FINAL)
|
||||
|
||||
Q_CLASSINFO("DefaultProperty", "defaultProperty")
|
||||
public:
|
||||
|
@ -370,15 +367,11 @@ public:
|
|||
}
|
||||
|
||||
QString stringProperty() const { return m_stringProperty;}
|
||||
char charProperty() const { return m_charProperty; }
|
||||
QChar qcharProperty() const { return m_qcharProperty; }
|
||||
|
||||
QChar constQChar() const { return 0x25cf; /* Unicode: black circle */ }
|
||||
char constChar() const { return 'A'; }
|
||||
int constInt() const { return 123456; }
|
||||
|
||||
void setStringProperty(QString arg) { m_stringProperty = arg; }
|
||||
void setCharProperty(char arg) { m_charProperty = arg; }
|
||||
void setQcharProperty(QChar arg) { m_qcharProperty = arg; }
|
||||
|
||||
signals:
|
||||
|
@ -395,7 +388,6 @@ private:
|
|||
MyQmlObject m_qmlObject;
|
||||
MyQObject *m_qObject;
|
||||
QString m_stringProperty;
|
||||
char m_charProperty;
|
||||
QChar m_qcharProperty;
|
||||
};
|
||||
|
||||
|
@ -1408,23 +1400,14 @@ void tst_qqmlproperty::write()
|
|||
// Char/string-property
|
||||
{
|
||||
PropertyObject o;
|
||||
QQmlProperty charProperty(&o, "charProperty");
|
||||
QQmlProperty qcharProperty(&o, "qcharProperty");
|
||||
QQmlProperty stringProperty(&o, "stringProperty");
|
||||
|
||||
const int black_circle = 0x25cf;
|
||||
|
||||
QCOMPARE(charProperty.write(QString("foo")), false);
|
||||
QCOMPARE(charProperty.write('Q'), true);
|
||||
QCOMPARE(charProperty.read(), QVariant('Q'));
|
||||
QCOMPARE(charProperty.write(QString("t")), true);
|
||||
QCOMPARE(charProperty.read(), QVariant('t'));
|
||||
|
||||
QCOMPARE(qcharProperty.write(QString("foo")), false);
|
||||
QCOMPARE(qcharProperty.write('Q'), true);
|
||||
QCOMPARE(qcharProperty.read(), QVariant('Q'));
|
||||
QCOMPARE(qcharProperty.write(QString("t")), true);
|
||||
QCOMPARE(qcharProperty.read(), QVariant('t'));
|
||||
QCOMPARE(qcharProperty.write(QChar(black_circle)), true);
|
||||
QCOMPARE(qcharProperty.read(), QVariant(QChar(black_circle)));
|
||||
|
||||
|
@ -1433,19 +1416,10 @@ void tst_qqmlproperty::write()
|
|||
QCOMPARE(o.stringProperty(), QString("bar"));
|
||||
QCOMPARE(stringProperty.write(QVariant(1234)), true);
|
||||
QCOMPARE(stringProperty.read().toString(), QString::number(1234));
|
||||
QCOMPARE(stringProperty.write('A'), true);
|
||||
QCOMPARE(stringProperty.read().toString(), QString::number('A'));
|
||||
QCOMPARE(stringProperty.write(QChar(black_circle)), true);
|
||||
QCOMPARE(stringProperty.read(), QVariant(QString(QChar(black_circle))));
|
||||
|
||||
{ // char -> QString
|
||||
QQmlComponent component(&engine);
|
||||
component.setData("import Test 1.0\nPropertyObject { stringProperty: constChar }", QUrl());
|
||||
PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
|
||||
QVERIFY(obj != 0);
|
||||
if (obj) {
|
||||
QQmlProperty stringProperty(obj, "stringProperty");
|
||||
QCOMPARE(stringProperty.read(), QVariant(QString(obj->constChar())));
|
||||
}
|
||||
}
|
||||
QCOMPARE(stringProperty.read(), QVariant(QChar(black_circle)));
|
||||
|
||||
{ // QChar -> QString
|
||||
QQmlComponent component(&engine);
|
||||
|
@ -1458,16 +1432,6 @@ void tst_qqmlproperty::write()
|
|||
}
|
||||
}
|
||||
|
||||
{ // int -> QString
|
||||
QQmlComponent component(&engine);
|
||||
component.setData("import Test 1.0\nPropertyObject { stringProperty: constInt }", QUrl());
|
||||
PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
|
||||
QVERIFY(obj != 0);
|
||||
if (obj) {
|
||||
QQmlProperty stringProperty(obj, "stringProperty");
|
||||
QCOMPARE(stringProperty.read(), QVariant(QString::number(obj->constInt())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VariantMap-property
|
||||
|
|
Loading…
Reference in New Issue