Make the QtMultimedia singleton type a QObject.

It was a QJSValue for the sake of being as lightweight as possible
and because we don't actually need any of the QObject features for that
type in its current state.
However, this implies that type information is not available at
runtime. This is a problem for qmlplugindump which currently crashes
because it always expects every QML type to have an associated meta
object.

We can safely make that type a QObject since it doesn't affect source
compatibility in any way. This type was bound to become a QObject at
some point anyway.

Task-number: QTBUG-44299
Change-Id: I2d9b874f15ffc94ed95ef74fadc3b1fd193fe1ef
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
This commit is contained in:
Yoann Lopes
2015-04-08 15:10:00 +02:00
parent ddec92543f
commit a700ff9674
3 changed files with 45 additions and 45 deletions

View File

@@ -57,6 +57,12 @@ QML_DECLARE_TYPE(QSoundEffect)
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
static QObject *multimedia_global_object(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
{
Q_UNUSED(qmlEngine)
return new QDeclarativeMultimediaGlobal(jsEngine);
}
class QMultimediaDeclarativeModule : public QQmlExtensionPlugin class QMultimediaDeclarativeModule : public QQmlExtensionPlugin
{ {
Q_OBJECT Q_OBJECT
@@ -98,7 +104,7 @@ public:
qmlRegisterType<QSoundEffect>(uri, 5, 3, "SoundEffect"); qmlRegisterType<QSoundEffect>(uri, 5, 3, "SoundEffect");
// 5.4 types // 5.4 types
qmlRegisterSingletonType(uri, 5, 4, "QtMultimedia", QDeclarativeMultimedia::initGlobalObject); qmlRegisterSingletonType<QDeclarativeMultimediaGlobal>(uri, 5, 4, "QtMultimedia", multimedia_global_object);
qmlRegisterRevision<QDeclarativeCamera, 1>(uri, 5, 4); qmlRegisterRevision<QDeclarativeCamera, 1>(uri, 5, 4);
qmlRegisterUncreatableType<QDeclarativeCameraViewfinder>(uri, 5, 4, "CameraViewfinder", qmlRegisterUncreatableType<QDeclarativeCameraViewfinder>(uri, 5, 4, "CameraViewfinder",
trUtf8("CameraViewfinder is provided by Camera")); trUtf8("CameraViewfinder is provided by Camera"));

View File

@@ -153,27 +153,6 @@ Camera {
\endqml \endqml
*/ */
namespace QDeclarativeMultimedia {
#define FREEZE_SOURCE "(function deepFreeze(o) { "\
" var prop, propKey;" \
" Object.freeze(o);" \
" for (propKey in o) {" \
" prop = o[propKey];" \
" if (!o.hasOwnProperty(propKey) || !(typeof prop === \"object\") || " \
" Object.isFrozen(prop)) {" \
" continue;" \
" }" \
" deepFreeze(prop);" \
" }" \
"})"
static void deepFreeze(QJSEngine *jsEngine, const QJSValue &obj)
{
QJSValue freezeFunc = jsEngine->evaluate(QString::fromUtf8(FREEZE_SOURCE));
freezeFunc.call(QJSValueList() << obj);
}
static QJSValue cameraInfoToJSValue(QJSEngine *jsEngine, const QCameraInfo &camera) static QJSValue cameraInfoToJSValue(QJSEngine *jsEngine, const QCameraInfo &camera)
{ {
QJSValue o = jsEngine->newObject(); QJSValue o = jsEngine->newObject();
@@ -184,29 +163,24 @@ static QJSValue cameraInfoToJSValue(QJSEngine *jsEngine, const QCameraInfo &came
return o; return o;
} }
QJSValue initGlobalObject(QQmlEngine *qmlEngine, QJSEngine *jsEngine) QDeclarativeMultimediaGlobal::QDeclarativeMultimediaGlobal(QJSEngine *engine, QObject *parent)
: QObject(parent)
, m_engine(engine)
{ {
Q_UNUSED(qmlEngine)
QJSValue globalObject = jsEngine->newObject();
// property object defaultCamera
globalObject.setProperty(QStringLiteral("defaultCamera"),
cameraInfoToJSValue(jsEngine, QCameraInfo::defaultCamera()));
// property list<object> availableCameras
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
QJSValue availableCameras = jsEngine->newArray(cameras.count());
for (int i = 0; i < cameras.count(); ++i)
availableCameras.setProperty(i, cameraInfoToJSValue(jsEngine, cameras.at(i)));
globalObject.setProperty(QStringLiteral("availableCameras"), availableCameras);
// freeze global object to prevent properties to be modified from QML
deepFreeze(jsEngine, globalObject);
return globalObject;
} }
QJSValue QDeclarativeMultimediaGlobal::defaultCamera() const
{
return cameraInfoToJSValue(m_engine, QCameraInfo::defaultCamera());
}
QJSValue QDeclarativeMultimediaGlobal::availableCameras() const
{
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
QJSValue availableCameras = m_engine->newArray(cameras.count());
for (int i = 0; i < cameras.count(); ++i)
availableCameras.setProperty(i, cameraInfoToJSValue(m_engine, cameras.at(i)));
return availableCameras;
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -46,12 +46,32 @@
// //
#include <QtQml/qqml.h> #include <QtQml/qqml.h>
#include <QtQml/qjsvalue.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace QDeclarativeMultimedia { class QDeclarativeMultimediaGlobal : public QObject
QJSValue initGlobalObject(QQmlEngine *, QJSEngine *); {
} Q_OBJECT
Q_PROPERTY(QJSValue defaultCamera READ defaultCamera NOTIFY defaultCameraChanged)
Q_PROPERTY(QJSValue availableCameras READ availableCameras NOTIFY availableCamerasChanged)
public:
explicit QDeclarativeMultimediaGlobal(QJSEngine *engine, QObject *parent = 0);
QJSValue defaultCamera() const;
QJSValue availableCameras() const;
Q_SIGNALS:
// Unused at the moment. QCameraInfo doesn't notify when cameras are added or removed,
// but it might change in the future.
void defaultCameraChanged();
void availableCamerasChanged();
private:
QJSEngine *m_engine;
};
QT_END_NAMESPACE QT_END_NAMESPACE