summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp3
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp74
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h4
-rw-r--r--src/declarative/qml/qdeclarativeprivate.h42
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/data/MyComponentType.qml5
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/data/qmlComponentType.qml4
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp14
7 files changed, 145 insertions, 1 deletions
diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp
index f401ac5..5d1ff36 100644
--- a/src/declarative/qml/qdeclarativeimport.cpp
+++ b/src/declarative/qml/qdeclarativeimport.cpp
@@ -529,6 +529,9 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp
if (QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin))
versionFound = true;
+ //Load any type->file mappings registered for this uri
+ qmldircomponents << QDeclarativeMetaType::qmlComponents(uri.toUtf8(), vmaj, vmin);
+
if (!versionFound && qmldircomponents.isEmpty()) {
if (errorString) {
bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1);
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index a94f4be..2fe181f 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -54,6 +54,8 @@
#include <QtCore/qmetaobject.h>
#include <QtCore/qbitarray.h>
#include <QtCore/qreadwritelock.h>
+#include <qfileinfo.h>
+#include <qdir.h>
#include <qmetatype.h>
#include <qobjectdefs.h>
#include <qdatetime.h>
@@ -122,6 +124,14 @@ struct QDeclarativeMetaTypeData
Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData)
Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+struct QDeclarativeRegisteredComponentData
+{
+ QMap<QByteArray, QDeclarativeDirComponents*> registeredComponents;
+};
+
+Q_GLOBAL_STATIC(QDeclarativeRegisteredComponentData, registeredComponentData)
+Q_GLOBAL_STATIC(QReadWriteLock, registeredComponentDataLock)
+
QDeclarativeMetaTypeData::~QDeclarativeMetaTypeData()
{
for (int i = 0; i < types.count(); ++i)
@@ -667,6 +677,45 @@ int registerType(const QDeclarativePrivate::RegisterType &type)
return index;
}
+int registerComponent(const QDeclarativePrivate::RegisterComponent& data)
+{
+ if (data.typeName) {
+ for (int ii = 0; data.typeName[ii]; ++ii) {
+ if (!isalnum(data.typeName[ii])) {
+ qWarning("qmlRegisterType(): Invalid QML type name \"%s\"", data.typeName);
+ return 0;
+ }
+ }
+ } else {
+ qWarning("qmlRegisterType(): No QML type name for \"%s\"", data.url.toString().toLatin1().constData());
+ return 0;
+ }
+
+ QWriteLocker lock(registeredComponentDataLock());
+ QString path;
+ // Relative paths are relative to application working directory
+ if (data.url.isRelative() || data.url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
+ path = QUrl::fromLocalFile(QDir::currentPath()+QLatin1String("/")).resolved(data.url).toString();
+ else
+ path = data.url.toString();
+ QDeclarativeRegisteredComponentData *d = registeredComponentData();
+ QDeclarativeDirParser::Component comp(
+ QString::fromUtf8(data.typeName),
+ path,
+ data.majorVersion,
+ data.minorVersion
+ );
+
+ QDeclarativeDirComponents* comps = d->registeredComponents.value(QByteArray(data.uri), 0);
+ if (!comps)
+ d->registeredComponents.insert(QByteArray(data.uri), comps = new QDeclarativeDirComponents);
+
+ // Types added later should take precedence, like registerType
+ comps->prepend(comp);
+
+ return 1;
+}
+
/*
This method is "over generalized" to allow us to (potentially) register more types of things in
the future without adding exported symbols.
@@ -679,6 +728,8 @@ int QDeclarativePrivate::qmlregister(RegistrationType type, void *data)
return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
} else if (type == AutoParentRegistration) {
return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
+ } else if (type == ComponentRegistration) {
+ return registerComponent(*reinterpret_cast<RegisterComponent *>(data));
}
return -1;
}
@@ -984,6 +1035,29 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(int userType)
}
/*!
+ Returns the component(s) that have been registered for the module specified by \a uri and the version specified
+ by \a version_major and \a version_minor. Returns an empty list if no such components were registered.
+*/
+QDeclarativeDirComponents QDeclarativeMetaType::qmlComponents(const QByteArray &module, int version_major, int version_minor)
+{
+ QReadLocker lock(registeredComponentDataLock());
+ QDeclarativeRegisteredComponentData *data = registeredComponentData();
+
+ QDeclarativeDirComponents* comps = data->registeredComponents.value(module, 0);
+ if (!comps)
+ return QDeclarativeDirComponents();
+ QDeclarativeDirComponents ret = *comps;
+ for (int i = ret.count() - 1; i >= 0; i--) {
+ QDeclarativeDirParser::Component &c = ret[i];
+ if (version_major >= 0 && (c.majorVersion != version_major || c.minorVersion > version_minor))
+ ret.removeAt(i);
+ }
+
+ return ret;
+}
+
+
+/*!
Returns the list of registered QML type names.
*/
QList<QByteArray> QDeclarativeMetaType::qmlTypeNames()
diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h
index 34064cd..117a669 100644
--- a/src/declarative/qml/qdeclarativemetatype_p.h
+++ b/src/declarative/qml/qdeclarativemetatype_p.h
@@ -59,6 +59,7 @@
#include <QtCore/qvariant.h>
#include <QtCore/qbitarray.h>
#include <private/qdeclarativeglobal_p.h>
+#include <private/qdeclarativedirparser_p.h>
QT_BEGIN_NAMESPACE
@@ -80,6 +81,8 @@ public:
static QDeclarativeType *qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor);
static QDeclarativeType *qmlType(int);
+ static QDeclarativeDirComponents qmlComponents(const QByteArray& module, int version_major, int version_minor);
+
static QMetaProperty defaultProperty(const QMetaObject *);
static QMetaProperty defaultProperty(QObject *);
static QMetaMethod defaultMethod(const QMetaObject *);
@@ -161,6 +164,7 @@ private:
friend struct QDeclarativeMetaTypeData;
friend int registerType(const QDeclarativePrivate::RegisterType &);
friend int registerInterface(const QDeclarativePrivate::RegisterInterface &);
+ friend int registerComponent(const QDeclarativePrivate::RegisterComponent &);
QDeclarativeType(int, const QDeclarativePrivate::RegisterInterface &);
QDeclarativeType(int, const QDeclarativePrivate::RegisterType &);
~QDeclarativeType();
diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h
index c90d04f..263d9b8 100644
--- a/src/declarative/qml/qdeclarativeprivate.h
+++ b/src/declarative/qml/qdeclarativeprivate.h
@@ -55,6 +55,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qurl.h>
QT_BEGIN_HEADER
@@ -233,13 +234,52 @@ namespace QDeclarativePrivate
AutoParentFunction function;
};
+ struct RegisterComponent {
+ const QUrl &url;
+ const char *uri;
+ const char *typeName;
+ int majorVersion;
+ int minorVersion;
+ };
+
enum RegistrationType {
TypeRegistration = 0,
InterfaceRegistration = 1,
- AutoParentRegistration = 2
+ AutoParentRegistration = 2,
+ ComponentRegistration = 3
};
int Q_DECLARATIVE_EXPORT qmlregister(RegistrationType, void *);
+
+
+ /*!
+ \internal
+ \fn int qmlRegisterType(const char *url, const char *uri, int versionMajor, int versionMinor, const char *qmlName);
+ \relates QDeclarativeEngine
+
+ This function registers a type in the QML system with the name \a qmlName, in the library imported from \a uri having the
+ version number composed from \a versionMajor and \a versionMinor. The type is defined by the QML file located at \a url.
+
+ Normally QML files can be loaded as types directly from other QML files, or using a qmldir file. This function allows
+ registration of files to types from a C++ module, such as when the type mapping needs to be procedurally determined at startup.
+
+ Returns non-zero if the registration was sucessful.
+
+ This function is added to QtQuick 1 in Qt 5, and is here as private API for developers needing compatibility.
+ */
+ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+ {
+ RegisterComponent type = {
+ url,
+ uri,
+ qmlName,
+ versionMajor,
+ versionMinor
+ };
+
+ return qmlregister(QDeclarativePrivate::ComponentRegistration, &type);
+ }
+
}
QT_END_NAMESPACE
diff --git a/tests/auto/declarative/qdeclarativelanguage/data/MyComponentType.qml b/tests/auto/declarative/qdeclarativelanguage/data/MyComponentType.qml
new file mode 100644
index 0000000..9ba0d61
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelanguage/data/MyComponentType.qml
@@ -0,0 +1,5 @@
+import QtQuick 1.0
+
+Item {
+ property int test: 11
+}
diff --git a/tests/auto/declarative/qdeclarativelanguage/data/qmlComponentType.qml b/tests/auto/declarative/qdeclarativelanguage/data/qmlComponentType.qml
new file mode 100644
index 0000000..a7c2ec4
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelanguage/data/qmlComponentType.qml
@@ -0,0 +1,4 @@
+import QtQuick 1.0
+import Test 1.0
+
+RegisteredComponentType {}
diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
index 14c7d82..dc965fd 100644
--- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
+++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp
@@ -41,6 +41,7 @@
#include <qtest.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeprivate.h>
#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
#include <QtCore/qfileinfo.h>
@@ -103,6 +104,7 @@ private slots:
void assignLiteralToVariant();
void customParserTypes();
void rootAsQmlComponent();
+ void qmlComponentType();
void inlineQmlComponents();
void idProperty();
void autoNotifyConnection();
@@ -642,6 +644,16 @@ void tst_qdeclarativelanguage::rootAsQmlComponent()
QCOMPARE(object->getChildren()->count(), 2);
}
+// Tests that types can be specified from a QML only component
+void tst_qdeclarativelanguage::qmlComponentType()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("qmlComponentType.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = qobject_cast<QObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("test"), QVariant(11));
+}
+
// Tests that components can be specified inline
void tst_qdeclarativelanguage::inlineQmlComponents()
{
@@ -1977,6 +1989,8 @@ void tst_qdeclarativelanguage::revisionOverloads()
void tst_qdeclarativelanguage::initTestCase()
{
registerTypes();
+ // Registered here because it uses TEST_FILE
+ QDeclarativePrivate::qmlRegisterType(TEST_FILE("MyComponentType.qml"), "Test", 1, 0, "RegisteredComponentType");
// Registering the TestType class in other modules should have no adverse effects
qmlRegisterType<TestType>("org.qtproject.TestPre", 1, 0, "Test");