diff options
Diffstat (limited to 'src/declarative/qml/qdeclarativeengine.cpp')
| -rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 261 | 
1 files changed, 195 insertions, 66 deletions
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 52a1f45..e459d0f 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -61,7 +61,6 @@  #include "private/qdeclarativeglobal_p.h"  #include "private/qdeclarativeworkerscript_p.h"  #include "private/qdeclarativecomponent_p.h" -#include "private/qdeclarativescriptclass_p.h"  #include "qdeclarativenetworkaccessmanagerfactory.h"  #include "qdeclarativeimageprovider.h"  #include "private/qdeclarativedirparser_p.h" @@ -183,11 +182,11 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)                  fileImportPath.append(canonicalPath);          }      } -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))      QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);      if (!builtinPath.isEmpty())          fileImportPath += builtinPath; -#endif + +    filePluginPath += QLatin1String(".");  } @@ -226,6 +225,7 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr      // XXX used to add Qt.Sound class.      //types +    qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1));      qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4));      qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4));      qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4)); @@ -346,6 +346,17 @@ Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer);  typedef QMap<QString, QString> StringStringMap;  Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri + +void QDeclarativeDeclarativeData::destroyed(QDeclarativeData *d, QObject *o) +{ +    static_cast<QDeclarativeDeclarativeData *>(d)->destroyed(o); +} + +void QDeclarativeDeclarativeData::parentChanged(QDeclarativeData *d, QObject *o, QObject *p) +{ +    static_cast<QDeclarativeDeclarativeData *>(d)->parentChanged(o, p); +} +  void QDeclarativeEnginePrivate::init()  {      Q_Q(QDeclarativeEngine); @@ -353,6 +364,8 @@ void QDeclarativeEnginePrivate::init()      qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");      qRegisterMetaType<QScriptValue>("QScriptValue"); +    QDeclarativeDeclarativeData::init(); +      contextClass = new QDeclarativeContextScriptClass(q);      objectClass = new QDeclarativeObjectScriptClass(q);      valueTypeClass = new QDeclarativeValueTypeScriptClass(q); @@ -396,7 +409,7 @@ QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine    \code    QDeclarativeEngine engine;    QDeclarativeComponent component(&engine); -  component.setData("import Qt 4.6\nText { text: \"Hello world!\" }", QUrl()); +  component.setData("import Qt 4.7\nText { text: \"Hello world!\" }", QUrl());    QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());    //add item to view, etc @@ -848,15 +861,16 @@ void QDeclarativeDeclarativeData::destroyed(QObject *object)      if (ownContext)          context->destroy(); +    if (scriptValue) +        delete scriptValue; +      if (ownMemory)          delete this; -    else  -        this->~QDeclarativeDeclarativeData();  }  void QDeclarativeDeclarativeData::parentChanged(QObject *, QObject *parent)  { -    if (!parent && scriptValue.isValid()) scriptValue = QScriptValue(); +    if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }  }  bool QDeclarativeDeclarativeData::hasBindingBit(int bit) const @@ -1014,6 +1028,14 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS      return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar);  } +QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine) +{ +    if (ctxt->argumentCount() == 0) +        return QScriptValue(engine, false); + +    return QScriptValue(engine, 0 != ctxt->argument(0).toQObject()); +} +  QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine)  {      if(ctxt->argumentCount() != 3) @@ -1310,7 +1332,6 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine      return qScriptValueFromValue(engine, qVariantFromValue(finalColor));  } -  QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)  {      if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { @@ -1321,6 +1342,14 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v          } else {              return scriptEngine.nullValue();          } +    } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) { +        const QList<QObject *> &list = *(QList<QObject *>*)val.constData(); +        QScriptValue rv = scriptEngine.newArray(list.count()); +        for (int ii = 0; ii < list.count(); ++ii) { +            QObject *object = list.at(ii); +            rv.setProperty(ii, objectClass->newQObject(object)); +        } +        return rv;      }       bool objOk; @@ -1332,35 +1361,29 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v      }  } -QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val) +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 == valueTypeClass)  +        return valueTypeClass->toVariant(val);      else if (dc == contextClass)          return QVariant(); -    QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val); -    if (!sc) { -        return val.toVariant(); -    } else if (sc == valueTypeClass) { -        return valueTypeClass->toVariant(val); -    } else { -        return QVariant(); +    // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted +    if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) { +        QList<QObject *> list; +        int length = val.property(QLatin1String("length")).toInt32(); +        for (int ii = 0; ii < length; ++ii) { +            QScriptValue arrayItem = val.property(ii); +            QObject *d = arrayItem.toQObject(); +            list << d; +        } +        return QVariant::fromValue(list);      } -} -QDeclarativeScriptClass::QDeclarativeScriptClass(QScriptEngine *engine) -: QScriptDeclarativeClass(engine) -{ -} - -QVariant QDeclarativeScriptClass::toVariant(QDeclarativeEngine *engine, const QScriptValue &val) -{ -    QDeclarativeEnginePrivate *ep = -        static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine)); - -    return ep->scriptValueToVariant(val); +    return val.toVariant();  }  // XXX this beyonds in QUrl::toLocalFile() @@ -1463,13 +1486,17 @@ public:      QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded; -    QDeclarativeDirComponents importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine) { +    QDeclarativeDirComponents importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine, QString *errorString) {          QFile file(absoluteFilePath);          QString filecontent;          if (file.open(QFile::ReadOnly)) {              filecontent = QString::fromUtf8(file.readAll());              if (qmlImportTrace())                  qDebug() << "QDeclarativeEngine::add: loaded" << absoluteFilePath; +        } else { +            if (errorString) +                *errorString = QDeclarativeEngine::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath); +            return QDeclarativeDirComponents();          }          QDir dir = QFileInfo(file).dir(); @@ -1483,19 +1510,21 @@ public:              foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { -                QDir pluginDir = dir.absoluteFilePath(plugin.path); - -                // hack for resources, should probably go away -                if (absoluteFilePath.startsWith(QLatin1Char(':'))) -                    pluginDir = QDir(QCoreApplication::applicationDirPath()); -                  QString resolvedFilePath =                          QDeclarativeEnginePrivate::get(engine) -                        ->resolvePlugin(pluginDir, +                        ->resolvePlugin(dir, plugin.path,                                          plugin.name);                  if (!resolvedFilePath.isEmpty()) { -                    engine->importExtension(resolvedFilePath, uri); +                    if (!engine->importPlugin(resolvedFilePath, uri)) { +                        if (errorString) +                            *errorString = QDeclarativeEngine::tr("plugin \"%1\" cannot be loaded for module \"%2\"").arg(resolvedFilePath).arg(uri); +                        return QDeclarativeDirComponents(); +                    } +                } else { +                    if (errorString) +                        *errorString = QDeclarativeEngine::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name); +                    return QDeclarativeDirComponents();                  }              }          } @@ -1560,7 +1589,9 @@ public:                      url = QUrl::fromLocalFile(fi.absolutePath()).toString();                      uri = resolvedUri(dir, engine); -                    qmldircomponents = importExtension(absoluteFilePath, uri, engine); +                    qmldircomponents = importExtension(absoluteFilePath, uri, engine, errorString); +                    if (qmldircomponents.isEmpty()) // error (or empty) +                        return false;                      break;                  }              } @@ -1591,12 +1622,14 @@ public:                          return false; // local import dirs must exist                      }                      uri = resolvedUri(toLocalFileOrQrc(base.resolved(QUrl(uri))), engine); -                    qmldircomponents = importExtension(localFileOrQrc, -                                                    uri, -                                                    engine); -                      if (uri.endsWith(QLatin1Char('/')))                          uri.chop(1); +                    if (QFile::exists(localFileOrQrc)) { +                        qmldircomponents = importExtension(localFileOrQrc, +                                                    uri,engine,errorString); +                        if (qmldircomponents.isEmpty()) // error (or empty) +                            return false; +                    }                  } else {                      if (prefix.isEmpty()) {                          // directory must at least exist for valid import @@ -1619,6 +1652,18 @@ public:                  url.chop(1);          } +        if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { +            QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin(); +            for (; it != qmldircomponents.end(); ++it) { +                if (it->majorVersion > vmaj || (it->majorVersion == vmaj && it->minorVersion >= vmin)) +                    break; +            } +            if (it == qmldircomponents.end()) { +                *errorString = QDeclarativeEngine::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); +                return false; +            } +        } +          s->uris.prepend(uri);          s->urls.prepend(url);          s->majversions.prepend(vmaj); @@ -1778,8 +1823,8 @@ QUrl QDeclarativeEnginePrivate::Imports::baseUrl() const  }  /*! -  Adds \a path as a directory where installed QML components are -  defined in a URL-based directory structure. +  Adds \a path as a directory where the engine searches for +  installed modules in a URL-based directory structure.    The newly added \a path will be first in the importPathList(). @@ -1802,7 +1847,7 @@ void QDeclarativeEngine::addImportPath(const QString& path)  /*!    Returns the list of directories where the engine searches for -  installed modules. +  installed modules in a URL-based directory structure.    For example, if \c /opt/MyApp/lib/imports is in the path, then QML that    imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look @@ -1823,7 +1868,7 @@ QStringList QDeclarativeEngine::importPathList() const  /*!    Sets the list of directories where the engine searches for -  installed modules. +  installed modules in a URL-based directory structure.    By default, the list contains the paths specified in the \c QML_IMPORT_PATH environment    variable, then the builtin \c ImportsPath from QLibraryInfo. @@ -1836,15 +1881,73 @@ void QDeclarativeEngine::setImportPathList(const QStringList &paths)      d->fileImportPath = paths;  } + +/*! +  Adds \a path as a directory where the engine searches for +  native plugins for imported modules (referenced in the \c qmldir file). + +  By default, the list contains only \c .,  i.e. the engine searches +  in the directory of the \c qmldir file itself. + +  The newly added \a path will be first in the pluginPathList(). + +  \sa setPluginPathList() +*/ +void QDeclarativeEngine::addPluginPath(const QString& path) +{ +    if (qmlImportTrace()) +        qDebug() << "QDeclarativeEngine::addPluginPath" << path; +    Q_D(QDeclarativeEngine); +    QUrl url = QUrl(path); +    if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) { +        QDir dir = QDir(path); +        d->filePluginPath.prepend(dir.canonicalPath()); +    } else { +        d->filePluginPath.prepend(path); +    } +} + + +/*! +  Returns the list of directories where the engine searches for +  native plugins for imported modules (referenced in the \c qmldir file). + +  By default, the list contains only \c .,  i.e. the engine searches +  in the directory of the \c qmldir file itself. + +  \sa addPluginPath() setPluginPathList() +*/ +QStringList QDeclarativeEngine::pluginPathList() const +{ +    Q_D(const QDeclarativeEngine); +    return d->filePluginPath; +} + +/*! +  Sets the list of directories where the engine searches for +  native plugins for imported modules (referenced in the \c qmldir file). + +  By default, the list contains only \c .,  i.e. the engine searches +  in the directory of the \c qmldir file itself. + +  \sa pluginPathList() addPluginPath() +  */ +void QDeclarativeEngine::setPluginPathList(const QStringList &paths) +{ +    Q_D(QDeclarativeEngine); +    d->filePluginPath = paths; +} + +  /*! -  Imports the extension named \a fileName from the \a uri provided. -  Returns true if the extension was successfully imported. +  Imports the plugin named \a filePath with the \a uri provided. +  Returns true if the plugin was successfully imported; otherwise returns false.  */ -bool QDeclarativeEngine::importExtension(const QString &fileName, const QString &uri) +bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri)  {      if (qmlImportTrace()) -        qDebug() << "QDeclarativeEngine::importExtension" << uri << "from" << fileName; -    QFileInfo fileInfo(fileName); +        qDebug() << "QDeclarativeEngine::importPlugin" << uri << "from" << filePath; +    QFileInfo fileInfo(filePath);      const QString absoluteFilePath = fileInfo.absoluteFilePath();      QDeclarativeEnginePrivate *d = QDeclarativeEnginePrivate::get(this); @@ -1917,27 +2020,53 @@ QString QDeclarativeEngine::offlineStoragePath() const  /*!    \internal -  Returns the result of the merge of \a baseName with \a dir, \a suffixes, and \a prefix. +  Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix.    The \a prefix must contain the dot. + +  \a qmldirPath is the location of the qmldir file.   */ -QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName, +QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName,                                          const QStringList &suffixes,                                          const QString &prefix)  { -    foreach (const QString &suffix, suffixes) { -        QString pluginFileName = prefix; +    QStringList searchPaths = filePluginPath; +    bool qmldirPluginPathIsRelative = QDir::isRelativePath(qmldirPluginPath); +    if (!qmldirPluginPathIsRelative) +        searchPaths.prepend(qmldirPluginPath); -        pluginFileName += baseName; -        pluginFileName += suffix; +    foreach (const QString &pluginPath, searchPaths) { -        QFileInfo fileInfo(dir, pluginFileName); +        QString resolvedPath; + +        if (pluginPath == QLatin1String(".")) { +            if (qmldirPluginPathIsRelative) +                resolvedPath = qmldirPath.absoluteFilePath(qmldirPluginPath); +            else +                resolvedPath = qmldirPath.absolutePath(); +        } else { +            resolvedPath = pluginPath; +        } -        if (fileInfo.exists()) -            return fileInfo.absoluteFilePath(); +        // hack for resources, should probably go away +        if (resolvedPath.startsWith(QLatin1Char(':'))) +            resolvedPath = QCoreApplication::applicationDirPath(); + +        QDir dir(resolvedPath); +        foreach (const QString &suffix, suffixes) { +            QString pluginFileName = prefix; + +            pluginFileName += baseName; +            pluginFileName += suffix; + +            QFileInfo fileInfo(dir, pluginFileName); + +            if (fileInfo.exists()) +                return fileInfo.absoluteFilePath(); +        }      }      if (qmlImportTrace()) -        qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << dir.absolutePath(); +        qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << qmldirPath.absolutePath();      return QString();  } @@ -1958,17 +2087,17 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString    Version number on unix are ignored.  */ -QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName) +QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName)  {  #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) -    return resolvePlugin(dir, baseName, +    return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,                           QStringList()  # ifdef QT_DEBUG                           << QLatin1String("d.dll") // try a qmake-style debug build first  # endif                           << QLatin1String(".dll"));  #elif defined(Q_OS_SYMBIAN) -    return resolvePlugin(dir, baseName, +    return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,                           QStringList()                           << QLatin1String(".dll")                           << QLatin1String(".qtplugin")); @@ -1976,7 +2105,7 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString  # if defined(Q_OS_DARWIN) -    return resolvePlugin(dir, baseName, +    return resolvePlugin(qmldirPath, qmldirPluginPath, baseName,                           QStringList()  # ifdef QT_DEBUG                           << QLatin1String("_debug.dylib") // try a qmake-style debug build first @@ -2010,7 +2139,7 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString      // Examples of valid library names:      //  libfoo.so -    return resolvePlugin(dir, baseName, validSuffixList, QLatin1String("lib")); +    return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));  # endif  #endif  | 
