| 216 | |
| 217 | === Value Conversion === |
| 218 | |
| 219 | When interacting with Qt/C++ objects in JS, it will often be necessary to perform value conversion between the two worlds. For reading properties, QMetaProperty::read() returns a QVariant; this value must be converted to a JS value of a suitable type. For writing properties, QMetaProperty::write() takes a QVariant as argument; hence, the value passed from JS must first be converted to a QVariant of a suitable type. For calling slots, we may have to perform conversion both ways; converting arguments from JS to C++, and converting the slot's return value back to JS. |
| 220 | |
| 221 | The two "top-level" Qt/C++ <--> JS conversion functions are: |
| 222 | |
| 223 | * '''qtVariantToJS(QVariant) : JSValue''': Converts a QVariant to a JS value. |
| 224 | * '''qtVariantFromJS(JSValue) : QVariant''': Converts a JSValue to a QVariant. |
| 225 | |
| 226 | A QVariant can contain a value of any type known to the Qt meta-type system; this includes both QMetaType's built-in types (bool, int, QString, etc.) and custom (user) types. |
| 227 | |
| 228 | A QVariant's meta-type can be obtained from QVariant::userType(). A void pointer to the value can be obtained from QVariant::constData(). For example, if the type is QMetaType::Double, it's safe to cast the data pointer to double*; if the type is QMetaType::QString, it's safe to cast the data pointer to QString*; and so on. |
| 229 | |
| 230 | Given a meta-type, storage for a value of that type can be allocated using the QMetaType(int type, const void *data) constructor. |
| 231 | |
| 232 | We introduce two helper functions to convert between (userType, data*) pairs and JS values: |
| 233 | |
| 234 | * '''qtMetaTypeToJS(int, void*) : JSValue''': Converts a meta-type to a JS value. |
| 235 | * '''qtMetaTypeFromJS(JSValue, int, void*) : bool''': Converts a JSValue to a meta-type. |
| 236 | |
| 237 | These functions are essentially huge switches on the type argument, that cast the data pointer and get/set the value accordingly. |
| 238 | |
| 239 | Some non-primitive types have special handling: |
| 240 | |
| 241 | * QDateTime: Converted from/to JS Date object. |
| 242 | * QRegExp: Converted from/to JS RegExp object. |
| 243 | * QStringList: Converted from/to JS Array object. |
| 244 | * QVariantList: Converted from/to JS Array object. |
| 245 | * QVariantMap: Converted from/to JS Object object. |
| 246 | |
| 247 | In many cases there is no "good" conversion between a C++ type and JS. For example, there's no obvious way to convert a QPixmap to a JS object. For types where no "standard" (read: automagic) conversion makes sense, including user types, QtScript falls back to creating a JS wrapper object that contains the QVariant. |
| 248 | |
| 249 | It's possible to override QtScript's conversion of any type by registering a pair of conversion functions for the type using qScriptRegisterMetaType(). |