forked from qt-creator/qt-creator
		
	Qml Live Preview: Support for updating complex types
Such as anchors and font. This required a little bit of refactoring. The Delta::update should now be faster.
This commit is contained in:
		@@ -276,8 +276,43 @@ static QString _methodName(UiSourceElement *source)
 | 
			
		||||
    return QString();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static UiObjectMemberList *objectMembers(UiObjectMember *object)
 | 
			
		||||
{
 | 
			
		||||
    if (UiObjectDefinition *def = cast<UiObjectDefinition *>(object))
 | 
			
		||||
        return def->initializer->members;
 | 
			
		||||
    else if (UiObjectBinding *binding = cast<UiObjectBinding *>(object))
 | 
			
		||||
        return binding->initializer->members;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static QHash<QString, UiObjectMember*> extractProperties(UiObjectDefinition *object)
 | 
			
		||||
{
 | 
			
		||||
    QHash<QString, UiObjectMember*> result;
 | 
			
		||||
    for (UiObjectMemberList *objectMemberIt = objectMembers(object); objectMemberIt; objectMemberIt = objectMemberIt->next) {
 | 
			
		||||
        if (UiScriptBinding *script = cast<UiScriptBinding *>(objectMemberIt->member)) {
 | 
			
		||||
            const QString property = _propertyName(script->qualifiedId);
 | 
			
		||||
            result.insert(property, script);
 | 
			
		||||
        } else if (UiObjectDefinition *uiObject = cast<UiObjectDefinition *>(objectMemberIt->member)) {
 | 
			
		||||
            const QString l = label(uiObject->qualifiedTypeNameId);
 | 
			
		||||
            if (!l.isEmpty() && !l[0].isUpper()) {
 | 
			
		||||
                QHash<QString, UiObjectMember *> recursiveResult = extractProperties(uiObject);
 | 
			
		||||
                for (QHash<QString, UiObjectMember *>::const_iterator it = recursiveResult.constBegin();
 | 
			
		||||
                     it != recursiveResult.constEnd(); ++it) {
 | 
			
		||||
                    result.insert(l + QLatin1Char('.') + it.key(), it.value());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (UiSourceElement *uiSource = cast<UiSourceElement*>(objectMemberIt->member)) {
 | 
			
		||||
            const QString methodName = _methodName(uiSource);
 | 
			
		||||
            result.insert(methodName, uiSource);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //end namespace
 | 
			
		||||
 | 
			
		||||
void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const QList<QDeclarativeDebugObjectReference > &debugReferences, const Document::Ptr &doc)
 | 
			
		||||
{
 | 
			
		||||
    if (doNotSendChanges)
 | 
			
		||||
@@ -314,9 +349,10 @@ void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const Q
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Delta::update(UiObjectDefinition* oldObject, const QmlJS::Document::Ptr& oldDoc,
 | 
			
		||||
                                             UiObjectDefinition* newObject, const QmlJS::Document::Ptr& newDoc,
 | 
			
		||||
                                             const QList< QDeclarativeDebugObjectReference >& debugReferences)
 | 
			
		||||
                   UiObjectDefinition* newObject, const QmlJS::Document::Ptr& newDoc,
 | 
			
		||||
                   const QList< QDeclarativeDebugObjectReference >& debugReferences)
 | 
			
		||||
{
 | 
			
		||||
    if (doNotSendChanges)
 | 
			
		||||
        return;
 | 
			
		||||
@@ -324,56 +360,29 @@ void Delta::update(UiObjectDefinition* oldObject, const QmlJS::Document::Ptr& ol
 | 
			
		||||
    Q_ASSERT (oldObject && newObject);
 | 
			
		||||
    QSet<QString> presentBinding;
 | 
			
		||||
 | 
			
		||||
    for (UiObjectMemberList *objectMemberIt = objectMembers(newObject); objectMemberIt; objectMemberIt = objectMemberIt->next) {
 | 
			
		||||
        if (UiScriptBinding *script = cast<UiScriptBinding *>(objectMemberIt->member)) {
 | 
			
		||||
            bool found = false;
 | 
			
		||||
            const QString property = _propertyName(script->qualifiedId);
 | 
			
		||||
            presentBinding.insert(property);
 | 
			
		||||
            for (UiObjectMemberList *previousObjectMemberIt = Delta::objectMembers(oldObject); previousObjectMemberIt; previousObjectMemberIt = previousObjectMemberIt->next) {
 | 
			
		||||
                if (UiScriptBinding *previousScript = cast<UiScriptBinding *>(previousObjectMemberIt->member)) {
 | 
			
		||||
                    if (compare(script->qualifiedId, previousScript->qualifiedId)) {
 | 
			
		||||
                        found = true;
 | 
			
		||||
                        const QString scriptCode = _scriptCode(script, newDoc);
 | 
			
		||||
                        const QString previousScriptCode = _scriptCode(previousScript, oldDoc);
 | 
			
		||||
    const QHash<QString, UiObjectMember *> oldProperties = extractProperties(oldObject);
 | 
			
		||||
    const QHash<QString, UiObjectMember *> newProperties = extractProperties(newObject);
 | 
			
		||||
 | 
			
		||||
                        if (scriptCode != previousScriptCode) {
 | 
			
		||||
                            foreach (const QDeclarativeDebugObjectReference &ref, debugReferences) {
 | 
			
		||||
                                if (ref.debugId() != -1)
 | 
			
		||||
                                    updateScriptBinding(ref, script, property, scriptCode);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!found) {
 | 
			
		||||
                const QString scriptCode = _scriptCode(script, newDoc);
 | 
			
		||||
    for (QHash<QString, UiObjectMember *>::const_iterator it = newProperties.constBegin();
 | 
			
		||||
         it != newProperties.constEnd(); ++it) {
 | 
			
		||||
 | 
			
		||||
        UiObjectMember *oldMember = oldProperties.value(it.key());
 | 
			
		||||
        if (UiScriptBinding *script = cast<UiScriptBinding *>(*it)) {
 | 
			
		||||
            const QString property = it.key();
 | 
			
		||||
            const QString scriptCode = _scriptCode(script, newDoc);
 | 
			
		||||
            UiScriptBinding *previousScript = cast<UiScriptBinding *>(oldMember);
 | 
			
		||||
            if (!previousScript || _scriptCode(previousScript, oldDoc) != scriptCode) {
 | 
			
		||||
                foreach (const QDeclarativeDebugObjectReference &ref, debugReferences) {
 | 
			
		||||
                    if (ref.debugId() != -1)
 | 
			
		||||
                        updateScriptBinding(ref, script, property, scriptCode);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (UiSourceElement *uiSource = cast<UiSourceElement*>(objectMemberIt->member)) {
 | 
			
		||||
            bool found = false;
 | 
			
		||||
            const QString methodName = _methodName(uiSource);
 | 
			
		||||
            for (UiObjectMemberList *previousObjectMemberIt = objectMembers(oldObject);
 | 
			
		||||
                previousObjectMemberIt; previousObjectMemberIt = previousObjectMemberIt->next) {
 | 
			
		||||
                if (UiSourceElement *previousSource = cast<UiSourceElement*>(previousObjectMemberIt->member)) {
 | 
			
		||||
                    if (compare(uiSource, previousSource)) {
 | 
			
		||||
                        found = true;
 | 
			
		||||
                        const QString methodCode = _methodCode(uiSource, newDoc);
 | 
			
		||||
                        const QString previousMethodCode = _methodCode(previousSource, oldDoc);
 | 
			
		||||
        } else if (UiSourceElement *uiSource = cast<UiSourceElement*>(*it)) {
 | 
			
		||||
            const QString methodName = it.key();
 | 
			
		||||
            const QString methodCode = _methodCode(uiSource, newDoc);
 | 
			
		||||
            UiSourceElement *previousSource = cast<UiSourceElement*>(oldMember);
 | 
			
		||||
 | 
			
		||||
                        if (methodCode != previousMethodCode) {
 | 
			
		||||
                            foreach (const QDeclarativeDebugObjectReference &ref, debugReferences) {
 | 
			
		||||
                                if (ref.debugId() != -1)
 | 
			
		||||
                                    updateMethodBody(ref, script, methodName, methodCode);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!found) {
 | 
			
		||||
                const QString methodCode = _methodCode(uiSource, newDoc);
 | 
			
		||||
            if (!previousSource || _methodCode(previousSource, oldDoc) != methodCode) {
 | 
			
		||||
                foreach (const QDeclarativeDebugObjectReference &ref, debugReferences) {
 | 
			
		||||
                    if (ref.debugId() != -1)
 | 
			
		||||
                        updateMethodBody(ref, script, methodName, methodCode);
 | 
			
		||||
@@ -382,18 +391,18 @@ void Delta::update(UiObjectDefinition* oldObject, const QmlJS::Document::Ptr& ol
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (doNotSendChanges)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    //reset property that are not present in the new object.
 | 
			
		||||
    for (UiObjectMemberList *previousObjectMemberIt = Delta::objectMembers(oldObject); previousObjectMemberIt; previousObjectMemberIt = previousObjectMemberIt->next) {
 | 
			
		||||
        if (UiScriptBinding *previousScript = cast<UiScriptBinding *>(previousObjectMemberIt->member)) {
 | 
			
		||||
            const QString property = _propertyName(previousScript->qualifiedId);
 | 
			
		||||
            if (!presentBinding.contains(property)) {
 | 
			
		||||
    for (QHash<QString, UiObjectMember *>::const_iterator it2 = oldProperties.constBegin();
 | 
			
		||||
         it2 != oldProperties.constEnd(); ++it2) {
 | 
			
		||||
 | 
			
		||||
        if (!newProperties.contains(it2.key())) {
 | 
			
		||||
            if (UiScriptBinding *previousScript = cast<UiScriptBinding *>(*it2)) {
 | 
			
		||||
                foreach (const QDeclarativeDebugObjectReference &ref, debugReferences) {
 | 
			
		||||
                    if (ref.debugId() != -1)
 | 
			
		||||
                        ClientProxy::instance()->resetBindingForObject(ref.debugId(), property); // ### remove
 | 
			
		||||
                        ClientProxy::instance()->resetBindingForObject(ref.debugId(), it2.key()); // ### remove
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -409,8 +418,6 @@ void Delta::remove(const QList< QDeclarativeDebugObjectReference >& debugReferen
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::Ptr &doc2, const DebugIdMap &debugIds)
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(doc1->qmlProgram());
 | 
			
		||||
@@ -643,16 +650,6 @@ bool Delta::compare(UiSourceElement *source, UiSourceElement *other)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UiObjectMemberList *Delta::objectMembers(UiObjectMember *object)
 | 
			
		||||
{
 | 
			
		||||
    if (UiObjectDefinition *def = cast<UiObjectDefinition *>(object))
 | 
			
		||||
        return def->initializer->members;
 | 
			
		||||
    else if (UiObjectBinding *binding = cast<UiObjectBinding *>(object))
 | 
			
		||||
        return binding->initializer->members;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Document::Ptr Delta::document() const
 | 
			
		||||
{
 | 
			
		||||
    return _doc;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user