diff options
Diffstat (limited to 'src/declarative/qml/qdeclarativeengine.cpp')
-rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 135 |
1 files changed, 128 insertions, 7 deletions
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 9fde18c81c..ba0ddbbfaf 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -55,6 +55,7 @@ #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativexmlhttprequest_p.h" #include "private/qdeclarativesqldatabase_p.h" +#include "private/qdeclarativescarceresourcescriptclass_p.h" #include "private/qdeclarativetypenamescriptclass_p.h" #include "private/qdeclarativelistscriptclass_p.h" #include "qdeclarativescriptstring.h" @@ -103,6 +104,8 @@ #include <private/qdeclarativeitemsmodule_p.h> #include <private/qdeclarativeutilmodule_p.h> +#include <private/qsgitemsmodule_p.h> +#include <qsgtexture.h> #ifdef Q_OS_WIN // for %APPDATA% #include <qt_windows.h> @@ -349,13 +352,15 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0), inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0), - typeLoader(e), importDatabase(e), uniqueId(1) + scarceResources(0), scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1), + sgContext(0) { if (!qt_QmlQtModule_registered) { qt_QmlQtModule_registered = true; QDeclarativeItemModule::defineModule(); QDeclarativeUtilModule::defineModule(); QDeclarativeEnginePrivate::defineModule(); + QSGItemsModule::defineModule(); QDeclarativeValueTypeFactory::registerValueTypes(); } globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine); @@ -499,6 +504,8 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate() contextClass = 0; delete objectClass; objectClass = 0; + delete scarceResourceClass; + scarceResourceClass = 0; delete valueTypeClass; valueTypeClass = 0; delete typeNameClass; @@ -514,7 +521,10 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate() (*iter)->release(); for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter) (*iter)->release(); - + for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) { + delete (*iter)->qobjectApi; + delete *iter; + } } void QDeclarativeEnginePrivate::clear(SimpleList<QDeclarativeAbstractBinding> &bvs) @@ -571,6 +581,7 @@ void QDeclarativeEnginePrivate::init() contextClass = new QDeclarativeContextScriptClass(q); objectClass = new QDeclarativeObjectScriptClass(q); + scarceResourceClass = new QDeclarativeScarceResourceScriptClass(q); valueTypeClass = new QDeclarativeValueTypeScriptClass(q); typeNameClass = new QDeclarativeTypeNameScriptClass(q); listClass = new QDeclarativeListScriptClass(q); @@ -647,6 +658,22 @@ QDeclarativeEngine::~QDeclarativeEngine() Q_D(QDeclarativeEngine); if (d->isDebugging) QDeclarativeEngineDebugServer::instance()->remEngine(this); + + // if we are the parent of any of the qobject module api instances, + // we need to remove them from our internal list, in order to prevent + // a segfault in engine private dtor. + QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys(); + QObject *currQObjectApi = 0; + QDeclarativeMetaType::ModuleApiInstance *currInstance = 0; + foreach (const QDeclarativeMetaType::ModuleApi &key, keys) { + currInstance = d->moduleApiInstances.value(key); + currQObjectApi = currInstance->qobjectApi; + if (this->children().contains(currQObjectApi)) { + delete currQObjectApi; + delete currInstance; + d->moduleApiInstances.remove(key); + } + } } /*! \fn void QDeclarativeEngine::quit() @@ -813,6 +840,18 @@ QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProvider return static_cast<QDeclarativeImageProvider::ImageType>(-1); } +QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size) +{ + QMutexLocker locker(&mutex); + QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host()); + locker.unlock(); + if (provider) { + QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); + return provider->requestTexture(imageId, size, req_size); + } + return 0; +} + QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size) { QMutexLocker locker(&mutex); @@ -1699,9 +1738,6 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine qsreal w = ctxt->argument(2).toNumber(); qsreal h = ctxt->argument(3).toNumber(); - if (w < 0 || h < 0) - return engine->nullValue(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } @@ -2056,7 +2092,9 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) { - if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { + if (variantIsScarceResource(val)) { + return scarceResourceClass->newScarceResource(val); + } else if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { QDeclarativeListReferencePrivate *p = QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData()); if (p->object) { @@ -2085,11 +2123,69 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } } +/* + If the variant is a scarce resource (consumes a large amount of memory, or + only a limited number of them can be held in memory at any given time without + exhausting supply for future use) we need to release the scarce resource + after evaluation of the javascript binding is complete. + */ +bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val) +{ + if (val.type() == QVariant::Pixmap) { + return true; + } else if (val.type() == QVariant::Image) { + return true; + } + + return false; +} + +/* + This function should be called prior to evaluation of any js expression, + so that scarce resources are not freed prematurely (eg, if there is a + nested javascript expression). + */ +void QDeclarativeEnginePrivate::referenceScarceResources() +{ + scarceResourcesRefCount += 1; +} + +/* + This function should be called after evaluation of the js expression is + complete, and so the scarce resources may be freed safely. + */ +void QDeclarativeEnginePrivate::dereferenceScarceResources() +{ + Q_ASSERT(scarceResourcesRefCount > 0); + scarceResourcesRefCount -= 1; + + // if the refcount is zero, then evaluation of the "top level" + // expression must have completed. We can safely release the + // scarce resources. + if (scarceResourcesRefCount == 0) { + // iterate through the list and release them all. + // note that the actual SRD is owned by the JS engine, + // so we cannot delete the SRD; but we can free the + // memory used by the variant in the SRD. + ScarceResourceData *srd = 0; + while (scarceResources) { + srd = scarceResources; // srd points to the "old" (current) head of the list + scarceResources = srd->next; // srd->next is the "new" head of the list + if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr. + srd->next = 0; + srd->prev = 0; + srd->releaseResource(); // release the old head node. + } + } +} + QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint) { QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); if (dc == objectClass) return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == scarceResourceClass) + return scarceResourceClass->toVariant(val); else if (dc == valueTypeClass) return valueTypeClass->toVariant(val); else if (dc == contextClass) @@ -2218,6 +2314,20 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths) Imports the plugin named \a filePath with the \a uri provided. Returns true if the plugin was successfully imported; otherwise returns false. + On failure and if non-null, the \a errors list will have any errors which occurred prepended to it. + + The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface. +*/ +bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors) +{ + Q_D(QDeclarativeEngine); + return d->importDatabase.importPlugin(filePath, uri, errors); +} + +/*! + Imports the plugin named \a filePath with the \a uri provided. + Returns true if the plugin was successfully imported; otherwise returns false. + On failure and if non-null, *\a errorString will be set to a message describing the failure. The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface. @@ -2225,7 +2335,18 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths) bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString) { Q_D(QDeclarativeEngine); - return d->importDatabase.importPlugin(filePath, uri, errorString); + QList<QDeclarativeError> errors; + bool retn = d->importDatabase.importPlugin(filePath, uri, &errors); + if (!errors.isEmpty()) { + QString builtError; + for (int i = 0; i < errors.size(); ++i) { + builtError = QString(QLatin1String("%1\n %2")) + .arg(builtError) + .arg(errors.at(i).toString()); + } + *errorString = builtError; + } + return retn; } /*! |